diff --git a/.vpython3 b/.vpython3 index 8872e87..c103d6f 100644 --- a/.vpython3 +++ b/.vpython3
@@ -166,7 +166,7 @@ version: "version:8.3.1" # There is currently no Linux arm/arm64 version in CIPD. not_match_tag < - platform: "linux_aarch64" + platform: "linux_arm64" > > wheel: < @@ -174,7 +174,7 @@ version: "version:4.5.3.56.chromium.4" # There is currently no Linux arm/arm64 version in CIPD. not_match_tag < - platform: "linux_aarch64" + platform: "linux_arm64" > > @@ -476,7 +476,7 @@ wheel: < name: "infra/python/wheels/websockets-py3" - version: "version:10.1" + version: "version:10.3" > # Used by: @@ -525,7 +525,7 @@ name: "infra/python/wheels/pandas/${vpython_platform}" version: "version:1.3.2.chromium.1" not_match_tag: < - platform: "linux_aarch64" + platform: "linux_arm64" > >
diff --git a/DEPS b/DEPS index 3f45a8e..d3c22a8 100644 --- a/DEPS +++ b/DEPS
@@ -251,7 +251,7 @@ # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:20c50aa39686d91330c2daceccaa4ef1a0a72ee4', + 'luci_go': 'git_revision:45c4b0ebf2c594bbd64adf3f042f3f491c16bbdf', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -308,7 +308,7 @@ # 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': '128982bf78aa76794254f67d9730b8305aeb3699', + 'skia_revision': '6937e7b311221aaff448abce8636bb09f2874962', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -316,11 +316,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '1d73bad50b314f1e82d2430e22d155ec06b8fbab', + 'angle_revision': 'be8aa9e9fbaa9278d5a0ebd18fd43357829d8c87', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '6ce35a782d41e4e585580e64784ee1e44ca71343', + 'swiftshader_revision': '08dfcbb377340fc51b72b942ac7748697dabdad2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -335,7 +335,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:9.20221003.2.1', + 'fuchsia_version': 'version:9.20221003.3.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -359,7 +359,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'b93f20ab7ad610c986497243ca963ca79013411c', + 'freetype_revision': '8faf57dd17088c37fa947fd565870648bbdbad18', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -379,7 +379,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '16eb7278843e4955064c980c5887668d6cba1035', + 'catapult_revision': '0237c57801ec63450b3af3050aed06ffcc31164e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -387,7 +387,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': '083a71314f9df7915f66871ca6abebe976e145bd', + 'devtools_frontend_revision': '23179707af80429b41360ac4066fb79608f8aa48', # 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. @@ -423,11 +423,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '2c26dbfc37c0e0e8932c030a85cb7d4c617f86f3', + 'dawn_revision': '4c569d14ab6573deb118cc916440d714eb9c7e8c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '3e90101e4b8f960b29ff93a8de8d4c37740a506b', + 'quiche_revision': '3a819a7a4f5d34eacc5797864c335de65618b118', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -993,7 +993,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'eKem4aR0h5tF6CwsZ5EAMu3gmdNf1T1b6oQSQTEi21gC', + 'version': 'tlL4NXCU9VloHEQBuJdPXXhRoEmQlCqfefFTxshooSUC', }, ], 'condition': 'checkout_android', @@ -1236,13 +1236,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a724859f7a9b3531c0373d86886a42314e772532', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'fe24047cdc1881176094cb61065402d67a20243f', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'a617a371fe0a37c396b1b204cbecdfc29bd81490', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'abc7a6bc6df55e64128f6f3ef10447a3141641ee', 'condition': 'checkout_src_internal', }, @@ -1250,7 +1250,7 @@ Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '199de96b345ada7c6e7e6ba3d2fa7a6911b8767d', 'src/third_party/eigen3/src': - Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + 'dceb779ecd822f55b4ae78f760371b0e08a889f2', + Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + 'b3bf8d6a13585ff248c079402654647d298de60b', 'src/third_party/emoji-metadata/src': { 'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '8de89a7a36cd024dcd30ac9f67f3f02c37a7c8fb', @@ -1786,7 +1786,7 @@ Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f', 'src/third_party/tflite/src': - Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'e6ca8d5097646089651f009d93eec1e4597d2fbf', + Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'da1ec73e06b2f1129aed8738ed3e530256899d07', 'src/third_party/turbine': { 'packages': [ @@ -1839,7 +1839,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e84b11b1d90efe59e94bb24d1f1276071f50481e', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '4426c4709db5f8090d407b05e76563475c72049e', + Var('webrtc_git') + '/src.git' + '@' + 'ef51274188d7cf4611bb869ca1304e2f85c3d943', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1866,7 +1866,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'UdHMUZDUIpKh3Fkx8MkPeRz_hbu1MnpCmJdM7inIoQ0C', + 'version': '4jQ6gzrqaKCyEn_8V_Y5qXFi7zg2AYJ-OdNJsmywBJUC', }, ], 'dep_type': 'cipd', @@ -1876,7 +1876,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'xQDgjyn3X4sbT9v84yOcqZKH28r7ZtHM7EMnTDPGkLMC', + 'version': 'v8uUG8MbJk5MqnqE-Oe0lpCWpvwrzmhT4Bb0jKxA-hoC', }, ], 'dep_type': 'cipd', @@ -1887,7 +1887,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'F6P1CZGSbpsEUcMbvplibXMpTLn8eJ2JEyFoJNFJRPcC', + 'version': '68Q-YqkF1ut4cqxu8AL0aBux2bqV8J1T1x6L9sOg8g0C', }, ], 'dep_type': 'cipd', @@ -1898,7 +1898,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': 'g7lVD9PQ8qtqyTgw31tXGQr3XYgNTGXbmo0SCsi5hJEC', + 'version': '2BbiGimzY0i9eeqhzJAe3mynFtS0uE4wB33voz1XNqYC', }, ], 'dep_type': 'cipd', @@ -1909,7 +1909,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fa6be2bfaee7304c03af2691d6bb06b99dd4d968', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@5ac75be1959dbcaf6c06a91ef7ea7e36a3e39637', 'condition': 'checkout_src_internal', },
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index c46683d..d575203b 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1762,6 +1762,8 @@ "system/tray/unfocusable_label.cc", "system/tray/unfocusable_label.h", "system/tray/view_click_listener.h", + "system/unified/buttons.cc", + "system/unified/buttons.h", "system/unified/camera_mic_tray_item_view.cc", "system/unified/camera_mic_tray_item_view.h", "system/unified/collapse_button.cc",
diff --git a/ash/accelerators/ash_accelerator_configuration.cc b/ash/accelerators/ash_accelerator_configuration.cc index 86bc1c8..3b557b9 100644 --- a/ash/accelerators/ash_accelerator_configuration.cc +++ b/ash/accelerators/ash_accelerator_configuration.cc
@@ -6,6 +6,7 @@ #include <vector> +#include "ash/accelerators/accelerator_layout_table.h" #include "ash/accelerators/accelerator_table.h" #include "ash/accelerators/debug_commands.h" #include "ash/constants/ash_features.h" @@ -13,6 +14,9 @@ #include "ash/public/mojom/accelerator_info.mojom.h" #include "base/containers/contains.h" #include "base/containers/span.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/ui_base_features.h" @@ -199,15 +203,21 @@ } void AshAcceleratorConfiguration::AddLayoutInfo(const AcceleratorData& data) { - // TODO(jimmyxgong): This a basic stub implementation, replace with real - // implementation. + DCHECK(kAcceleratorLayouts.contains(data.action)); + const AcceleratorLayoutDetails& layout_details = + kAcceleratorLayouts.at(data.action); + mojom::AcceleratorLayoutInfoPtr layout_info = mojom::AcceleratorLayoutInfo::New(); - layout_info->category = mojom::AcceleratorCategory::kSystem; - layout_info->sub_category = mojom::AcceleratorSubcategory::kGeneral; + layout_info->category = layout_details.category; + layout_info->sub_category = layout_details.sub_category; // TODO(jimmyxgong): Create a mapping between action_id and description. - layout_info->description = u"Stub description"; - layout_info->style = mojom::AcceleratorLayoutStyle::kDefault; + const std::string stub_description = + base::StrCat({"action: ", base::NumberToString(data.action), + " : keycode: ", base::NumberToString(data.keycode), + " : modifiers: ", base::NumberToString(data.modifiers)}); + layout_info->description = base::UTF8ToUTF16(stub_description); + layout_info->style = layout_details.layout_style; layout_info->source = mojom::AcceleratorSource::kAsh; layout_info->action = static_cast<uint32_t>(data.action);
diff --git a/ash/accelerators/ash_accelerator_configuration_unittest.cc b/ash/accelerators/ash_accelerator_configuration_unittest.cc index 5ee946d7..f7007b4 100644 --- a/ash/accelerators/ash_accelerator_configuration_unittest.cc +++ b/ash/accelerators/ash_accelerator_configuration_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include "ash/accelerators/accelerator_layout_table.h" #include "ash/public/cpp/accelerators.h" #include "base/test/scoped_feature_list.h" #include "ui/base/ui_base_features.h" @@ -61,6 +62,25 @@ return deprecated_infos; } +// Validates that the passed in layouts have matching accelerator layouts in +// `kAcceleratorLayouts`. If this throws an expectation error it means that +// the there is a inconsistency between the layouts in `kAcceleratorLayouts` and +// the data provided by `AshAcceleratorConfiguration`. +void ValidateAcceleratorLayouts( + const std::vector<ash::mojom::AcceleratorLayoutInfoPtr>& actual_layouts) { + for (const auto& actual : actual_layouts) { + EXPECT_TRUE(ash::kAcceleratorLayouts.contains(actual->action)); + + const ash::AcceleratorLayoutDetails& expected = + ash::kAcceleratorLayouts.at(actual->action); + + EXPECT_EQ(expected.category, actual->category); + EXPECT_EQ(expected.sub_category, actual->sub_category); + EXPECT_EQ(expected.layout_style, actual->style); + EXPECT_EQ(ash::mojom::AcceleratorSource::kAsh, actual->source); + } +} + } // namespace namespace ash { @@ -159,4 +179,16 @@ ui::EF_COMMAND_DOWN); EXPECT_FALSE(config_->IsDeprecated(active_accelerator)); } + +TEST_F(AshAcceleratorConfigurationTest, ValidateAllAcceleratorLayouts) { + // Initialize with all default accelerators. + config_->Initialize(); + const std::vector<mojom::AcceleratorLayoutInfoPtr>& actual_layouts = + config_->GetAcceleratorLayoutInfos(); + + // Verify that all default accelerators have the correctly mapped layout + // details. + ValidateAcceleratorLayouts(actual_layouts); +} + } // namespace ash
diff --git a/ash/capture_mode/folder_selection_dialog_controller.h b/ash/capture_mode/folder_selection_dialog_controller.h index dcbb00a..0a3ee7d 100644 --- a/ash/capture_mode/folder_selection_dialog_controller.h +++ b/ash/capture_mode/folder_selection_dialog_controller.h
@@ -82,7 +82,7 @@ WindowDimmer dialog_background_dimmer_; // Provides us with the APIs needed to construct a folder selection dialog. - std::unique_ptr<ui::SelectFileDialog> select_folder_dialog_; + scoped_refptr<ui::SelectFileDialog> select_folder_dialog_; // This is the window of the dialog that gets created by // |select_folder_dialog_| as a transient child of the dimming window.
diff --git a/ash/components/arc/mojom/net.mojom b/ash/components/arc/mojom/net.mojom index 33939500..9a78c23 100644 --- a/ash/components/arc/mojom/net.mojom +++ b/ash/components/arc/mojom/net.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Next MinVersion: 20 +// Next MinVersion: 21 // This file defines the mojo interface between the ARC networking stack and // Chrome OS. There are three different groups of interactions: @@ -262,9 +262,6 @@ // IP family for that configuration IPAddressType type; - - // URL of the HTTP proxy to use for that network. - string web_proxy_auto_discovery_url; }; // The subset of wireless security protocols that Android defines in @@ -489,6 +486,74 @@ // Set of EAP credentials used to connect to a network that matched these // credentials. [MinVersion=16] EapCredentials? eap@8; + + // Indicates if the App has expressed an explicit opinion about the + // meteredness of this network. + [MinVersion=20] MeteredOverride metered_override@9; + + // The proxy configuration of this object. + [MinVersion=20] ArcProxyInfo? http_proxy@10; + + // Static IPv4 configuration of the network + [MinVersion=20] StaticIpv4Configuration? static_ipv4_config@11; + + // List of domains to search when resolving host names on this + // link, in priority order. + [MinVersion=20] array<string>? domains@12; + + // DNS server IP addresses included in the configuration + [MinVersion=20] array<string>? dns_servers@13; +}; + +[Extensible] +enum MeteredOverride { + // No metered override + [Default] kNone = 0, + + // Override network to be metered + kMetered = 1, + + // Override network to be unmetered + kNotmetered = 2, +}; + +// Static Ipv4 configuration +struct StaticIpv4Configuration { + // Static IPv4 address included in the configuration + string? ipv4_addr@0; + + // Static IPv4 address of the gateway included in the configuration + string? gateway_ipv4_addr@1; + + // Prefix length of the network + int32 prefix_length@2; +}; + +// For ProxyInfo, we have 2 options to set up proxy: +// 1. a direct configuration: host, port, and exclusion_list are +// used and pac_url is ignored +// 2. a PAC URL configuration: only pac_url +// is used and other fields are ignored. +union ArcProxyInfo { + ManualProxyConfig manual_proxy@0; + PacUrlProxyConfig pac_url_proxy@1; +}; + +struct PacUrlProxyConfig { + // PAC script download URL for that network. + url.mojom.Url pac_url@0; +}; + +struct ManualProxyConfig { + // The host IP address of this proxy + string host@0; + + // The port of this proxy + int32 port@1; + + // When configured to use a Direct Proxy this returns the list of hosts + // for which the proxy is ignored. + array<string> exclusion_list@2; }; // Response object sent back to ARC when it queries existing networks on
diff --git a/ash/components/arc/net/arc_net_host_impl.cc b/ash/components/arc/net/arc_net_host_impl.cc index 24824ef..7ea6643 100644 --- a/ash/components/arc/net/arc_net_host_impl.cc +++ b/ash/components/arc/net/arc_net_host_impl.cc
@@ -708,6 +708,9 @@ // WifiConfiguration object. std::unique_ptr<base::DictionaryValue> properties(new base::DictionaryValue); std::unique_ptr<base::DictionaryValue> wifi_dict(new base::DictionaryValue); + std::unique_ptr<base::DictionaryValue> ipconfig_dict( + new base::DictionaryValue); + std::unique_ptr<base::DictionaryValue> proxy_dict(new base::DictionaryValue); if (!cfg->hexssid.has_value() || !cfg->details) { NET_LOG(ERROR) @@ -726,6 +729,7 @@ properties->SetKey(onc::network_config::kType, base::Value(onc::network_config::kWiFi)); + // StaticIPConfig dictionary wifi_dict->SetKey(onc::wifi::kHexSSID, base::Value(cfg->hexssid.value())); wifi_dict->SetKey(onc::wifi::kAutoConnect, base::Value(details->autoconnect)); if (cfg->security.empty()) { @@ -738,9 +742,82 @@ base::Value(details->passphrase.value())); } } + wifi_dict->SetKey(onc::wifi::kBSSID, base::Value(cfg->bssid)); properties->SetKey(onc::network_config::kWiFi, base::Value::FromUniquePtrValue(std::move(wifi_dict))); + // Set up static IPv4 config. + if (cfg->dns_servers.has_value()) { + ipconfig_dict->SetKey(onc::ipconfig::kNameServers, + TranslateStringListToValue(cfg->dns_servers.value())); + properties->SetKey(onc::network_config::kNameServersConfigType, + base::Value(onc::network_config::kIPConfigTypeStatic)); + } + + if (cfg->domains.has_value()) { + ipconfig_dict->SetKey(onc::ipconfig::kSearchDomains, + TranslateStringListToValue(cfg->domains.value())); + } + + // Static IPv4 address, static IPv4 address of the gateway and + // prefix length are made sure to be all valid or all empty on + // ARC side so we only need to check one of them. + if (cfg->static_ipv4_config && cfg->static_ipv4_config->ipv4_addr) { + ipconfig_dict->SetKey(onc::ipconfig::kType, + base::Value(onc::ipconfig::kIPv4)); + properties->SetKey(onc::network_config::kIPAddressConfigType, + base::Value(onc::network_config::kIPConfigTypeStatic)); + ipconfig_dict->SetKey( + onc::ipconfig::kIPAddress, + base::Value(cfg->static_ipv4_config->ipv4_addr.value())); + ipconfig_dict->SetKey( + onc::ipconfig::kGateway, + base::Value(cfg->static_ipv4_config->gateway_ipv4_addr.value())); + ipconfig_dict->SetKey(onc::ipconfig::kRoutingPrefix, + base::Value(cfg->static_ipv4_config->prefix_length)); + } + // Set up proxy info. If proxy auto discovery pac url is available, + // we set up proxy auto discovery pac url, otherwise we set up + // host, port and exclusion list. + if (cfg->http_proxy) { + if (cfg->http_proxy->get_pac_url_proxy()) { + proxy_dict->SetKey(onc::proxy::kType, base::Value(onc::proxy::kPAC)); + proxy_dict->SetKey( + onc::proxy::kPAC, + base::Value(cfg->http_proxy->get_pac_url_proxy()->pac_url.spec())); + } else { + std::unique_ptr<base::DictionaryValue> manual(new base::DictionaryValue); + manual->SetKey(onc::proxy::kHost, + base::Value(cfg->http_proxy->get_manual_proxy()->host)); + manual->SetKey(onc::proxy::kPort, + base::Value(cfg->http_proxy->get_manual_proxy()->port)); + manual->SetKey(onc::proxy::kExcludeDomains, + TranslateStringListToValue(std::move( + cfg->http_proxy->get_manual_proxy()->exclusion_list))); + proxy_dict->SetKey(onc::proxy::kType, base::Value(onc::proxy::kManual)); + proxy_dict->SetKey(onc::proxy::kManual, + base::Value::FromUniquePtrValue(std::move(manual))); + } + } + + // Set up meteredness based on meteredOverride config from mojom. + if (cfg->metered_override == arc::mojom::MeteredOverride::kMetered) { + properties->SetKey(onc::network_config::kMetered, base::Value(true)); + } else if (cfg->metered_override == + arc::mojom::MeteredOverride::kNotmetered) { + properties->SetKey(onc::network_config::kMetered, base::Value(false)); + } + + if (!ipconfig_dict->DictEmpty()) { + properties->SetKey( + onc::network_config::kStaticIPConfig, + base::Value::FromUniquePtrValue(std::move(ipconfig_dict))); + } + if (!proxy_dict->DictEmpty()) { + properties->SetKey(onc::network_config::kProxySettings, + base::Value::FromUniquePtrValue(std::move(proxy_dict))); + } + std::string user_id_hash = chromeos::LoginState::Get()->primary_user_hash(); // TODO(crbug.com/730593): Remove SplitOnceCallback() by updating // the callee interface. @@ -942,7 +1019,6 @@ top_dict->SetKey(onc::network_config::kType, base::Value(onc::network_config::kVPN)); - // StaticIPConfig dictionary top_dict->SetKey(onc::network_config::kIPAddressConfigType, base::Value(onc::network_config::kIPConfigTypeStatic)); top_dict->SetKey(onc::network_config::kNameServersConfigType,
diff --git a/ash/public/cpp/holding_space/holding_space_client.h b/ash/public/cpp/holding_space/holding_space_client.h index 0a4a852..86cbdbc 100644 --- a/ash/public/cpp/holding_space/holding_space_client.h +++ b/ash/public/cpp/holding_space/holding_space_client.h
@@ -68,6 +68,10 @@ // Pins the specified holding space `items`. virtual void PinItems(const std::vector<const HoldingSpaceItem*>& items) = 0; + // Remove file suggestions specified by absolute file paths. + virtual void RemoveFileSuggestions( + const std::vector<base::FilePath>& absolute_file_paths) = 0; + // Attempts to show the specified holding space `item` in its folder. // Success is returned via the supplied `callback`. virtual void ShowItemInFolder(const HoldingSpaceItem& item,
diff --git a/ash/public/cpp/holding_space/mock_holding_space_client.h b/ash/public/cpp/holding_space/mock_holding_space_client.h index 3e531f3..87588bce 100644 --- a/ash/public/cpp/holding_space/mock_holding_space_client.h +++ b/ash/public/cpp/holding_space/mock_holding_space_client.h
@@ -56,6 +56,10 @@ (const std::vector<base::FilePath>& file_paths), (override)); MOCK_METHOD(void, + RemoveFileSuggestions, + (const std::vector<base::FilePath>& absolute_file_paths), + (override)); + MOCK_METHOD(void, PinItems, (const std::vector<const HoldingSpaceItem*>& items), (override));
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index a64d1b2..23cde06f 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -199,6 +199,7 @@ "notification_center_settings.icon", "notification_charging_usb_c.icon", "notification_chromevox.icon", + "notification_help_app.icon", "notification_keyboard.icon", "notification_linux.icon", "notification_low_power_charger.icon",
diff --git a/ash/resources/vector_icons/notification_help_app.icon b/ash/resources/vector_icons/notification_help_app.icon new file mode 100644 index 0000000..f7fa76e --- /dev/null +++ b/ash/resources/vector_icons/notification_help_app.icon
@@ -0,0 +1,62 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 20, +R_MOVE_TO, 6.6f, 16.1f, +R_LINE_TO, 2.2f, 2.2f, +R_CUBIC_TO, 0.2f, 0.2f, 0.7f, 0.2f, 0.9f, 0, +R_LINE_TO, 2, -2, +LINE_TO, 6.4f, 11, +R_V_LINE_TO, 4.6f, +R_CUBIC_TO, 0, 0.2f, 0.1f, 0.3f, 0.2f, 0.5f, +CLOSE, +MOVE_TO, 6.4f, 11, +R_LINE_TO, 5.3f, 5.3f, +CLOSE, +MOVE_TO, 18.5f, 9.3f, +R_CUBIC_TO, 0, -0.2f, -0.1f, -0.3f, -0.2f, -0.5f, +R_LINE_TO, -2.2f, -2.2f, +R_CUBIC_TO, -0.1f, -0.1f, -0.3f, -0.2f, -0.5f, -0.2f, +H_LINE_TO, 11, +R_LINE_TO, 5.4f, 5.4f, +R_LINE_TO, 2, -2, +R_CUBIC_TO, 0, -0.1f, 0.1f, -0.3f, 0.1f, -0.5f, +CLOSE, +MOVE_TO, 11, 6.4f, +R_LINE_TO, 5.3f, 5.3f, +LINE_TO, 11, 6.4f, +CLOSE, +MOVE_TO, 12.5f, 10.8f, +R_LINE_TO, 2.4f, 2.4f, +R_LINE_TO, 1.1f, -1.1f, +R_LINE_TO, -6.2f, -6.2f, +R_LINE_TO, -0.8f, -0.8f, +R_CUBIC_TO, -0.7f, -0.7f, -1.8f, -1.4f, -2.9f, -1.7f, +R_CUBIC_TO, -0.4f, -0.1f, -0.8f, -0.2f, -1.2f, -0.2f, +R_CUBIC_TO, -0.5f, 0, -1, 0.1f, -1.2f, 0.4f, +R_CUBIC_TO, -0.5f, 0.5f, -0.6f, 1.4f, -0.3f, 2.5f, +R_CUBIC_TO, 0.3f, 1.1f, 1, 2.2f, 1.7f, 2.9f, +R_LINE_TO, 0.8f, 0.8f, +R_LINE_TO, 6.2f, 6.2f, +R_LINE_TO, 1.1f, -1.1f, +R_LINE_TO, -2.4f, -2.4f, +R_CUBIC_TO, -0.5f, -0.5f, -0.5f, -1.2f, 0, -1.7f, +R_CUBIC_TO, 0.5f, -0.5f, 1.3f, -0.5f, 1.7f, 0, +CLOSE, +MOVE_TO, 7.3f, 7.3f, +R_CUBIC_TO, -0.5f, 0.4f, -1.3f, 0.4f, -1.8f, 0, +CUBIC_TO_SHORTHAND, 5, 6, 5.5f, 5.5f, +R_CUBIC_TO, 0.5f, -0.5f, 1.3f, -0.5f, 1.7f, 0, +R_CUBIC_TO, 0.4f, 0.5f, 0.5f, 1.3f, 0.1f, 1.8f, +CLOSE, +NEW_PATH, +R_MOVE_TO, 15.7f, 14.7f, +R_LINE_TO, -3.6f, -3.6f, +R_CUBIC_TO, -0.1f, -0.1f, -0.2f, -0.1f, -0.4f, -0.1f, +R_CUBIC_TO, -0.2f, 0, -0.4f, 0.1f, -0.5f, 0.2f, +R_CUBIC_TO, -0.3f, 0.3f, -0.3f, 0.7f, 0, 1, +R_LINE_TO, 3.6f, 3.6f, +R_CUBIC_TO, 0.3f, 0.3f, 0.7f, 0.3f, 1, 0, +R_CUBIC_TO, 0.2f, -0.3f, 0.2f, -0.8f, -0.1f, -1.1f, +CLOSE
diff --git a/ash/system/holding_space/holding_space_tray_unittest.cc b/ash/system/holding_space/holding_space_tray_unittest.cc index b4e3b83..3ec57c6 100644 --- a/ash/system/holding_space/holding_space_tray_unittest.cc +++ b/ash/system/holding_space/holding_space_tray_unittest.cc
@@ -219,6 +219,22 @@ return GetHoldingSpaceSection(section_id)->max_visible_item_count.value(); } +// Returns whether a context menu is currently showing. +bool IsShowingContextMenu() { + return views::MenuController::GetActiveInstance(); +} + +// Returns the menu item matched by `id`. +const views::MenuItemView* GetMenuItemByCommandId(HoldingSpaceCommandId id) { + if (!IsShowingContextMenu()) + return nullptr; + if (auto* menu_item = + views::MenuController::GetActiveInstance()->GetSelectedMenuItem()) { + return menu_item->GetMenuItemByID(static_cast<int>(id)); + } + return nullptr; +} + // PredicateWaiter ------------------------------------------------------------- // A class capable of waiting until a predicate returns true. @@ -2852,6 +2868,32 @@ EXPECT_TRUE(test_api()->GetSuggestionChips().empty()); } +// Tests the code flow when a suggestion item is removed through the context +// menu. +TEST_P(HoldingSpaceTraySuggestionsSectionTest, SuggestionsRemoval) { + StartSession(); + + // Add a suggestion item. + const base::FilePath path("/tmp/fake_1"); + AddItem(GetType(), path); + + test_api()->Show(); + std::vector<views::View*> item_views = test_api()->GetHoldingSpaceItemViews(); + ASSERT_EQ(item_views.size(), 1u); + + // Hover over the item view. + MoveMouseTo(item_views.front()); + + // Right click the item view to show the context menu. + RightClick(item_views.front()); + + // Click at the menu item of item removal. Verify that + // `HoldingSpaceClient::RemoveFileSuggestions()` is called. + EXPECT_CALL(*client(), + RemoveFileSuggestions(std::vector<base::FilePath>({path}))); + Click(GetMenuItemByCommandId(HoldingSpaceCommandId::kRemoveItem)); +} + // Base class for tests of the holding space downloads section parameterized by // the set of holding space item types which are expected to appear there. class HoldingSpaceTrayDownloadsSectionTest @@ -3749,11 +3791,6 @@ return progress_indicator->inner_icon_visible(); } - // Returns whether a context menu is currently showing. - bool IsShowingContextMenu() const { - return views::MenuController::GetActiveInstance(); - } - // Returns whether the holding space image is currently showing. bool IsShowingImage(views::View* view) const { auto* v = view->GetViewByID(kHoldingSpaceItemImageId); @@ -3774,11 +3811,7 @@ // Returns whether a context menu is showing with a command matching `id`. bool HasContextMenuCommand(HoldingSpaceCommandId id) const { - if (!IsShowingContextMenu()) - return false; - auto* menu_controller = views::MenuController::GetActiveInstance(); - auto* menu_item = menu_controller->GetSelectedMenuItem(); - return menu_item && menu_item->GetMenuItemByID(static_cast<int>(id)); + return !!GetMenuItemByCommandId(id); } };
diff --git a/ash/system/holding_space/holding_space_view_delegate.cc b/ash/system/holding_space/holding_space_view_delegate.cc index ab7fda74..ccdf730e 100644 --- a/ash/system/holding_space/holding_space_view_delegate.cc +++ b/ash/system/holding_space/holding_space_view_delegate.cc
@@ -508,19 +508,26 @@ case HoldingSpaceCommandId::kPinItem: client->PinItems(items); break; - case HoldingSpaceCommandId::kRemoveItem: + case HoldingSpaceCommandId::kRemoveItem: { + std::vector<base::FilePath> suggested_file_paths; HoldingSpaceController::Get()->model()->RemoveIf(base::BindRepeating( [](const std::vector<const HoldingSpaceItem*>& items, + std::vector<base::FilePath>& suggested_file_paths, const HoldingSpaceItem* item) { const bool remove = base::Contains(items, item); if (remove) { + if (HoldingSpaceItem::IsSuggestion(item->type())) + suggested_file_paths.push_back(item->file_path()); holding_space_metrics::RecordItemAction( {item}, holding_space_metrics::ItemAction::kRemove); } return remove; }, - std::cref(items))); + std::cref(items), std::ref(suggested_file_paths))); + HoldingSpaceController::Get()->client()->RemoveFileSuggestions( + suggested_file_paths); break; + } case HoldingSpaceCommandId::kShowInFolder: DCHECK_EQ(items.size(), 1u); client->ShowItemInFolder(*items.front(), base::DoNothing());
diff --git a/ash/system/unified/buttons.cc b/ash/system/unified/buttons.cc new file mode 100644 index 0000000..59178b8 --- /dev/null +++ b/ash/system/unified/buttons.cc
@@ -0,0 +1,199 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/unified/buttons.h" + +#include "ash/constants/ash_features.h" +#include "ash/constants/quick_settings_catalogs.h" +#include "ash/public/cpp/ash_view_ids.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/style/ash_color_provider.h" +#include "ash/system/power/power_status.h" +#include "ash/system/tray/tray_constants.h" +#include "ash/system/unified/quick_settings_metrics_util.h" +#include "ash/system/unified/unified_system_tray_controller.h" +#include "base/functional/bind.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/compositor/layer.h" +#include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/background.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +namespace { + +// Helper function for getting ContentLayerColor. +inline SkColor GetContentLayerColor(AshColorProvider::ContentLayerType type) { + return AshColorProvider::Get()->GetContentLayerColor(type); +} + +// Helper function for configuring label in BatteryInfoView. +void ConfigureLabel(views::Label* label, SkColor color) { + label->SetAutoColorReadabilityEnabled(false); + label->SetSubpixelRenderingEnabled(false); + label->SetEnabledColor(color); + label->GetViewAccessibility().OverrideIsIgnored(true); +} + +} // namespace + +BatteryInfoViewBase::BatteryInfoViewBase( + UnifiedSystemTrayController* controller) + : Button(base::BindRepeating( + [](UnifiedSystemTrayController* controller, const ui::Event& event) { + quick_settings_metrics_util::RecordQsButtonActivated( + QsButtonCatalogName::kBatteryButton, event); + controller->HandleOpenPowerSettingsAction(); + }, + controller)) { + PowerStatus::Get()->AddObserver(this); +} + +BatteryInfoViewBase::~BatteryInfoViewBase() { + PowerStatus::Get()->RemoveObserver(this); +} + +void BatteryInfoViewBase::GetAccessibleNodeData(ui::AXNodeData* node_data) { + node_data->role = ax::mojom::Role::kLabelText; + node_data->SetName(PowerStatus::Get()->GetAccessibleNameString(true)); +} + +void BatteryInfoViewBase::ChildPreferredSizeChanged(views::View* child) { + PreferredSizeChanged(); +} + +void BatteryInfoViewBase::ChildVisibilityChanged(views::View* child) { + PreferredSizeChanged(); +} + +// PowerStatus::Observer: +void BatteryInfoViewBase::OnPowerStatusChanged() { + Update(); +} + +BEGIN_METADATA(BatteryInfoViewBase, views::Button) +END_METADATA + +BatteryLabelView::BatteryLabelView(UnifiedSystemTrayController* controller, + bool use_smart_charging_ui) + : BatteryInfoViewBase(controller), + use_smart_charging_ui_(use_smart_charging_ui) { + SetID(VIEW_ID_QS_BATTERY_BUTTON); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal)); + + percentage_ = AddChildView(std::make_unique<views::Label>()); + auto seperator = std::make_unique<views::Label>(); + seperator->SetText( + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_BATTERY_STATUS_SEPARATOR)); + separator_view_ = AddChildView(std::move(seperator)); + status_ = AddChildView(std::make_unique<views::Label>()); + Update(); +} + +BatteryLabelView::~BatteryLabelView() = default; + +void BatteryLabelView::OnThemeChanged() { + views::View::OnThemeChanged(); + const auto color = GetContentLayerColor( + AshColorProvider::ContentLayerType::kTextColorSecondary); + ConfigureLabel(percentage_, color); + ConfigureLabel(separator_view_, color); + ConfigureLabel(status_, color); +} + +void BatteryLabelView::Update() { + std::u16string percentage_text; + std::u16string status_text; + std::tie(percentage_text, status_text) = + PowerStatus::Get()->GetStatusStrings(); + + percentage_->SetText(percentage_text); + status_->SetText(status_text); + + percentage_->SetVisible(!percentage_text.empty() && !use_smart_charging_ui_); + separator_view_->SetVisible(!percentage_text.empty() && + !use_smart_charging_ui_ && !status_text.empty()); + status_->SetVisible(!status_text.empty()); + + percentage_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); + status_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); +} + +BEGIN_METADATA(BatteryLabelView, BatteryInfoViewBase) +END_METADATA + +BatteryIconView::BatteryIconView(UnifiedSystemTrayController* controller) + : BatteryInfoViewBase(controller) { + SetID(VIEW_ID_QS_BATTERY_BUTTON); + auto layout = std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal); + layout->set_inside_border_insets(kUnifiedSystemInfoBatteryIconPadding); + SetLayoutManager(std::move(layout)); + + battery_image_ = AddChildView(std::make_unique<views::ImageView>()); + if (features::IsDarkLightModeEnabled()) { + // The battery icon requires its own layer to properly render the masked + // outline of the badge within the battery icon. + battery_image_->SetPaintToLayer(); + battery_image_->layer()->SetFillsBoundsOpaquely(false); + } + ConfigureIcon(); + + percentage_ = AddChildView(std::make_unique<views::Label>()); + + SetBackground(views::CreateRoundedRectBackground( + GetContentLayerColor(AshColorProvider::ContentLayerType:: + kBatterySystemInfoBackgroundColor), + GetPreferredSize().height() / 2)); + + Update(); +} + +BatteryIconView::~BatteryIconView() = default; + +void BatteryIconView::OnThemeChanged() { + views::View::OnThemeChanged(); + const auto color = GetContentLayerColor( + AshColorProvider::ContentLayerType::kButtonLabelColorPrimary); + ConfigureLabel(percentage_, color); + ConfigureIcon(); +} + +void BatteryIconView::Update() { + const std::u16string percentage_text = + PowerStatus::Get()->GetStatusStrings().first; + + percentage_->SetText(percentage_text); + percentage_->SetVisible(!percentage_text.empty()); + percentage_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); + + ConfigureIcon(); +} + +void BatteryIconView::ConfigureIcon() { + const SkColor battery_icon_color = GetContentLayerColor( + AshColorProvider::ContentLayerType::kBatterySystemInfoIconColor); + + const SkColor badge_color = GetContentLayerColor( + AshColorProvider::ContentLayerType::kBatterySystemInfoBackgroundColor); + + PowerStatus::BatteryImageInfo info = + PowerStatus::Get()->GetBatteryImageInfo(); + info.alert_if_low = false; + battery_image_->SetImage(PowerStatus::GetBatteryImage( + info, kUnifiedTrayBatteryIconSize, battery_icon_color, battery_icon_color, + badge_color)); +} + +BEGIN_METADATA(BatteryIconView, BatteryInfoViewBase) +END_METADATA + +} // namespace ash
diff --git a/ash/system/unified/buttons.h b/ash/system/unified/buttons.h new file mode 100644 index 0000000..4280e56 --- /dev/null +++ b/ash/system/unified/buttons.h
@@ -0,0 +1,111 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_UNIFIED_BUTTONS_H_ +#define ASH_SYSTEM_UNIFIED_BUTTONS_H_ + +#include "ash/system/power/power_status.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/controls/button/button.h" + +// This file carries the buttons that will be shared in both the revamped +// `QuickSettingsView` and the old `UnifiedSystemTrayView`. +// +// TODO(crbug/1370847) When the old`UnifiedSystemTrayView` is removed, these +// buttons should be moved to the cc files that use them. + +namespace views { +class Button; +class ImageView; +class Label; +class View; +} // namespace views + +namespace ash { + +class UnifiedSystemTrayController; + +// A base class for both `BatteryLabelView` and `BatteryIconView`. It updates by +// observing PowerStatus. +class BatteryInfoViewBase : public views::Button, public PowerStatus::Observer { + public: + METADATA_HEADER(BatteryInfoViewBase); + + explicit BatteryInfoViewBase(UnifiedSystemTrayController* controller); + BatteryInfoViewBase(const BatteryInfoViewBase&) = delete; + BatteryInfoViewBase& operator=(const BatteryInfoViewBase&) = delete; + ~BatteryInfoViewBase() override; + + // Updates the subclass view's ui when `OnPowerStatusChanged`. + virtual void Update() = 0; + + private: + // views::View: + void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + void ChildPreferredSizeChanged(views::View* child) override; + void ChildVisibilityChanged(views::View* child) override; + + // PowerStatus::Observer: + void OnPowerStatusChanged() override; +}; + +// A view that shows battery status, which is used in the `QuickSettingsView` +// footer. +class BatteryLabelView : public BatteryInfoViewBase { + public: + METADATA_HEADER(BatteryLabelView); + + BatteryLabelView(UnifiedSystemTrayController* controller, + bool use_smart_charging_ui); + BatteryLabelView(const BatteryLabelView&) = delete; + BatteryLabelView& operator=(const BatteryLabelView&) = delete; + ~BatteryLabelView() override; + + private: + // views::View: + void OnThemeChanged() override; + + // BatteryInfoViewBase: + void Update() override; + + // Owned by this view, which is owned by views hierarchy. + views::Label* percentage_ = nullptr; + views::Label* separator_view_ = nullptr; + views::Label* status_ = nullptr; + + // If true, this view will only show the status and let the `BatteryIconView` + // show the rest. If false, the `percentage_` and separator will be visible. + // Smart charging means `ash::features::IsAdaptiveChargingEnabled()` and it + // is adaptive delaying charge. + const bool use_smart_charging_ui_; +}; + +// A view that shows battery icon and charging state when smart charging is +// enabled, which is used in the `QuickSettingsView` footer. +class BatteryIconView : public BatteryInfoViewBase { + public: + METADATA_HEADER(BatteryIconView); + + explicit BatteryIconView(UnifiedSystemTrayController* controller); + BatteryIconView(const BatteryIconView&) = delete; + BatteryIconView& operator=(const BatteryIconView&) = delete; + ~BatteryIconView() override; + + private: + // views::View: + void OnThemeChanged() override; + + // BatteryInfoViewBase: + void Update() override; + + // Builds the battery icon image. + void ConfigureIcon(); + + // Owned by this view, which is owned by views hierarchy. + views::Label* percentage_ = nullptr; + views::ImageView* battery_image_ = nullptr; +}; +} // namespace ash + +#endif // ASH_SYSTEM_UNIFIED_BUTTONS_H_
diff --git a/ash/system/unified/unified_system_info_view.cc b/ash/system/unified/unified_system_info_view.cc index 19afa33..0afd5d9 100644 --- a/ash/system/unified/unified_system_info_view.cc +++ b/ash/system/unified/unified_system_info_view.cc
@@ -28,6 +28,7 @@ #include "ash/system/time/calendar_metrics.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/system/tray/tray_popup_utils.h" +#include "ash/system/unified/buttons.h" #include "ash/system/unified/quick_settings_metrics_util.h" #include "base/bind.h" #include "base/callback_helpers.h" @@ -41,11 +42,8 @@ #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/chromeos/devicetype_utils.h" #include "ui/color/color_id.h" -#include "ui/compositor/layer.h" #include "ui/gfx/paint_vector_icon.h" -#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/animation/ink_drop.h" -#include "ui/views/background.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/focus_ring.h" #include "ui/views/controls/image_view.h" @@ -71,19 +69,6 @@ return base::TimeFormatWithPattern(time, "EEE"); } -// Helper function for getting ContentLayerColor. -inline SkColor GetContentLayerColor(ContentLayerType type) { - return ash::AshColorProvider::Get()->GetContentLayerColor(type); -} - -// Helper function for configuring label in BatteryInfoView. -void ConfigureLabel(views::Label* label, SkColor color) { - label->SetAutoColorReadabilityEnabled(false); - label->SetSubpixelRenderingEnabled(false); - label->SetEnabledColor(color); - label->GetViewAccessibility().OverrideIsIgnored(true); -} - // Returns whether SmartChargingUI should be used. bool UseSmartChargingUI() { return ash::features::IsAdaptiveChargingEnabled() && @@ -206,203 +191,6 @@ Update(); } -// A base class for both BatteryLabelView and BatteryIconView. It updates by -// observing PowerStatus. -class BatteryInfoViewBase : public views::Button, public PowerStatus::Observer { - public: - METADATA_HEADER(BatteryInfoViewBase); - explicit BatteryInfoViewBase(UnifiedSystemTrayController* controller) - : Button(base::BindRepeating(&BatteryInfoViewBase::OnButtonPressed, - base::Unretained(this))), - controller_(controller) { - power_status_observation_.Observe(PowerStatus::Get()); - } - - BatteryInfoViewBase(const BatteryInfoViewBase&) = delete; - BatteryInfoViewBase& operator=(const BatteryInfoViewBase&) = delete; - - ~BatteryInfoViewBase() override = default; - - // views::View: - void GetAccessibleNodeData(ui::AXNodeData* node_data) override { - node_data->role = ax::mojom::Role::kLabelText; - node_data->SetName(PowerStatus::Get()->GetAccessibleNameString(true)); - } - - void ChildPreferredSizeChanged(views::View* child) override { - PreferredSizeChanged(); - } - - void ChildVisibilityChanged(views::View* child) override { - PreferredSizeChanged(); - } - - // PowerStatus::Observer: - void OnPowerStatusChanged() override { Update(); } - - // Should be override by subclass. - virtual void Update() = 0; - - private: - // Callback called when this is pressed. - void OnButtonPressed(const ui::Event& event) { - quick_settings_metrics_util::RecordQsButtonActivated( - QsButtonCatalogName::kBatteryButton, event); - controller_->HandleOpenPowerSettingsAction(); - } - - // Unowned. - ash::UnifiedSystemTrayController* const controller_; - - base::ScopedObservation<PowerStatus, PowerStatus::Observer> - power_status_observation_{this}; -}; -BEGIN_METADATA(BatteryInfoViewBase, views::Button) -END_METADATA - -// A view that shows battery status. -class BatteryLabelView : public BatteryInfoViewBase { - public: - METADATA_HEADER(BatteryLabelView); - BatteryLabelView(UnifiedSystemTrayController* controller, - bool use_smart_charging_ui) - : BatteryInfoViewBase(controller), - use_smart_charging_ui_(use_smart_charging_ui) { - SetID(VIEW_ID_QS_BATTERY_BUTTON); - SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal)); - - percentage_ = AddChildView(std::make_unique<views::Label>()); - auto seperator = std::make_unique<views::Label>(); - seperator->SetText(l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_BATTERY_STATUS_SEPARATOR)); - separator_view_ = AddChildView(std::move(seperator)); - status_ = AddChildView(std::make_unique<views::Label>()); - Update(); - } - - BatteryLabelView(const BatteryLabelView&) = delete; - BatteryLabelView& operator=(const BatteryLabelView&) = delete; - ~BatteryLabelView() override = default; - - // views::View: - void OnThemeChanged() override { - views::View::OnThemeChanged(); - const auto color = - GetContentLayerColor(ContentLayerType::kTextColorSecondary); - ConfigureLabel(percentage_, color); - ConfigureLabel(separator_view_, color); - ConfigureLabel(status_, color); - } - - private: - void Update() override { - std::u16string percentage_text; - std::u16string status_text; - std::tie(percentage_text, status_text) = - PowerStatus::Get()->GetStatusStrings(); - - percentage_->SetText(percentage_text); - status_->SetText(status_text); - - percentage_->SetVisible(!percentage_text.empty() && - !use_smart_charging_ui_); - separator_view_->SetVisible(!percentage_text.empty() && - !use_smart_charging_ui_ && - !status_text.empty()); - status_->SetVisible(!status_text.empty()); - - percentage_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); - status_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); - } - - views::Label* percentage_ = nullptr; - views::Label* separator_view_ = nullptr; - views::Label* status_ = nullptr; - - const bool use_smart_charging_ui_; -}; -BEGIN_METADATA(BatteryLabelView, BatteryInfoViewBase) -END_METADATA - -// A view that shows battery icon and charging state when smart charging is -// enabled. -class BatteryIconView : public BatteryInfoViewBase { - public: - METADATA_HEADER(BatteryIconView); - explicit BatteryIconView(UnifiedSystemTrayController* controller) - : BatteryInfoViewBase(controller) { - SetID(VIEW_ID_QS_BATTERY_BUTTON); - auto layout = std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal); - layout->set_inside_border_insets(kUnifiedSystemInfoBatteryIconPadding); - SetLayoutManager(std::move(layout)); - - battery_image_ = AddChildView(std::make_unique<views::ImageView>()); - if (features::IsDarkLightModeEnabled()) { - // The battery icon requires its own layer to properly render the masked - // outline of the badge within the battery icon. - battery_image_->SetPaintToLayer(); - battery_image_->layer()->SetFillsBoundsOpaquely(false); - } - ConfigureIcon(); - - percentage_ = AddChildView(std::make_unique<views::Label>()); - - SetBackground(views::CreateRoundedRectBackground( - GetContentLayerColor(AshColorProvider::ContentLayerType:: - kBatterySystemInfoBackgroundColor), - GetPreferredSize().height() / 2)); - - Update(); - } - - BatteryIconView(const BatteryIconView&) = delete; - BatteryIconView& operator=(const BatteryIconView&) = delete; - ~BatteryIconView() override = default; - - // views::View: - void OnThemeChanged() override { - views::View::OnThemeChanged(); - const auto color = - GetContentLayerColor(ContentLayerType::kButtonLabelColorPrimary); - ConfigureLabel(percentage_, color); - ConfigureIcon(); - } - - private: - void Update() override { - const std::u16string percentage_text = - PowerStatus::Get()->GetStatusStrings().first; - - percentage_->SetText(percentage_text); - percentage_->SetVisible(!percentage_text.empty()); - percentage_->NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); - - ConfigureIcon(); - } - - void ConfigureIcon() { - const SkColor battery_icon_color = GetContentLayerColor( - AshColorProvider::ContentLayerType::kBatterySystemInfoIconColor); - - const SkColor badge_color = GetContentLayerColor( - AshColorProvider::ContentLayerType::kBatterySystemInfoBackgroundColor); - - PowerStatus::BatteryImageInfo info = - PowerStatus::Get()->GetBatteryImageInfo(); - info.alert_if_low = false; - battery_image_->SetImage(PowerStatus::GetBatteryImage( - info, kUnifiedTrayBatteryIconSize, battery_icon_color, - battery_icon_color, badge_color)); - } - - views::Label* percentage_ = nullptr; - views::ImageView* battery_image_ = nullptr; -}; -BEGIN_METADATA(BatteryIconView, BatteryInfoViewBase) -END_METADATA - // A base class of the views showing device management state. class ManagedStateView : public views::Button { public:
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings.grd b/ash/webui/camera_app_ui/resources/strings/camera_strings.grd index 60f23d5..622022f 100644 --- a/ash/webui/camera_app_ui/resources/strings/camera_strings.grd +++ b/ash/webui/camera_app_ui/resources/strings/camera_strings.grd
@@ -672,16 +672,16 @@ 16 to 9 </message> <message desc="Label of the 4K video resolution option." name="IDS_LABEL_VIDEO_RESOLUTION_4K"> - 4K + 4K (2160p) </message> <message desc="Label of the Quad HD (QHD) video resolution option." name="IDS_LABEL_VIDEO_RESOLUTION_QUAD_HD"> - Quad HD + Quad HD (1440p) </message> <message desc="Label of the Full HD video resolution option." name="IDS_LABEL_VIDEO_RESOLUTION_FULL_HD"> - Full HD + Full HD (1080p) </message> <message desc="Label of the HD video resolution option." name="IDS_LABEL_VIDEO_RESOLUTION_HD"> - HD + HD (720p) </message> <message desc="Label of the 360p video resolution option." name="IDS_LABEL_VIDEO_RESOLUTION_360P"> 360p
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_4K.png.sha1 b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_4K.png.sha1 index ee23903..b003b43 100644 --- a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_4K.png.sha1 +++ b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_4K.png.sha1
@@ -1 +1 @@ -1bf1855354a5901a4bb4f92e8afb9b555f26a59d \ No newline at end of file +bd12d440b746b5de03d150c81335e2dc684ffc3a \ No newline at end of file
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_FULL_HD.png.sha1 b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_FULL_HD.png.sha1 index 50411a5..b003b43 100644 --- a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_FULL_HD.png.sha1 +++ b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_FULL_HD.png.sha1
@@ -1 +1 @@ -6ce03d8a8824ee5e146837dfebdb80a4b95882de \ No newline at end of file +bd12d440b746b5de03d150c81335e2dc684ffc3a \ No newline at end of file
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_HD.png.sha1 b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_HD.png.sha1 index 50411a5..b003b43 100644 --- a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_HD.png.sha1 +++ b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_HD.png.sha1
@@ -1 +1 @@ -6ce03d8a8824ee5e146837dfebdb80a4b95882de \ No newline at end of file +bd12d440b746b5de03d150c81335e2dc684ffc3a \ No newline at end of file
diff --git a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_QUAD_HD.png.sha1 b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_QUAD_HD.png.sha1 index ee23903..b003b43 100644 --- a/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_QUAD_HD.png.sha1 +++ b/ash/webui/camera_app_ui/resources/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION_QUAD_HD.png.sha1
@@ -1 +1 @@ -1bf1855354a5901a4bb4f92e8afb9b555f26a59d \ No newline at end of file +bd12d440b746b5de03d150c81335e2dc684ffc3a \ No newline at end of file
diff --git a/ash/webui/diagnostics_ui/backend/session_log_handler.h b/ash/webui/diagnostics_ui/backend/session_log_handler.h index a96b3fb..366647e 100644 --- a/ash/webui/diagnostics_ui/backend/session_log_handler.h +++ b/ash/webui/diagnostics_ui/backend/session_log_handler.h
@@ -94,7 +94,7 @@ std::unique_ptr<NetworkingLog> networking_log_; ash::HoldingSpaceClient* const holding_space_client_; std::string save_session_log_callback_id_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; base::OnceClosure log_created_closure_; // Task runner for tasks posted by save session log handler. Used to ensure // posted tasks are handled while SessionLogHandler is in scope to stop
diff --git a/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html b/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html index 1bf259fc..050b56f9 100644 --- a/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html +++ b/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html
@@ -7,6 +7,10 @@ --feedback-medium-font-weight: 500; } + :host-context([dir='rtl']) .dialog-back-arrow { + transform: rotate(180deg); + } + html { background-color: var(--cros-bg-color); }
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html index dfe4c88a..893ce431 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_preview_element.html
@@ -42,6 +42,7 @@ #imageContainer, #imagePlaceholder { + background-color: var(--personalization-app-grid-item-background-color); grid-area: image; justify-self: center; max-width: 360px;
diff --git a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html index 957e6ae..c51805e 100644 --- a/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html +++ b/ash/webui/personalization_app/resources/js/wallpaper/wallpaper_selected_element.html
@@ -28,6 +28,7 @@ #imageContainer, #imagePlaceholder { --animation-delay: 1s; + background-color: var(--personalization-app-grid-item-background-color); grid-area: image; }
diff --git a/ash/webui/scanning/scanning_handler.h b/ash/webui/scanning/scanning_handler.h index 12785891..5789f64 100644 --- a/ash/webui/scanning/scanning_handler.h +++ b/ash/webui/scanning/scanning_handler.h
@@ -98,7 +98,7 @@ std::string scan_location_callback_id_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; // Provides browser functionality from //chrome to the Scan app UI. std::unique_ptr<ScanningAppDelegate> scanning_app_delegate_;
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h index bcceb87..93b2ccc 100644 --- a/base/memory/raw_ptr.h +++ b/base/memory/raw_ptr.h
@@ -375,7 +375,8 @@ // will occur. static ALWAYS_INLINE bool IsSupportedAndNotNull(uintptr_t address) { - // This covers the nullptr case, as address 0 is never in GigaCage. + // This covers the nullptr case, as address 0 is never in any + // PartitionAlloc pool. bool is_in_brp_pool = partition_alloc::IsManagedByPartitionAllocBRPPool(address); @@ -521,15 +522,15 @@ return wrapped_ptr + delta_elems; #else // In the "before allocation" mode, on 32-bit, we can run into a problem - // that the end-of-allocation address could fall out of "GigaCage", if this - // is the last slot of the super page, thus pointing to the guard page. This - // mean the ref-count won't be decreased when the pointer is released - // (leak). + // that the end-of-allocation address could fall outside of + // PartitionAlloc's pools, if this is the last slot of the super page, + // thus pointing to the guard page. This mean the ref-count won't be + // decreased when the pointer is released (leak). // // We could possibly solve it in a few different ways: - // - Add the trailing guard page to "GigaCage", but we'd have to think very + // - Add the trailing guard page to the pool, but we'd have to think very // hard if this doesn't create another hole. - // - Add an address adjustment to "GigaCage" check, similar as the one in + // - Add an address adjustment to "is in pool?" check, similar as the one in // PartitionAllocGetSlotStartInBRPPool(), but that seems fragile, not to // mention adding an extra instruction to an inlined hot path. // - Let the leak happen, since it should a very rare condition.
diff --git a/base/strings/safe_sprintf_unittest.cc b/base/strings/safe_sprintf_unittest.cc index 0037429..df0a4e0 100644 --- a/base/strings/safe_sprintf_unittest.cc +++ b/base/strings/safe_sprintf_unittest.cc
@@ -12,6 +12,7 @@ #include <limits> #include <memory> +#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/check_op.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -482,7 +483,14 @@ } // anonymous namespace -TEST(SafeSPrintfTest, Truncation) { +// TODO(crbug.com/1369007): Fails when OOB protection is turned on. +#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \ + BUILDFLAG(ENABLE_MTE_CHECKED_PTR_SUPPORT) +#define MAYBE_Truncation DISABLED_Truncation +#else +#define MAYBE_Truncation Truncation +#endif +TEST(SafeSPrintfTest, MAYBE_Truncation) { // We use PrintLongString() to print a complex long string and then // truncate to all possible lengths. This ends up exercising a lot of // different code paths in SafeSPrintf() and IToASCII(), as truncation can
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc index a37d6ad..a30d7d4 100644 --- a/base/test/scoped_feature_list.cc +++ b/base/test/scoped_feature_list.cc
@@ -287,15 +287,14 @@ } // namespace -ScopedFeatureList::FeatureAndParams::FeatureAndParams( - const Feature& feature, - const FieldTrialParams& params) +FeatureRefAndParams::FeatureRefAndParams(const Feature& feature, + const FieldTrialParams& params) : feature(feature), params(params) {} -ScopedFeatureList::FeatureAndParams::~FeatureAndParams() = default; +FeatureRefAndParams::~FeatureRefAndParams() = default; -ScopedFeatureList::FeatureAndParams::FeatureAndParams( - const FeatureAndParams& other) = default; +FeatureRefAndParams::FeatureRefAndParams(const FeatureRefAndParams& other) = + default; ScopedFeatureList::ScopedFeatureList() = default; @@ -414,9 +413,29 @@ } void ScopedFeatureList::InitWithFeatures( + const std::vector<FeatureRef>& enabled_features, + const std::vector<FeatureRef>& disabled_features) { + InitWithFeaturesImpl(enabled_features, {}, disabled_features); +} + +void ScopedFeatureList::InitWithFeatures( const std::vector<Feature>& enabled_features, const std::vector<Feature>& disabled_features) { - InitWithFeaturesImpl(enabled_features, {}, disabled_features); + std::vector<FeatureRef> enabled_features_as_refs(enabled_features.begin(), + enabled_features.end()); + std::vector<FeatureRef> disabled_features_as_refs(disabled_features.begin(), + disabled_features.end()); + InitWithFeaturesImpl(enabled_features_as_refs, {}, disabled_features_as_refs); +} + +void ScopedFeatureList::InitWithFeatures( + std::initializer_list<Feature> enabled_features, + std::initializer_list<Feature> disabled_features) { + std::vector<FeatureRef> enabled_features_as_refs(enabled_features.begin(), + enabled_features.end()); + std::vector<FeatureRef> disabled_features_as_refs(disabled_features.begin(), + disabled_features.end()); + InitWithFeaturesImpl(enabled_features_as_refs, {}, disabled_features_as_refs); } void ScopedFeatureList::InitAndEnableFeature(const Feature& feature) { @@ -437,9 +456,9 @@ } void ScopedFeatureList::InitWithFeaturesImpl( - const std::vector<Feature>& enabled_features, + const std::vector<FeatureRef>& enabled_features, const std::vector<FeatureAndParams>& enabled_features_and_params, - const std::vector<Feature>& disabled_features, + const std::vector<FeatureRef>& disabled_features, bool keep_existing_states) { DCHECK(!init_called_); DCHECK(enabled_features.empty() || enabled_features_and_params.empty()); @@ -469,10 +488,10 @@ create_associated_field_trials = true; } else { for (const auto& feature : enabled_features) - merged_features.enabled_feature_list.emplace_back(feature.name); + merged_features.enabled_feature_list.emplace_back(feature->name); } for (const auto& feature : disabled_features) - merged_features.disabled_feature_list.emplace_back(feature.name); + merged_features.disabled_feature_list.emplace_back(feature->name); InitWithMergedFeatures(std::move(merged_features), create_associated_field_trials, keep_existing_states); @@ -486,10 +505,26 @@ void ScopedFeatureList::InitWithFeaturesAndParameters( const std::vector<FeatureAndParams>& enabled_features, - const std::vector<Feature>& disabled_features) { + const std::vector<FeatureRef>& disabled_features) { InitWithFeaturesImpl({}, enabled_features, disabled_features); } +void ScopedFeatureList::InitWithFeaturesAndParameters( + const std::vector<FeatureAndParams>& enabled_features, + const std::vector<Feature>& disabled_features) { + std::vector<FeatureRef> disabled_features_as_refs(disabled_features.begin(), + disabled_features.end()); + InitWithFeaturesImpl({}, enabled_features, disabled_features_as_refs); +} + +void ScopedFeatureList::InitWithFeaturesAndParameters( + const std::vector<FeatureAndParams>& enabled_features, + std::initializer_list<Feature> disabled_features) { + std::vector<FeatureRef> disabled_features_as_refs(disabled_features.begin(), + disabled_features.end()); + InitWithFeaturesImpl({}, enabled_features, disabled_features_as_refs); +} + void ScopedFeatureList::InitWithMergedFeatures( Features&& merged_features, bool create_associated_field_trials,
diff --git a/base/test/scoped_feature_list.h b/base/test/scoped_feature_list.h index 6b1cf2b..46ad9835 100644 --- a/base/test/scoped_feature_list.h +++ b/base/test/scoped_feature_list.h
@@ -12,14 +12,45 @@ #include "base/feature_list.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "base/memory/ref_counted.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" #include "base/types/pass_key.h" +#include "third_party/abseil-cpp/absl/base/attributes.h" namespace base { namespace test { +struct FeatureRefAndParams { + // TODO(https://crbug.com/1370851): Add ABSL_ATTRIBUTE_LIFETIME_BOUND here to + // match FeatureRef below. + FeatureRefAndParams(const Feature& feature, const FieldTrialParams& params); + ~FeatureRefAndParams(); + + FeatureRefAndParams(const FeatureRefAndParams& other); + + const Feature& feature; + const FieldTrialParams params; +}; + +// A lightweight wrapper for a reference to a base::Feature. Allows lists of +// features to be enabled/disabled to be easily passed without actually copying +// the underlying base::Feature. Actual C++ references do not work well for this +// purpose, as vectors of references are disallowed. +class FeatureRef { + public: + // NOLINTNEXTLINE(google-explicit-constructor) + FeatureRef(const Feature& feature ABSL_ATTRIBUTE_LIFETIME_BOUND) + : feature_(feature) {} + + const Feature& operator*() const { return *feature_; } + const Feature* operator->() const { return &*feature_; } + + private: + raw_ref<const Feature> feature_; +}; + // ScopedFeatureList resets the global FeatureList instance to a new empty // instance and restores the original instance upon destruction. When using the // non-deprecated APIs, a corresponding FieldTrialList is also created. @@ -46,6 +77,12 @@ struct Features; struct FeatureWithStudyGroup; + // TODO(https://crbug.com/1370851): Temporary "alias" to allow incremental + // migration. + struct FeatureAndParams : public ::base::test::FeatureRefAndParams { + using ::base::test::FeatureRefAndParams::FeatureRefAndParams; + }; + // Constructs the instance in a non-initialized state. ScopedFeatureList(); @@ -57,16 +94,6 @@ ~ScopedFeatureList(); - struct FeatureAndParams { - FeatureAndParams(const Feature& feature, const FieldTrialParams& params); - ~FeatureAndParams(); - - FeatureAndParams(const FeatureAndParams& other); - - const Feature& feature; - const FieldTrialParams params; - }; - // Resets the instance to a non-initialized state. void Reset(); @@ -110,8 +137,13 @@ // continue to apply, unless they conflict with the overrides passed into this // method. This is important for testing potentially unexpected feature // interactions. + void InitWithFeatures(const std::vector<FeatureRef>& enabled_features, + const std::vector<FeatureRef>& disabled_features); + // TODO(https://crbug.com/1370572): Remove these temporary forwarding helpers. void InitWithFeatures(const std::vector<Feature>& enabled_features, const std::vector<Feature>& disabled_features); + void InitWithFeatures(std::initializer_list<Feature> enabled_features, + std::initializer_list<Feature> disabled_features); // Initializes and registers a FeatureList instance based on the current // FeatureList and overridden with single enabled feature. @@ -133,7 +165,14 @@ // currently one. void InitWithFeaturesAndParameters( const std::vector<FeatureAndParams>& enabled_features, + const std::vector<FeatureRef>& disabled_features); + // TODO(https://crbug.com/1370572): Remove these temporary forwarding helpers. + void InitWithFeaturesAndParameters( + const std::vector<FeatureAndParams>& enabled_features, const std::vector<Feature>& disabled_features); + void InitWithFeaturesAndParameters( + const std::vector<FeatureAndParams>& enabled_features, + std::initializer_list<Feature> disabled_features); // Initializes and registers a FeatureList instance based on the current // FeatureList and overridden with single disabled feature. @@ -156,9 +195,9 @@ // |enabled_feature_and_params|, but not both (i.e. one of these must be // empty). void InitWithFeaturesImpl( - const std::vector<Feature>& enabled_features, + const std::vector<FeatureRef>& enabled_features, const std::vector<FeatureAndParams>& enabled_features_and_params, - const std::vector<Feature>& disabled_features, + const std::vector<FeatureRef>& disabled_features, bool keep_existing_states = true); // Initializes and registers a FeatureList instance based on the current
diff --git a/chrome/VERSION b/chrome/VERSION index 4c95d2d..3c721df 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=108 MINOR=0 -BUILD=5339 +BUILD=5340 PATCH=0
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java index dc5e2fe..1749485 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java
@@ -105,12 +105,6 @@ new BooleanCachedFieldTrialParameter( ChromeFeatureList.START_SURFACE_ANDROID, IS_DOODLE_SUPPORTED_PARAM, false); - private static final String HIDE_START_WHEN_LAST_VISITED_TAB_IS_SRP_PARAM = - "hide_start_when_last_visited_tab_is_srp"; - public static final BooleanCachedFieldTrialParameter HIDE_START_WHEN_LAST_VISITED_TAB_IS_SRP = - new BooleanCachedFieldTrialParameter(ChromeFeatureList.START_SURFACE_ANDROID, - HIDE_START_WHEN_LAST_VISITED_TAB_IS_SRP_PARAM, false); - private static final String STARTUP_UMA_PREFIX = "Startup.Android."; private static final String INSTANT_START_SUBFIX = ".Instant"; private static final String REGULAR_START_SUBFIX = ".NoInstant";
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java index 510d62d..4446cbd 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
@@ -67,8 +67,6 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.homepage.HomepageManager; import org.chromium.chrome.browser.layouts.LayoutType; -import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; -import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.suggestions.SiteSuggestion; import org.chromium.chrome.browser.suggestions.mostvisited.MostVisitedSitesMetadataUtils; import org.chromium.chrome.browser.suggestions.tile.Tile; @@ -499,21 +497,6 @@ testShowLastTabAtStartUp(); } - @Test - @MediumTest - // clang-format off - @EnableFeatures({ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study,", - ChromeFeatureList.START_SURFACE_ANDROID + "<Study"}) - @DisableFeatures(ChromeFeatureList.INSTANT_START) - @CommandLineFlags.Add({INSTANT_START_TEST_BASE_PARAMS + - "/hide_start_when_last_visited_tab_is_srp/true"}) - public void testShowLastTabWhenLastTabIsSRP_NoInstant() throws IOException { - // clang-format on - SharedPreferencesManager.getInstance().writeBoolean( - ChromePreferenceKeys.IS_LAST_VISITED_TAB_SRP, true); - testShowLastTabAtStartUp(); - } - private void testShowLastTabAtStartUp() throws IOException { StartSurfaceTestUtils.createTabStateFile(new int[] {0}); StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(0);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index 628a63e..f8c624d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -158,7 +158,6 @@ add(CustomTabIntentDataProvider.THIRD_PARTIES_DEFAULT_POLICY); add(CustomTabIntentDataProvider.DENYLIST_ENTRIES); add(CustomTabIntentDataProvider.ALLOWLIST_ENTRIES); - add(StartSurfaceConfiguration.HIDE_START_WHEN_LAST_VISITED_TAB_IS_SRP); add(StartSurfaceConfiguration.IS_DOODLE_SUPPORTED); add(StartSurfaceConfiguration.NUM_DAYS_KEEP_SHOW_START_AT_STARTUP); add(StartSurfaceConfiguration.NUM_DAYS_USER_CLICK_BELOW_THRESHOLD);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java index 9813b64..0b3fe36 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.ChromeApplicationImpl; import org.chromium.chrome.browser.browserservices.TrustedWebActivityClientWrappers.Connection; import org.chromium.chrome.browser.browserservices.TrustedWebActivityClientWrappers.ConnectionPool; -import org.chromium.chrome.browser.browserservices.constants.LocationUpdateError; import org.chromium.chrome.browser.browserservices.metrics.TrustedWebActivityUmaRecorder; import org.chromium.chrome.browser.browserservices.metrics.TrustedWebActivityUmaRecorder.DelegatedNotificationSmallIconFallback; import org.chromium.chrome.browser.browserservices.permissiondelegation.InstalledWebappPermissionManager; @@ -498,6 +497,5 @@ Bundle error = new Bundle(); error.putString("message", message); callback.onExtraCallback(EXTRA_NEW_LOCATION_ERROR_CALLBACK, error); - mRecorder.recordLocationUpdateError(LocationUpdateError.NO_TWA); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java index 39508df..a906a3c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadItem.java
@@ -180,7 +180,6 @@ offlineItem.completionTimeMs = item.getEndTime(); offlineItem.externallyRemoved = item.hasBeenExternallyRemoved(); offlineItem.canRename = item.getDownloadInfo().state() == DownloadState.COMPLETE; - offlineItem.schedule = downloadInfo.getOfflineItemSchedule(); switch (downloadInfo.state()) { case DownloadState.IN_PROGRESS: offlineItem.state = downloadInfo.isPaused() ? OfflineItemState.PAUSED
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java index c5067b3d..8945657 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java
@@ -90,8 +90,6 @@ @Override public void notifyDownloadSuccessful(DownloadInfo info, long systemDownloadId, boolean canResolve, boolean isSupportedMimeType) { - if (info.getOfflineItemSchedule() != null) return; - NotificationInfo notificationInfo = new NotificationInfo( NotificationType.SUCCEEDED, info, PendingNotificationTask.Priority.HIGH); notificationInfo.mSystemDownloadId = systemDownloadId; @@ -102,8 +100,6 @@ @Override public void notifyDownloadFailed(DownloadInfo info) { - if (info.getOfflineItemSchedule() != null) return; - NotificationInfo notificationInfo = new NotificationInfo( NotificationType.FAILED, info, PendingNotificationTask.Priority.HIGH); addPendingNotification(notificationInfo); @@ -112,8 +108,6 @@ @Override public void notifyDownloadProgress( DownloadInfo info, long startTime, boolean canDownloadWhileMetered) { - if (info.getOfflineItemSchedule() != null) return; - NotificationInfo notificationInfo = new NotificationInfo( NotificationType.PROGRESS, info, PendingNotificationTask.Priority.LOW); notificationInfo.mStartTime = startTime; @@ -123,8 +117,6 @@ @Override public void notifyDownloadPaused(DownloadInfo info) { - if (info.getOfflineItemSchedule() != null) return; - NotificationInfo notificationInfo = new NotificationInfo( NotificationType.PAUSED, info, PendingNotificationTask.Priority.HIGH); addPendingNotification(notificationInfo); @@ -133,8 +125,6 @@ @Override public void notifyDownloadInterrupted( DownloadInfo info, boolean isAutoResumable, @PendingState int pendingState) { - if (info.getOfflineItemSchedule() != null) return; - NotificationInfo notificationInfo = new NotificationInfo( NotificationType.INTERRUPTED, info, PendingNotificationTask.Priority.HIGH); notificationInfo.mIsAutoResumable = isAutoResumable;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java index 9064b16..182ad1d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java
@@ -153,7 +153,7 @@ // TODO(http://crbug.com/855141): Find a cleaner way to hide unimportant UI updates. // If it's a suggested page, or the user choose to download later. Do not add it to the // notification UI. - if (item.isSuggested || item.schedule != null) return; + if (item.isSuggested) return; // If the download is cancelled, no need to DownloadInfo object and it is enough to notify // that the download is canceled.
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 56e3201..479026f8 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
@@ -500,9 +500,6 @@ return true; } - // Checks whether to hide Start surface when last visited tab is a search result page. - if (isStartSurfaceEnabled && shouldHideStartSurfaceWhenLastVisitedTabIsSRP()) return false; - // Checks whether to show the Start surface / grid Tab switcher due to feature flag // TAB_SWITCHER_ON_RETURN_MS. long lastBackgroundedTimeMillis = inactivityTracker.getLastBackgroundedTimeMs(); @@ -957,13 +954,4 @@ public static void recordBackNavigationToStart(String from) { RecordUserAction.record(SHOWN_FROM_BACK_NAVIGATION_UMA + from); } - - /** - * Returns whether Start surface should be hidden when last visited tab is a search result page. - */ - private static boolean shouldHideStartSurfaceWhenLastVisitedTabIsSRP() { - return StartSurfaceConfiguration.HIDE_START_WHEN_LAST_VISITED_TAB_IS_SRP.getValue() - && SharedPreferencesManager.getInstance().readBoolean( - ChromePreferenceKeys.IS_LAST_VISITED_TAB_SRP, false); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstallService.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstallService.java index 115a434d..20f2030 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstallService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstallService.java
@@ -43,7 +43,7 @@ /** Displays a notification when a WebAPK is successfully installed. */ @CalledByNative @VisibleForTesting - static void showInstalledNotification(String webApkPackage, String manifestUrl, + static void showInstalledNotification(String webApkPackage, String notificationId, String shortName, String url, Bitmap icon, boolean isIconMaskable) { Context context = ContextUtils.getApplicationContext(); Intent intent = WebApkNavigationClient.createLaunchWebApkIntent(webApkPackage, url, false @@ -55,7 +55,7 @@ icon = WebappsIconUtils.generateAdaptiveIconBitmap(icon); } - showNotification(manifestUrl, shortName, url, icon, + showNotification(notificationId, shortName, url, icon, context.getResources().getString(R.string.notification_webapk_installed), clickPendingIntent, true /* isCompleted */); } @@ -63,14 +63,15 @@ /** Display a notification when an install starts. */ @CalledByNative @VisibleForTesting - static void showInstallInProgressNotification( - String manifestUrl, String shortName, String url, Bitmap icon, boolean isIconMaskable) { + static void showInstallInProgressNotification(String notificationId, String shortName, + String url, Bitmap icon, boolean isIconMaskable) { String message = ContextUtils.getApplicationContext().getResources().getString( R.string.notification_webapk_install_in_progress, shortName); if (isIconMaskable && WebappsIconUtils.doesAndroidSupportMaskableIcons()) { icon = WebappsIconUtils.generateAdaptiveIconBitmap(icon); } - showNotification(manifestUrl, shortName, url, icon, message, null, false /* isCompleted */); + showNotification( + notificationId, shortName, url, icon, message, null, false /* isCompleted */); WebappsUtils.showToast(message); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadSettingsTest.java index 2248389..6c5c7d0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadSettingsTest.java
@@ -27,7 +27,6 @@ import org.chromium.chrome.browser.settings.SettingsActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate; @@ -97,17 +96,6 @@ @Test @MediumTest - @EnableFeatures({ChromeFeatureList.DOWNLOAD_LATER, ChromeFeatureList.OFFLINE_PAGES_PREFETCHING}) - public void testGeneralSettings() throws Exception { - mSettingsActivityTestRule.startSettingsActivity(); - assertPreference(DownloadSettings.PREF_LOCATION_CHANGE); - assertPreference(DownloadSettings.PREF_LOCATION_PROMPT_ENABLED); - mSettingsActivityTestRule.getActivity().finish(); - } - - @Test - @MediumTest - @DisableFeatures(ChromeFeatureList.DOWNLOAD_LATER) @EnableFeatures(ChromeFeatureList.OFFLINE_PAGES_PREFETCHING) public void testWithoutDownloadLater() throws Exception { mSettingsActivityTestRule.startSettingsActivity();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java index 47a6a4c..3ca7016a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/SystemDownloadNotifierTest.java
@@ -25,8 +25,6 @@ import org.chromium.base.test.util.Feature; import org.chromium.components.browser_ui.notifications.ThrottlingNotificationScheduler; import org.chromium.components.offline_items_collection.ContentId; -import org.chromium.components.offline_items_collection.OfflineItemSchedule; -import org.chromium.components.offline_items_collection.PendingState; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.UUID; @@ -155,24 +153,4 @@ Assert.assertEquals( notificationId, mMockDownloadNotificationService.getLastNotificationId()); } - - /** - * No notifications when {@link DownloadInfo#getOfflineItemSchedule()} exists. - */ - @Test - @SmallTest - @Feature({"Download"}) - public void testDownloadLaterNotification() { - DownloadInfo info = getDownloadInfoBuilder(new ContentId("download", "1")) - .setOfflineItemSchedule(new OfflineItemSchedule(true, -1)) - .build(); - - mSystemDownloadNotifier.notifyDownloadProgress( - info, 100, true /* canDownloadWhileMetered */); - mSystemDownloadNotifier.notifyDownloadPaused(info); - mSystemDownloadNotifier.notifyDownloadFailed(info); - mSystemDownloadNotifier.notifyDownloadInterrupted(info, true, PendingState.PENDING_NETWORK); - - Assert.assertEquals(0, mMockDownloadNotificationService.getNumberOfNotifications()); - } }
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 26d2a1c..6e5bcdc 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -497,6 +497,9 @@ <message name="IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_LABEL" desc="Label for the section for users to add words that they don’t want get flagged by the spell check."> Customize spell check </message> + <message name="IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL" desc="Label for the section of the Japanese user settings which allows them to manage their custom dictionaries for Japaneses input. This is the string which appears at the top of the User dictionaries subpage."> + User dictionaries + </message> <message name="IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_DESCRIPTION" desc="Description for the section for users to add words that they don’t want get flagged by the spell check."> Add words you want spell check to skip </message> @@ -582,7 +585,7 @@ <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_SECTION_TITLE" desc="The label for the section in input method options page section title."> Section </message> - <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_AUTOMATICALLY_SWITCH_TO_HALFWIDTH" desc="The label for the setting to toggle if the Japanese input method should automatically switch to using halfwidth."> + <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_AUTOMATICALLY_SWITCH_TO_HALFWIDTH" desc="The label for the input method option to enable double-space to type period (when an user types two consecutive space, it outputs a period)."> Automatically switch to halfwidth </message> <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_SHIFT_KEY_MODE_STYLE" desc="The label for the setting to set the shift key mode style."> @@ -738,6 +741,12 @@ <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_KEYMAP_STYLE_CHROMEOS" translateable="false"> ChromeOS </message> + <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY" desc="Label on the settings page which if the user clicks on, will bring up the Japaneses dictionary management page. There are multiple dictionary which the user can modify."> + Manage user dictionaries + </message> + <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY_SUBTITLE" desc="Subheading for the label on the settings page which if the user clicks on, will bring up the Japaneses dictionary management page. There are multiple dictionary which the user can modify."> + Add your own words to the user dictionaries in order to customize the conversion candidates. + </message> <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_CHINESE_PUNCTUATION" desc="The label for the pinyin input method option for whether to output full-width or half-with punctuation."> Initial punctuation width is Full </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL.png.sha1 new file mode 100644 index 0000000..88a79fb --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL.png.sha1
@@ -0,0 +1 @@ +61cc74fd023cbca183d255b177b6156493e0a1dc \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY.png.sha1 new file mode 100644 index 0000000..2db59f0 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY.png.sha1
@@ -0,0 +1 @@ +4e8331d89469aac97561654b5150779c25928af4 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY_SUBTITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY_SUBTITLE.png.sha1 new file mode 100644 index 0000000..2db59f0 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +4e8331d89469aac97561654b5150779c25928af4 \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 9b2f010..dda9f98 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1111,14 +1111,9 @@ std::size(kPageEntitiesPageContentAnnotationsAllLocalesParams), nullptr}, }; -const FeatureEntry::FeatureParam - kJourneysSortClustersWithinBatchForQueryParams[] = { - {"JourneysLocaleOrLanguageAllowlist", "*"}, - {"JourneysSortClustersWithinBatchForQuery", "true"}, -}; -const FeatureEntry::FeatureParam kJourneysDropHiddenVisitsParams[] = { +const FeatureEntry::FeatureParam kJourneysHiddenVisitsParams[] = { {"JourneysLocaleOrLanguageAllowlist", "*"}, - {"drop_hidden_visits", "true"}, + {"drop_hidden_visits", "false"}, }; const FeatureEntry::FeatureParam kJourneysShowAllVisitsParams[] = { {"JourneysLocaleOrLanguageAllowlist", "*"}, @@ -1132,13 +1127,10 @@ {"JourneysLocaleOrLanguageAllowlist", "*"}, }; const FeatureEntry::FeatureVariation kJourneysVariations[] = { - {"Sort Clusters Within Batch for Query", - kJourneysSortClustersWithinBatchForQueryParams, - std::size(kJourneysSortClustersWithinBatchForQueryParams), nullptr}, - {"No 'Show More' - Drop hidden visits", kJourneysDropHiddenVisitsParams, - std::size(kJourneysDropHiddenVisitsParams), nullptr}, {"No 'Show More' - Show all visits", kJourneysShowAllVisitsParams, std::size(kJourneysShowAllVisitsParams), nullptr}, + {"'Show More' - Hide hidden visits", kJourneysHiddenVisitsParams, + std::size(kJourneysHiddenVisitsParams), nullptr}, {"All Supported Locales", kJourneysAllLocalesParams, std::size(kJourneysAllLocalesParams), nullptr}, };
diff --git a/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/TrustedWebActivityUmaRecorder.java b/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/TrustedWebActivityUmaRecorder.java index fbc2681..a81d33a 100644 --- a/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/TrustedWebActivityUmaRecorder.java +++ b/chrome/browser/android/browserservices/metrics/java/src/org/chromium/chrome/browser/browserservices/metrics/TrustedWebActivityUmaRecorder.java
@@ -11,7 +11,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; -import org.chromium.chrome.browser.browserservices.constants.LocationUpdateError; import org.chromium.chrome.browser.browserservices.constants.QualityEnforcementViolationType; import org.chromium.components.content_settings.ContentSettingValues; import org.chromium.components.ukm.UkmRecorder; @@ -235,11 +234,6 @@ "TrustedWebActivity.LocationPermissionRequestIsGranted", enabled); } - public void recordLocationUpdateError(@LocationUpdateError int error) { - RecordHistogram.recordEnumeratedHistogram("TrustedWebActivity.LocationUpdateErrorCode", - error, LocationUpdateError.MAX_VALUE + 1); - } - public void recordQualityEnforcementViolation( WebContents webContents, @QualityEnforcementViolationType int type) { RecordHistogram.recordEnumeratedHistogram("TrustedWebActivity.QualityEnforcementViolation",
diff --git a/chrome/browser/android/webapk/webapk_install_service.cc b/chrome/browser/android/webapk/webapk_install_service.cc index 1b35793..9116a65 100644 --- a/chrome/browser/android/webapk/webapk_install_service.cc +++ b/chrome/browser/android/webapk/webapk_install_service.cc
@@ -9,6 +9,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/bind.h" +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/strings/utf_string_conversions.h" #include "chrome/android/chrome_jni_headers/WebApkInstallService_jni.h" @@ -19,10 +20,21 @@ #include "components/webapps/browser/android/shortcut_info.h" #include "components/webapps/browser/android/webapk/webapk_types.h" #include "components/webapps/browser/android/webapps_utils.h" +#include "components/webapps/browser/features.h" #include "components/webapps/browser/installable/installable_logging.h" #include "content/public/browser/web_contents.h" #include "ui/gfx/android/java_bitmap.h" +namespace { + +GURL GetNotificationId(const GURL& manifest_url, const GURL& manifest_id) { + if (base::FeatureList::IsEnabled(webapps::features::kWebApkUniqueId)) + return manifest_id; + return manifest_url; +} + +} // namespace + // static WebApkInstallService* WebApkInstallService::Get( content::BrowserContext* context) { @@ -35,7 +47,11 @@ WebApkInstallService::~WebApkInstallService() {} -bool WebApkInstallService::IsInstallInProgress(const GURL& web_manifest_url) { +bool WebApkInstallService::IsInstallInProgress(const GURL& web_manifest_url, + const GURL& web_manifest_id) { + if (base::FeatureList::IsEnabled(webapps::features::kWebApkUniqueId)) + return install_ids_.count(web_manifest_id); + return installs_.count(web_manifest_url); } @@ -45,18 +61,21 @@ const SkBitmap& primary_icon, bool is_primary_icon_maskable, webapps::WebappInstallSource install_source) { - if (IsInstallInProgress(shortcut_info.manifest_url)) { + if (IsInstallInProgress(shortcut_info.manifest_url, + shortcut_info.manifest_id)) { webapps::WebappsUtils::ShowWebApkInstallResultToast( webapps::WebApkInstallResult::INSTALL_ALREADY_IN_PROGRESS); return; } installs_.insert(shortcut_info.manifest_url); + install_ids_.insert(shortcut_info.manifest_id); webapps::InstallableMetrics::TrackInstallEvent(install_source); - ShowInstallInProgressNotification(shortcut_info.manifest_url, - shortcut_info.short_name, shortcut_info.url, - primary_icon, is_primary_icon_maskable); + ShowInstallInProgressNotification( + GetNotificationId(shortcut_info.manifest_url, shortcut_info.manifest_id), + shortcut_info.short_name, shortcut_info.url, primary_icon, + is_primary_icon_maskable); // We pass an weak ptr to a WebContents to the callback, since the // installation may take more than 10 seconds so there is a chance that the @@ -81,28 +100,30 @@ } GURL manifest_url(proto->manifest_url()); - if (IsInstallInProgress(manifest_url)) { + GURL manifest_id(proto->manifest().id()); + if (IsInstallInProgress(manifest_url, manifest_id)) { std::move(finish_callback) .Run(webapps::WebApkInstallResult::INSTALL_ALREADY_IN_PROGRESS); return; } installs_.insert(manifest_url); + install_ids_.insert(manifest_id); std::u16string short_name = base::UTF8ToUTF16(proto->manifest().short_name()); GURL manifest_start_url = GURL(proto->manifest().start_url()); webapps::InstallableMetrics::TrackInstallEvent( webapps::WebappInstallSource::CHROME_SERVICE); - ShowInstallInProgressNotification(manifest_url, short_name, - manifest_start_url, primary_icon, - is_primary_icon_maskable); + ShowInstallInProgressNotification( + GetNotificationId(manifest_url, manifest_id), short_name, + manifest_start_url, primary_icon, is_primary_icon_maskable); WebApkInstaller::InstallForServiceAsync( browser_context_, std::move(serialized_proto), short_name, webapps::ShortcutInfo::SOURCE_CHROME_SERVICE, primary_icon, is_primary_icon_maskable, manifest_url, base::BindOnce(&WebApkInstallService::OnFinishedInstallForService, - weak_ptr_factory_.GetWeakPtr(), manifest_url, + weak_ptr_factory_.GetWeakPtr(), manifest_url, manifest_id, manifest_start_url, short_name, primary_icon, is_primary_icon_maskable, std::move(finish_callback))); } @@ -123,10 +144,12 @@ bool relax_updates, const std::string& webapk_package_name) { installs_.erase(shortcut_info.manifest_url); + install_ids_.erase(shortcut_info.manifest_id); HandleFinishInstallNotifications( - shortcut_info.manifest_url, shortcut_info.url, shortcut_info.short_name, - primary_icon, is_primary_icon_maskable, result, webapk_package_name); + GetNotificationId(shortcut_info.manifest_url, shortcut_info.manifest_id), + shortcut_info.url, shortcut_info.short_name, primary_icon, + is_primary_icon_maskable, result, webapk_package_name); // If WebAPK install failed, try adding a shortcut instead. // If the install didn't definitely fail (i.e. PROBABLE_FAILURE), we don't add @@ -147,6 +170,7 @@ void WebApkInstallService::OnFinishedInstallForService( const GURL& manifest_url, + const GURL& manifest_id, const GURL& url, const std::u16string& short_name, const SkBitmap& primary_icon, @@ -156,15 +180,16 @@ bool relax_updates, const std::string& webapk_package_name) { installs_.erase(manifest_url); - HandleFinishInstallNotifications(manifest_url, url, short_name, primary_icon, - is_primary_icon_maskable, result, - webapk_package_name); + install_ids_.erase(manifest_id); + HandleFinishInstallNotifications( + GetNotificationId(manifest_url, manifest_id), url, short_name, + primary_icon, is_primary_icon_maskable, result, webapk_package_name); std::move(finish_callback).Run(result); } void WebApkInstallService::HandleFinishInstallNotifications( - const GURL& manifest_url, + const GURL& notification_id, const GURL& url, const std::u16string& short_name, const SkBitmap& primary_icon, @@ -172,27 +197,27 @@ webapps::WebApkInstallResult result, const std::string& webapk_package_name) { if (result == webapps::WebApkInstallResult::SUCCESS) { - ShowInstalledNotification(manifest_url, short_name, url, primary_icon, + ShowInstalledNotification(notification_id, short_name, url, primary_icon, is_primary_icon_maskable, webapk_package_name); return; } JNIEnv* env = base::android::AttachCurrentThread(); - base::android::ScopedJavaLocalRef<jstring> java_manifest_url = - base::android::ConvertUTF8ToJavaString(env, manifest_url.spec()); - Java_WebApkInstallService_cancelNotification(env, java_manifest_url); + base::android::ScopedJavaLocalRef<jstring> java_notification_id = + base::android::ConvertUTF8ToJavaString(env, notification_id.spec()); + Java_WebApkInstallService_cancelNotification(env, java_notification_id); } // static void WebApkInstallService::ShowInstallInProgressNotification( - const GURL& manifest_url, + const GURL& notification_id, const std::u16string& short_name, const GURL& url, const SkBitmap& primary_icon, bool is_primary_icon_maskable) { JNIEnv* env = base::android::AttachCurrentThread(); - base::android::ScopedJavaLocalRef<jstring> java_manifest_url = - base::android::ConvertUTF8ToJavaString(env, manifest_url.spec()); + base::android::ScopedJavaLocalRef<jstring> java_notification_id = + base::android::ConvertUTF8ToJavaString(env, notification_id.spec()); base::android::ScopedJavaLocalRef<jstring> java_short_name = base::android::ConvertUTF16ToJavaString(env, short_name); base::android::ScopedJavaLocalRef<jstring> java_url = @@ -201,13 +226,13 @@ gfx::ConvertToJavaBitmap(primary_icon); Java_WebApkInstallService_showInstallInProgressNotification( - env, java_manifest_url, java_short_name, java_url, java_primary_icon, + env, java_notification_id, java_short_name, java_url, java_primary_icon, is_primary_icon_maskable); } // static void WebApkInstallService::ShowInstalledNotification( - const GURL& manifest_url, + const GURL& notification_id, const std::u16string& short_name, const GURL& url, const SkBitmap& primary_icon, @@ -216,8 +241,8 @@ JNIEnv* env = base::android::AttachCurrentThread(); base::android::ScopedJavaLocalRef<jstring> java_webapk_package = base::android::ConvertUTF8ToJavaString(env, webapk_package_name); - base::android::ScopedJavaLocalRef<jstring> java_manifest_url = - base::android::ConvertUTF8ToJavaString(env, manifest_url.spec()); + base::android::ScopedJavaLocalRef<jstring> java_notification_id = + base::android::ConvertUTF8ToJavaString(env, notification_id.spec()); base::android::ScopedJavaLocalRef<jstring> java_short_name = base::android::ConvertUTF16ToJavaString(env, short_name); base::android::ScopedJavaLocalRef<jstring> java_url = @@ -226,6 +251,6 @@ gfx::ConvertToJavaBitmap(primary_icon); Java_WebApkInstallService_showInstalledNotification( - env, java_webapk_package, java_manifest_url, java_short_name, java_url, + env, java_webapk_package, java_notification_id, java_short_name, java_url, java_primary_icon, is_primary_icon_maskable); }
diff --git a/chrome/browser/android/webapk/webapk_install_service.h b/chrome/browser/android/webapk/webapk_install_service.h index 7fba3e3..928c03f 100644 --- a/chrome/browser/android/webapk/webapk_install_service.h +++ b/chrome/browser/android/webapk/webapk_install_service.h
@@ -65,7 +65,8 @@ ~WebApkInstallService() override; // Returns whether an install for |web_manifest_url| is in progress. - bool IsInstallInProgress(const GURL& web_manifest_url); + bool IsInstallInProgress(const GURL& web_manifest_url, + const GURL& manifest_id); // Installs WebAPK and adds shortcut to the launcher. It talks to the Chrome // WebAPK server to generate a WebAPK on the server and to Google Play to @@ -109,6 +110,7 @@ // Triggers the callback to propagate the |WebApkInstallResult| to the // scheduling Client. void OnFinishedInstallForService(const GURL& manifest_url, + const GURL& manifest_id, const GURL& url, const std::u16string& short_name, const SkBitmap& primary_icon, @@ -149,6 +151,9 @@ // In progress installs. std::set<GURL> installs_; + // In progress installs's id. + std::set<GURL> install_ids_; + // Used to get |weak_ptr_|. base::WeakPtrFactory<WebApkInstallService> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/android/webapk/webapk_update_data_fetcher.cc b/chrome/browser/android/webapk/webapk_update_data_fetcher.cc index 9ff9062..ec06608 100644 --- a/chrome/browser/android/webapk/webapk_update_data_fetcher.cc +++ b/chrome/browser/android/webapk/webapk_update_data_fetcher.cc
@@ -170,7 +170,7 @@ return; } - GURL new_manifest_id(webapps::ShortcutInfo::GetManifestId(data.manifest)); + GURL new_manifest_id(blink::GetIdFromManifest(data.manifest)); // If the fetched manifest id is different from the current one, we also // continue observing as the id is the identity for the application. We // will treat the manifest with different id as the one of another WebAPK.
diff --git a/chrome/browser/apps/app_service/browser_app_instance_registry.cc b/chrome/browser/apps/app_service/browser_app_instance_registry.cc index e7577da..c1ac8d6 100644 --- a/chrome/browser/apps/app_service/browser_app_instance_registry.cc +++ b/chrome/browser/apps/app_service/browser_app_instance_registry.cc
@@ -409,11 +409,11 @@ } } else { auto id = update.id; - auto& instance = AddInstance( + auto& new_instance = AddInstance( lacros_app_instances_, id, std::make_unique<BrowserAppInstance>(std::move(update), window)); for (auto& observer : observers_) { - observer.OnBrowserAppAdded(instance); + observer.OnBrowserAppAdded(new_instance); } } }
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc index e42ed08..74c0375 100644 --- a/chrome/browser/apps/app_service/publishers/arc_apps.cc +++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -338,7 +338,6 @@ } void ResetVerifiedLinks( - const apps::IntentFilterPtr& intent_filter, const apps::ReplacedAppPreferences& replaced_app_preferences, arc::ArcServiceManager* arc_service_manager, ArcAppListPrefs* prefs) { @@ -1109,8 +1108,7 @@ } AddPreferredApp(app_id, intent_filter, std::move(intent), arc_service_manager, prefs); - ResetVerifiedLinks(intent_filter, replaced_app_preferences, - arc_service_manager, prefs); + ResetVerifiedLinks(replaced_app_preferences, arc_service_manager, prefs); } void ArcApps::SetResizeLocked(const std::string& app_id, bool locked) { @@ -1449,8 +1447,7 @@ AddPreferredApp(app_id, ConvertMojomIntentFilterToIntentFilter(intent_filter), ConvertMojomIntentToIntent(intent), arc_service_manager, prefs); - ResetVerifiedLinks(ConvertMojomIntentFilterToIntentFilter(intent_filter), - ConvertMojomReplacedAppPreferencesToReplacedAppPreferences( + ResetVerifiedLinks(ConvertMojomReplacedAppPreferencesToReplacedAppPreferences( replaced_app_preferences), arc_service_manager, prefs); }
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc index faff54ea..2a8fc47 100644 --- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc +++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.cc
@@ -253,7 +253,7 @@ friend class base::RefCounted<SelectDirectoryDialog>; ~SelectDirectoryDialog() override = default; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; raw_ptr<WebContents> web_contents_; Callback callback_; };
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 709fabe..dc0f4ef 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -1341,6 +1341,8 @@ "lock_screen_apps/app_manager.h", "lock_screen_apps/app_manager_impl.cc", "lock_screen_apps/app_manager_impl.h", + "lock_screen_apps/app_registry_cache_observer_with_profile.cc", + "lock_screen_apps/app_registry_cache_observer_with_profile.h", "lock_screen_apps/app_window_metrics_tracker.cc", "lock_screen_apps/app_window_metrics_tracker.h", "lock_screen_apps/first_app_run_toast_manager.cc",
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc index 3171082..f9ece6f 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc +++ b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc
@@ -4,7 +4,9 @@ #include "chrome/browser/ash/app_restore/arc_ghost_window_delegate.h" +#include "chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h" #include "chrome/browser/ash/app_restore/arc_window_utils.h" +#include "chrome/browser/ash/arc/window_predictor/window_predictor_utils.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -17,10 +19,12 @@ ArcGhostWindowDelegate::ArcGhostWindowDelegate( exo::ClientControlledShellSurface* shell_surface, int window_id, + const std::string& app_id, int64_t display_id, const gfx::Rect& bounds, chromeos::WindowStateType window_state) : window_id_(window_id), + app_id_(app_id), bounds_(gfx::Rect(bounds)), pending_close_(false), window_state_(window_state), @@ -145,6 +149,20 @@ UpdateWindowInfoToArc(); } +void ArcGhostWindowDelegate::OnAppStatesUpdate(const std::string& app_id, + bool ready, + bool need_fixup) { + if (app_id != app_id_) + return; + + // Currently the type update is oneway. If an App need fixup, is not able to + // become another state before it's ready. + if (need_fixup) { + static_cast<ArcGhostWindowShellSurface*>(shell_surface_) + ->SetWindowType(arc::GhostWindowType::kFixup); + } +} + bool ArcGhostWindowDelegate::SetDisplayId(int64_t display_id) { absl::optional<double> scale_factor = GetDisplayScaleFactor(display_id); if (!scale_factor.has_value()) {
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h index 1351f29..40e9c64 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h +++ b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h
@@ -21,6 +21,7 @@ public: ArcGhostWindowDelegate(exo::ClientControlledShellSurface* shell_surface, int window_id, + const std::string& app_id, int64_t display_id, const gfx::Rect& bounds, chromeos::WindowStateType window_state); @@ -50,11 +51,16 @@ void OnWindowCloseRequested(int window_id) override; + void OnAppStatesUpdate(const std::string& app_id, + bool ready, + bool need_fixup) override; + private: bool SetDisplayId(int64_t display_id); void UpdateWindowInfoToArc(); int window_id_; + std::string app_id_; gfx::Rect bounds_; bool pending_close_; int64_t display_id_;
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_handler.cc b/chrome/browser/ash/app_restore/arc_ghost_window_handler.cc index a09086d..2600dfe 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_handler.cc +++ b/chrome/browser/ash/app_restore/arc_ghost_window_handler.cc
@@ -128,6 +128,18 @@ return true; } +bool ArcGhostWindowHandler::UpdateArcGhostWindowType( + int32_t session_id, + arc::GhostWindowType window_type) { + auto it = session_id_to_shell_surface_.find(session_id); + if (it == session_id_to_shell_surface_.end()) + return false; + auto* shell_surface = + static_cast<ArcGhostWindowShellSurface*>(it->second.get()); + shell_surface->SetWindowType(window_type); + return true; +} + void ArcGhostWindowHandler::CloseWindow(int session_id) { auto it = session_id_to_shell_surface_.find(session_id); if (it == session_id_to_shell_surface_.end())
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_handler.h b/chrome/browser/ash/app_restore/arc_ghost_window_handler.h index a8cd7b0e..d40ff77 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_handler.h +++ b/chrome/browser/ash/app_restore/arc_ghost_window_handler.h
@@ -16,6 +16,10 @@ struct AppRestoreData; } // namespace app_restore +namespace arc { +enum class GhostWindowType; +} // namespace arc + namespace ash::full_restore { // The ArcGhostWindowHandler class provides control for ARC ghost window. @@ -77,6 +81,9 @@ int32_t session_id, ::app_restore::AppRestoreData* restore_data); + bool UpdateArcGhostWindowType(int32_t session_id, + arc::GhostWindowType window_type); + void CloseWindow(int session_id); void AddObserver(Observer* observer);
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc index b755aeb..ea0d1d0 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc +++ b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
@@ -121,7 +121,7 @@ // TODO(sstan): Add set_surface_destroyed_callback. shell_surface->set_delegate(std::make_unique<ArcGhostWindowDelegate>( - shell_surface.get(), window_id, display_id_value, local_bounds, + shell_surface.get(), window_id, app_id, display_id_value, local_bounds, window_state.value_or(chromeos::WindowStateType::kDefault))); shell_surface->set_close_callback(std::move(close_callback)); @@ -186,6 +186,7 @@ uint32_t theme_color) { auto view = std::make_unique<ArcGhostWindowView>(type_, kDiameter, theme_color); + view_observer_ = view.get(); view->LoadIcon(app_id); exo::ShellSurfaceBase::OverlayParams overlay_params(std::move(view)); overlay_params.translucent = true; @@ -210,4 +211,10 @@ property_handler->ClearProperty(app_restore::kAppIdKey); } +void ArcGhostWindowShellSurface::SetWindowType( + arc::GhostWindowType window_type) { + DCHECK(view_observer_); + view_observer_->SetType(window_type); +} + } // namespace ash::full_restore
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h index 5256629..088ce44 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h +++ b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h
@@ -23,6 +23,8 @@ // Explicitly identifies ARC ghost surface. extern const aura::WindowProperty<bool>* const kArcGhostSurface; +class ArcGhostWindowView; + // ArcGhostWindowShellSurface class is a shell surface which controlled its // root surface. class ArcGhostWindowShellSurface : public exo::ClientControlledShellSurface { @@ -42,6 +44,8 @@ void OverrideInitParams(views::Widget::InitParams* params) override; + void SetWindowType(arc::GhostWindowType window_type); + exo::Surface* controller_surface(); private: @@ -56,6 +60,7 @@ void SetShellAppId(ui::PropertyHandler* property_handler, const absl::optional<std::string>& id); + ArcGhostWindowView* view_observer_ = nullptr; arc::GhostWindowType type_; absl::optional<std::string> app_id_;
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_view.cc b/chrome/browser/ash/app_restore/arc_ghost_window_view.cc index dd79b12..87ac436 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_view.cc +++ b/chrome/browser/ash/app_restore/arc_ghost_window_view.cc
@@ -92,14 +92,7 @@ throbber->SetPreferredSize(gfx::Size(diameter, diameter)); throbber->GetViewAccessibility().OverrideRole(ax::mojom::Role::kImage); - if (type == arc::GhostWindowType::kFixup) { - auto label = std::make_unique<views::Label>( - l10n_util::GetStringUTF16(IDS_ARC_GHOST_WINDOW_APP_FIXUP_MESSAGE)); - // TODO(sstan): Set font size or height, according to future UI update. - label->SetMultiLine(true); - message_label_ = label.get(); - AddChildView(std::move(label)); - } + SetType(type); // TODO(sstan): Set window title and accessible name from saved data. } @@ -121,6 +114,28 @@ : std::move(icon_loaded_cb_for_testing_)); } +void ArcGhostWindowView::SetType(arc::GhostWindowType type) { + // Currently the only difference of App Fixup and other type of ghost window + // is that App Fixup ghost window has a message label. + if (type == arc::GhostWindowType::kFixup) { + if (!message_label_) { + auto label = std::make_unique<views::Label>( + l10n_util::GetStringUTF16(IDS_ARC_GHOST_WINDOW_APP_FIXUP_MESSAGE)); + // TODO(sstan): Set font size or height, according to future UI update. + label->SetMultiLine(true); + message_label_ = label.get(); + AddChildView(std::move(label)); + Layout(); + } + } else { + if (message_label_) { + RemoveChildView(message_label_); + message_label_ = nullptr; + Layout(); + } + } +} + void ArcGhostWindowView::OnIconLoaded(apps::IconValuePtr icon_value) { if (!icon_value || icon_value->icon_type != apps::IconType::kStandard) return;
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_view.h b/chrome/browser/ash/app_restore/arc_ghost_window_view.h index 8e80eca..7146aef 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_view.h +++ b/chrome/browser/ash/app_restore/arc_ghost_window_view.h
@@ -38,17 +38,20 @@ void LoadIcon(const std::string& app_id); + void SetType(arc::GhostWindowType type); + private: FRIEND_TEST_ALL_PREFIXES(ArcGhostWindowViewTest, IconLoadTest); FRIEND_TEST_ALL_PREFIXES(ArcGhostWindowViewTest, FixupMessageTest); + FRIEND_TEST_ALL_PREFIXES(ArcGhostWindowViewTest, SetTypeTest); void InitLayout(arc::GhostWindowType type, uint32_t theme_color, int diameter); void OnIconLoaded(apps::IconValuePtr icon_value); - views::ImageView* icon_view_; - views::Label* message_label_; + views::ImageView* icon_view_ = nullptr; + views::Label* message_label_ = nullptr; base::OnceCallback<void(apps::IconValuePtr icon_value)> icon_loaded_cb_for_testing_;
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_view_unittest.cc b/chrome/browser/ash/app_restore/arc_ghost_window_view_unittest.cc index f8ad42c..40bb8f2 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_view_unittest.cc +++ b/chrome/browser/ash/app_restore/arc_ghost_window_view_unittest.cc
@@ -143,4 +143,20 @@ l10n_util::GetStringUTF16(IDS_ARC_GHOST_WINDOW_APP_FIXUP_MESSAGE)); } +TEST_F(ArcGhostWindowViewTest, SetTypeTest) { + const int kDiameter = 24; + const uint32_t kThemeColor = SK_ColorWHITE; + const std::string kAppId = "test_app"; + InstallApp(kAppId); + + CreateView(arc::GhostWindowType::kFullRestore, kDiameter, kThemeColor); + EXPECT_EQ(view()->message_label_, nullptr); + + view()->SetType(arc::GhostWindowType::kFixup); + EXPECT_NE(view()->message_label_, nullptr); + + view()->SetType(arc::GhostWindowType::kAppLaunch); + EXPECT_EQ(view()->message_label_, nullptr); +} + } // namespace ash::full_restore
diff --git a/chrome/browser/ash/app_restore/arc_window_utils.cc b/chrome/browser/ash/app_restore/arc_window_utils.cc index b67a36b3..023b8e9 100644 --- a/chrome/browser/ash/app_restore/arc_window_utils.cc +++ b/chrome/browser/ash/app_restore/arc_window_utils.cc
@@ -56,6 +56,12 @@ } absl::optional<double> GetDisplayScaleFactor(int64_t display_id) { + // The `kDefaultDisplayId` should not be a valid parameter. Here replace it to + // primary display id to keep it as the same semantics with Android, since the + // ARC app window will not be shown on chromium default display (placeholder + // display when no display connected). + if (display_id == display::kDefaultDisplayId) + display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); display::Display display; if (display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id, &display)) {
diff --git a/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc b/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc index 8701dcf4..0650b99 100644 --- a/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc +++ b/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc
@@ -373,9 +373,10 @@ } SelectFileDialogHolder::SelectFileDialogHolder( - ui::SelectFileDialog::Listener* listener) - : select_file_dialog_( - SelectFileDialogExtension::Create(listener, nullptr)) {} + ui::SelectFileDialog::Listener* listener) { + select_file_dialog_ = static_cast<SelectFileDialogExtension*>( + ui::SelectFileDialog::Create(listener, nullptr).get()); +} SelectFileDialogHolder::~SelectFileDialogHolder() { // select_file_dialog_ can be nullptr only in unit tests.
diff --git a/chrome/browser/ash/arc/fileapi/arc_select_files_handler.h b/chrome/browser/ash/arc/fileapi/arc_select_files_handler.h index 7b080fc5..e304ae15 100644 --- a/chrome/browser/ash/arc/fileapi/arc_select_files_handler.h +++ b/chrome/browser/ash/arc/fileapi/arc_select_files_handler.h
@@ -5,11 +5,11 @@ #ifndef CHROME_BROWSER_ASH_ARC_FILEAPI_ARC_SELECT_FILES_HANDLER_H_ #define CHROME_BROWSER_ASH_ARC_FILEAPI_ARC_SELECT_FILES_HANDLER_H_ -#include <memory> #include <vector> #include "ash/components/arc/mojom/file_system.mojom.h" #include "base/files/file_path.h" +#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/views/select_file_dialog_extension.h" #include "content/public/browser/render_frame_host.h" @@ -146,7 +146,7 @@ content::RenderFrameHost::JavaScriptResultCallback callback); private: - std::unique_ptr<SelectFileDialogExtension> select_file_dialog_; + scoped_refptr<SelectFileDialogExtension> select_file_dialog_; }; } // namespace arc
diff --git a/chrome/browser/ash/arc/fileapi/arc_select_files_handler_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_select_files_handler_unittest.cc index 4d914cc..eca76e3 100644 --- a/chrome/browser/ash/arc/fileapi/arc_select_files_handler_unittest.cc +++ b/chrome/browser/ash/arc/fileapi/arc_select_files_handler_unittest.cc
@@ -111,8 +111,7 @@ std::make_unique<ArcSelectFilesHandler>(profile); std::unique_ptr<MockSelectFileDialogHolder> mock_dialog_holder = - std::make_unique<MockSelectFileDialogHolder>( - arc_select_files_handler_.get()); + std::make_unique<MockSelectFileDialogHolder>(nullptr); mock_dialog_holder_ = mock_dialog_holder.get(); arc_select_files_handler_->SetDialogHolderForTesting( std::move(mock_dialog_holder));
diff --git a/chrome/browser/ash/arc/survey/arc_survey_service.cc b/chrome/browser/ash/arc/survey/arc_survey_service.cc index 7ef855d..908128b1 100644 --- a/chrome/browser/ash/arc/survey/arc_survey_service.cc +++ b/chrome/browser/ash/arc/survey/arc_survey_service.cc
@@ -123,7 +123,7 @@ VLOG(1) << "List of package names not found in the survey data."; return false; } - const base::Value::ConstListView items = list->GetListDeprecated(); + const base::Value::List& items = list->GetList(); if (items.empty()) { VLOG(1) << "List of package names is empty in the survey data."; return false;
diff --git a/chrome/browser/ash/arc/window_predictor/OWNERS b/chrome/browser/ash/arc/window_predictor/OWNERS new file mode 100644 index 0000000..e4f702a8 --- /dev/null +++ b/chrome/browser/ash/arc/window_predictor/OWNERS
@@ -0,0 +1 @@ +sstan@chromium.org
diff --git a/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc b/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc index 5866282..8fcd2dc 100644 --- a/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc +++ b/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc
@@ -7,7 +7,7 @@ #include "chrome/browser/ash/arc/window_predictor/window_predictor_utils.h" #include "components/app_restore/app_launch_info.h" #include "components/app_restore/window_info.h" -#include "ui/display/types/display_constants.h" +#include "ui/display/screen.h" namespace arc { @@ -28,7 +28,7 @@ // and user cannot launch another instance of the same app by click icon. But // from code side it still can launch the same app by calling this function. int arc_session_id = -1; - int64_t display_id = display::kDefaultDisplayId; + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); if (window_info) { arc_session_id = window_info->window_id; // Default invalid display id in WindowInfo struct.
diff --git a/chrome/browser/ash/crosapi/select_file_ash.cc b/chrome/browser/ash/crosapi/select_file_ash.cc index 3108f1fe..ea8b0a8 100644 --- a/chrome/browser/ash/crosapi/select_file_ash.cc +++ b/chrome/browser/ash/crosapi/select_file_ash.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ash/crosapi/select_file_ash.h" -#include <memory> #include <utility> #include <vector> @@ -13,6 +12,7 @@ #include "ash/wm/desks/desks_util.h" #include "base/cxx17_backports.h" #include "base/files/file_path.h" +#include "base/memory/ref_counted.h" #include "chrome/browser/ash/crosapi/window_util.h" #include "chrome/browser/ui/views/select_file_dialog_extension.h" #include "chromeos/crosapi/mojom/select_file.mojom-shared.h" @@ -165,7 +165,7 @@ mojom::SelectFile::SelectCallback select_callback_; // The file select dialog. - std::unique_ptr<SelectFileDialogExtension> select_file_dialog_; + scoped_refptr<SelectFileDialogExtension> select_file_dialog_; // Optional file type extension filters. std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> file_types_;
diff --git a/chrome/browser/ash/crostini/crostini_export_import.h b/chrome/browser/ash/crostini/crostini_export_import.h index cda269c1..cde3ddb 100644 --- a/chrome/browser/ash/crostini/crostini_export_import.h +++ b/chrome/browser/ash/crostini/crostini_export_import.h
@@ -258,7 +258,7 @@ TrackerMap::iterator it); Profile* profile_; - std::unique_ptr<ui::SelectFileDialog> select_folder_dialog_; + scoped_refptr<ui::SelectFileDialog> select_folder_dialog_; TrackerMap status_trackers_; // |operation_data_storage_| persists the data required to complete an // operation while the file selection dialog is open/operation is in progress.
diff --git a/chrome/browser/ash/crostini/crostini_file_selector.h b/chrome/browser/ash/crostini/crostini_file_selector.h index 92eb247..892c537 100644 --- a/chrome/browser/ash/crostini/crostini_file_selector.h +++ b/chrome/browser/ash/crostini/crostini_file_selector.h
@@ -41,7 +41,7 @@ raw_ptr<content::WebUI> web_ui_; base::OnceCallback<void(const base::FilePath&)> selected_callback_; base::OnceCallback<void(void)> cancelled_callback_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; }; } // namespace crostini
diff --git a/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc b/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc index 13bb776..adf0546 100644 --- a/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc +++ b/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc
@@ -40,7 +40,7 @@ namespace { struct SelectFileData { - std::unique_ptr<ui::SelectFileDialog> dialog; + scoped_refptr<ui::SelectFileDialog> dialog; vm_tools::cicerone::FileSelectedSignal signal; };
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index fb8a347c..d822668 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -35,7 +35,6 @@ #include "base/json/json_value_converter.h" #include "base/json/json_writer.h" #include "base/json/values_util.h" -#include "base/memory/weak_ptr.h" #include "base/no_destructor.h" #include "base/path_service.h" #include "base/ranges/algorithm.h" @@ -162,10 +161,9 @@ ui::SelectFileDialog* Create( ui::SelectFileDialog::Listener* listener, std::unique_ptr<ui::SelectFilePolicy> policy) override { - std::unique_ptr<SelectFileDialogExtension> dialog = + last_select_ = SelectFileDialogExtension::Create(listener, std::move(policy)); - last_select_ = base::AsWeakPtr(dialog.get()); - return dialog.release(); + return last_select_.get(); } content::RenderFrameHost* GetFrameHost() { @@ -173,7 +171,7 @@ } private: - base::WeakPtr<SelectFileDialogExtension> last_select_; + scoped_refptr<SelectFileDialogExtension> last_select_; }; namespace file_manager {
diff --git a/chrome/browser/ash/guest_os/guest_os_registry_service.cc b/chrome/browser/ash/guest_os/guest_os_registry_service.cc index 8f07929..eb2c12c 100644 --- a/chrome/browser/ash/guest_os/guest_os_registry_service.cc +++ b/chrome/browser/ash/guest_os/guest_os_registry_service.cc
@@ -82,7 +82,7 @@ if (!list) { return result; } - for (const base::Value& value : list->GetListDeprecated()) { + for (const base::Value& value : list->GetList()) { result.insert(to_lower_ascii ? base::ToLowerASCII(value.GetString()) : value.GetString()); }
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path.cc b/chrome/browser/ash/guest_os/guest_os_share_path.cc index 6699837..f7407e8 100644 --- a/chrome/browser/ash/guest_os/guest_os_share_path.cc +++ b/chrome/browser/ash/guest_os/guest_os_share_path.cc
@@ -559,7 +559,7 @@ profile_->GetPrefs()->GetDict(prefs::kGuestOSPathsSharedToVms); for (const auto it : shared_paths) { base::FilePath path(it.first); - for (const auto& vm : it.second.GetListDeprecated()) { + for (const auto& vm : it.second.GetList()) { // Register all shared paths for all VMs since we want FilePathWatchers // to start immediately. RegisterSharedPath(vm.GetString(), path); @@ -653,7 +653,7 @@ if (path != volume.mount_path() && !volume.mount_path().IsParent(path)) { continue; } - const auto& vms = it.second.GetListDeprecated(); + const auto& vms = it.second.GetList(); for (const auto& vm : vms) { RegisterSharedPath(vm.GetString(), path); if (crostini::CrostiniManager::GetForProfile(profile_)->IsVmRunning(
diff --git a/chrome/browser/ash/input_method/component_extension_ime_manager_delegate_impl.cc b/chrome/browser/ash/input_method/component_extension_ime_manager_delegate_impl.cc index 04a7c5f9..b3e8532 100644 --- a/chrome/browser/ash/input_method/component_extension_ime_manager_delegate_impl.cc +++ b/chrome/browser/ash/input_method/component_extension_ime_manager_delegate_impl.cc
@@ -271,7 +271,7 @@ if (language_value->is_string()) { languages.insert(language_value->GetString()); } else if (language_value->is_list()) { - for (const base::Value& elem : language_value->GetListDeprecated()) { + for (const base::Value& elem : language_value->GetList()) { if (elem.is_string()) languages.insert(elem.GetString()); } @@ -289,7 +289,7 @@ if (!dict.GetList(extensions::manifest_keys::kLayouts, &layouts)) return false; - base::Value::ConstListView layouts_list = layouts->GetListDeprecated(); + const base::Value::List& layouts_list = layouts->GetList(); if (!layouts_list.empty() && layouts_list[0].is_string()) out->layout = layouts_list[0].GetString(); else @@ -412,7 +412,7 @@ continue; } - for (const base::Value& value : component_list->GetListDeprecated()) { + for (const base::Value& value : component_list->GetList()) { if (!value.is_dict()) continue;
diff --git a/chrome/browser/ash/input_method/ime_rules_config.cc b/chrome/browser/ash/input_method/ime_rules_config.cc index d44b96bbe..6097063 100644 --- a/chrome/browser/ash/input_method/ime_rules_config.cc +++ b/chrome/browser/ash/input_method/ime_rules_config.cc
@@ -77,7 +77,7 @@ auto* ac_domains_items = ac_domain_denylist->FindListKey(kConfigRuleItemsKey); if (ac_domains_items != nullptr) { - for (const auto& domain : ac_domains_items->GetListDeprecated()) { + for (const auto& domain : ac_domains_items->GetList()) { if (domain.is_string()) { rule_auto_correct_domain_denylist_.push_back(*domain.GetIfString()); }
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc b/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc index a44a2af0..1dcf6c69 100644 --- a/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc +++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc
@@ -16,17 +16,22 @@ #include "base/callback.h" #include "base/check.h" #include "base/check_op.h" +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/location.h" #include "base/metrics/histogram_base.h" #include "base/metrics/histogram_macros.h" +#include "base/notreached.h" #include "base/task/sequenced_task_runner.h" +#include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/tick_clock.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/lock_screen_apps/lock_screen_apps.h" #include "chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator.h" #include "chrome/browser/ash/note_taking_helper.h" @@ -35,13 +40,24 @@ #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/external_install_options.h" +#include "chrome/browser/web_applications/user_display_mode.h" +#include "chrome/browser/web_applications/web_app_constants.h" +#include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/app_types.h" +#include "components/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/cpp/types_util.h" #include "components/sync/model/string_ordinal.h" +#include "components/webapps/browser/install_result_code.h" +#include "content/public/common/content_features.h" #include "extensions/browser/extension_file_task_runner.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/install_flag.h" +#include "extensions/browser/uninstall_reason.h" #include "extensions/common/api/app_runtime.h" #include "extensions/common/extension.h" #include "extensions/common/extension_id.h" @@ -101,8 +117,6 @@ case ash::LockScreenAppSupport::kEnabled: return ActionAvailability::kAvailable; } - - return ActionAvailability::kAppNotSupportingLockScreen; } void InvokeCallbackOnTaskRunner( @@ -179,6 +193,59 @@ updates_from_webstore_or_empty_update_url); } +// Returns whether `app_id` is an installed web app in `profile`. +bool IsInstalledWebApp(const std::string& app_id, Profile* profile) { + if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) + return false; + auto* cache = + &apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); + + bool result = false; + cache->ForOneApp(app_id, [&result](const apps::AppUpdate& update) { + if (apps_util::IsInstalled(update.Readiness()) && + update.AppType() == apps::AppType::kWeb) { + result = true; + } + }); + return result; +} + +// Returns the start_url of the web app identified by `app_id` in `profile`, or +// an invalid GURL on error. +GURL GetStartUrl(const std::string& app_id, Profile* profile) { + if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) + return GURL(); + + auto* cache = + &apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); + GURL start_url; + cache->ForOneApp(app_id, [&start_url](const apps::AppUpdate& update) { + if (update.AppType() == apps::AppType::kWeb) { + // Publisher ID is start_url for web apps. + start_url = GURL(update.PublisherId()); + } + }); + return start_url; +} + +// Returns the name of the app identified by `app_id` in `profile`, or a null +// optional on error. +absl::optional<std::string> GetName(const std::string& app_id, + Profile* profile) { + if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) + return absl::nullopt; + + auto* cache = + &apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); + absl::optional<std::string> name; + cache->ForOneApp( + app_id, [&name](const apps::AppUpdate& update) { name = update.Name(); }); + return name; +} + +AppManagerImpl::OverrideInstallOptionsCallback + g_override_install_options_callback_for_testing_ = nullptr; + } // namespace AppManagerImpl::AppManagerImpl(const base::TickClock* tick_clock) @@ -223,14 +290,18 @@ CHECK(!ash::ProfileHelper::Get()->GetUserByProfile(lock_screen_profile_)) << "Lock screen profile should not be associated with any users."; + if (base::FeatureList::IsEnabled(features::kWebLockScreenApi)) { + lock_screen_profile_app_registry_observer_.emplace(this, + lock_screen_profile_); + } + UpdateLockScreenAppState(); } -void AppManagerImpl::Start( - const base::RepeatingClosure& note_taking_changed_callback) { +void AppManagerImpl::Start(const base::RepeatingClosure& app_changed_callback) { DCHECK_NE(State::kNotInitialized, state_); - app_changed_callback_ = note_taking_changed_callback; + app_changed_callback_ = app_changed_callback; if (state_ == State::kActive || state_ == State::kActivating) return; @@ -238,6 +309,12 @@ extensions_observation_.Observe( extensions::ExtensionRegistry::Get(primary_profile_)); + if (base::FeatureList::IsEnabled(features::kWebLockScreenApi)) { + DCHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile( + primary_profile_)); + primary_profile_app_registry_observer_.emplace(this, primary_profile_); + } + lock_screen_app_id_.clear(); std::string app_id = FindLockScreenAppId(); if (app_id.empty()) { @@ -255,6 +332,8 @@ app_changed_callback_.Reset(); extensions_observation_.Reset(); + lock_screen_profile_app_registry_observer_.reset(); + primary_profile_app_registry_observer_.reset(); available_lock_screen_app_reloads_ = 0; if (state_ == State::kInactive) @@ -279,7 +358,16 @@ if (!IsLockScreenAppAvailable()) return false; - // TODO(crbug.com/1006642): Handle web apps here. + if (base::FeatureList::IsEnabled(features::kWebLockScreenApi) && + IsInstalledWebApp(lock_screen_app_id_, primary_profile_)) { + DCHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile( + lock_screen_profile_)); + DCHECK(IsInstalledWebApp(lock_screen_app_id_, lock_screen_profile_)); + + // TODO(crbug.com/1006642): Launch web apps here. + NOTIMPLEMENTED(); + return false; + } const extensions::Extension* app = GetChromeAppForLockScreenAppLaunch(); // If the app cannot be found at this point, it either got unexpectedly @@ -302,6 +390,8 @@ return true; } +// Cannot be replaced with OnAppUpdate because OnAppUpdate is not called with a +// readiness change after unloading and reinstalling an extension. void AppManagerImpl::OnExtensionLoaded(content::BrowserContext* browser_context, const extensions::Extension* extension) { if (browser_context == primary_profile_ && @@ -325,14 +415,35 @@ } } -void AppManagerImpl::OnExtensionUninstalled( - content::BrowserContext* browser_context, - const extensions::Extension* extension, - extensions::UninstallReason reason) { - // If the app is uninstalled from the lock screen apps profile, make sure - // it's not reported as available anymore. - if (browser_context == lock_screen_profile_ && - extension->id() == lock_screen_app_id_) { +void AppManagerImpl::OnAppUpdate(const apps::AppUpdate& update, + Profile* profile) { + if (update.AppId().empty()) + return; + if (!update.ReadinessChanged()) + return; + + bool is_preferred_app = + update.AppId() == + ash::NoteTakingHelper::Get()->GetPreferredAppId(primary_profile_); + bool is_current_lock_screen_app = update.AppId() == lock_screen_app_id_; + bool is_app_available = update.Readiness() == apps::Readiness::kReady || + update.Readiness() == apps::Readiness::kTerminated; + bool is_primary_profile = profile == primary_profile_; + bool is_lock_screen_profile = profile == lock_screen_profile_; + + // App became available in primary profile. + if (is_preferred_app && is_app_available && is_primary_profile) { + UpdateLockScreenAppState(); + } + + // App became unavailable in primary profile. + if (is_current_lock_screen_app && !is_app_available && is_primary_profile) { + UpdateLockScreenAppState(); + } + + // App became unavailable in lock screen profile. + if (is_current_lock_screen_app && !is_app_available && + is_lock_screen_profile) { RemoveLockScreenAppDueToError(); } } @@ -346,6 +457,11 @@ UpdateLockScreenAppState(); } +AppManagerImpl::OverrideInstallOptionsCallback& +AppManagerImpl::OverrideInstallOptions() { + return g_override_install_options_callback_for_testing_; +} + void AppManagerImpl::UpdateLockScreenAppState() { if (state_ == State::kInactive) return; @@ -401,7 +517,48 @@ AppManagerImpl::State AppManagerImpl::AddAppToLockScreenProfile( const std::string& app_id) { - // TODO(crbug.com/1006642): First check if app_id is an installed web app. + DCHECK(lock_screen_profile_); + if (base::FeatureList::IsEnabled(features::kWebLockScreenApi)) { + if (!IsInstalledWebApp(app_id, primary_profile_)) { + // Installing a Chrome App. Ensure no web apps are left installed. + RemoveAllWebAppsFromLockScreenProfile(); + } else { + if (IsInstalledWebApp(app_id, lock_screen_profile_)) { + return State::kActive; + } + // Only one `SynchronizeInstalledApps` call may run at once. + if (is_synchronizing_installed_web_apps_) { + opt_app_id_pending_synchronize_ = app_id; + return State::kActivating; + } + is_synchronizing_installed_web_apps_ = true; + + GURL install_url = GetStartUrl(app_id, primary_profile_); + web_app::ExternalInstallOptions options( + install_url, web_app::UserDisplayMode::kStandalone, + web_app::ExternalInstallSource::kExternalLockScreen); + options.fallback_app_name = GetName(app_id, primary_profile_); + if (OverrideInstallOptions()) + OverrideInstallOptions()(options); + + // CrOSAPI currently only supports one profile (the main profile) so we + // cannot use a lock screen app profile on the Lacros side. So, directly + // use the lock screen app profile on the Ash side here. + // TODO(crbug.com/1343692): Once lacros supports multiple profiles, use + // CrOSAPI to install to a lacros-based lock-screen app profile. + auto* lock_screen_provider = + web_app::WebAppProvider::GetForLocalAppsUnchecked( + lock_screen_profile_); + DCHECK(lock_screen_provider); + lock_screen_provider->externally_managed_app_manager() + .SynchronizeInstalledApps( + {options}, web_app::ExternalInstallSource::kExternalLockScreen, + base::BindOnce(&AppManagerImpl::RecordLockScreenWebAppInstall, + weak_ptr_factory_.GetWeakPtr(), ++install_count_, + tick_clock_->NowTicks())); + return State::kActivating; + } + } extensions::ExtensionRegistry* primary_registry = extensions::ExtensionRegistry::Get(primary_profile_); @@ -438,9 +595,13 @@ install_count_++; if (is_unpacked) { - InstallAndEnableLockScreenChromeAppInLockScreenProfile( - lock_profile_app.get()); - return State::kActive; + // Post the completion so that this class can update state first. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&AppManagerImpl::CompleteLockScreenChromeAppInstall, + weak_ptr_factory_.GetWeakPtr(), install_count_, + tick_clock_->NowTicks(), lock_profile_app)); + return State::kActivating; } extensions::ExtensionService* lock_screen_service = @@ -470,6 +631,70 @@ return State::kActivating; } +bool AppManagerImpl::MaybeRunPendingWebAppSynchronize() { + is_synchronizing_installed_web_apps_ = false; + + if (!opt_app_id_pending_synchronize_.has_value()) + return false; + + std::string pending_app_id = opt_app_id_pending_synchronize_.value(); + opt_app_id_pending_synchronize_.reset(); + if (pending_app_id.empty()) { + RemoveAllWebAppsFromLockScreenProfile(); + } else { + AddAppToLockScreenProfile(pending_app_id); + } + return true; +} + +void AppManagerImpl::RecordLockScreenWebAppInstall( + int install_id, + base::TimeTicks install_start_time, + std::map<GURL, web_app::ExternallyManagedAppManager::InstallResult> + install_results, + std::map<GURL, bool> uninstall_results) { + DCHECK(base::FeatureList::IsEnabled(features::kWebLockScreenApi)); + // Only one web app can be installed to the lock screen profile at a time. + DCHECK_EQ(install_results.size(), 1u); + + UMA_HISTOGRAM_TIMES( + "Apps.LockScreen.NoteTakingApp.LockScreenInstallationDuration", + tick_clock_->NowTicks() - install_start_time); + + if (MaybeRunPendingWebAppSynchronize()) + return; + + // Bail out if the app manager is no longer waiting for this app's + // installation. + if (install_id != install_count_ || state_ != State::kActivating) + return; + + const auto result = install_results.begin()->second; + if (webapps::IsSuccess(result.code)) { + DCHECK_EQ(lock_screen_app_id_, result.app_id.value_or(std::string())); + state_ = State::kActive; + } else { + state_ = State::kAppUnavailable; + } + + if (!app_changed_callback_.is_null()) + app_changed_callback_.Run(); +} + +void AppManagerImpl::RecordLockScreenWebAppUninstall( + std::map<GURL, web_app::ExternallyManagedAppManager::InstallResult> + install_results, + std::map<GURL, bool> uninstall_results) { + DCHECK(install_results.empty()); + + if (MaybeRunPendingWebAppSynchronize()) + return; + + if (!uninstall_results.empty() && !app_changed_callback_.is_null()) { + app_changed_callback_.Run(); + } +} + void AppManagerImpl::CompleteLockScreenChromeAppInstall( int install_id, base::TimeTicks install_start_time, @@ -514,6 +739,9 @@ void AppManagerImpl::RemoveChromeAppFromLockScreenProfile( const std::string& app_id) { + // Note: web apps are removed by the `SynchronizeInstalledApps` call in + // `AddAppToLockScreenProfile` when a different app is set, instead of being + // explicitly removed here. if (app_id.empty()) return; @@ -535,8 +763,6 @@ const extensions::Extension* AppManagerImpl::GetChromeAppForLockScreenAppLaunch() { - // TODO(crbug.com/1006642): First check if app_id is an installed web app. - const extensions::ExtensionRegistry* extension_registry = extensions::ExtensionRegistry::Get(lock_screen_profile_); @@ -623,14 +849,40 @@ } } +void AppManagerImpl::RemoveAllWebAppsFromLockScreenProfile() { + if (is_synchronizing_installed_web_apps_) { + opt_app_id_pending_synchronize_ = std::string(); + return; + } + is_synchronizing_installed_web_apps_ = true; + + // CrOSAPI currently only supports one profile (the main profile) so we + // cannot use a lock screen app profile on the Lacros side. So, directly + // use the lock screen app profile on the Ash side here. + // TODO(crbug.com/1343692): Once lacros supports multiple profiles, use + // CrOSAPI to install to a lacros-based lock-screen app profile. + auto* lock_screen_provider = + web_app::WebAppProvider::GetForLocalAppsUnchecked(lock_screen_profile_); + DCHECK(lock_screen_provider); + lock_screen_provider->externally_managed_app_manager() + .SynchronizeInstalledApps( + /*desired_apps_install_options=*/{}, + web_app::ExternalInstallSource::kExternalLockScreen, + base::BindOnce(&AppManagerImpl::RecordLockScreenWebAppUninstall, + weak_ptr_factory_.GetWeakPtr())); +} + void AppManagerImpl::RemoveLockScreenAppDueToError() { if (state_ != State::kActive && state_ != State::kActivating) return; - RemoveChromeAppFromLockScreenProfile(lock_screen_app_id_); + std::string prev_lock_screen_app_id = lock_screen_app_id_; lock_screen_app_id_.clear(); state_ = State::kInactive; + RemoveChromeAppFromLockScreenProfile(prev_lock_screen_app_id); + RemoveAllWebAppsFromLockScreenProfile(); + if (!app_changed_callback_.is_null()) app_changed_callback_.Run(); }
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl.h b/chrome/browser/ash/lock_screen_apps/app_manager_impl.h index a389659..1e3b553 100644 --- a/chrome/browser/ash/lock_screen_apps/app_manager_impl.h +++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_ASH_LOCK_SCREEN_APPS_APP_MANAGER_IMPL_H_ #define CHROME_BROWSER_ASH_LOCK_SCREEN_APPS_APP_MANAGER_IMPL_H_ +#include <map> #include <string> #include "base/callback_forward.h" @@ -12,13 +13,20 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "chrome/browser/ash/lock_screen_apps/app_manager.h" +#include "chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.h" #include "chrome/browser/ash/note_taking_helper.h" +#include "chrome/browser/web_applications/externally_managed_app_manager.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" -#include "extensions/browser/uninstall_reason.h" #include "extensions/browser/unloaded_extension_reason.h" +#include "third_party/abseil-cpp/absl/types/optional.h" class Profile; +class GURL; + +namespace apps { +class AppUpdate; +} namespace base { class TickClock; @@ -33,14 +41,20 @@ class Extension; } // namespace extensions +namespace web_app { +struct ExternalInstallOptions; +} + namespace lock_screen_apps { class LockScreenProfileCreator; // The default implementation of lock_screen_apps::AppManager. -class AppManagerImpl : public AppManager, - public ash::NoteTakingHelper::Observer, - public extensions::ExtensionRegistryObserver { +class AppManagerImpl + : public AppManager, + public ash::NoteTakingHelper::Observer, + public apps::AppRegistryCacheObserverWithProfile::Delegate, + public extensions::ExtensionRegistryObserver { public: explicit AppManagerImpl(const base::TickClock* tick_clock); @@ -64,14 +78,19 @@ void OnExtensionUnloaded(content::BrowserContext* browser_context, const extensions::Extension* extension, extensions::UnloadedExtensionReason reason) override; - void OnExtensionUninstalled(content::BrowserContext* browser_context, - const extensions::Extension* extension, - extensions::UninstallReason reason) override; + + // apps::AppRegistryCacheObserverWithProfile::Delegate + void OnAppUpdate(const apps::AppUpdate& update, Profile* profile) override; // ash::NoteTakingHelper::Observer: void OnAvailableNoteTakingAppsUpdated() override; void OnPreferredNoteTakingAppUpdated(Profile* profile) override; + // Modify web app external install options for testing. + using OverrideInstallOptionsCallback = + void (*)(web_app::ExternalInstallOptions&); + OverrideInstallOptionsCallback& OverrideInstallOptions(); + private: enum class State { // The manager has not yet been initialized. @@ -139,6 +158,26 @@ // method. State AddAppToLockScreenProfile(const std::string& app_id); + // Reset synchronizing state, and run any pending web app synchronize + // operation. Returns whether an operation was run. + bool MaybeRunPendingWebAppSynchronize(); + + // Records a web app installation to the lock screen profile, updating + // internal state and metrics. + void RecordLockScreenWebAppInstall( + int install_id, + base::TimeTicks install_start_time, + std::map<GURL, web_app::ExternallyManagedAppManager::InstallResult> + install_results, + std::map<GURL, bool> uninstall_results); + + // Records a possible web app uninstallation from the lock screen profile, + // notifying listeners. + void RecordLockScreenWebAppUninstall( + std::map<GURL, web_app::ExternallyManagedAppManager::InstallResult> + install_results, + std::map<GURL, bool> uninstall_results); + // Uninstalls lock screen note taking app from the lock screen profile. void RemoveChromeAppFromLockScreenProfile(const std::string& app_id); @@ -158,6 +197,9 @@ void HandleLockScreenChromeAppUnload( extensions::UnloadedExtensionReason reason); + // Synchronizes state to remove all web apps from the lock screen profile. + void RemoveAllWebAppsFromLockScreenProfile(); + // Removes the lock screen app from the lock screen apps profile if the app // manager encountered an error - e.g. if the app unexpectedly got disabled in // the lock screen apps profile. @@ -173,6 +215,12 @@ const base::TickClock* tick_clock_; + // Because synchronize operations cannot overlap, track when one is running. + bool is_synchronizing_installed_web_apps_ = false; + // Because synchronize operations cannot overlap, hold on to the latest App ID + // (may be empty) waiting to synchronize. + absl::optional<std::string> opt_app_id_pending_synchronize_ = absl::nullopt; + base::ScopedObservation<extensions::ExtensionRegistry, extensions::ExtensionRegistryObserver> extensions_observation_{this}; @@ -184,10 +232,16 @@ ash::NoteTakingHelper::Observer> note_taking_helper_observation_{this}; - // To be called when the lock screen app availability changes. + absl::optional<apps::AppRegistryCacheObserverWithProfile> + primary_profile_app_registry_observer_; + + absl::optional<apps::AppRegistryCacheObserverWithProfile> + lock_screen_profile_app_registry_observer_; + + // Called when the lock screen app availability changes. base::RepeatingClosure app_changed_callback_; - // Counts Chrome app installs. Passed to app install callback as install + // Counts app installs. Passed to app install callback as install // request identifier to determine whether the completed install is stale. int install_count_ = 0;
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc index 7443da7..15160b7 100644 --- a/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc +++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl_unittest.cc
@@ -18,17 +18,26 @@ #include "base/callback_helpers.h" #include "base/check.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/json/json_file_value_serializer.h" #include "base/location.h" #include "base/memory/raw_ptr.h" +#include "base/notreached.h" #include "base/run_loop.h" +#include "base/strings/string_piece_forward.h" +#include "base/strings/utf_string_conversions.h" #include "base/task/sequenced_task_runner.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" #include "base/test/simple_test_tick_clock.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/traits_bag.h" #include "base/values.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/arc/session/arc_session_manager.h" #include "chrome/browser/ash/arc/test/test_arc_session_manager.h" #include "chrome/browser/ash/lock_screen_apps/fake_lock_screen_profile_creator.h" @@ -38,6 +47,15 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/external_install_options.h" +#include "chrome/browser/web_applications/test/fake_web_app_provider.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/user_display_mode.h" +#include "chrome/browser/web_applications/web_app_constants.h" +#include "chrome/browser/web_applications/web_app_install_finalizer.h" +#include "chrome/browser/web_applications/web_app_install_info.h" +#include "chrome/browser/web_applications/web_app_provider.h" +#include "chrome/browser/web_applications/web_app_sync_bridge.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -45,7 +63,14 @@ #include "chromeos/ash/components/dbus/concierge/concierge_client.h" #include "components/account_id/account_id.h" #include "components/prefs/pref_service.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/app_types.h" +#include "components/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/cpp/types_util.h" #include "components/user_manager/scoped_user_manager.h" +#include "components/webapps/browser/installable/installable_metrics.h" +#include "components/webapps/browser/uninstall_result_code.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_task_environment.h" #include "extensions/browser/disable_reason.h" #include "extensions/browser/event_router.h" @@ -53,6 +78,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/test_event_router.h" +#include "extensions/browser/uninstall_reason.h" #include "extensions/common/api/app_runtime.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" @@ -61,6 +87,8 @@ #include "extensions/common/value_builder.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/features.h" +#include "url/gurl.h" using extensions::DictionaryBuilder; using extensions::ListBuilder; @@ -148,41 +176,125 @@ bool expect_restore_action_state_ = true; }; -enum class TestAppType { kUnpackedChromeApp, kInternalChromeApp }; +enum class TestAppType { kUnpackedChromeApp, kInternalChromeApp, kWebApp }; struct TestApp { + const char* name = ""; + // GURLs cannot be statically initialized, so use a string. + const char* url = ""; const char* extension_id = ""; const char* version = ""; bool supports_lock_screen = false; }; -// TODO (crbug.com/1332379): Stop using real extension IDs here. // A lock screen capable app. const TestApp kLockScreenCapableApp{ + .name = "Lock Screen Capable App", + .url = "https://lockscreencapable.example.com", .extension_id = ash::NoteTakingHelper::kProdKeepExtensionId, .version = "1.0", .supports_lock_screen = true}; // An updated version of `kLockScreenCapable` (same ID). const TestApp kLockScreenCapableAppUpdated{ + .name = "Lock Screen Capable App Updated", + .url = "https://lockscreencapable.example.com", .extension_id = ash::NoteTakingHelper::kProdKeepExtensionId, .version = "1.1", .supports_lock_screen = true}; // Another lock screen capable app (different ID from `kLockScreenCapable`). const TestApp kLockScreenCapableApp2{ + .name = "Lock Screen Capable App 2", + .url = "https://lockscreencapable2.example.com", .extension_id = ash::NoteTakingHelper::kDevKeepExtensionId, .version = "1.0", .supports_lock_screen = true}; // A note-taking app that is not lock screen capable. const TestApp kNotLockScreenCapableApp{ + .name = "Not Lock Screen Capable App", + .url = "https://notlockscreencapable.example.com", .extension_id = ash::NoteTakingHelper::kNoteTakingWebAppIdTest, .version = "1.0", .supports_lock_screen = false}; +const TestApp* const kTestApps[] = { + &kLockScreenCapableApp, &kLockScreenCapableAppUpdated, + &kLockScreenCapableApp2, &kNotLockScreenCapableApp}; + +std::unique_ptr<WebAppInstallInfo> MakeWebAppInfo(const TestApp& test_app) { + GURL url(test_app.url); + auto info = std::make_unique<WebAppInstallInfo>(); + info->title = base::UTF8ToUTF16(test_app.name); + info->install_url = url; + info->start_url = url; + info->scope = url; + info->user_display_mode = web_app::UserDisplayMode::kStandalone; + info->note_taking_new_note_url = url; + if (test_app.supports_lock_screen) + info->lock_screen_start_url = url; + + return info; +} + +void ModifyExternalInstallOptions(web_app::ExternalInstallOptions& options) { + for (const TestApp* test_app : kTestApps) { + if (options.install_url == GURL(test_app->url) && + options.fallback_app_name == test_app->name) { + options.only_use_app_info_factory = true; + options.app_info_factory = base::BindLambdaForTesting( + [test_app]() { return MakeWebAppInfo(*test_app); }); + return; + } + } + NOTREACHED() << "Unrecognised app install " << options.install_url.spec() + << " " << options.fallback_app_name.value_or("(no name)"); +} + +apps::AppRegistryCache& app_registry_cache(Profile* profile) { + DCHECK( + apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)); + return apps::AppServiceProxyFactory::GetForProfile(profile) + ->AppRegistryCache(); +} + +bool IsInstalled(const std::string& app_id, Profile* profile) { + bool result = false; + app_registry_cache(profile).ForOneApp( + app_id, [&result](const apps::AppUpdate& update) { + result = apps_util::IsInstalled(update.Readiness()); + }); + return result; +} + +bool IsInstalledWebApp(const std::string& app_id, Profile* profile) { + bool result = false; + app_registry_cache(profile).ForOneApp( + app_id, [&result](const apps::AppUpdate& update) { + if (apps_util::IsInstalled(update.Readiness()) && + update.AppType() == apps::AppType::kWeb) { + result = true; + } + }); + return result; +} + +bool IsInstalledAndEnabled(const std::string& app_id, Profile* profile) { + bool result = false; + app_registry_cache(profile).ForOneApp( + app_id, [&result](const apps::AppUpdate& update) { + result = update.Readiness() == apps::Readiness::kReady; + }); + return result; +} class LockScreenAppManagerImplTest : public testing::TestWithParam<TestAppType> { public: LockScreenAppManagerImplTest() - : profile_manager_(TestingBrowserProcess::GetGlobal()) {} + : profile_manager_(TestingBrowserProcess::GetGlobal()) { + feature_list_.InitWithFeatures( + /*enabled_features=*/{features::kWebLockScreenApi, + blink::features::kWebAppManifestLockScreen}, + /*disabled_features=*/{}); + } LockScreenAppManagerImplTest(const LockScreenAppManagerImplTest&) = delete; LockScreenAppManagerImplTest& operator=(const LockScreenAppManagerImplTest&) = @@ -199,6 +311,8 @@ InitExtensionSystem(profile()); + InitWebAppsSystem(profile()); + // Initialize arc session manager - NoteTakingHelper expects it to be set. arc_session_manager_ = arc::CreateTestArcSessionManager( std::make_unique<arc::ArcSessionRunner>( @@ -210,6 +324,10 @@ std::make_unique<lock_screen_apps::FakeLockScreenProfileCreator>( &profile_manager_); lock_screen_profile_creator_->Initialize(); + // Ensure lock screen profiles don't spawn new processes to install apps. + lock_screen_profile_creator_->AddCreateProfileCallback(base::BindOnce( + &LockScreenAppManagerImplTest::OnLockScreenProfileCreated, + base::Unretained(this))); ResetAppManager(); } @@ -238,6 +356,14 @@ /*autoupdate_enabled=*/false); } + web_app::FakeWebAppProvider* InitWebAppsSystem(Profile* profile) { + auto* provider = web_app::FakeWebAppProvider::Get(profile); + provider->SetDefaultFakeSubsystems(); + provider->SetRunSubsystemStartupTasks(true); + web_app::test::AwaitStartWebAppProviderAndSubsystems(profile); + return provider; + } + void SetUpTestEventRouter() { LockScreenEventRouter* event_router = extensions::CreateAndUseTestEventRouter<LockScreenEventRouter>( @@ -247,11 +373,11 @@ event_router->AddEventObserver(event_observer_.get()); } - base::FilePath GetTestAppSourcePath(TestAppType appType, - Profile* profile, - const std::string& id, - const std::string& version) { - switch (appType) { + base::FilePath GetChromeAppSourcePath(TestAppType app_type, + Profile* profile, + const std::string& id, + const std::string& version) { + switch (app_type) { case TestAppType::kUnpackedChromeApp: return profile->GetPath().Append("Downloads").Append("app"); case TestAppType::kInternalChromeApp: @@ -260,19 +386,49 @@ ->install_directory() .Append(id) .Append(version); + case TestAppType::kWebApp: + return base::FilePath(); } } + bool PathExists(const std::string& app_id, Profile* profile) { + return PathExists(app_id, profile, GetParam()); + } + + bool PathExists(const std::string& app_id, + Profile* profile, + TestAppType type) { + // Web Apps don't have a path. + if (type == TestAppType::kWebApp) + return IsInstalled(app_id, profile); + + const extensions::Extension* app = + extensions::ExtensionRegistry::Get(profile)->GetExtensionById( + app_id, extensions::ExtensionRegistry::ENABLED); + return app && base::PathExists(app->path()); + } + + base::FilePath GetPath(const std::string& app_id, Profile* profile) { + // Web Apps don't have a path. + if (GetParam() == TestAppType::kWebApp) + return base::FilePath(); + + const extensions::Extension* app = + extensions::ExtensionRegistry::Get(profile)->GetExtensionById( + app_id, extensions::ExtensionRegistry::ENABLED); + return app ? app->path() : base::FilePath(); + } + base::FilePath GetExpectedLockScreenAppPath(const TestApp& test_app) { return GetExpectedLockScreenAppPathForAppType(GetParam(), profile(), test_app); } base::FilePath GetExpectedLockScreenAppPathForAppType( - TestAppType appType, + TestAppType app_type, Profile* original_profile, const TestApp& test_app) { - switch (appType) { + switch (app_type) { case TestAppType::kUnpackedChromeApp: return original_profile->GetPath().Append("Downloads").Append("app"); case TestAppType::kInternalChromeApp: @@ -281,39 +437,61 @@ ->install_directory() .Append(test_app.extension_id) .Append(std::string(test_app.version) + "_0"); + case TestAppType::kWebApp: + // Web apps don't have a path. + return base::FilePath(); } } - extensions::mojom::ManifestLocation GetAppLocation(TestAppType appType) { - switch (appType) { + extensions::mojom::ManifestLocation GetChromeAppLocation( + TestAppType app_type) { + switch (app_type) { case TestAppType::kUnpackedChromeApp: return extensions::mojom::ManifestLocation::kUnpacked; case TestAppType::kInternalChromeApp: return extensions::mojom::ManifestLocation::kInternal; + case TestAppType::kWebApp: + NOTREACHED(); + return extensions::mojom::ManifestLocation::kInvalidLocation; } } // Returns the ID of installed app. std::string InstallTestApp(const TestApp& test_app) { - return InstallTestAppWithType(GetParam(), profile(), test_app); + return InstallTestAppWithType(test_app, GetParam(), profile()); } // Returns the ID of installed app. - std::string InstallTestAppWithType(TestAppType type, - Profile* profile, - const TestApp& test_app) { - scoped_refptr<const extensions::Extension> extension = - MakeChromeApp(type, profile, test_app); - extensions::ExtensionSystem::Get(profile) - ->extension_service() - ->AddExtension(extension.get()); - return extension->id(); + std::string InstallTestAppWithType(const TestApp& test_app, + TestAppType type, + Profile* profile) { + if (type == TestAppType::kUnpackedChromeApp || + type == TestAppType::kInternalChromeApp) { + scoped_refptr<const extensions::Extension> extension = + MakeChromeApp(test_app, type, profile); + extensions::ExtensionSystem::Get(profile) + ->extension_service() + ->AddExtension(extension.get()); + return extension->id(); + } else if (type == TestAppType::kWebApp) { + return web_app::test::InstallWebApp( + profile, MakeWebAppInfo(test_app), + /*overwrite_existing_manifest_fields=*/true, + webapps::WebappInstallSource::MENU_BROWSER_TAB); + } else { + NOTREACHED(); + return std::string(); + } } - scoped_refptr<const extensions::Extension> MakeChromeApp( - TestAppType appType, - Profile* profile, - const TestApp& test_app) { + scoped_refptr<const extensions::Extension> MakeChromeApp(TestApp test_app, + TestAppType app_type, + Profile* profile) { + if (app_type == TestAppType::kWebApp) { + NOTREACHED(); + return nullptr; + } + std::string id = test_app.extension_id; std::string version = test_app.version; bool supports_lock_screen = test_app.supports_lock_screen; @@ -341,14 +519,14 @@ .Set("action_handlers", std::move(action_handlers)); base::FilePath extension_path = - GetTestAppSourcePath(appType, profile, id, version); + GetChromeAppSourcePath(app_type, profile, id, version); scoped_refptr<const extensions::Extension> extension = extensions::ExtensionBuilder() .SetManifest(manifest_builder.Build()) .SetID(id) .SetPath(extension_path) - .SetLocation(GetAppLocation(appType)) + .SetLocation(GetChromeAppLocation(app_type)) .Build(); // Create the app path with required files - app manager *will* attempt to @@ -380,6 +558,7 @@ TestingProfile* profile = profile_manager_.CreateTestingProfile("secondary_profile"); InitExtensionSystem(profile); + InitWebAppsSystem(profile); return profile; } @@ -406,16 +585,16 @@ app_manager()->Initialize(profile, lock_screen_profile_creator_.get()); if (create_lock_screen_profile) CreateLockScreenProfile(); - app_manager()->Start( - base::BindRepeating(&LockScreenAppManagerImplTest::OnNoteTakingChanged, - base::Unretained(this))); + app_manager()->Start(base::BindRepeating( + &LockScreenAppManagerImplTest::OnNoteTakingAppChanged, + base::Unretained(this))); } void RestartLockScreenAppManager() { app_manager()->Stop(); - app_manager()->Start( - base::BindRepeating(&LockScreenAppManagerImplTest::OnNoteTakingChanged, - base::Unretained(this))); + app_manager()->Start(base::BindRepeating( + &LockScreenAppManagerImplTest::OnNoteTakingAppChanged, + base::Unretained(this))); } void CreateLockScreenProfile() { @@ -428,6 +607,12 @@ needs_lock_screen_event_router_ = true; } + void OnLockScreenProfileCreated() { + // Skip if profile creation failed. + if (LockScreenProfile()) + InitWebAppsSystem(LockScreenProfile()); + } + TestingProfile* profile() { return profile_; } Profile* LockScreenProfile() { @@ -438,27 +623,52 @@ void ResetAppManager() { app_manager_ = std::make_unique<AppManagerImpl>(&tick_clock_); + // Prevent lock screen web app installs from attempting to fetch URLs. + app_manager_->OverrideInstallOptions() = &ModifyExternalInstallOptions; } int note_taking_changed_count() const { return note_taking_changed_count_; } void ResetNoteTakingChangedCount() { note_taking_changed_count_ = 0; } - // Waits for a round trip between file task runner used by the profile's - // extension service and the main thread - used to ensure that all pending - // file runner task finish, - void RunExtensionServiceTaskRunner(Profile* profile) { + void AwaitNoteTakingChanged() { + base::RunLoop run_loop; + on_note_taking_app_changed_ = run_loop.QuitClosure(); + run_loop.Run(); + on_note_taking_app_changed_.Reset(); + } + + void AwaitNoteTakingChangedCount(int count) { + base::RunLoop run_loop; + // Post a task to ensure we don't race with something changing the count. + if (note_taking_changed_count_ >= count) { + base::SequencedTaskRunnerHandle::Get()->PostTaskAndReply( + FROM_HERE, base::DoNothing(), run_loop.QuitClosure()); + run_loop.Run(); + return; + } + + on_note_taking_app_changed_ = base::BindLambdaForTesting([&]() { + if (note_taking_changed_count_ >= count) + run_loop.Quit(); + }); + run_loop.Run(); + on_note_taking_app_changed_.Reset(); + } + + // Waits for a round trip between file task runner used by the extension + // service and the main thread - used to ensure that all pending file runner + // task finish, + void RunExtensionServiceTaskRunner() { base::RunLoop run_loop; extensions::GetExtensionFileTaskRunner()->PostTaskAndReply( FROM_HERE, base::DoNothing(), run_loop.QuitClosure()); run_loop.Run(); } - bool IsInstallAsync() { - return GetParam() != TestAppType::kUnpackedChromeApp; - } + bool IsUninstallAsync() { return GetParam() == TestAppType::kWebApp; } - int NoteTakingChangedCountOnStart() { return IsInstallAsync() ? 1 : 0; } + int NoteTakingChangedCountOnStart() { return 1; } LockScreenEventObserver* event_observer() { return event_observer_.get(); } @@ -466,13 +676,22 @@ return lock_screen_profile_creator_.get(); } + // Doubly-parameterised test for changing from the `GetParam()` TestAppType to + // `new_type` during app activation. Defined below. + void TestChangeAppTypeWhileActivating(TestAppType new_type); + protected: base::SimpleTestTickClock tick_clock_; std::unique_ptr<lock_screen_apps::FakeLockScreenProfileCreator> lock_screen_profile_creator_; private: - void OnNoteTakingChanged() { ++note_taking_changed_count_; } + void OnNoteTakingAppChanged() { + ++note_taking_changed_count_; + if (on_note_taking_app_changed_) { + on_note_taking_app_changed_.Run(); + } + } TestingProfile* CreatePrimaryProfile() { DCHECK(!scoped_user_manager_) << "there can be only one primary profile"; @@ -486,8 +705,9 @@ } content::BrowserTaskEnvironment task_environment_; - + base::test::ScopedFeatureList feature_list_; ash::ScopedCrosSettingsTestHelper cros_settings_test_helper_; + base::RepeatingClosure on_note_taking_app_changed_; std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; @@ -499,42 +719,28 @@ std::unique_ptr<arc::ArcServiceManager> arc_service_manager_; std::unique_ptr<arc::ArcSessionManager> arc_session_manager_; - std::unique_ptr<AppManager> app_manager_; + std::unique_ptr<AppManagerImpl> app_manager_; bool needs_lock_screen_event_router_ = false; int note_taking_changed_count_ = 0; }; -bool IsInstalled(const std::string& app_id, Profile* profile) { - const extensions::Extension* app = - extensions::ExtensionRegistry::Get(profile)->GetExtensionById( - app_id, extensions::ExtensionRegistry::EVERYTHING); - return app; -} - -bool IsInstalledAndEnabled(const std::string& app_id, Profile* profile) { - const extensions::Extension* app = - extensions::ExtensionRegistry::Get(profile)->GetExtensionById( - app_id, extensions::ExtensionRegistry::ENABLED); - return app; -} - -bool PathExists(const std::string& app_id, Profile* profile) { - const extensions::Extension* app = - extensions::ExtensionRegistry::Get(profile)->GetExtensionById( - app_id, extensions::ExtensionRegistry::ENABLED); - return app && base::PathExists(app->path()); -} - -base::FilePath GetPath(const std::string& app_id, Profile* profile) { - const extensions::Extension* app = - extensions::ExtensionRegistry::Get(profile)->GetExtensionById( - app_id, extensions::ExtensionRegistry::ENABLED); - return app ? app->path() : base::FilePath(); -} - absl::optional<std::string> GetVersion(const std::string& app_id, Profile* profile) { + std::string app_name; + app_registry_cache(profile).ForOneApp( + app_id, [&app_name](const apps::AppUpdate& update) { + if (apps_util::IsInstalled(update.Readiness()) && + update.AppType() == apps::AppType::kWeb) { + app_name = update.Name(); + } + }); + for (const TestApp* app : kTestApps) { + if (app->name == app_name) { + return app->version; + } + } + const extensions::Extension* app = extensions::ExtensionRegistry::Get(profile)->GetExtensionById( app_id, extensions::ExtensionRegistry::ENABLED); @@ -544,18 +750,34 @@ } void UnloadApp(const std::string& app_id, Profile* profile) { + // Web Apps cannot be unloaded, so locally uninstall instead. + if (IsInstalledWebApp(app_id, profile)) { + web_app::WebAppProvider::GetForTest(profile) + ->sync_bridge() + .SetAppIsLocallyInstalled(app_id, false); + return; + } + extensions::ExtensionSystem::Get(profile) ->extension_service() ->UnloadExtension(app_id, extensions::UnloadedExtensionReason::UPDATE); } void SimulateAppCrash(const std::string& app_id, Profile* profile) { + // Web Apps don't have an equivalent, so just skip them. extensions::ExtensionSystem::Get(profile) ->extension_service() ->TerminateExtension(app_id); } void DisableApp(const std::string& app_id, Profile* profile) { + if (IsInstalledWebApp(app_id, profile)) { + web_app::WebAppProvider::GetForTest(profile) + ->sync_bridge() + .SetAppIsDisabled(app_id, true); + return; + } + extensions::ExtensionSystem::Get(profile) ->extension_service() ->DisableExtension(app_id, @@ -563,20 +785,51 @@ } void UninstallApp(const std::string& app_id, Profile* profile) { + if (IsInstalledWebApp(app_id, profile)) { + base::RunLoop run_loop; + web_app::WebAppProvider::GetForTest(profile) + ->install_finalizer() + .UninstallExternalWebApp( + app_id, web_app::WebAppManagement::Type::kSystem, + webapps::WebappUninstallSource::kExternalLockScreen, + base::BindLambdaForTesting( + [&run_loop](webapps::UninstallResultCode code) { + DCHECK(code == webapps::UninstallResultCode::kSuccess); + run_loop.Quit(); + })); + run_loop.Run(); + return; + } + extensions::ExtensionSystem::Get(profile) ->extension_service() ->UninstallExtension(app_id, extensions::UNINSTALL_REASON_FOR_TESTING, nullptr); } +std::string ToString(TestAppType type) { + switch (type) { + case TestAppType::kUnpackedChromeApp: + return "UnpackedChromeApp"; + case TestAppType::kInternalChromeApp: + return "InternalChromeApp"; + case TestAppType::kWebApp: + return "WebApp"; + } +} + +std::string ParamToString(testing::TestParamInfo<TestAppType> param) { + return ToString(param.param); +} + } // namespace -INSTANTIATE_TEST_SUITE_P(Unpacked, +INSTANTIATE_TEST_SUITE_P(/* no prefix */, LockScreenAppManagerImplTest, - ::testing::Values(TestAppType::kUnpackedChromeApp)); -INSTANTIATE_TEST_SUITE_P(Internal, - LockScreenAppManagerImplTest, - ::testing::Values(TestAppType::kInternalChromeApp)); + ::testing::Values(TestAppType::kUnpackedChromeApp, + TestAppType::kInternalChromeApp, + TestAppType::kWebApp), + ParamToString); TEST_P(LockScreenAppManagerImplTest, StartAddsAppToTarget) { std::string app_id = AddTestAppWithLockScreenSupport( @@ -585,9 +838,10 @@ InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); EXPECT_EQ(0, note_taking_changed_count()); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -607,11 +861,12 @@ EXPECT_EQ(0, note_taking_changed_count()); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); + // Chrome apps are uninstalled at Stop() but web apps are uninstalled only + // when a different app is installed. + EXPECT_EQ(IsInstalled(app_id, LockScreenProfile()), + GetParam() == TestAppType::kWebApp); - EXPECT_FALSE(IsInstalled(app_id, LockScreenProfile())); - - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(PathExists(app_id, profile())); } @@ -621,7 +876,7 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/false); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(0, note_taking_changed_count()); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); @@ -630,14 +885,13 @@ EXPECT_FALSE(IsInstalled(app_id, LockScreenProfile())); app_manager()->Stop(); + EXPECT_EQ(0, note_taking_changed_count()); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); - EXPECT_FALSE(IsInstalled(app_id, LockScreenProfile())); - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(PathExists(app_id, profile())); } @@ -649,9 +903,9 @@ InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); EXPECT_EQ(0, note_taking_changed_count()); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -669,7 +923,7 @@ ash::NoteTakingHelper::Get()->SetPreferredAppEnabledOnLockScreen(profile(), false); - EXPECT_EQ(1, note_taking_changed_count()); + AwaitNoteTakingChangedCount(2); ResetNoteTakingChangedCount(); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); @@ -682,8 +936,7 @@ EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(PathExists(app_id, profile())); } @@ -693,7 +946,7 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/false); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(0, note_taking_changed_count()); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); @@ -706,9 +959,10 @@ EXPECT_EQ(1, note_taking_changed_count()); ResetNoteTakingChangedCount(); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -729,8 +983,7 @@ EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(PathExists(app_id, profile())); } @@ -744,9 +997,10 @@ InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); EXPECT_EQ(0, note_taking_changed_count()); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -763,11 +1017,12 @@ ash::NoteTakingHelper::Get()->SetPreferredApp(profile(), app_id_2); - EXPECT_EQ(1, note_taking_changed_count()); + EXPECT_EQ(IsUninstallAsync() ? 1 : 2, note_taking_changed_count()); ResetNoteTakingChangedCount(); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -789,8 +1044,7 @@ EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(PathExists(app_id_2, profile())); EXPECT_TRUE(PathExists(app_id_1, profile())); @@ -808,7 +1062,7 @@ // Initialize app manager - the note taking should be disabled initially // because the preferred app is not lock-screen-capable. InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(0, note_taking_changed_count()); EXPECT_EQ(false, app_manager()->IsLockScreenAppAvailable()); @@ -820,8 +1074,10 @@ ResetNoteTakingChangedCount(); // If test app is installed asynchronously. the app won't be enabled on // lock screen until extension service task runner tasks are run. - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); + + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -849,8 +1105,7 @@ EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); // Make sure original app paths are not deleted. EXPECT_TRUE(PathExists(app_id, profile())); @@ -858,11 +1113,16 @@ } TEST_P(LockScreenAppManagerImplTest, LockScreenNoteTakingReloadedWhileStarted) { + // TODO(crbug.com/1368944): Fix crash on trybots then re-enable this test. + if (GetParam() == TestAppType::kWebApp) + return; + std::string app_id = AddTestAppWithLockScreenSupport( kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -881,7 +1141,9 @@ UnloadApp(app_id, profile()); - EXPECT_EQ(1, note_taking_changed_count()); + AwaitNoteTakingChangedCount(2); + RunExtensionServiceTaskRunner(); + EXPECT_EQ(2, note_taking_changed_count()); ResetNoteTakingChangedCount(); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); @@ -896,9 +1158,10 @@ EXPECT_EQ(1, note_taking_changed_count()); ResetNoteTakingChangedCount(); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -918,77 +1181,33 @@ EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(PathExists(app_id, profile())); } -TEST_P(LockScreenAppManagerImplTest, - NoteTakingAppChangeToUnpackedWhileActivating) { +void LockScreenAppManagerImplTest::TestChangeAppTypeWhileActivating( + TestAppType new_type) { std::string app_id_1 = AddTestAppWithLockScreenSupport( kLockScreenCapableApp, /*enable_on_lock_screen=*/true); - std::string app_id_2 = InstallTestAppWithType( - TestAppType::kUnpackedChromeApp, profile(), kLockScreenCapableApp2); + std::string app_id_2 = + InstallTestAppWithType(kLockScreenCapableApp2, new_type, profile()); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); EXPECT_EQ(0, note_taking_changed_count()); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); - - ash::NoteTakingHelper::Get()->SetPreferredApp(profile(), app_id_2); - - EXPECT_TRUE(app_manager()->IsLockScreenAppAvailable()); - EXPECT_EQ(app_id_2, app_manager()->GetLockScreenAppId()); - EXPECT_EQ(1, note_taking_changed_count()); - ResetNoteTakingChangedCount(); - - RunExtensionServiceTaskRunner(LockScreenProfile()); - - EXPECT_EQ(0, note_taking_changed_count()); - - EXPECT_TRUE(app_manager()->IsLockScreenAppAvailable()); - EXPECT_EQ(app_id_2, app_manager()->GetLockScreenAppId()); - - ASSERT_TRUE(IsInstalledAndEnabled(app_id_2, LockScreenProfile())); - EXPECT_TRUE(PathExists(app_id_2, LockScreenProfile())); - - EXPECT_EQ( - GetExpectedLockScreenAppPathForAppType(TestAppType::kUnpackedChromeApp, - profile(), kLockScreenCapableApp2), - GetPath(app_id_2, LockScreenProfile())); - - app_manager()->Stop(); - - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); - - EXPECT_TRUE(PathExists(app_id_1, profile())); - EXPECT_TRUE(PathExists(app_id_2, profile())); -} - -TEST_P(LockScreenAppManagerImplTest, - NoteTakingAppChangeToInternalWhileActivating) { - std::string app_id_1 = AddTestAppWithLockScreenSupport( - kLockScreenCapableApp, /*enable_on_lock_screen=*/true); - - std::string app_id_2 = InstallTestAppWithType( - TestAppType::kInternalChromeApp, profile(), kLockScreenCapableApp2); - - InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - - EXPECT_EQ(0, note_taking_changed_count()); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); ash::NoteTakingHelper::Get()->SetPreferredApp(profile(), app_id_2); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - EXPECT_EQ(1, note_taking_changed_count()); + EXPECT_EQ(note_taking_changed_count(), 1); ResetNoteTakingChangedCount(); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); + AwaitNoteTakingChangedCount(1); EXPECT_EQ(1, note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -996,20 +1215,28 @@ EXPECT_EQ(app_id_2, app_manager()->GetLockScreenAppId()); ASSERT_TRUE(IsInstalledAndEnabled(app_id_2, LockScreenProfile())); - EXPECT_TRUE(PathExists(app_id_2, LockScreenProfile())); - - EXPECT_EQ( - GetExpectedLockScreenAppPathForAppType(TestAppType::kInternalChromeApp, - profile(), kLockScreenCapableApp2), - GetPath(app_id_2, LockScreenProfile())); + EXPECT_TRUE(PathExists(app_id_2, LockScreenProfile(), new_type)); app_manager()->Stop(); - RunExtensionServiceTaskRunner(LockScreenProfile()); - RunExtensionServiceTaskRunner(profile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(PathExists(app_id_1, profile())); - EXPECT_TRUE(PathExists(app_id_2, profile())); + EXPECT_TRUE(PathExists(app_id_2, profile(), new_type)); +} + +TEST_P(LockScreenAppManagerImplTest, + NoteTakingAppChangeToUnpackedWhileActivating) { + TestChangeAppTypeWhileActivating(TestAppType::kUnpackedChromeApp); +} + +TEST_P(LockScreenAppManagerImplTest, + NoteTakingAppChangeToInternalWhileActivating) { + TestChangeAppTypeWhileActivating(TestAppType::kInternalChromeApp); +} + +TEST_P(LockScreenAppManagerImplTest, NoteTakingAppChangeToWebWhileActivating) { + TestChangeAppTypeWhileActivating(TestAppType::kWebApp); } TEST_P(LockScreenAppManagerImplTest, ShutdownWhenStarted) { @@ -1017,19 +1244,24 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(IsInstalled(app_id, LockScreenProfile())); } TEST_P(LockScreenAppManagerImplTest, LaunchAppWhenEnabled) { + // TODO(crbug.com/1006642): Enable test when web apps can be launched. + if (GetParam() == TestAppType::kWebApp) + return; + set_needs_lock_screen_event_router(); std::string app_id = AddTestAppWithLockScreenSupport( kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); ASSERT_EQ(app_id, app_manager()->GetLockScreenAppId()); @@ -1046,6 +1278,10 @@ } TEST_P(LockScreenAppManagerImplTest, LaunchAppWithFalseRestoreLastActionState) { + // TODO(crbug.com/1006642): Enable test when web apps can be launched. + if (GetParam() == TestAppType::kWebApp) + return; + set_needs_lock_screen_event_router(); profile()->GetPrefs()->SetBoolean(prefs::kRestoreLastLockScreenNote, false); @@ -1054,7 +1290,7 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); ASSERT_EQ(app_id, app_manager()->GetLockScreenAppId()); @@ -1078,7 +1314,7 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/false); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); EXPECT_FALSE(app_manager()->LaunchLockScreenApp()); EXPECT_TRUE(event_observer()->launched_apps().empty()); @@ -1097,9 +1333,10 @@ InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/false); EXPECT_EQ(0, note_taking_changed_count()); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -1131,9 +1368,10 @@ EXPECT_EQ(1, note_taking_changed_count()); ResetNoteTakingChangedCount(); - EXPECT_EQ(!IsInstallAsync(), app_manager()->IsLockScreenAppAvailable()); + EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(NoteTakingChangedCountOnStart(), note_taking_changed_count()); ResetNoteTakingChangedCount(); @@ -1162,7 +1400,7 @@ EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); CreateLockScreenProfile(); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); EXPECT_EQ(0, note_taking_changed_count()); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); @@ -1207,13 +1445,17 @@ } TEST_P(LockScreenAppManagerImplTest, ReloadLockScreenAppAfterAppCrash) { + // TODO(crbug.com/1006642): Enable test when web apps can be launched. + if (GetParam() == TestAppType::kWebApp) + return; + set_needs_lock_screen_event_router(); std::string app_id = AddTestAppWithLockScreenSupport( kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); ResetNoteTakingChangedCount(); SimulateAppCrash(app_id, LockScreenProfile()); @@ -1238,13 +1480,18 @@ } TEST_P(LockScreenAppManagerImplTest, AppReloadFailure) { + // TODO(crbug.com/1006642): Enable test when web apps can be launched. + if (GetParam() == TestAppType::kWebApp) + return; + set_needs_lock_screen_event_router(); std::string app_id = AddTestAppWithLockScreenSupport( kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); ResetNoteTakingChangedCount(); SimulateAppCrash(app_id, LockScreenProfile()); @@ -1264,6 +1511,7 @@ EXPECT_FALSE(app_manager()->LaunchLockScreenApp()); // Make sure that note taking is not reported as available any longer. + AwaitNoteTakingChangedCount(1); EXPECT_EQ(1, note_taking_changed_count()); ResetNoteTakingChangedCount(); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); @@ -1276,10 +1524,13 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); ResetNoteTakingChangedCount(); UninstallApp(app_id, LockScreenProfile()); + RunExtensionServiceTaskRunner(); + AwaitNoteTakingChangedCount(1); // Note taking should be reported to be unavailable if the app was uninstalled // from the lock screen profile. @@ -1294,7 +1545,8 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); ResetNoteTakingChangedCount(); SimulateAppCrash(app_id, LockScreenProfile()); @@ -1306,6 +1558,7 @@ // Prevent app reload. UninstallApp(app_id, LockScreenProfile()); + AwaitNoteTakingChangedCount(1); // Note taking should be reported to be unavailable if the app was uninstalled // from the lock screen profile. @@ -1320,12 +1573,13 @@ kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + AwaitNoteTakingChangedCount(NoteTakingChangedCountOnStart()); + RunExtensionServiceTaskRunner(); ResetNoteTakingChangedCount(); DisableApp(app_id, LockScreenProfile()); - EXPECT_EQ(1, note_taking_changed_count()); + AwaitNoteTakingChangedCount(IsUninstallAsync() ? 2 : 1); EXPECT_FALSE(app_manager()->IsLockScreenAppAvailable()); EXPECT_TRUE(app_manager()->GetLockScreenAppId().empty()); EXPECT_FALSE(app_manager()->LaunchLockScreenApp()); @@ -1336,13 +1590,17 @@ TEST_P(LockScreenAppManagerImplTest, RestartingAppManagerAfterLockScreenAppDisabled) { + // TODO(crbug.com/1006642): Enable test when web apps can be launched. + if (GetParam() == TestAppType::kWebApp) + return; + set_needs_lock_screen_event_router(); std::string app_id = AddTestAppWithLockScreenSupport( kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); ResetNoteTakingChangedCount(); DisableApp(app_id, LockScreenProfile()); @@ -1352,7 +1610,7 @@ // Restarting the app manager should enable lock screen app again. RestartLockScreenAppManager(); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(app_manager()->IsLockScreenAppAvailable()); EXPECT_EQ(app_id, app_manager()->GetLockScreenAppId()); @@ -1364,13 +1622,17 @@ } TEST_P(LockScreenAppManagerImplTest, AppNotReloadedAfterRepeatedCrashes) { + // TODO(crbug.com/1006642): Enable test when web apps can be launched. + if (GetParam() == TestAppType::kWebApp) + return; + set_needs_lock_screen_event_router(); std::string app_id = AddTestAppWithLockScreenSupport( kLockScreenCapableApp, /*enable_on_lock_screen=*/true); InitializeAndStartAppManager(profile(), /*create_lock_screen_profile=*/true); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); ResetNoteTakingChangedCount(); // Simulate lock screen note app crash and launch few times. @@ -1392,7 +1654,7 @@ // Restarting the app manager should enable lock screen app again. RestartLockScreenAppManager(); - RunExtensionServiceTaskRunner(LockScreenProfile()); + RunExtensionServiceTaskRunner(); EXPECT_TRUE(app_manager()->IsLockScreenAppAvailable()); EXPECT_EQ(app_id, app_manager()->GetLockScreenAppId());
diff --git a/chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.cc b/chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.cc new file mode 100644 index 0000000..3adebd4 --- /dev/null +++ b/chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.cc
@@ -0,0 +1,44 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.h" + +#include "base/check.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" + +class Profile; + +namespace apps { + +class AppUpdate; + +AppRegistryCacheObserverWithProfile::AppRegistryCacheObserverWithProfile( + Delegate* delegate, + Profile* profile) + : delegate_(delegate), profile_(profile) { + DCHECK(delegate); + DCHECK(profile); + DCHECK( + apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)); + app_registry_observation_.Observe( + &apps::AppServiceProxyFactory::GetForProfile(profile) + ->AppRegistryCache()); +} + +AppRegistryCacheObserverWithProfile::~AppRegistryCacheObserverWithProfile() { + app_registry_observation_.Reset(); +} + +void AppRegistryCacheObserverWithProfile::OnAppUpdate( + const apps::AppUpdate& update) { + delegate_->OnAppUpdate(update, profile_); +} + +void AppRegistryCacheObserverWithProfile::OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) { + app_registry_observation_.Reset(); +} + +} // namespace apps
diff --git a/chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.h b/chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.h new file mode 100644 index 0000000..7b3fed5 --- /dev/null +++ b/chrome/browser/ash/lock_screen_apps/app_registry_cache_observer_with_profile.h
@@ -0,0 +1,57 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_LOCK_SCREEN_APPS_APP_REGISTRY_CACHE_OBSERVER_WITH_PROFILE_H_ +#define CHROME_BROWSER_ASH_LOCK_SCREEN_APPS_APP_REGISTRY_CACHE_OBSERVER_WITH_PROFILE_H_ + +#include "base/memory/raw_ptr.h" +#include "base/scoped_observation.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" + +class Profile; + +namespace apps { + +class AppUpdate; + +// Observes an AppRegistryCache and holds an associated profile to pass on to +// the delegate on observed calls, so the delegate can differentiate calls from +// multiple profiles. +class AppRegistryCacheObserverWithProfile + : public apps::AppRegistryCache::Observer { + public: + class Delegate { + public: + // Forwards calls from `apps::AppRegistryCache::Observer` with an additional + // `profile`. + virtual void OnAppUpdate(const apps::AppUpdate& update, + Profile* profile) = 0; + }; + + // Delegate must outlive this. + explicit AppRegistryCacheObserverWithProfile(Delegate* observer, + Profile* profile); + ~AppRegistryCacheObserverWithProfile() override; + + AppRegistryCacheObserverWithProfile( + const AppRegistryCacheObserverWithProfile&) = delete; + AppRegistryCacheObserverWithProfile& operator=( + const AppRegistryCacheObserverWithProfile&) = delete; + + // apps::AppRegistryCache::Observer + void OnAppUpdate(const apps::AppUpdate& update) override; + void OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) override; + + private: + const base::raw_ptr<Delegate> delegate_; + const base::raw_ptr<Profile> profile_; + base::ScopedObservation<apps::AppRegistryCache, + apps::AppRegistryCache::Observer> + app_registry_observation_{this}; +}; + +} // namespace apps + +#endif // CHROME_BROWSER_ASH_LOCK_SCREEN_APPS_APP_REGISTRY_CACHE_OBSERVER_WITH_PROFILE_H_
diff --git a/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc b/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc index f924510..c8c1cf0 100644 --- a/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc +++ b/chrome/browser/ash/lock_screen_apps/lock_screen_apps.cc
@@ -132,7 +132,7 @@ auto allowed_apps = std::make_unique<std::set<std::string>>(); for (const base::Value& app_value : - allowed_lock_screen_apps_value->GetListDeprecated()) { + allowed_lock_screen_apps_value->GetList()) { if (!app_value.is_string()) { LOG(ERROR) << "Invalid app ID value " << app_value; continue;
diff --git a/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc b/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc index 8815571..1632f39 100644 --- a/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc +++ b/chrome/browser/ash/lock_screen_apps/note_taking_browsertest.cc
@@ -313,6 +313,8 @@ session_manager::SessionState::ACTIVE); session_manager::SessionManager::Get()->SetSessionState( session_manager::SessionState::LOCKED); + LockScreenAppsEnabledWaiter().WaitForState( + ash::mojom::TrayActionState::kAvailable); profile()->GetPrefs()->SetBoolean(prefs::kRestoreLastLockScreenNote, false);
diff --git a/chrome/browser/ash/login/saml/saml_browsertest.cc b/chrome/browser/ash/login/saml/saml_browsertest.cc index 54bb987..a7752df0 100644 --- a/chrome/browser/ash/login/saml/saml_browsertest.cc +++ b/chrome/browser/ash/login/saml/saml_browsertest.cc
@@ -107,6 +107,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" +#include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/common/features/feature_channel.h" #include "google_apis/gaia/fake_gaia.h" #include "google_apis/gaia/gaia_constants.h" @@ -502,11 +503,11 @@ // WebContents. WaitForGaiaPageLoad(); - content::WebContents* gaia_frame_web_contents = - signin::GetAuthFrameWebContents(GetLoginUI()->GetWebContents(), - gaia_frame_parent_); + extensions::WebViewGuest* gaia_guest = signin::GetAuthWebViewGuest( + GetLoginUI()->GetWebContents(), gaia_frame_parent_); + ASSERT_TRUE(gaia_guest); content::NavigationController* gaia_frame_navigation_controller = - &(gaia_frame_web_contents->GetController()); + &gaia_guest->GetController(); // Start observing before initiating SAML sign-in. content::DOMMessageQueue message_queue(GetLoginUI()->GetWebContents());
diff --git a/chrome/browser/ash/login/test/cryptohome_mixin.cc b/chrome/browser/ash/login/test/cryptohome_mixin.cc index 386b906..3cb1c3eb 100644 --- a/chrome/browser/ash/login/test/cryptohome_mixin.cc +++ b/chrome/browser/ash/login/test/cryptohome_mixin.cc
@@ -23,7 +23,7 @@ void CryptohomeMixin::MarkUserAsExisting(const AccountId& user) { auto account_id = cryptohome::CreateAccountIdentifierFromAccountId(user); - if (FakeUserDataAuthClient::TestApi::Get() != nullptr) { + if (FakeUserDataAuthClient::TestApi::Get()) { FakeUserDataAuthClient::TestApi::Get()->AddExistingUser( std::move(account_id)); } else {
diff --git a/chrome/browser/ash/login/test/cryptohome_mixin.h b/chrome/browser/ash/login/test/cryptohome_mixin.h index 21fce63..62fe635 100644 --- a/chrome/browser/ash/login/test/cryptohome_mixin.h +++ b/chrome/browser/ash/login/test/cryptohome_mixin.h
@@ -10,13 +10,15 @@ #include "base/gtest_prod_util.h" #include "chrome/test/base/mixin_based_in_process_browser_test.h" #include "chromeos/ash/components/dbus/cryptohome/rpc.pb.h" +#include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h" #include "components/account_id/account_id.h" namespace ash { // Mixin that acts as a broker between tests // and FakeUserDataAuthClient, handling all interactions and transformations -class CryptohomeMixin : public InProcessBrowserTestMixin { +class CryptohomeMixin : public InProcessBrowserTestMixin, + public ash::FakeUserDataAuthClient::TestApi { public: explicit CryptohomeMixin(InProcessBrowserTestMixinHost* host); CryptohomeMixin(const CryptohomeMixin&) = delete;
diff --git a/chrome/browser/ash/login/users/avatar/user_image_file_selector.h b/chrome/browser/ash/login/users/avatar/user_image_file_selector.h index 27d9dff6..1782f9c 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_file_selector.h +++ b/chrome/browser/ash/login/users/avatar/user_image_file_selector.h
@@ -46,7 +46,7 @@ base::OnceCallback<void(void)> canceled_cb_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; }; } // namespace ash
diff --git a/chrome/browser/ash/login/webview_login_browsertest.cc b/chrome/browser/ash/login/webview_login_browsertest.cc index ca97623..c17434f 100644 --- a/chrome/browser/ash/login/webview_login_browsertest.cc +++ b/chrome/browser/ash/login/webview_login_browsertest.cc
@@ -1950,11 +1950,12 @@ // Only care for notifications originating from the frame which is // displaying gaia. content::WebContents* main_web_contents = GetLoginUI()->GetWebContents(); - content::WebContents* gaia_frame_web_contents = - signin::GetAuthFrameWebContents(main_web_contents, gaia_frame_parent_); + content::RenderFrameHost* gaia_rfh = + signin::GetAuthFrame(main_web_contents, gaia_frame_parent_); LoginHandler* login_handler = content::Details<LoginNotificationDetails>(details)->handler(); - if (login_handler->web_contents() != gaia_frame_web_contents) + if (login_handler->web_contents() != + content::WebContents::FromRenderFrameHost(gaia_rfh)) return false; gaia_frame_login_handler_ = login_handler;
diff --git a/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc b/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc index d669f07..f49dd50 100644 --- a/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc +++ b/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc
@@ -87,7 +87,7 @@ bool FindInListValue(const std::string& needle, const base::Value* haystack) { if (!haystack->is_list()) return false; - return base::Contains(haystack->GetListDeprecated(), base::Value(needle)); + return base::Contains(haystack->GetList(), base::Value(needle)); } } // namespace
diff --git a/chrome/browser/ash/release_notes/release_notes_notification.cc b/chrome/browser/ash/release_notes/release_notes_notification.cc index 81381b2..073bf75 100644 --- a/chrome/browser/ash/release_notes/release_notes_notification.cc +++ b/chrome/browser/ash/release_notes/release_notes_notification.cc
@@ -8,6 +8,7 @@ #include "ash/constants/notifier_catalogs.h" #include "ash/public/cpp/notification_utils.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "base/strings/string_util.h" @@ -19,7 +20,6 @@ #include "chrome/grit/generated_resources.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "components/services/app_service/public/cpp/app_launch_util.h" -#include "components/vector_icons/vector_icons.h" #include "content/public/browser/notification_service.h" #include "ui/base/l10n/l10n_util.h" #include "ui/chromeos/devicetype_utils.h" @@ -73,7 +73,7 @@ base::BindRepeating( &ReleaseNotesNotification::HandleClickShowNotification, weak_ptr_factory_.GetWeakPtr())), - vector_icons::kNotificationExploreIcon, + kNotificationHelpAppIcon, message_center::SystemNotificationWarningLevel::NORMAL); SystemNotificationHelper::GetInstance()->Display( *release_notes_available_notification_);
diff --git a/chrome/browser/ash/system_logs/shill_log_source.cc b/chrome/browser/ash/system_logs/shill_log_source.cc index 9568793..baacad95 100644 --- a/chrome/browser/ash/system_logs/shill_log_source.cc +++ b/chrome/browser/ash/system_logs/shill_log_source.cc
@@ -84,7 +84,7 @@ const base::Value* devices = result->FindListKey(shill::kDevicesProperty); if (devices) { - for (const base::Value& device : devices->GetListDeprecated()) { + for (const base::Value& device : devices->GetList()) { std::string path = GetString(&device); if (path.empty()) continue; @@ -98,7 +98,7 @@ const base::Value* services = result->FindListKey(shill::kServicesProperty); if (services) { - for (const base::Value& service : services->GetListDeprecated()) { + for (const base::Value& service : services->GetList()) { std::string path = GetString(&service); if (path.empty()) continue; @@ -135,7 +135,7 @@ if (!ip_configs) return; - for (const base::Value& ip_config : ip_configs->GetListDeprecated()) { + for (const base::Value& ip_config : ip_configs->GetList()) { std::string ip_config_path = GetString(&ip_config); if (ip_config_path.empty()) continue;
diff --git a/chrome/browser/ash/web_applications/help_app/help_app_discover_tab_notification.cc b/chrome/browser/ash/web_applications/help_app/help_app_discover_tab_notification.cc index 993d825fb..f9ffac4a 100644 --- a/chrome/browser/ash/web_applications/help_app/help_app_discover_tab_notification.cc +++ b/chrome/browser/ash/web_applications/help_app/help_app_discover_tab_notification.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ash/web_applications/help_app/help_app_discover_tab_notification.h" #include "ash/public/cpp/notification_utils.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "chrome/browser/ash/system_web_apps/types/system_web_app_type.h" @@ -14,7 +15,6 @@ #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "components/services/app_service/public/cpp/app_launch_util.h" -#include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" namespace ash { @@ -41,7 +41,7 @@ base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( base::BindRepeating(&HelpAppDiscoverTabNotification::OnClick, weak_ptr_factory_.GetWeakPtr())), - vector_icons::kNotificationExploreIcon, + kNotificationHelpAppIcon, message_center::SystemNotificationWarningLevel::NORMAL); SystemNotificationHelper::GetInstance()->Display(*notification);
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc index 34c4020fa..eeeca51 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc
@@ -171,12 +171,12 @@ bool selected) { switch (topic_source) { case (ash::AmbientModeTopicSource::kGooglePhotos): { - ash::PersonalAlbum* personal_album = FindPersonalAlbumById(id); - if (!personal_album) { + ash::PersonalAlbum* target_personal_album = FindPersonalAlbumById(id); + if (!target_personal_album) { mojo::ReportBadMessage("Invalid album id."); return; } - personal_album->selected = selected; + target_personal_album->selected = selected; // For Google Photos, we will populate the |selected_album_ids| with IDs // of selected albums.
diff --git a/chrome/browser/ash/web_applications/terminal_source.cc b/chrome/browser/ash/web_applications/terminal_source.cc index b85c720d..ca881353 100644 --- a/chrome/browser/ash/web_applications/terminal_source.cc +++ b/chrome/browser/ash/web_applications/terminal_source.cc
@@ -155,11 +155,11 @@ // Refresh the $i8n{themeColor} replacement for css files. if (base::EndsWith(path, ".css", base::CompareCase::INSENSITIVE_ASCII)) { - GURL url; + GURL contents_url; absl::optional<SkColor> opener_background_color; content::WebContents* contents = wc_getter.Run(); if (contents) { - url = contents->GetVisibleURL(); + contents_url = contents->GetVisibleURL(); TabStripModel* tab_strip; int tab_index; extensions::ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, @@ -172,7 +172,7 @@ } replacements_["themeColor"] = base::EscapeForHTML(guest_os::GetTerminalSettingBackgroundColor( - profile_, url, opener_background_color)); + profile_, contents_url, opener_background_color)); } base::ThreadPool::PostTask(
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index 36030b0..b76f49c 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -1091,18 +1091,18 @@ request.set_match_behavior( ::attestation::DeleteKeysRequest::MATCH_BEHAVIOR_PREFIX); - auto callback = base::BindOnce( + auto clear_platform_keys_callback = base::BindOnce( &ChromeBrowsingDataRemoverDelegate::OnClearPlatformKeys, weak_ptr_factory_.GetWeakPtr(), CreateTaskCompletionClosure(TracingDataType::kTpmAttestationKeys)); ash::AttestationClient::Get()->DeleteKeys( request, base::BindOnce( - [](decltype(callback) cb, + [](decltype(clear_platform_keys_callback) cb, const ::attestation::DeleteKeysReply& reply) { std::move(cb).Run(reply.status() == ::attestation::STATUS_SUCCESS); }, - std::move(callback))); + std::move(clear_platform_keys_callback))); } } #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/chromeos/extensions/echo_private/echo_private_api.cc b/chrome/browser/chromeos/extensions/echo_private/echo_private_api.cc index 3c796af..00f75592 100644 --- a/chrome/browser/chromeos/extensions/echo_private/echo_private_api.cc +++ b/chrome/browser/chromeos/extensions/echo_private/echo_private_api.cc
@@ -146,8 +146,8 @@ chromeos::echo_offer::RemoveEmptyValueDicts(dict); PrefService* local_state = g_browser_process->local_state(); - DictionaryPrefUpdate offer_update(local_state, prefs::kEchoCheckedOffers); - offer_update->SetKey("echo." + service_id, base::Value(std::move(dict))); + ScopedDictPrefUpdate offer_update(local_state, prefs::kEchoCheckedOffers); + offer_update->Set("echo." + service_id, std::move(dict)); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/chromeos/extensions/external_cache_impl_unittest.cc b/chrome/browser/chromeos/extensions/external_cache_impl_unittest.cc index af547ff..fbc14ef7 100644 --- a/chrome/browser/chromeos/extensions/external_cache_impl_unittest.cc +++ b/chrome/browser/chromeos/extensions/external_cache_impl_unittest.cc
@@ -197,12 +197,12 @@ base::FilePath temp_dir(CreateTempDir()); base::FilePath temp_file2 = temp_dir.Append("b.crx"); CreateFile(temp_file2); - extensions::CRXFileInfo crx_info(temp_file2, - extensions::GetTestVerifierFormat()); - crx_info.extension_id = kTestExtensionId2; - crx_info.expected_version = base::Version("2"); + extensions::CRXFileInfo crx_info_v2(temp_file2, + extensions::GetTestVerifierFormat()); + crx_info_v2.extension_id = kTestExtensionId2; + crx_info_v2.expected_version = base::Version("2"); external_cache.OnExtensionDownloadFinished( - crx_info, true, GURL(), + crx_info_v2, true, GURL(), extensions::ExtensionDownloaderDelegate::PingResult(), std::set<int>(), extensions::ExtensionDownloaderDelegate::InstallCallback()); @@ -228,12 +228,12 @@ base::FilePath temp_file4 = temp_dir.Append("d.crx"); CreateFile(temp_file4); { - extensions::CRXFileInfo crx_info(temp_file4, - extensions::GetTestVerifierFormat()); - crx_info.extension_id = kTestExtensionId4; - crx_info.expected_version = base::Version("4"); + extensions::CRXFileInfo crx_info_v4(temp_file4, + extensions::GetTestVerifierFormat()); + crx_info_v4.extension_id = kTestExtensionId4; + crx_info_v4.expected_version = base::Version("4"); external_cache.OnExtensionDownloadFinished( - crx_info, true, GURL(), + crx_info_v4, true, GURL(), extensions::ExtensionDownloaderDelegate::PingResult(), std::set<int>(), extensions::ExtensionDownloaderDelegate::InstallCallback()); }
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc index be5f4b1b..dd9683f 100644 --- a/chrome/browser/chromeos/extensions/input_method_api.cc +++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -396,11 +396,10 @@ const auto params = SetSettings::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params.get()); - DictionaryPrefUpdate update( + ScopedDictPrefUpdate update( Profile::FromBrowserContext(browser_context())->GetPrefs(), prefs::kLanguageInputMethodSpecificSettings); - update->GetDict().SetByDottedPath(params->engine_id, - params->settings.ToValue()); + update->SetByDottedPath(params->engine_id, params->settings.ToValue()); // The router will only send the event to extensions that are listening. extensions::EventRouter* router =
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_apitest.cc b/chrome/browser/chromeos/extensions/wm/wm_desks_private_apitest.cc index 95db134..93112078 100644 --- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_apitest.cc
@@ -25,13 +25,7 @@ }; // TODO(crbug.com/1370233): Re-enable this test -#if BUILDFLAG(IS_LINUX) -#define MAYBE_WmDesksPrivateApiTest DISABLED_WmDesksPrivateApiTest -#else -#define MAYBE_WmDesksPrivateApiTest WmDesksPrivateApiTest -#endif -IN_PROC_BROWSER_TEST_F(MAYBE_WmDesksPrivateApiTest, - MAYBE_WmDesksPrivateApiTest) { +IN_PROC_BROWSER_TEST_F(WmDesksPrivateApiTest, DISABLED_WmDesksPrivateApiTest) { // This loads and runs an extension from // chrome/test/data/extensions/api_test/wm_desks_private. ASSERT_TRUE(RunExtensionTest("wm_desks_private"));
diff --git a/chrome/browser/content_index/content_index_provider_impl.cc b/chrome/browser/content_index/content_index_provider_impl.cc index 886b5f3..f4e902d5 100644 --- a/chrome/browser/content_index/content_index_provider_impl.cc +++ b/chrome/browser/content_index/content_index_provider_impl.cc
@@ -41,7 +41,6 @@ using offline_items_collection::LaunchLocation; using offline_items_collection::OfflineItem; using offline_items_collection::OfflineItemFilter; -using offline_items_collection::OfflineItemSchedule; namespace {
diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc index 9784c21a..4e2d706 100644 --- a/chrome/browser/devtools/devtools_file_helper.cc +++ b/chrome/browser/devtools/devtools_file_helper.cc
@@ -125,7 +125,7 @@ platform_util::GetTopLevel(web_contents->GetNativeView()), nullptr); } - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; SelectedCallback selected_callback_; CanceledCallback canceled_callback_; };
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn index 3ba1e60..ab95043d 100644 --- a/chrome/browser/download/android/BUILD.gn +++ b/chrome/browser/download/android/BUILD.gn
@@ -46,7 +46,6 @@ "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogCoordinator.java", "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogProperties.java", "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogViewBinder.java", - "java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java", "java/src/org/chromium/chrome/browser/download/dialogs/MixedContentDownloadDialog.java", "java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinator.java", "java/src/org/chromium/chrome/browser/download/home/DownloadManagerUiConfig.java",
diff --git a/chrome/browser/download/android/download_dialog_bridge.cc b/chrome/browser/download/android/download_dialog_bridge.cc index da991fc..47a559a8 100644 --- a/chrome/browser/download/android/download_dialog_bridge.cc +++ b/chrome/browser/download/android/download_dialog_bridge.cc
@@ -16,9 +16,6 @@ #include "components/prefs/pref_service.h" #include "ui/android/window_android.h" -// Default minimum file size in kilobyte to trigger download later feature. -const int64_t kDownloadLaterDefaultMinFileSizeKb = 204800; - // ----------------------------------------------------------------------------- // DownloadDialogResult DownloadDialogResult::DownloadDialogResult() = default; @@ -86,15 +83,13 @@ static_cast<int>(dialog_type), base::android::ConvertUTF8ToJavaString(env, suggested_path.AsUTF8Unsafe()), - false /*supports_later_dialog*/, is_incognito); + is_incognito); } void DownloadDialogBridge::OnComplete( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jstring>& returned_path, - jboolean on_wifi, - jlong start_time) { + const base::android::JavaParamRef<jstring>& returned_path) { DownloadDialogResult dialog_result; dialog_result.location_result = DownloadLocationDialogResult::USER_CONFIRMED; dialog_result.file_path = base::FilePath( @@ -147,35 +142,9 @@ pref_service->SetFilePath(prefs::kSaveFileDefaultDirectory, path); } -// static -jlong JNI_DownloadDialogBridge_GetDownloadLaterMinFileSize(JNIEnv* env) { - return DownloadDialogBridge::GetDownloadLaterMinFileSize(); -} - -// static -jboolean JNI_DownloadDialogBridge_ShouldShowDateTimePicker(JNIEnv* env) { - return DownloadDialogBridge::ShouldShowDateTimePicker(); -} - jboolean JNI_DownloadDialogBridge_IsLocationDialogManaged(JNIEnv* env) { PrefService* pref_service = ProfileManager::GetActiveUserProfile()->GetOriginalProfile()->GetPrefs(); return pref_service->IsManagedPreference(prefs::kPromptForDownload); } - -// static -long DownloadDialogBridge::GetDownloadLaterMinFileSize() { - return base::GetFieldTrialParamByFeatureAsInt( - download::features::kDownloadLater, - download::features::kDownloadLaterMinFileSizeKb, - kDownloadLaterDefaultMinFileSizeKb); -} - -// static -bool DownloadDialogBridge::ShouldShowDateTimePicker() { - return base::GetFieldTrialParamByFeatureAsBool( - download::features::kDownloadLater, - download::features::kDownloadLaterShowDateTimePicker, - /*default_value=*/true); -}
diff --git a/chrome/browser/download/android/download_dialog_bridge.h b/chrome/browser/download/android/download_dialog_bridge.h index cd1a2f5..e9c1c52 100644 --- a/chrome/browser/download/android/download_dialog_bridge.h +++ b/chrome/browser/download/android/download_dialog_bridge.h
@@ -33,9 +33,6 @@ public: using DialogCallback = base::OnceCallback<void(DownloadDialogResult)>; - static long GetDownloadLaterMinFileSize(); - static bool ShouldShowDateTimePicker(); - DownloadDialogBridge(); DownloadDialogBridge(const DownloadDialogBridge&) = delete; DownloadDialogBridge& operator=(const DownloadDialogBridge&) = delete; @@ -54,9 +51,7 @@ void OnComplete(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jstring>& returned_path, - jboolean on_wifi, - jlong start_time); + const base::android::JavaParamRef<jstring>& returned_path); void OnCanceled(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
diff --git a/chrome/browser/download/android/download_manager_service.cc b/chrome/browser/download/android/download_manager_service.cc index 3b3f8dc..5db6604 100644 --- a/chrome/browser/download/android/download_manager_service.cc +++ b/chrome/browser/download/android/download_manager_service.cc
@@ -61,7 +61,6 @@ using base::android::JavaParamRef; using base::android::ScopedJavaLocalRef; using offline_items_collection::android::OfflineItemBridge; -using OfflineItemSchedule = offline_items_collection::OfflineItemSchedule; namespace { @@ -161,9 +160,6 @@ otr_profile_id = profile->GetOTRProfileID().ConvertToJavaOTRProfileID(env); } - absl::optional<OfflineItemSchedule> offline_item_schedule; - auto j_offline_item_schedule = - OfflineItemBridge::CreateOfflineItemSchedule(env, offline_item_schedule); return Java_DownloadInfo_createDownloadInfo( env, ConvertUTF8ToJavaString(env, item->GetGuid()), ConvertUTF8ToJavaString(env, item->GetFileNameToReportUser().value()), @@ -181,8 +177,7 @@ item->GetLastAccessTime().ToJavaTime(), item->IsDangerous(), static_cast<int>( OfflineItemUtils::ConvertDownloadInterruptReasonToFailState( - item->GetLastReason())), - j_offline_item_schedule); + item->GetLastReason()))); } static jlong JNI_DownloadManagerService_Init(JNIEnv* env,
diff --git a/chrome/browser/download/android/java/res/values-v17/styles.xml b/chrome/browser/download/android/java/res/values-v17/styles.xml index 8234e42..267a3e4d 100644 --- a/chrome/browser/download/android/java/res/values-v17/styles.xml +++ b/chrome/browser/download/android/java/res/values-v17/styles.xml
@@ -11,8 +11,4 @@ <style name="TextAppearance.DownloadDialogTitle" parent="TextAppearance.AlertDialogTitleStyle"> <item name="android:textSize">20sp</item> </style> - <style name="ThemeOverlay.DownloadDateTimePickerDialog" parent="ThemeOverlay.BrowserUI.ModalDialog"> - <item name="android:windowMinWidthMajor">@null</item> - <item name="android:windowMinWidthMinor">@null</item> - </style> </resources>
diff --git a/chrome/browser/download/android/java/res/xml/download_preferences.xml b/chrome/browser/download/android/java/res/xml/download_preferences.xml index 81007d440..9f964af 100644 --- a/chrome/browser/download/android/java/res/xml/download_preferences.xml +++ b/chrome/browser/download/android/java/res/xml/download_preferences.xml
@@ -13,12 +13,6 @@ android:negativeButtonText="@null" /> <org.chromium.components.browser_ui.settings.ChromeSwitchPreference - android:key="download_later_prompt_enabled" - android:title="@string/download_later_prompt_enabled_title" - android:summaryOn="@string/text_on" - android:summaryOff="@string/text_off" /> - - <org.chromium.components.browser_ui.settings.ChromeSwitchPreference android:key="location_prompt_enabled" android:title="@string/download_location_prompt_enabled_title" android:summaryOn="@string/text_on"
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java index 8b91238..7b9120a 100644 --- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java
@@ -28,11 +28,6 @@ /** * Glues download dialogs UI code and handles the communication to download native backend. - * When {@link ChromeFeatureList#DOWNLOAD_LATER} is enabled, the following dialogs will be shown in - * a sequence. - * Download later dialog ==> (optional) Download date time picker ==> Download location dialog - * When {@link ChromeFeatureList#DOWNLOAD_LATER} is disabled, only the download location dialog will - * be shown. */ public class DownloadDialogBridge implements DownloadLocationDialogController { private static final long INVALID_START_TIME = -1; @@ -49,12 +44,6 @@ private String mSuggestedPath; private PrefService mPrefService; - // Whether the user clicked the edit text to open download location dialog. - private boolean mEditLocation; - - // Whether to show the edit location text in download later dialog. - private boolean mShowEditLocation; - public DownloadDialogBridge( long nativeDownloadDialogBridge, DownloadLocationDialogCoordinator locationDialog) { mNativeDownloadDialogBridge = nativeDownloadDialogBridge; @@ -79,7 +68,7 @@ @CalledByNative private void showDialog(WindowAndroid windowAndroid, long totalBytes, @ConnectionType int connectionType, @DownloadLocationDialogType int dialogType, - String suggestedPath, boolean supportsLaterDialog, boolean isIncognito) { + String suggestedPath, boolean isIncognito) { mWindowAndroid = windowAndroid; Activity activity = windowAndroid.getActivity().get(); if (activity == null) { @@ -88,7 +77,6 @@ } DownloadDirectoryProvider.getInstance().getAllDirectoriesOptions((dirs) -> { - mShowEditLocation = (dirs != null && dirs.size() > 1); ModalDialogManager modalDialogManager = ((ModalDialogManagerHolder) activity).getModalDialogManager(); @@ -104,15 +92,14 @@ } showDialog(activity, modalDialogManager, getPrefService(), totalBytes, connectionType, - suggestedDialogType, suggestedPath, supportsLaterDialog, isIncognito); + suggestedDialogType, suggestedPath, isIncognito); }); } @VisibleForTesting void showDialog(Context context, ModalDialogManager modalDialogManager, PrefService prefService, long totalBytes, @ConnectionType int connectionType, - @DownloadLocationDialogType int dialogType, String suggestedPath, - boolean supportsLaterDialog, boolean isIncognito) { + @DownloadLocationDialogType int dialogType, String suggestedPath, boolean isIncognito) { mContext = context; mModalDialogManager = modalDialogManager; mPrefService = prefService; @@ -129,8 +116,8 @@ private void onComplete() { if (mNativeDownloadDialogBridge == 0) return; - DownloadDialogBridgeJni.get().onComplete(mNativeDownloadDialogBridge, - DownloadDialogBridge.this, mSuggestedPath, false, INVALID_START_TIME); + DownloadDialogBridgeJni.get().onComplete( + mNativeDownloadDialogBridge, DownloadDialogBridge.this, mSuggestedPath); } private void onCancel() { @@ -153,27 +140,12 @@ DownloadLocationDialogMetrics.recordDownloadLocationSuggestionChoice(isSelected); } - // The location dialog is triggered automatically, complete the flow. - if (!mEditLocation) { - onComplete(); - return; - } - - // The location dialog is triggered by the "Edit" text. Show the download later dialog - // again. - mEditLocation = false; + onComplete(); } @Override public void onDownloadLocationDialogCanceled() { - if (!mEditLocation) { - onCancel(); - return; - } - - // The location dialog is triggered by the "Edit" text. Show the download later dialog - // again. - mEditLocation = false; + onCancel(); } void setPrefServiceForTesting(PrefService prefService) { @@ -224,23 +196,17 @@ return DownloadDialogBridgeJni.get().isLocationDialogManaged(); } - public static boolean shouldShowDateTimePicker() { - return DownloadDialogBridgeJni.get().shouldShowDateTimePicker(); - } - private static PrefService getPrefService() { return UserPrefs.get(Profile.getLastUsedRegularProfile()); } @NativeMethods public interface Natives { - void onComplete(long nativeDownloadDialogBridge, DownloadDialogBridge caller, - String returnedPath, boolean onWifi, long startTime); + void onComplete( + long nativeDownloadDialogBridge, DownloadDialogBridge caller, String returnedPath); void onCanceled(long nativeDownloadDialogBridge, DownloadDialogBridge caller); String getDownloadDefaultDirectory(); void setDownloadAndSaveFileDefaultDirectory(String directory); - long getDownloadLaterMinFileSize(); - boolean shouldShowDateTimePicker(); boolean isLocationDialogManaged(); } }
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridgeUnitTest.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridgeUnitTest.java index 087f88719..7bcd14c 100644 --- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridgeUnitTest.java +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridgeUnitTest.java
@@ -30,7 +30,6 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.download.dialogs.DownloadLocationDialogCoordinator; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.prefs.PrefService; import org.chromium.net.ConnectionType; @@ -100,7 +99,7 @@ private void showDialog() { mBridge.showDialog(mActivity, mModalDialogManager, mPrefService, TOTAL_BYTES, - CONNECTION_TYPE, LOCATION_DIALOG_TYPE, SUGGESTED_PATH, true, isIncognito); + CONNECTION_TYPE, LOCATION_DIALOG_TYPE, SUGGESTED_PATH, isIncognito); } private void locationDialogWillReturn(String newPath) { @@ -114,8 +113,7 @@ } @Test - @Features.DisableFeatures({ChromeFeatureList.DOWNLOAD_LATER}) - public void testShowDialog_disableDownloadLater() { + public void testShowDialog() { doAnswer(invocation -> { mBridge.onDownloadLocationDialogComplete(NEW_SUGGESTED_PATH); return null; @@ -128,9 +126,7 @@ verify(mLocationDialog) .showDialog(any(), any(), eq(TOTAL_BYTES), eq(LOCATION_DIALOG_TYPE), eq(SUGGESTED_PATH), eq(isIncognito)); - verify(mNativeMock) - .onComplete(anyLong(), any(), eq(NEW_SUGGESTED_PATH), eq(false), - eq(INVALID_START_TIME)); + verify(mNativeMock).onComplete(anyLong(), any(), eq(NEW_SUGGESTED_PATH)); } @Test @@ -140,8 +136,7 @@ } @Test - @Features.DisableFeatures({ChromeFeatureList.DOWNLOAD_LATER}) - public void testLocationDialogCanceled_disableDownloadLater() { + public void testLocationDialogCanceled() { doAnswer(invocation -> { mBridge.onDownloadLocationDialogCanceled(); return null;
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java index 087eaeff..225e806 100644 --- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadInfo.java
@@ -17,7 +17,6 @@ import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItem.Progress; import org.chromium.components.offline_items_collection.OfflineItemProgressUnit; -import org.chromium.components.offline_items_collection.OfflineItemSchedule; import org.chromium.components.offline_items_collection.OfflineItemState; import org.chromium.components.offline_items_collection.OfflineItemVisuals; import org.chromium.components.offline_items_collection.PendingState; @@ -64,7 +63,6 @@ @FailState private final int mFailState; private final boolean mShouldPromoteOrigin; - private final OfflineItemSchedule mSchedule; private DownloadInfo(Builder builder) { mUrl = builder.mUrl == null ? GURL.emptyGURL() : builder.mUrl; @@ -105,7 +103,6 @@ mPendingState = builder.mPendingState; mFailState = builder.mFailState; mShouldPromoteOrigin = builder.mShouldPromoteOrigin; - mSchedule = builder.mSchedule; } @NonNull @@ -246,10 +243,6 @@ return mShouldPromoteOrigin; } - public OfflineItemSchedule getOfflineItemSchedule() { - return mSchedule; - } - /** * Helper method to build a {@link DownloadInfo} from an {@link OfflineItem}. * @param item The {@link OfflineItem} to mimic. @@ -316,8 +309,7 @@ .setIcon(visuals == null ? null : visuals.icon) .setPendingState(item.pendingState) .setFailState(item.failState) - .setShouldPromoteOrigin(item.promoteOrigin) - .setOfflineItemSchedule(item.schedule); + .setShouldPromoteOrigin(item.promoteOrigin); } /** @@ -359,7 +351,6 @@ @FailState private int mFailState; private boolean mShouldPromoteOrigin; - private OfflineItemSchedule mSchedule; public Builder setUrl(GURL url) { mUrl = url; @@ -522,11 +513,6 @@ return this; } - public Builder setOfflineItemSchedule(OfflineItemSchedule schedule) { - mSchedule = schedule; - return this; - } - public DownloadInfo build() { return new DownloadInfo(this); } @@ -567,8 +553,7 @@ .setIcon(downloadInfo.getIcon()) .setPendingState(downloadInfo.getPendingState()) .setFailState(downloadInfo.getFailState()) - .setShouldPromoteOrigin(downloadInfo.getShouldPromoteOrigin()) - .setOfflineItemSchedule(downloadInfo.getOfflineItemSchedule()); + .setShouldPromoteOrigin(downloadInfo.getShouldPromoteOrigin()); return builder; } } @@ -579,7 +564,7 @@ OTRProfileID otrProfileId, int state, int percentCompleted, boolean isPaused, boolean hasUserGesture, boolean isResumable, boolean isParallelDownload, GURL originalUrl, GURL referrerUrl, long timeRemainingInMs, long lastAccessTime, - boolean isDangerous, @FailState int failState, OfflineItemSchedule schedule) { + boolean isDangerous, @FailState int failState) { String remappedMimeType = MimeUtils.remapGenericMimeType(mimeType, url.getSpec(), fileName); Progress progress = new Progress(bytesReceived, @@ -606,7 +591,6 @@ .setIsDangerous(isDangerous) .setUrl(url) .setFailState(failState) - .setOfflineItemSchedule(schedule) .build(); } }
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java deleted file mode 100644 index dcef4c7..0000000 --- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadTimePickerDialog.java +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2020 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.download.dialogs; - -import android.app.TimePickerDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.widget.Button; -import android.widget.TimePicker; - -import androidx.annotation.NonNull; - -import org.chromium.chrome.browser.download.R; - -/** - * A {@link TimePickerDialog} subclass for download time selection. Works on all Android versions. - */ -class DownloadTimePickerDialog extends TimePickerDialog { - interface Controller { - void onDownloadTimePicked(int hourOfDay, int minute); - void onDownloadTimePickerCanceled(); - } - - private int mHourOfDay; - private int mMinute; - private final Controller mController; - private boolean mButtonClicked; - - DownloadTimePickerDialog( - Context context, @NonNull Controller controller, int hourOfDay, int minute) { - super(context, R.style.ThemeOverlay_DownloadDateTimePickerDialog, null, hourOfDay, minute, - false /*is24HourView*/); - mHourOfDay = hourOfDay; - mMinute = minute; - mController = controller; - setOnDismissListener((dialogInterface) -> { - if (mButtonClicked) return; - mController.onDownloadTimePickerCanceled(); - }); - } - - // TimePickerDialog overrides. - @Override - public void show() { - super.show(); - - // Override button click listeners. Notice the default behavior varies on different Android - // versions. - Button button = getButton(DialogInterface.BUTTON_POSITIVE); - assert button != null; - button.setText(R.string.download_date_time_picker_next_text); - button.setOnClickListener((view) -> { - mButtonClicked = true; - mController.onDownloadTimePicked(mHourOfDay, mMinute); - dismiss(); - }); - - button = getButton(DialogInterface.BUTTON_NEGATIVE); - button.setText(R.string.cancel); - button.setOnClickListener((view) -> { - mButtonClicked = true; - mController.onDownloadTimePickerCanceled(); - dismiss(); - }); - } - - @Override - public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { - mHourOfDay = hourOfDay; - mMinute = minute; - } -} \ No newline at end of file
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h index df1cd91..b1dd0621 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.h +++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -257,7 +257,6 @@ RequestConfirmation_Android); FRIEND_TEST_ALL_PREFIXES(ChromeDownloadManagerDelegateTest, CancelAllEphemeralWarnings); - FRIEND_TEST_ALL_PREFIXES(DownloadLaterTriggerTest, DownloadLaterTrigger); using IdCallbackVector = std::vector<content::DownloadIdCallback>;
diff --git a/chrome/browser/download/download_file_picker.h b/chrome/browser/download/download_file_picker.h index f7de56c..f6ad7db 100644 --- a/chrome/browser/download/download_file_picker.h +++ b/chrome/browser/download/download_file_picker.h
@@ -70,7 +70,7 @@ ConfirmationCallback file_selected_callback_; // For managing select file dialogs. - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; // The item to be downloaded. raw_ptr<download::DownloadItem> download_item_;
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index a4b81c3..04d7b8a 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc
@@ -407,14 +407,6 @@ #endif } -bool DownloadPrefs::PromptDownloadLater() const { - return false; -} - -bool DownloadPrefs::HasDownloadLaterPromptShown() const { - return false; -} - bool DownloadPrefs::IsDownloadPathManaged() const { return download_path_.IsManaged(); }
diff --git a/chrome/browser/download/download_prefs.h b/chrome/browser/download/download_prefs.h index cec4a7e..20f096a9 100644 --- a/chrome/browser/download/download_prefs.h +++ b/chrome/browser/download/download_prefs.h
@@ -93,13 +93,6 @@ // to choose another download location). bool PromptForDownload() const; - // Returns whether to prompt download later dialog to let the user choose - // download time. - bool PromptDownloadLater() const; - - // Returns whether the download later prompt is ever shown to the user. - bool HasDownloadLaterPromptShown() const; - // Returns true if the download path preference is managed. bool IsDownloadPathManaged() const;
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc index 51835ef..5f8bb99a 100644 --- a/chrome/browser/download/download_prefs_unittest.cc +++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -690,7 +690,7 @@ #endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_ANDROID) -// Verfies the returned value of PromptForDownload() +// Verifies the returned value of PromptForDownload() // when prefs::kPromptForDownload is managed by enterprise policy, TEST(DownloadPrefsTest, ManagedPromptForDownload) { content::BrowserTaskEnvironment task_environment_;
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc index 4924a94..6de8ef2 100644 --- a/chrome/browser/download/download_target_determiner.cc +++ b/chrome/browser/download/download_target_determiner.cc
@@ -1119,8 +1119,7 @@ // The user may still be prompted even if this pref is disabled due to, for // example, there being an unresolvable filename conflict or the target path // is not writeable. - return (download_prefs_->PromptForDownload() || - download_prefs_->PromptDownloadLater()) + return download_prefs_->PromptForDownload() ? DownloadConfirmationReason::PREFERENCE : DownloadConfirmationReason::NONE; }
diff --git a/chrome/browser/download/internal/android/BUILD.gn b/chrome/browser/download/internal/android/BUILD.gn index f6adc7a..e2f2453 100644 --- a/chrome/browser/download/internal/android/BUILD.gn +++ b/chrome/browser/download/internal/android/BUILD.gn
@@ -166,7 +166,6 @@ "java/res/drawable/group_card_footer_curved_border.xml", "java/res/drawable/group_card_header_curved_border.xml", "java/res/drawable/group_card_item_border.xml", - "java/res/drawable/ic_file_download_scheduled_24dp.xml", "java/res/drawable/infobar_download_complete_animation.xml", "java/res/layout/download_home_tabs.xml", "java/res/layout/download_home_toolbar.xml",
diff --git a/chrome/browser/download/internal/android/java/res/drawable/ic_file_download_scheduled_24dp.xml b/chrome/browser/download/internal/android/java/res/drawable/ic_file_download_scheduled_24dp.xml deleted file mode 100644 index c00172c..0000000 --- a/chrome/browser/download/internal/android/java/res/drawable/ic_file_download_scheduled_24dp.xml +++ /dev/null
@@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2020 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24"> - <group> - <clip-path - android:pathData="M19,10H15V4H9V10H5L12,17L19,10V10ZM5,19V21H19V19H5V19Z" - android:fillType="evenOdd"/> - <path - android:pathData="M0,0h24v24h-24z" - android:fillColor="@color/modern_blue_600"/> - </group> - <group> - <clip-path - android:pathData="M10,8h14v14h-14z"/> - <path - android:pathData="M17.5,15.5m-7.5,0a7.5,7.5 0,1 1,15 0a7.5,7.5 0,1 1,-15 0" - android:fillColor="@color/infobar_background_color"/> - <path - android:pathData="M17.4945,10.0834C14.5045,10.0834 12.0833,12.51 12.0833,15.5C12.0833,18.49 14.5045,20.9167 17.4945,20.9167C20.4899,20.9167 22.9166,18.49 22.9166,15.5C22.9166,12.51 20.4899,10.0834 17.4945,10.0834ZM17.4999,19.8334C15.1058,19.8334 13.1666,17.8942 13.1666,15.5C13.1666,13.1059 15.1058,11.1667 17.4999,11.1667C19.8941,11.1667 21.8333,13.1059 21.8333,15.5C21.8333,17.8942 19.8941,19.8334 17.4999,19.8334ZM20.3328,17.0925L19.6503,17.9321L16.9583,16.0417V12.25H18.0416V15.5L20.3328,17.0925Z" - android:fillColor="@color/modern_blue_600"/> - </group> -</vector>
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java index 1130b0b9..e8e5bc7c 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
@@ -8,7 +8,6 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.text.TextUtils; -import android.text.format.DateUtils; import androidx.annotation.IntDef; import androidx.annotation.Nullable; @@ -26,7 +25,6 @@ import org.chromium.chrome.browser.download.internal.R; import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory; import org.chromium.chrome.browser.profiles.OTRProfileID; -import org.chromium.components.browser_ui.util.date.CalendarUtils; import org.chromium.components.messages.DismissReason; import org.chromium.components.messages.MessageBannerProperties; import org.chromium.components.messages.MessageDispatcher; @@ -36,7 +34,6 @@ import org.chromium.components.offline_items_collection.LegacyHelpers; import org.chromium.components.offline_items_collection.OfflineContentProvider; import org.chromium.components.offline_items_collection.OfflineItem; -import org.chromium.components.offline_items_collection.OfflineItemSchedule; import org.chromium.components.offline_items_collection.OfflineItemState; import org.chromium.components.offline_items_collection.UpdateDelta; import org.chromium.components.url_formatter.SchemeDisplay; @@ -47,10 +44,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -63,7 +58,6 @@ */ public class DownloadMessageUiControllerImpl implements DownloadMessageUiController { private static final long DURATION_SHOW_RESULT_IN_MS = 6000; - private static final long DURATION_SHOW_RESULT_DOWNLOAD_SCHEDULED_IN_MS = 12000; // The description can be an extremely long data url, whose length can cause a low memory // error when applied to a text view. https://crbug.com/1250423 @@ -132,7 +126,6 @@ int COMPLETE = 0; int FAILED = 1; int PENDING = 2; - int SCHEDULED = 3; } @IntDef({IconType.DRAWABLE, IconType.VECTOR_DRAWABLE, IconType.ANIMATED_VECTOR_DRAWABLE}) @@ -191,9 +184,6 @@ @ResultState public int resultState; - // Contains the information to change the download schedule for download later feature. - public OfflineItemSchedule schedule; - @Override public int hashCode() { int result = (id == null ? 0 : id.hashCode()); @@ -225,7 +215,6 @@ forceShow = other.forceShow; downloadCount = other.downloadCount; resultState = other.resultState; - schedule = other.schedule; } } @@ -237,11 +226,10 @@ public int pending; public int failed; public int completed; - public int scheduled; /** @return The total number of downloads being tracked. */ public int totalCount() { - return inProgress + pending + failed + completed + scheduled; + return inProgress + pending + failed + completed; } public int getCountForResultState(@ResultState int state) { @@ -252,8 +240,6 @@ return failed; case ResultState.PENDING: return pending; - case ResultState.SCHEDULED: - return scheduled; default: assert false; } @@ -266,7 +252,6 @@ result = 31 * result + pending; result = 31 * result + failed; result = 31 * result + completed; - result = 31 * result + scheduled; return result; } @@ -277,8 +262,7 @@ DownloadCount other = (DownloadCount) obj; return inProgress == other.inProgress && pending == other.pending - && failed == other.failed && completed == other.completed - && scheduled == other.scheduled; + && failed == other.failed && completed == other.completed; } } @@ -531,7 +515,7 @@ preProcessUpdatedItem(updatedItem); boolean isNewDownload = forceShowDownloadStarted || (updatedItem != null && updatedItem.state == OfflineItemState.IN_PROGRESS - && updatedItem.schedule == null && !mSeenItems.contains(updatedItem.id)); + && !mSeenItems.contains(updatedItem.id)); boolean itemResumedFromPending = itemResumedFromPending(updatedItem); if (updatedItem != null) { @@ -547,9 +531,8 @@ DownloadCount downloadCount = getDownloadCount(); - boolean shouldShowResult = (downloadCount.completed + downloadCount.failed - + downloadCount.pending + downloadCount.scheduled) - > 0; + boolean shouldShowResult = + (downloadCount.completed + downloadCount.failed + downloadCount.pending) > 0; @UiState int nextState = mState; @@ -604,8 +587,7 @@ if (nextState == UiState.INITIAL) { mTrackedItems.clear(); } else { - clearFinishedItems(ResultState.COMPLETE, ResultState.FAILED, ResultState.PENDING, - ResultState.SCHEDULED); + clearFinishedItems(ResultState.COMPLETE, ResultState.FAILED, ResultState.PENDING); } clearEndTimerRunnable(); } @@ -643,7 +625,6 @@ // If there are completed downloads, show immediately. if (downloadCount.completed > 0) return ResultState.COMPLETE; - if (downloadCount.scheduled > 0) return ResultState.SCHEDULED; // If the message is already showing this state, just add this item to the same state. int previousResultState = @@ -690,9 +671,6 @@ stringRes = R.plurals.download_message_multiple_download_pending; info.icon = org.chromium.components.browser_ui.widget.R.drawable .ic_error_outline_googblue_24dp; - } else if (resultState == ResultState.SCHEDULED) { - stringRes = R.plurals.download_message_multiple_download_scheduled; - info.icon = R.drawable.ic_file_download_scheduled_24dp; } else { assert false : "Unexpected resultState " + resultState + " and uiState " + uiState; } @@ -716,8 +694,6 @@ } else if (uiState == UiState.SHOW_RESULT) { int itemCount = getDownloadCount().getCountForResultState(resultState); boolean singleDownloadCompleted = itemCount == 1 && resultState == ResultState.COMPLETE; - boolean singleDownloadScheduled = - itemCount == 1 && resultState == ResultState.SCHEDULED; info.message = getContext().getResources().getQuantityString(stringRes, itemCount, itemCount); if (singleDownloadCompleted) { @@ -732,12 +708,6 @@ info.id = itemToShow.id; info.link = getContext().getString(R.string.open_downloaded_label); info.icon = R.drawable.infobar_download_complete_animation; - } else if (singleDownloadScheduled) { - // TODO(shaktisahu, xingliu): Find out what the message should be. - info.description = getMessageForDownloadScheduled(itemToShow); - info.link = getContext().getString(R.string.change_link); - info.id = itemToShow.id; - info.schedule = itemToShow.schedule.clone(); } else { // TODO(shaktisahu): Incorporate various types of failure messages. // TODO(shaktisahu, xingliu): Consult UX to handle multiple schedule variations. @@ -775,36 +745,13 @@ info.downloadCount = getDownloadCount(); info.forceShow = !info.downloadCount.equals( mCurrentInfo == null ? null : mCurrentInfo.downloadCount); - - // TODO(xingliu, shaktisahu): downloadCount may not be updated at the correct time, see - // https://crbug.com/1127522. For now, scheduled download will always show in new tabs. - if (info.downloadCount.scheduled > 0) { - info.forceShow = true; - } } + private void clearEndTimerRunnable() { mHandler.removeCallbacks(mEndTimerRunnable); mEndTimerRunnable = null; } - private String getMessageForDownloadScheduled(OfflineItem offlineItem) { - assert offlineItem != null && offlineItem.schedule != null; - if (offlineItem.schedule.onlyOnWifi) { - return getContext().getString( - R.string.download_message_download_scheduled_description_on_wifi); - } else { - long now = new Date().getTime(); - String dateTimeString = DateUtils - .formatSameDayTime(offlineItem.schedule.startTimeMs, - now, DateFormat.MEDIUM, DateFormat.SHORT) - .toString(); - int stringId = CalendarUtils.isSameDay(now, offlineItem.schedule.startTimeMs) - ? R.string.download_message_download_scheduled_description_on_time - : R.string.download_message_download_scheduled_description_on_date; - return getContext().getString(stringId, dateTimeString); - } - } - private void preProcessUpdatedItem(OfflineItem updatedItem) { if (updatedItem == null) return; @@ -824,9 +771,7 @@ @VisibleForTesting protected long getDelayToNextStep(@ResultState int resultState) { - // Scheduled download uses a longer delay to reset tracking downloads states. - return resultState == ResultState.SCHEDULED ? DURATION_SHOW_RESULT_DOWNLOAD_SCHEDULED_IN_MS - : DURATION_SHOW_RESULT_IN_MS; + return DURATION_SHOW_RESULT_IN_MS; } /** @@ -884,8 +829,8 @@ mPropertyModel.set(MessageBannerProperties.DESCRIPTION_MAX_LINES, 3); mPropertyModel.set(MessageBannerProperties.PRIMARY_BUTTON_TEXT, info.link); mPropertyModel.set(MessageBannerProperties.ON_DISMISSED, this::onMessageDismissed); - mPropertyModel.set(MessageBannerProperties.ON_PRIMARY_ACTION, - () -> onPrimaryAction(info.id, info.schedule)); + mPropertyModel.set( + MessageBannerProperties.ON_PRIMARY_ACTION, () -> onPrimaryAction(info.id)); final MessageDispatcher dispatcher = getMessageDispatcher(); mDismissRunnable = () -> { if (dispatcher == null) return; @@ -925,11 +870,6 @@ private DownloadCount getDownloadCount() { DownloadCount downloadCount = new DownloadCount(); for (OfflineItem item : mTrackedItems.values()) { - if (item.schedule != null) { - downloadCount.scheduled++; - continue; - } - switch (item.state) { case OfflineItemState.IN_PROGRESS: downloadCount.inProgress++; @@ -980,8 +920,6 @@ } private @ResultState int fromOfflineItemState(OfflineItem offlineItem) { - if (offlineItem.schedule != null) return ResultState.SCHEDULED; - switch (offlineItem.state) { case OfflineItemState.COMPLETE: return ResultState.COMPLETE; @@ -1006,8 +944,7 @@ mNotificationIds.remove(contentId); } - private @PrimaryActionClickBehavior int onPrimaryAction( - ContentId itemId, final OfflineItemSchedule schedule) { + private @PrimaryActionClickBehavior int onPrimaryAction(ContentId itemId) { OfflineItem offlineItem = mTrackedItems.remove(itemId); removeNotification(itemId); if (itemId != null) { @@ -1064,11 +1001,6 @@ shownState = info.downloadCount.pending == 1 ? UmaInfobarShown.PENDING : UmaInfobarShown.MULTIPLE_PENDING; break; - case ResultState.SCHEDULED: - shownState = info.downloadCount.scheduled == 1 - ? UmaInfobarShown.SCHEDULED - : UmaInfobarShown.MULTIPLE_SCHEDULED; - break; default: assert false : "Unexpected state " + info.resultState; break;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java index 7fa07e2..f867e720 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java
@@ -28,7 +28,6 @@ import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.LegacyHelpers; import org.chromium.components.offline_items_collection.OfflineItem; -import org.chromium.components.offline_items_collection.OfflineItemSchedule; import org.chromium.components.offline_items_collection.OfflineItemState; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modaldialog.ModalDialogManager; @@ -54,13 +53,9 @@ private static final String MESSAGE_TWO_DOWNLOAD_FAILED = "2 downloads failed"; private static final String MESSAGE_DOWNLOAD_PENDING = "1 download pending"; private static final String MESSAGE_TWO_DOWNLOAD_PENDING = "2 downloads pending"; - private static final String MESSAGE_DOWNLOAD_SCHEDULED_WIFI = "1 download scheduled"; - private static final String MESSAGE_TWO_DOWNLOAD_SCHEDULED = "2 downloads scheduled"; private static final String DESCRIPTION_DOWNLOADING = "See notification for download status"; private static final String DESCRIPTION_DOWNLOAD_COMPLETE = "(0.01 KB) www.example.com"; - private static final String DESCRIPTION_DOWNLOAD_SCHEDULED = - "Download will start when on Wi-Fi"; private static final String TEST_FILE_NAME = "TestFile"; private static final long TEST_TO_NEXT_STEP_DELAY = 100; @@ -256,31 +251,6 @@ @Test @SmallTest @Feature({"Download"}) - public void testSingleOfflineItemScheduled() { - OfflineItem item = createOfflineItem(OfflineItemState.PENDING); - item.schedule = new OfflineItemSchedule(true, 0); - mTestController.onItemUpdated(item); - mTestController.verify(MESSAGE_DOWNLOAD_SCHEDULED_WIFI, DESCRIPTION_DOWNLOAD_SCHEDULED); - } - - @Test - @SmallTest - @Feature({"Download"}) - public void testMultipleOfflineItemScheduled() { - OfflineItem item1 = createOfflineItem(OfflineItemState.IN_PROGRESS); - item1.schedule = new OfflineItemSchedule(true, 0); - mTestController.onItemUpdated(item1); - mTestController.verify(MESSAGE_DOWNLOAD_SCHEDULED_WIFI, DESCRIPTION_DOWNLOAD_SCHEDULED); - - OfflineItem item2 = createOfflineItem(OfflineItemState.PENDING); - item2.schedule = new OfflineItemSchedule(true, 0); - mTestController.onItemUpdated(item2); - mTestController.verify(MESSAGE_TWO_DOWNLOAD_SCHEDULED, null); - } - - @Test - @SmallTest - @Feature({"Download"}) public void testNewDownloadShowsUpImmediately() { OfflineItem item1 = createOfflineItem(OfflineItemState.COMPLETE); mTestController.onItemUpdated(item1);
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StableIds.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StableIds.java index b433d13..8c7f2cc6 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StableIds.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StableIds.java
@@ -17,7 +17,4 @@ /** The stable ID associated with the pagination header. */ public static long PAGINATION_HEADER = Long.MAX_VALUE - 4; - - /** The stable ID associated with the scheduled for later section. */ - public static long SCHEDULE_LATER_SECTION = Long.MAX_VALUE - 5; }
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java index ad74aac..d550c24 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java
@@ -31,8 +31,6 @@ InvalidStateOfflineItemFilter.isInPrimaryStorageDownloadDirectory(item.filePath); if ((item.externallyRemoved && inPrimaryDirectory) || item.isTransient) return true; - if (item.schedule != null) return false; - switch (item.state) { case OfflineItemState.CANCELLED: case OfflineItemState.FAILED:
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutatorTest.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutatorTest.java index ab91792..c7b434f2 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutatorTest.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMutatorTest.java
@@ -38,7 +38,6 @@ import org.chromium.components.offline_items_collection.LegacyHelpers; import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItemFilter; -import org.chromium.components.offline_items_collection.OfflineItemSchedule; import org.chromium.components.offline_items_collection.OfflineItemState; import org.chromium.components.url_formatter.SchemeDisplay; import org.chromium.components.url_formatter.UrlFormatter; @@ -323,35 +322,6 @@ /** * Action List - * 1. Set(item1 @ 1:00 1/1/2018 [ Header Scheduled for later, - * Scheduled for later, item1 @ 1:00 1/1/2018 - * item2 @ 1:00 2/1/2018 Header Just Now - * Video IN_PROGRESS item2 @ 1:00 2/1/2018 - * item3 @ 1:00 1/1/2018 DATE 1/1/2018 - * Audio COMPLETE) item3 @ 1:00 1/1/2018 ] - */ - @Test - public void testScheduledForLaterSection() { - Calendar calendar = buildCalendar(2018, 1, 1, 1); - OfflineItem item1 = buildItem("1", calendar, OfflineItemFilter.VIDEO); - item1.schedule = new OfflineItemSchedule(false, calendar.getTimeInMillis() + 1000); - OfflineItem item2 = buildItem("1", buildCalendar(2018, 2, 1, 1), OfflineItemFilter.VIDEO); - OfflineItem item3 = buildItem("2", buildCalendar(2018, 1, 1, 1), OfflineItemFilter.AUDIO); - item2.state = OfflineItemState.IN_PROGRESS; - when(mSource.getItems()).thenReturn(Arrays.asList(item1, item2, item3)); - DateOrderedListMutator list = createMutatorWithJustNowProvider(); - - Assert.assertEquals(6, mModel.size()); - assertScheduledLaterHeader(mModel.get(0)); - assertOfflineItem(mModel.get(1), calendar, item1); - assertJustNowSection(mModel.get(2)); - assertOfflineItem(mModel.get(3), buildCalendar(2018, 2, 1, 1), item2); - assertSectionHeader(mModel.get(4), buildCalendar(2018, 1, 1, 0)); - assertOfflineItem(mModel.get(5), buildCalendar(2018, 1, 1, 1), item3); - } - - /** - * Action List * 1. Set(item1 @ 0:00 1/2/2018, [ DATE @ 0:00 1/2/2018, * item2 @ 0:00 1/1/2018) * item1 @ 0:00 1/2/2018, @@ -1276,9 +1246,6 @@ Assert.assertEquals(SectionHeaderListItem.generateStableId( SectionHeaderType.JUST_NOW, calendar.getTimeInMillis()), StableIds.JUST_NOW_SECTION); - Assert.assertEquals(SectionHeaderListItem.generateStableId( - SectionHeaderType.SCHEDULED_LATER, calendar.getTimeInMillis()), - StableIds.SCHEDULE_LATER_SECTION); } private static void assertJustNowSection(ListItem item) { @@ -1288,13 +1255,6 @@ Assert.assertEquals(StableIds.JUST_NOW_SECTION, item.stableId); } - private static void assertScheduledLaterHeader(ListItem item) { - Assert.assertTrue(item instanceof SectionHeaderListItem); - SectionHeaderListItem sectionHeader = (SectionHeaderListItem) item; - Assert.assertEquals(SectionHeaderType.SCHEDULED_LATER, sectionHeader.type); - Assert.assertEquals(StableIds.SCHEDULE_LATER_SECTION, item.stableId); - } - private static void assertCardHeader(ListItem item, Calendar calendar, String domain) { Assert.assertTrue(item instanceof ListItem.CardHeaderListItem); ListItem.CardHeaderListItem headerItem = (ListItem.CardHeaderListItem) item;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java index 76fbbb7..4ee7dfd 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListItem.java
@@ -131,14 +131,12 @@ /** * The type of the section header. */ - @IntDef({SectionHeaderType.INVALID, SectionHeaderType.DATE, SectionHeaderType.JUST_NOW, - SectionHeaderType.SCHEDULED_LATER}) + @IntDef({SectionHeaderType.INVALID, SectionHeaderType.DATE, SectionHeaderType.JUST_NOW}) @Retention(RetentionPolicy.SOURCE) public @interface SectionHeaderType { int INVALID = -1; int DATE = 0; int JUST_NOW = 1; - int SCHEDULED_LATER = 2; } /** A {@link ListItem} representing a section header. */ @@ -161,8 +159,6 @@ return hash + SECTION_HEADER_HASH_CODE_OFFSET; case SectionHeaderType.JUST_NOW: return StableIds.JUST_NOW_SECTION; - case SectionHeaderType.SCHEDULED_LATER: - return StableIds.SCHEDULE_LATER_SECTION; } assert false : "Unknown section header type."; return -1;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java index e97e1259..6c7226b 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListUtils.java
@@ -110,7 +110,6 @@ if (item instanceof OfflineItemListItem) { OfflineItemListItem offlineItem = (OfflineItemListItem) item; if (offlineItem.isGrouped) return ViewType.GROUP_CARD_ITEM; - if (offlineItem.item.schedule != null) return ViewType.GENERIC; boolean inProgress = offlineItem.item.state == OfflineItemState.IN_PROGRESS || offlineItem.item.state == OfflineItemState.PAUSED @@ -222,20 +221,6 @@ if (comparison != 0) return comparison; return a.id.id.compareTo(b.id.id); } - /** - * Helper method to compare list items based on {@link OfflineItemSchedule}. - * @return -1 if {@code a} should be shown before {@code b}. - * 0 if {@code a} == {@code b}. - * 1 if {@code a} should be shown after {@code b}. - */ - public static int compareItemBySchedule(OfflineItem a, OfflineItem b) { - if (a.schedule != null && b.schedule != null) { - return a.schedule.startTimeMs <= b.schedule.startTimeMs ? -1 : 1; - } - - if (a.schedule == null && b.schedule == null) return 0; - return a.schedule != null ? -1 : 1; - } private static int getVisualPriorityForFilter(@FilterType int type) { for (int i = 0; i < FILTER_TYPE_ORDER_LIST.length; i++) {
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java index ea759d20..94719bb 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
@@ -52,7 +52,6 @@ // flag to hide rename list menu option for offline pages private boolean mCanRename; private boolean mCanShare; - private boolean mIsScheduled; /** * Creates a new instance of a {@link OfflineItemViewHolder}. @@ -73,7 +72,6 @@ OfflineItem offlineItem = ((ListItem.OfflineItemListItem) item).item; mCanRename = offlineItem.canRename; mCanShare = UiUtils.canShare(offlineItem); - mIsScheduled = offlineItem.schedule != null; // Push 'interaction' state bindOnClick(properties, item, offlineItem); @@ -108,11 +106,6 @@ } private void bindOnClick(PropertyModel properties, ListItem item, OfflineItem offlineItem) { - // For scheduled items, click doesn't do anything. - if (mIsScheduled) { - return; - } - itemView.setOnClickListener(v -> { if (mSelectionView != null && mSelectionView.isInSelectionMode()) { properties.get(ListProperties.CALLBACK_SELECTION).onResult(item);
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java index 32d4d1f6..8abcf6f43 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/SectionTitleViewHolder.java
@@ -49,8 +49,6 @@ return StringUtils.dateToHeaderString(sectionItem.date); case SectionHeaderType.JUST_NOW: return context.getResources().getString(R.string.download_manager_just_now); - case SectionHeaderType.SCHEDULED_LATER: - return context.getResources().getString(R.string.download_manager_scheduled_later); } assert false : "Unknown section header type."; return null;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateLabelAdder.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateLabelAdder.java index 3c07ec9..2f9dcf0 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateLabelAdder.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateLabelAdder.java
@@ -98,9 +98,6 @@ private @SectionHeaderType int getSectionHeaderType(@Nullable OfflineItem offlineItem) { if (offlineItem == null) return SectionHeaderType.INVALID; - // Scheduled for later section shows at the top. - if (offlineItem.schedule != null) return SectionHeaderType.SCHEDULED_LATER; - // Just now section follows the scheduled for later section. boolean isJustNow = mJustNowProvider != null && mJustNowProvider.isJustNowItem(offlineItem); if (isJustNow) return SectionHeaderType.JUST_NOW;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateOrderedListMutator.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateOrderedListMutator.java index c9c89c9..f153118 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateOrderedListMutator.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateOrderedListMutator.java
@@ -104,8 +104,8 @@ // If the update changed the creation time or filter type, remove and add the element to get // it positioned. if (oldItem.creationTimeMs != item.creationTimeMs || oldItem.filter != item.filter - || mJustNowProvider.isJustNowItem(oldItem) != mJustNowProvider.isJustNowItem((item)) - || offlineItemScheduleDiffer(item, oldItem)) { + || mJustNowProvider.isJustNowItem(oldItem) + != mJustNowProvider.isJustNowItem(item)) { // TODO(shaktisahu): Collect UMA when this happens. onItemsRemoved(Collections.singletonList(oldItem)); onItemsAdded(Collections.singletonList(item)); @@ -134,9 +134,4 @@ } } } - - private static boolean offlineItemScheduleDiffer(OfflineItem item, OfflineItem oldItem) { - return (item.schedule == null && oldItem.schedule != null) - || (item.schedule != null && oldItem.schedule == null); - } }
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateSorter.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateSorter.java index 645d917..c9f86ab 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateSorter.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/DateSorter.java
@@ -49,10 +49,7 @@ OfflineItem lhs = ((ListItem.OfflineItemListItem) listItem1).item; OfflineItem rhs = ((ListItem.OfflineItemListItem) listItem2).item; - int comparison = ListUtils.compareItemBySchedule(lhs, rhs); - if (comparison != 0) return comparison; - - comparison = compareItemByJustNowProvider(lhs, rhs); + int comparison = compareItemByJustNowProvider(lhs, rhs); if (comparison != 0) return comparison; comparison = ListUtils.compareItemByDate(lhs, rhs);
diff --git a/chrome/browser/download/notification/download_notification_manager.cc b/chrome/browser/download/notification/download_notification_manager.cc index 219ff3e1..81f89ba 100644 --- a/chrome/browser/download/notification/download_notification_manager.cc +++ b/chrome/browser/download/notification/download_notification_manager.cc
@@ -21,11 +21,11 @@ void DownloadNotificationManager::OnNewDownloadReady( download::DownloadItem* item) { // Lower the priority of all existing in-progress download notifications. - for (auto& item : items_) { - DownloadUIModel* model = item.second->GetDownload(); - DownloadItemNotification* download_notification = item.second.get(); + for (auto& it : items_) { + DownloadItemNotification* notification = it.second.get(); + DownloadUIModel* model = notification->GetDownload(); if (model->GetState() == download::DownloadItem::IN_PROGRESS) - download_notification->DisablePopup(); + notification->DisablePopup(); } auto model = std::make_unique<DownloadItemModel>(item);
diff --git a/chrome/browser/download/offline_item_utils.cc b/chrome/browser/download/offline_item_utils.cc index 9716aef6a..fcc1704 100644 --- a/chrome/browser/download/offline_item_utils.cc +++ b/chrome/browser/download/offline_item_utils.cc
@@ -23,7 +23,6 @@ using ContentId = offline_items_collection::ContentId; using OfflineItem = offline_items_collection::OfflineItem; using OfflineItemFilter = offline_items_collection::OfflineItemFilter; -using OfflineItemSchedule = offline_items_collection::OfflineItemSchedule; using OfflineItemState = offline_items_collection::OfflineItemState; using OfflineItemProgressUnit = offline_items_collection::OfflineItemProgressUnit;
diff --git a/chrome/browser/download/offline_item_utils_unittest.cc b/chrome/browser/download/offline_item_utils_unittest.cc index 8eb93e9..c3f8546 100644 --- a/chrome/browser/download/offline_item_utils_unittest.cc +++ b/chrome/browser/download/offline_item_utils_unittest.cc
@@ -18,7 +18,6 @@ using OfflineItemState = offline_items_collection::OfflineItemState; using OfflineItemProgressUnit = offline_items_collection::OfflineItemProgressUnit; -using OfflineItemSchedule = offline_items_collection::OfflineItemSchedule; using FailState = offline_items_collection::FailState; using PendingState = offline_items_collection::PendingState; using DownloadItem = download::DownloadItem;
diff --git a/chrome/browser/download/save_package_file_picker.h b/chrome/browser/download/save_package_file_picker.h index ec2968c3..f74b237 100644 --- a/chrome/browser/download/save_package_file_picker.h +++ b/chrome/browser/download/save_package_file_picker.h
@@ -57,7 +57,7 @@ std::vector<content::SavePageType> save_types_; // For managing select file dialogs. - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; }; #endif // CHROME_BROWSER_DOWNLOAD_SAVE_PACKAGE_FILE_PICKER_H_
diff --git a/chrome/browser/extensions/api/bookmarks/bookmarks_api.h b/chrome/browser/extensions/api/bookmarks/bookmarks_api.h index 691f8ec..2d6caef7 100644 --- a/chrome/browser/extensions/api/bookmarks/bookmarks_api.h +++ b/chrome/browser/extensions/api/bookmarks/bookmarks_api.h
@@ -334,7 +334,7 @@ protected: ~BookmarksIOFunction() override; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; }; class BookmarksImportFunction : public BookmarksIOFunction {
diff --git a/chrome/browser/extensions/api/developer_private/entry_picker.h b/chrome/browser/extensions/api/developer_private/entry_picker.h index baebd27..cce72a1 100644 --- a/chrome/browser/extensions/api/developer_private/entry_picker.h +++ b/chrome/browser/extensions/api/developer_private/entry_picker.h
@@ -54,7 +54,7 @@ void MultiFilesSelected(const std::vector<base::FilePath>& files, void* params) override; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; raw_ptr<EntryPickerClient> client_; };
diff --git a/chrome/browser/extensions/api/file_manager/file_selector_impl.h b/chrome/browser/extensions/api/file_manager/file_selector_impl.h index b5635a3..6ce8b1f 100644 --- a/chrome/browser/extensions/api/file_manager/file_selector_impl.h +++ b/chrome/browser/extensions/api/file_manager/file_selector_impl.h
@@ -60,7 +60,7 @@ void SendResponse(bool success, const base::FilePath& selected_path); // Dialog shown by selector. - std::unique_ptr<ui::SelectFileDialog> dialog_; + scoped_refptr<ui::SelectFileDialog> dialog_; // Callback to receive results. OnSelectedCallback callback_;
diff --git a/chrome/browser/extensions/api/file_system/file_entry_picker.h b/chrome/browser/extensions/api/file_system/file_entry_picker.h index 13b17623..47290ef 100644 --- a/chrome/browser/extensions/api/file_system/file_entry_picker.h +++ b/chrome/browser/extensions/api/file_system/file_entry_picker.h
@@ -60,7 +60,7 @@ FileSystemDelegate::FilesSelectedCallback files_selected_callback_; base::OnceClosure file_selection_canceled_callback_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; }; } // namespace extensions
diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h index cd7acbfc..a1fff2a 100644 --- a/chrome/browser/file_select_helper.h +++ b/chrome/browser/file_select_helper.h
@@ -301,7 +301,7 @@ scoped_refptr<content::FileSelectListener> listener_; // Dialog box used for choosing files to upload from file form fields. - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> select_file_types_; // The type of file dialog last shown. This is SELECT_NONE if an
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index cddabea..509e7b2 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -107,7 +107,6 @@ &content_creation::kLightweightReactions, &content_settings::kDarkenWebsitesCheckboxInThemesSetting, &download::features::kDownloadAutoResumptionNative, - &download::features::kDownloadLater, &download::features::kSmartSuggestionForLargeDownloads, &download::features::kUseDownloadOfflineContentProvider, &embedder_support::kShowTrustedPublisherURL,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 613f984..59101b8 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -342,7 +342,6 @@ public static final String DOWNLOADS_AUTO_RESUMPTION_NATIVE = "DownloadsAutoResumptionNative"; public static final String DOWNLOAD_OFFLINE_CONTENT_PROVIDER = "UseDownloadOfflineContentProvider"; - public static final String DOWNLOAD_LATER = "DownloadLater"; public static final String EARLY_LIBRARY_LOAD = "EarlyLibraryLoad"; public static final String ELIDE_PRIORITIZATION_OF_PRE_NATIVE_BOOTSTRAP_TASKS = "ElidePrioritizationOfPreNativeBootstrapTasks";
diff --git a/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.cc b/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.cc index 963e47fb..e5ad717 100644 --- a/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.cc +++ b/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.cc
@@ -18,19 +18,22 @@ using extensions::ProcessManager; ContextMenuContentTypeWebView::ContextMenuContentTypeWebView( - content::WebContents* web_contents, + const base::WeakPtr<extensions::WebViewGuest> web_view_guest, const content::ContextMenuParams& params) - : ContextMenuContentType(web_contents, params, true) { -} + : ContextMenuContentType(params, true), + web_view_guest_(std::move(web_view_guest)) {} ContextMenuContentTypeWebView::~ContextMenuContentTypeWebView() { } const Extension* ContextMenuContentTypeWebView::GetExtension() const { - ProcessManager* process_manager = - ProcessManager::Get(source_web_contents()->GetBrowserContext()); - return process_manager->GetExtensionForWebContents( - source_web_contents()); + if (!web_view_guest_) + return nullptr; + + ProcessManager* process_manager = ProcessManager::Get( + web_view_guest_->GetGuestMainFrame()->GetBrowserContext()); + return process_manager->GetExtensionForRenderFrameHost( + web_view_guest_->GetGuestMainFrame()); } bool ContextMenuContentTypeWebView::SupportsGroup(int group) { @@ -49,22 +52,20 @@ return true; case ITEM_GROUP_DEVELOPER: { - const extensions::Extension* embedder_extension = GetExtension(); - if (chrome::GetChannel() >= version_info::Channel::DEV) { - // Hide dev tools items in guests inside WebUI if we are not running - // canary or tott. - auto* web_view_guest = - extensions::WebViewGuest::FromWebContents(source_web_contents()); - // Note that this check might not be sufficient to hide dev tools - // items on OS_MAC if we start supporting <webview> inside - // component extensions. - // For a list of places where <webview>/GuestViews are supported, see: - // https://goo.gl/xfJkwp. - if (!embedder_extension && web_view_guest && - web_view_guest->owner_web_contents()->GetWebUI()) { - return false; - } + const extensions::Extension* embedder_extension = GetExtension(); + if (chrome::GetChannel() >= version_info::Channel::DEV) { + // Hide dev tools items in guests inside WebUI if we are not running + // canary or tott. + // Note that this check might not be sufficient to hide dev tools + // items on OS_MAC if we start supporting <webview> inside + // component extensions. + // For a list of places where <webview>/GuestViews are supported, see: + // https://goo.gl/xfJkwp. + if (!embedder_extension && web_view_guest_ && + web_view_guest_->owner_web_contents()->GetWebUI()) { + return false; } + } // TODO(lazyboy): Enable this for mac too when http://crbug.com/380405 // is fixed.
diff --git a/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.h b/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.h index eb9f4ec..bd8190c8 100644 --- a/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.h +++ b/chrome/browser/guest_view/web_view/context_menu_content_type_web_view.h
@@ -9,6 +9,7 @@ namespace extensions { class Extension; +class WebViewGuest; } // A ContextMenuContentType for <webview> guest. @@ -27,13 +28,16 @@ bool SupportsGroup(int group) override; protected: - ContextMenuContentTypeWebView(content::WebContents* web_contents, - const content::ContextMenuParams& params); + ContextMenuContentTypeWebView( + const base::WeakPtr<extensions::WebViewGuest> web_view_guest, + const content::ContextMenuParams& params); private: friend class ContextMenuContentTypeFactory; const extensions::Extension* GetExtension() const; + + base::WeakPtr<extensions::WebViewGuest> web_view_guest_; }; #endif // CHROME_BROWSER_GUEST_VIEW_WEB_VIEW_CONTEXT_MENU_CONTENT_TYPE_WEB_VIEW_H_
diff --git a/chrome/browser/installable/BUILD.gn b/chrome/browser/installable/BUILD.gn index 0a82b58..8bd73c30e 100644 --- a/chrome/browser/installable/BUILD.gn +++ b/chrome/browser/installable/BUILD.gn
@@ -5,8 +5,5 @@ import("//build/config/android/rules.gni") java_cpp_enum("browser_services_enums_srcjar") { - sources = [ - "installed_webapp_geolocation_bridge.cc", - "quality_enforcer.cc", - ] + sources = [ "quality_enforcer.cc" ] }
diff --git a/chrome/browser/installable/installed_webapp_geolocation_bridge.cc b/chrome/browser/installable/installed_webapp_geolocation_bridge.cc index 3ede9e5..eb1eb15 100644 --- a/chrome/browser/installable/installed_webapp_geolocation_bridge.cc +++ b/chrome/browser/installable/installed_webapp_geolocation_bridge.cc
@@ -15,31 +15,6 @@ #include "services/device/public/cpp/geolocation/geoposition.h" #include "url/android/gurl_android.h" -namespace { - -const char kLocationUpdateHistogramName[] = - "TrustedWebActivity.LocationUpdateErrorCode"; - -// Do not modify or reuse existing entries; they are used in a UMA histogram. -// Please edit TrustedWebActivityLocationErrorCode in the enums.xml if a value -// is added. -// GENERATED_JAVA_ENUM_PACKAGE: ( -// org.chromium.chrome.browser.browserservices.constants) -enum class LocationUpdateError { - // There was no error. - kNone = 0, - // Geoposition could not be determined, i.e. error from the TWA client app. - kLocationError = 1, - // Invalid position. - kInvalidPosition = 2, - // Trusted web activity service not found or does not handle the request. - kNoTwa = 3, - // NOTE: Add entries only immediately above this line. - kMaxValue = kNoTwa -}; - -} // namespace - InstalledWebappGeolocationBridge::InstalledWebappGeolocationBridge( mojo::PendingReceiver<Geolocation> receiver, const GURL& url, @@ -173,11 +148,6 @@ if (!device::ValidateGeoposition(position)) { position.error_code = device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE; - base::UmaHistogramEnumeration(kLocationUpdateHistogramName, - LocationUpdateError::kInvalidPosition); - } else { - base::UmaHistogramEnumeration(kLocationUpdateHistogramName, - LocationUpdateError::kNone); } OnLocationUpdate(position); @@ -185,9 +155,6 @@ void InstalledWebappGeolocationBridge::OnNewErrorAvailable(JNIEnv* env, jstring message) { - base::UmaHistogramEnumeration(kLocationUpdateHistogramName, - LocationUpdateError::kLocationError); - device::mojom::Geoposition position_error; position_error.error_code = device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE;
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_browsertest.cc b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_browsertest.cc index 3679b34..82c3feb 100644 --- a/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_browsertest.cc +++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_sink_service_browsertest.cc
@@ -94,8 +94,9 @@ GetPrefUpdater()->GetMediaSinkInternalValueBySinkId("cast:<1234>")); } +// TODO(crbug/1370898): The test is flaky on Network Service Linux. IN_PROC_BROWSER_TEST_F(AccessCodeCastSinkServiceBrowserTest, - InstantExpiration) { + DISABLED_InstantExpiration) { // This test is run after an instant expiration device was successfully // added to the browser. Upon restart it should not exists in prefs nor should // it be added to the media router.
diff --git a/chrome/browser/media_galleries/media_galleries_permission_controller.h b/chrome/browser/media_galleries/media_galleries_permission_controller.h index 8d7f368..0f55cb8 100644 --- a/chrome/browser/media_galleries/media_galleries_permission_controller.h +++ b/chrome/browser/media_galleries/media_galleries_permission_controller.h
@@ -216,7 +216,7 @@ // The view that's showing. std::unique_ptr<MediaGalleriesDialog> dialog_; - std::unique_ptr<ui::SelectFileDialog> select_folder_dialog_; + scoped_refptr<ui::SelectFileDialog> select_folder_dialog_; std::unique_ptr<MediaGalleryContextMenu> context_menu_;
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 35e28885..9a481f9 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -388,9 +388,13 @@ } // Hooks to set up feature flags. - virtual std::vector<base::Feature> GetEnabledFeatures() const { return {}; } + virtual std::vector<base::test::FeatureRef> GetEnabledFeatures() const { + return {}; + } - virtual std::vector<base::Feature> GetDisabledFeatures() const { return {}; } + virtual std::vector<base::test::FeatureRef> GetDisabledFeatures() const { + return {}; + } private: base::test::ScopedFeatureList feature_list_; @@ -399,7 +403,7 @@ class PDFExtensionTestWithPartialLoading : public PDFExtensionTest { protected: - std::vector<base::Feature> GetEnabledFeatures() const override { + std::vector<base::test::FeatureRef> GetEnabledFeatures() const override { auto enabled = PDFExtensionTest::GetEnabledFeatures(); enabled.push_back(chrome_pdf::features::kPdfIncrementalLoading); enabled.push_back(chrome_pdf::features::kPdfPartialLoading); @@ -1360,7 +1364,7 @@ class PDFExtensionWebUICodeCacheJSTest : public PDFExtensionJSTest { protected: - std::vector<base::Feature> GetEnabledFeatures() const override { + std::vector<base::test::FeatureRef> GetEnabledFeatures() const override { auto enabled = PDFExtensionJSTest::GetEnabledFeatures(); enabled.push_back(features::kWebUICodeCache); return enabled; @@ -2107,7 +2111,7 @@ class PDFExtensionRegionSearchTest : public PDFExtensionTest { protected: - std::vector<base::Feature> GetEnabledFeatures() const override { + std::vector<base::test::FeatureRef> GetEnabledFeatures() const override { auto enabled = PDFExtensionTest::GetEnabledFeatures(); enabled.push_back(lens::features::kLensStandalone); return enabled; @@ -3929,7 +3933,7 @@ } protected: - std::vector<base::Feature> GetEnabledFeatures() const override { + std::vector<base::test::FeatureRef> GetEnabledFeatures() const override { auto enabled = PDFExtensionTest::GetEnabledFeatures(); enabled.push_back(chrome_pdf::features::kAccessiblePDFForm); return enabled; @@ -4142,7 +4146,7 @@ } protected: - std::vector<base::Feature> GetEnabledFeatures() const override { + std::vector<base::test::FeatureRef> GetEnabledFeatures() const override { auto enabled = PDFExtensionTest::GetEnabledFeatures(); enabled.push_back(chrome_pdf::features::kAccessiblePDFForm); return enabled;
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc index a66cc50..fb2b778 100644 --- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc +++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -405,7 +405,7 @@ {{"max_attempts_per_caching_duration", "3"}, {"cache_size", "1"}, {"device_memory_threshold_MB", "0"}}}}; - std::vector<base::Feature> disabled_features = {}; + std::vector<base::test::FeatureRef> disabled_features = {}; if (BlockOnHeadersEnabled()) { enabled_features.push_back({kSearchPrefetchBlockBeforeHeaders, {}}); } else { @@ -3382,7 +3382,7 @@ {"cache_size", "1"}, {"device_memory_threshold_MB", "0"}}}, {kSearchNavigationPrefetch, {}}}; - std::vector<base::Feature> disabled_features = {}; + std::vector<base::test::FeatureRef> disabled_features = {}; feature_list_.InitWithFeaturesAndParameters(enabled_features, disabled_features); @@ -3677,7 +3677,7 @@ {"device_memory_threshold_MB", "0"}, {"prefetch_holdback", "true"}}}, {kSearchNavigationPrefetch, {{}}}}; - std::vector<base::Feature> disabled_features = {}; + std::vector<base::test::FeatureRef> disabled_features = {}; feature_list_.InitWithFeaturesAndParameters(enabled_features, disabled_features); @@ -3780,7 +3780,7 @@ {"device_memory_threshold_MB", "0"}}}, {kSearchPrefetchSkipsCancel, {}}, {kSearchNavigationPrefetch, {{}}}}; - std::vector<base::Feature> disabled_features = {}; + std::vector<base::test::FeatureRef> disabled_features = {}; feature_list_.InitWithFeaturesAndParameters(enabled_features, disabled_features);
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc index 2450219..857db45 100644 --- a/chrome/browser/printing/pdf_to_emf_converter.cc +++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -89,9 +89,9 @@ private: class GetPageCallbackData { public: - GetPageCallbackData(uint32_t page_number, + GetPageCallbackData(uint32_t page_index, PdfConverter::GetPageCallback callback) - : page_number_(page_number), callback_(callback) {} + : page_index_(page_index), callback_(callback) {} GetPageCallbackData(const GetPageCallbackData&) = delete; GetPageCallbackData& operator=(const GetPageCallbackData&) = delete; @@ -101,24 +101,24 @@ } GetPageCallbackData& operator=(GetPageCallbackData&& rhs) { - page_number_ = rhs.page_number_; + page_index_ = rhs.page_index_; callback_ = rhs.callback_; return *this; } - uint32_t page_number() const { return page_number_; } + uint32_t page_index() const { return page_index_; } PdfConverter::GetPageCallback callback() const { return callback_; } private: - uint32_t page_number_; + uint32_t page_index_; PdfConverter::GetPageCallback callback_; }; void Initialize(scoped_refptr<base::RefCountedMemory> data); - void GetPage(uint32_t page_number, + void GetPage(uint32_t page_index, PdfConverter::GetPageCallback get_page_callback) override; void Stop(); @@ -255,20 +255,20 @@ } void PdfConverterImpl::GetPage( - uint32_t page_number, + uint32_t page_index, PdfConverter::GetPageCallback get_page_callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(pdf_to_emf_converter_.is_bound()); // Store callback before any OnFailed() call to make it called on failure. - get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); + get_page_callbacks_.push(GetPageCallbackData(page_index, get_page_callback)); if (!pdf_to_emf_converter_) return OnFailed(std::string("No PdfToEmfConverter.")); pdf_to_emf_converter_->ConvertPage( - page_number, base::BindOnce(&PdfConverterImpl::OnPageDone, - weak_ptr_factory_.GetWeakPtr())); + page_index, base::BindOnce(&PdfConverterImpl::OnPageDone, + weak_ptr_factory_.GetWeakPtr())); } void PdfConverterImpl::OnPageDone(base::ReadOnlySharedMemoryRegion emf_region, @@ -293,7 +293,7 @@ } base::WeakPtr<PdfConverterImpl> weak_this = weak_ptr_factory_.GetWeakPtr(); - data.callback().Run(data.page_number(), scale_factor, std::move(metafile)); + data.callback().Run(data.page_index(), scale_factor, std::move(metafile)); // WARNING: the callback might have deleted `this`! if (!weak_this) return;
diff --git a/chrome/browser/printing/pdf_to_emf_converter.h b/chrome/browser/printing/pdf_to_emf_converter.h index a8ece8fa..6d535729 100644 --- a/chrome/browser/printing/pdf_to_emf_converter.h +++ b/chrome/browser/printing/pdf_to_emf_converter.h
@@ -19,7 +19,7 @@ public: using StartCallback = base::OnceCallback<void(uint32_t page_count)>; using GetPageCallback = - base::RepeatingCallback<void(uint32_t page_number, + base::RepeatingCallback<void(uint32_t page_index, float scale_factor, std::unique_ptr<MetafilePlayer> file)>; virtual ~PdfConverter(); @@ -31,11 +31,11 @@ const PdfRenderSettings& conversion_settings, StartCallback start_callback); - // Requests conversion of the page. `page_number` is 0-base page number in + // Requests conversion of the page. `page_index` is 0-base page index for the // PDF provided in Start() call. - // Calls `get_page_callback` after conversion. `emf` of callback in not NULL - // if conversion succeeded. - virtual void GetPage(uint32_t page_number, + // Calls `get_page_callback` after conversion. The `file` parameter in the + // callback is non-null if the conversion succeeded. + virtual void GetPage(uint32_t page_index, GetPageCallback get_page_callback) = 0; };
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc index e5566f0..7bf40d0 100644 --- a/chrome/browser/printing/print_job.cc +++ b/chrome/browser/printing/print_job.cc
@@ -297,11 +297,7 @@ class PrintJob::PdfConversionState { public: PdfConversionState(const gfx::Size& page_size, const gfx::Rect& content_area) - : page_count_(0), - current_page_(0), - pages_in_progress_(0), - page_size_(page_size), - content_area_(content_area) {} + : page_size_(page_size), content_area_(content_area) {} void Start(scoped_refptr<base::RefCountedMemory> data, const PdfRenderSettings& conversion_settings, @@ -313,9 +309,9 @@ void GetMorePages(PdfConverter::GetPageCallback get_page_callback) { const int kMaxNumberOfTempFilesPerDocument = 3; while (pages_in_progress_ < kMaxNumberOfTempFilesPerDocument && - current_page_ < page_count_) { + current_page_index_ < page_count_) { ++pages_in_progress_; - converter_->GetPage(current_page_++, get_page_callback); + converter_->GetPage(current_page_index_++, get_page_callback); } } @@ -323,7 +319,7 @@ --pages_in_progress_; GetMorePages(get_page_callback); // Release converter if we don't need this any more. - if (!pages_in_progress_ && current_page_ >= page_count_) + if (!pages_in_progress_ && current_page_index_ >= page_count_) converter_.reset(); } @@ -332,11 +328,11 @@ const gfx::Rect& content_area() const { return content_area_; } private: - uint32_t page_count_; - uint32_t current_page_; - int pages_in_progress_; - gfx::Size page_size_; - gfx::Rect content_area_; + uint32_t page_count_ = 0; + uint32_t current_page_index_ = 0; + int pages_in_progress_ = 0; + const gfx::Size page_size_; + const gfx::Rect content_area_; std::unique_ptr<PdfConverter> converter_; };
diff --git a/chrome/browser/push_messaging/push_messaging_app_identifier.cc b/chrome/browser/push_messaging/push_messaging_app_identifier.cc index 1eba1c3..7b3e2b1a 100644 --- a/chrome/browser/push_messaging/push_messaging_app_identifier.cc +++ b/chrome/browser/push_messaging/push_messaging_app_identifier.cc
@@ -221,10 +221,8 @@ // static void PushMessagingAppIdentifier::DeleteAllFromPrefs(Profile* profile) { - DictionaryPrefUpdate update(profile->GetPrefs(), - prefs::kPushMessagingAppIdentifierMap); - base::Value* map = update.Get(); - map->DictClear(); + profile->GetPrefs()->SetDict(prefs::kPushMessagingAppIdentifierMap, + base::Value::Dict()); } // static @@ -259,29 +257,28 @@ void PushMessagingAppIdentifier::PersistToPrefs(Profile* profile) const { DCheckValid(); - DictionaryPrefUpdate update(profile->GetPrefs(), + ScopedDictPrefUpdate update(profile->GetPrefs(), prefs::kPushMessagingAppIdentifierMap); - base::Value* map = update.Get(); + base::Value::Dict& map = update.Get(); // Delete any stale entry with the same origin and Service Worker // registration id (hence we ensure there is a 1:1 not 1:many mapping). PushMessagingAppIdentifier old = FindByServiceWorker(profile, origin_, service_worker_registration_id_); if (!old.is_null()) - map->RemoveKey(old.app_id_); + map.Remove(old.app_id_); - map->SetKey(app_id_, - base::Value(MakePrefValue( - origin_, service_worker_registration_id_, expiration_time_))); + map.Set(app_id_, MakePrefValue(origin_, service_worker_registration_id_, + expiration_time_)); } void PushMessagingAppIdentifier::DeleteFromPrefs(Profile* profile) const { DCheckValid(); - DictionaryPrefUpdate update(profile->GetPrefs(), + ScopedDictPrefUpdate update(profile->GetPrefs(), prefs::kPushMessagingAppIdentifierMap); - base::Value* map = update.Get(); - map->RemoveKey(app_id_); + base::Value::Dict& map = update.Get(); + map.Remove(app_id_); } void PushMessagingAppIdentifier::DCheckValid() const {
diff --git a/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc b/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc index 0394ab1..a56a89c 100644 --- a/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc +++ b/chrome/browser/push_messaging/push_messaging_app_identifier_unittest.cc
@@ -142,7 +142,7 @@ // Create a legacy preferences entry (the test happens to use PersistToPrefs // since that currently works, but it's ok to change the behavior of - // PersistToPrefs; if so, this test can just do a raw DictionaryPrefUpdate). + // PersistToPrefs; if so, this test can just do a raw ScopedDictPrefUpdate). original_.app_id_ = legacy_app_id; original_.PersistToPrefs(profile());
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.cc index 8e8dc75f..2a9462c 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.cc +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.cc
@@ -5,10 +5,8 @@ #include "chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.h" ContextMenuContentTypeAppMode::ContextMenuContentTypeAppMode( - content::WebContents* web_contents, const content::ContextMenuParams& params) - : ContextMenuContentType(web_contents, params, false) { -} + : ContextMenuContentType(params, false) {} ContextMenuContentTypeAppMode::~ContextMenuContentTypeAppMode() { }
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.h b/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.h index a2f788d..49126ad7 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.h +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_app_mode.h
@@ -19,8 +19,8 @@ bool SupportsGroup(int group) override; protected: - ContextMenuContentTypeAppMode(content::WebContents* web_contents, - const content::ContextMenuParams& params); + explicit ContextMenuContentTypeAppMode( + const content::ContextMenuParams& params); private: friend class ContextMenuContentTypeFactory;
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.cc index 5d1065a..fba3539 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.cc +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.cc
@@ -5,10 +5,8 @@ #include "chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.h" ContextMenuContentTypeExtensionPopup::ContextMenuContentTypeExtensionPopup( - content::WebContents* web_contents, const content::ContextMenuParams& params) - : ContextMenuContentType(web_contents, params, false) { -} + : ContextMenuContentType(params, false) {} ContextMenuContentTypeExtensionPopup::~ContextMenuContentTypeExtensionPopup() { }
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.h b/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.h index 6235d6e..c45da84 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.h +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_extension_popup.h
@@ -21,7 +21,6 @@ protected: ContextMenuContentTypeExtensionPopup( - content::WebContents* web_contents, const content::ContextMenuParams& params); private:
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc index 7463ba90..f4c3c79 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_factory.cc
@@ -46,9 +46,8 @@ // Context menu content with no supported groups. class NullContextMenuContentType : public ContextMenuContentType { public: - NullContextMenuContentType(content::WebContents* web_contents, - const content::ContextMenuParams& params) - : ContextMenuContentType(web_contents, params, false) {} + explicit NullContextMenuContentType(const content::ContextMenuParams& params) + : ContextMenuContentType(params, false) {} NullContextMenuContentType(const NullContextMenuContentType&) = delete; NullContextMenuContentType& operator=(const NullContextMenuContentType&) = @@ -69,30 +68,33 @@ // static. std::unique_ptr<ContextMenuContentType> ContextMenuContentTypeFactory::Create( - content::WebContents* web_contents, + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { if (IsUserSessionBlocked()) - return std::make_unique<NullContextMenuContentType>(web_contents, params); + return std::make_unique<NullContextMenuContentType>(params); - return CreateInternal(web_contents, params); + return CreateInternal(render_frame_host, params); } // static std::unique_ptr<ContextMenuContentType> ContextMenuContentTypeFactory::CreateInternal( - content::WebContents* web_contents, + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { #if BUILDFLAG(ENABLE_EXTENSIONS) if (chrome::IsRunningInForcedAppMode()) { - return base::WrapUnique( - new ContextMenuContentTypeAppMode(web_contents, params)); + return base::WrapUnique(new ContextMenuContentTypeAppMode(params)); } - if (extensions::WebViewGuest::FromWebContents(web_contents)) { - return base::WrapUnique( - new ContextMenuContentTypeWebView(web_contents, params)); + extensions::WebViewGuest* web_view_guest = + extensions::WebViewGuest::FromRenderFrameHost(render_frame_host); + if (web_view_guest) { + return base::WrapUnique(new ContextMenuContentTypeWebView( + web_view_guest->GetWeakPtr(), params)); } + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(render_frame_host); const extensions::mojom::ViewType view_type = extensions::GetViewType(web_contents); @@ -102,11 +104,10 @@ } if (view_type == extensions::mojom::ViewType::kExtensionPopup) { - return base::WrapUnique( - new ContextMenuContentTypeExtensionPopup(web_contents, params)); + return base::WrapUnique(new ContextMenuContentTypeExtensionPopup(params)); } #endif - return std::make_unique<ContextMenuContentType>(web_contents, params, true); + return std::make_unique<ContextMenuContentType>(params, true); }
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_factory.h b/chrome/browser/renderer_context_menu/context_menu_content_type_factory.h index fb2a142..d059be66 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_factory.h +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_factory.h
@@ -12,13 +12,13 @@ class ContextMenuContentType; namespace content { -class WebContents; +class RenderFrameHost; } class ContextMenuContentTypeFactory { public: static std::unique_ptr<ContextMenuContentType> Create( - content::WebContents* web_contents, + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params); ContextMenuContentTypeFactory(const ContextMenuContentTypeFactory&) = delete; @@ -30,7 +30,7 @@ virtual ~ContextMenuContentTypeFactory(); static std::unique_ptr<ContextMenuContentType> CreateInternal( - content::WebContents* web_contents, + content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params); };
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc index 66225da..603eea6 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.cc
@@ -17,17 +17,16 @@ ContextMenuContentTypePlatformApp::ContextMenuContentTypePlatformApp( content::WebContents* web_contents, const content::ContextMenuParams& params) - : ContextMenuContentType(web_contents, params, false) { -} + : ContextMenuContentType(params, false), + source_web_contents_(web_contents) {} ContextMenuContentTypePlatformApp::~ContextMenuContentTypePlatformApp() { } const Extension* ContextMenuContentTypePlatformApp::GetExtension() { ProcessManager* process_manager = - ProcessManager::Get(source_web_contents()->GetBrowserContext()); - return process_manager->GetExtensionForWebContents( - source_web_contents()); + ProcessManager::Get(source_web_contents_->GetBrowserContext()); + return process_manager->GetExtensionForWebContents(source_web_contents_); } bool ContextMenuContentTypePlatformApp::SupportsGroup(int group) {
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h index cc5f38e..038a49e 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_platform_app.h
@@ -7,6 +7,10 @@ #include "components/renderer_context_menu/context_menu_content_type.h" +namespace content { +class WebContents; +} + namespace extensions { class Extension; } @@ -31,6 +35,8 @@ friend class ContextMenuContentTypeFactory; const extensions::Extension* GetExtension(); + + const raw_ptr<content::WebContents> source_web_contents_; }; #endif // CHROME_BROWSER_RENDERER_CONTEXT_MENU_CONTEXT_MENU_CONTENT_TYPE_PLATFORM_APP_H_
diff --git a/chrome/browser/renderer_context_menu/context_menu_content_type_unittest.cc b/chrome/browser/renderer_context_menu/context_menu_content_type_unittest.cc index 957aeb5..153ed6d 100644 --- a/chrome/browser/renderer_context_menu/context_menu_content_type_unittest.cc +++ b/chrome/browser/renderer_context_menu/context_menu_content_type_unittest.cc
@@ -15,14 +15,7 @@ using extensions::MenuItem; -class ContextMenuContentTypeTest : public ChromeRenderViewHostTestHarness { - public: - static std::unique_ptr<ContextMenuContentType> Create( - content::WebContents* web_contents, - const content::ContextMenuParams& params) { - return std::make_unique<ContextMenuContentType>(web_contents, params, true); - } -}; +using ContextMenuContentTypeTest = ChromeRenderViewHostTestHarness; // Generates a ContextMenuParams that matches the specified contexts. content::ContextMenuParams CreateParams(int contexts) { @@ -67,8 +60,7 @@ TEST_F(ContextMenuContentTypeTest, CheckTypes) { { content::ContextMenuParams params = CreateParams(MenuItem::LINK); - std::unique_ptr<ContextMenuContentType> content_type( - Create(web_contents(), params)); + auto content_type = std::make_unique<ContextMenuContentType>(params, true); EXPECT_TRUE(content_type->SupportsGroup( ContextMenuContentType::ITEM_GROUP_LINK)); EXPECT_TRUE(content_type->SupportsGroup( @@ -79,8 +71,7 @@ { content::ContextMenuParams params = CreateParams(MenuItem::SELECTION); - std::unique_ptr<ContextMenuContentType> content_type( - Create(web_contents(), params)); + auto content_type = std::make_unique<ContextMenuContentType>(params, true); EXPECT_FALSE(content_type->SupportsGroup( ContextMenuContentType::ITEM_GROUP_LINK)); EXPECT_TRUE(content_type->SupportsGroup( @@ -93,8 +84,7 @@ { content::ContextMenuParams params = CreateParams(MenuItem::EDITABLE); - std::unique_ptr<ContextMenuContentType> content_type( - Create(web_contents(), params)); + auto content_type = std::make_unique<ContextMenuContentType>(params, true); EXPECT_FALSE(content_type->SupportsGroup( ContextMenuContentType::ITEM_GROUP_LINK)); EXPECT_FALSE(content_type->SupportsGroup( @@ -105,8 +95,7 @@ { content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); - std::unique_ptr<ContextMenuContentType> content_type( - Create(web_contents(), params)); + auto content_type = std::make_unique<ContextMenuContentType>(params, true); EXPECT_TRUE(content_type->SupportsGroup( ContextMenuContentType::ITEM_GROUP_MEDIA_IMAGE)); EXPECT_TRUE(content_type->SupportsGroup( @@ -124,8 +113,7 @@ { content::ContextMenuParams params = CreateParams(MenuItem::VIDEO); - std::unique_ptr<ContextMenuContentType> content_type( - Create(web_contents(), params)); + auto content_type = std::make_unique<ContextMenuContentType>(params, true); EXPECT_TRUE(content_type->SupportsGroup( ContextMenuContentType::ITEM_GROUP_MEDIA_VIDEO)); @@ -139,8 +127,7 @@ { content::ContextMenuParams params = CreateParams(MenuItem::AUDIO); - std::unique_ptr<ContextMenuContentType> content_type( - Create(web_contents(), params)); + auto content_type = std::make_unique<ContextMenuContentType>(params, true); EXPECT_TRUE(content_type->SupportsGroup( ContextMenuContentType::ITEM_GROUP_MEDIA_AUDIO)); @@ -154,8 +141,7 @@ { content::ContextMenuParams params = CreateParams(MenuItem::FRAME); - std::unique_ptr<ContextMenuContentType> content_type( - Create(web_contents(), params)); + auto content_type = std::make_unique<ContextMenuContentType>(params, true); EXPECT_TRUE(content_type->SupportsGroup( ContextMenuContentType::ITEM_GROUP_FRAME)); EXPECT_TRUE(content_type->SupportsGroup(
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 1b75a2e..fdc3e61 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -733,7 +733,7 @@ IDC_CONTENT_CONTEXT_CUSTOM_LAST); } set_content_type( - ContextMenuContentTypeFactory::Create(source_web_contents_, params)); + ContextMenuContentTypeFactory::Create(&render_frame_host, params)); #if BUILDFLAG(IS_CHROMEOS_ASH) system_app_ = GetBrowser() && GetBrowser()->app_controller() @@ -873,7 +873,9 @@ return; extensions::WebViewGuest* web_view_guest = - extensions::WebViewGuest::FromWebContents(source_web_contents_); + extensions::WebViewGuest::FromRenderFrameHost( + content::RenderFrameHost::FromID(render_process_id_, + render_frame_id_)); MenuItem::ExtensionKey key; if (web_view_guest) { key = MenuItem::ExtensionKey(extension->id(),
diff --git a/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn b/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn index 077b45e8..c7f4a47 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn +++ b/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn
@@ -12,8 +12,8 @@ web_component_files = [ "emoji_button.js", "emoji_category_button.js", - "emoji_group_button.js", "emoji_group.js", + "emoji_group_button.ts", "emoji_picker.js", "emoji_search.js", "emoji_variants.js", @@ -193,7 +193,6 @@ deps = [ ":constants", ":emoji_group", - ":emoji_group_button", ":emoji_picker_api_proxy", ":emoji_search", ":events", @@ -221,13 +220,6 @@ ] } -js_library("emoji_group_button") { - deps = [ - ":events", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - js_library("emoji_group") { deps = [ ":emoji_button", @@ -311,7 +303,6 @@ ":emoji_button", ":emoji_category_button", ":emoji_group", - ":emoji_group_button", ":emoji_picker", ":emoji_picker_api_proxy", ":emoji_search",
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html b/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html index 5c04d8a9..8f41d589 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.html
@@ -28,10 +28,9 @@ <cr-icon-button id="group-button" iron-icon="[[icon]]" - class$="[[_className(active)]]" + class$="[[calculateClassName(active)]]" on-click="handleClick" aria-label="[[name]]" disabled="[[disabled]]" - custom-tab-index="[[customTabIndex]]" - > + custom-tab-index="[[customTabIndex]]"> </cr-icon-button>
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.js b/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.ts similarity index 76% rename from chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.js rename to chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.ts index a99b035..4f03259d 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.js +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_group_button.ts
@@ -12,7 +12,7 @@ export class EmojiGroupButton extends PolymerElement { static get is() { - return 'emoji-group-button'; + return 'emoji-group-button' as const; } static get template() { @@ -21,33 +21,37 @@ static get properties() { return { - /** @type {!string} */ - name: {type: String, readonly: true}, - /** @type {!string} */ - icon: {type: String, readonly: true}, - /** @type {!string} */ - groupId: {type: String, readonly: true}, - /** @type {!boolean} */ active: {type: Boolean, value: false}, - /** @type {!boolean} */ - disabled: {type: Boolean, value: false}, - /** @type {number} */ customTabIndex: {type: Number, value: -1}, + disabled: {type: Boolean, value: false}, + groupId: {type: String, readonly: true}, + icon: {type: String, readonly: true}, + name: {type: String, readonly: true}, }; } - constructor() { - super(); - } + active: boolean; + customTabIndex: number; + disabled: boolean; + groupId: string; + icon: string; + name: string; - handleClick(ev) { + handleClick(): void { this.dispatchEvent( createCustomEvent(GROUP_BUTTON_CLICK, {group: this.groupId})); } - _className(active) { + private calculateClassName(active: boolean): string { return active ? 'emoji-group-active' : ''; } } +declare global { + interface HTMLElementTagNameMap { + [EmojiGroupButton.is]: EmojiGroupButton; + } +} + + customElements.define(EmojiGroupButton.is, EmojiGroupButton);
diff --git a/chrome/browser/resources/family_link_user_internals/DIR_METADATA b/chrome/browser/resources/family_link_user_internals/DIR_METADATA index c0ebf85..7c567602 100644 --- a/chrome/browser/resources/family_link_user_internals/DIR_METADATA +++ b/chrome/browser/resources/family_link_user_internals/DIR_METADATA
@@ -1,3 +1,4 @@ -monorail { - component: "FamilyExperiences" -} \ No newline at end of file +# Chrome Browser +mixins: "//chrome/browser/supervised_user/android/COMMON_METADATA" +# ChromeOS specific +mixins: "//chrome/browser/supervised_user/chromeos/COMMON_METADATA"
diff --git a/chrome/browser/resources/history/BUILD.gn b/chrome/browser/resources/history/BUILD.gn index 278a88cd..0040aa2 100644 --- a/chrome/browser/resources/history/BUILD.gn +++ b/chrome/browser/resources/history/BUILD.gn
@@ -10,7 +10,6 @@ static_files = [ "history.html", - "images/journeys.svg", "images/list.svg", "images/sign_in_promo_dark.svg", "images/sign_in_promo.svg",
diff --git a/chrome/browser/resources/history/app.ts b/chrome/browser/resources/history/app.ts index f590743..6b54282 100644 --- a/chrome/browser/resources/history/app.ts +++ b/chrome/browser/resources/history/app.ts
@@ -211,7 +211,8 @@ tabsIcons_: { type: Array, - value: () => ['images/list.svg', 'images/journeys.svg'], + value: () => + ['images/list.svg', 'chrome://resources/images/icon_journeys.svg'], }, tabsNames_: {
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html index 2f3e8cb6..7ec5fe1 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.html
@@ -29,7 +29,8 @@ } </style> <div class="settings-box two-line no-padding"> - <div actionable$="[[isItemActionable_(activeNetworkState, + <div id="networkSummaryItemRow" + actionable$="[[isItemActionable_(activeNetworkState, deviceState, networkStateList)]]" class="flex layout horizontal center link-wrapper" on-click="onShowDetailsTap_">
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js index 96dfcc9..7021bb4 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js
@@ -27,6 +27,8 @@ import {ConnectionStateType, DeviceStateType, NetworkType, OncSource, PortalState} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {InternetPageBrowserProxy, InternetPageBrowserProxyImpl} from './internet_page_browser_proxy.js'; + /** * @constructor * @extends {PolymerElement} @@ -118,6 +120,13 @@ }; } + constructor() { + super(); + + /** @private {!InternetPageBrowserProxy} */ + this.browserProxy_ = InternetPageBrowserProxyImpl.getInstance(); + } + /* * Returns the device enabled toggle element. * @return {?CrToggleElement} @@ -532,6 +541,10 @@ }); this.dispatchEvent(deviceEnabledToggledEvent); } + } else if ( + this.isCaptivePortalUI2022Enabled_ && + this.isPortalState_(this.activeNetworkState.portalState)) { + this.browserProxy_.showPortalSignin(this.activeNetworkState.guid); } else if (this.shouldShowSubpage_( this.deviceState, this.networkStateList)) { const showNetworksEvent = new CustomEvent('show-networks', { @@ -579,6 +592,12 @@ return this.enableToggleIsEnabled_(this.deviceState); } + // Item is actionable if tapping should show the user to the portal signin. + if (this.isCaptivePortalUI2022Enabled_ && + this.isPortalState_(this.activeNetworkState.portalState)) { + return true; + } + // Item is actionable if tapping should show either networks subpage or the // network details page. return this.shouldShowSubpage_(this.deviceState, this.networkStateList) ||
diff --git a/chrome/browser/resources/settings/chromeos/lazy_load.js b/chrome/browser/resources/settings/chromeos/lazy_load.js index 83b52f8..b70ffffb 100644 --- a/chrome/browser/resources/settings/chromeos/lazy_load.js +++ b/chrome/browser/resources/settings/chromeos/lazy_load.js
@@ -41,6 +41,7 @@ import './os_languages_page/input_method_options_page.js'; import './os_languages_page/input_page.js'; import './os_languages_page/os_edit_dictionary_page.js'; +import './os_languages_page/os_japanese_manage_user_dictionary_page.js'; import './os_languages_page/os_languages_page_v2.js'; import './os_languages_page/os_languages_section.js'; import './os_languages_page/smart_inputs_page.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn index 43714aa..f5b1d1d 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
@@ -27,6 +27,7 @@ ":languages_types", ":os_add_languages_dialog", ":os_edit_dictionary_page", + ":os_japanese_manage_user_dictionary_page", ":os_languages_page_v2", ":os_languages_section", ":smart_inputs_page", @@ -158,6 +159,7 @@ ":input_method_util", ":languages_metrics_proxy", ":os_edit_dictionary_page", + ":os_japanese_manage_user_dictionary_page", "..:deep_linking_behavior", "..:os_route", "..:route_observer_behavior", @@ -197,6 +199,14 @@ ] } +js_library("os_japanese_manage_user_dictionary_page") { + deps = [ + "..:global_scroll_target_behavior", + "..:os_route", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + js_library("os_languages_page_v2") { deps = [ ":input_method_util",
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js index ff1cf63..9a93784c 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
@@ -81,6 +81,7 @@ JAPANESE_SPACE_INPUT_STYLE: 'JapaneseSpaceInputStyle', JAPANESE_SECTION_SHORTCUT: 'JapaneseSectionShortcut', JAPANESE_KEYMAP_STYLE: 'JapaneseKeymapStyle', + JAPANESE_MANAGE_USER_DICTIONARY: 'JapaneseManageUserDictionary', // Options for Korean input method. KOREAN_ENABLE_SYLLABLE_INPUT: 'koreanEnableSyllableInput', KOREAN_KEYBOARD_LAYOUT: 'koreanKeyboardLayout', @@ -265,13 +266,9 @@ ], }, { - // TODO(b/234790486): Customize userDictionaries with the correct values. - // The correct values are the ones from the legacy settings page that used - // to be found in - // chrome-extension://jkghodnilhceideoidjikpgommlajknk/mozc_option.html. title: SettingsHeaders.USER_DICTIONARIES, optionNames: [{ - name: OptionType.JAPANESE_INPUT_MODE, + name: OptionType.JAPANESE_MANAGE_USER_DICTIONARY, }], }, { @@ -488,6 +485,7 @@ case OptionType.ZHUYIN_PAGE_SIZE: return UiType.DROPDOWN; case OptionType.EDIT_USER_DICT: + case OptionType.JAPANESE_MANAGE_USER_DICTIONARY: return UiType.LINK; default: assertNotReached(); @@ -576,6 +574,8 @@ return 'inputMethodOptionsJapaneseUseSystemDictionary'; case OptionType.JAPANESE_NUMBER_OF_SUGGESTIONS: return 'inputMethodOptionsJapaneseNumberOfSuggestions'; + case OptionType.JAPANESE_MANAGE_USER_DICTIONARY: + return 'inputMethodOptionsJapaneseManageUserDictionary'; case OptionType.XKB_LAYOUT: return 'inputMethodOptionsXkbLayout'; case OptionType.EDIT_USER_DICT: @@ -604,6 +604,14 @@ switch (option) { case OptionType.PHYSICAL_KEYBOARD_ENABLE_DIACRITICS_ON_LONGPRESS: return 'inputMethodOptionsDiacriticsOnPhysicalKeyboardLongpressSubtitle'; + // TODO(b/234790486): The subtitle is not forced to the next line if it is + // too short. You end up with something like : + // https://screenshot.googleplex.com/8xk2BfbBXcGqhvs This likely also + // affects the diacritics label. This is not currently an issue since both + // string are long enough and force themself to the next line, but it may be + // an issue in other languages or with future strings which may be shorter. + case OptionType.JAPANESE_MANAGE_USER_DICTIONARY: + return 'inputMethodOptionsJapaneseManageUserDictionarySubtitle'; default: return ''; } @@ -869,6 +877,9 @@ if (option === OptionType.EDIT_USER_DICT) { return routes.OS_LANGUAGES_EDIT_DICTIONARY; } + if (option === OptionType.JAPANESE_MANAGE_USER_DICTIONARY) { + return routes.OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY; + } return undefined; }
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js index 62aa4c01..e8b5784 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
@@ -15,6 +15,7 @@ import './add_input_methods_dialog.js'; import './add_spellcheck_languages_dialog.js'; import './os_edit_dictionary_page.js'; +import './os_japanese_manage_user_dictionary_page.js'; import '../keyboard_shortcut_banner/keyboard_shortcut_banner.js'; import '../../controls/settings_toggle_button.js'; import '../../settings_shared.css.js'; @@ -185,6 +186,7 @@ return loadTimeData.getBoolean('onDeviceGrammarCheckEnabled'); }, }, + /** @private */ onJapaneseSettingsEnabled_: { type: Boolean, @@ -611,6 +613,15 @@ Router.getInstance().navigateTo(routes.OS_LANGUAGES_EDIT_DICTIONARY); } + + /** + * @private + */ + onJapaneseManageUserDictionaryClick_() { + Router.getInstance().navigateTo( + routes.OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY); + } + /** * Gets the appropriate CSS class for the Enhanced spell check toggle * depending on whether Update 2 is enabled or not.
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_japanese_manage_user_dictionary_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_japanese_manage_user_dictionary_page.html new file mode 100644 index 0000000..970c534b --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_japanese_manage_user_dictionary_page.html
@@ -0,0 +1,10 @@ +<style include="settings-shared"> + :host { + display: flex; + flex-direction: column; + } +</style> +<div class="cr-row continuation"> + TODO(b/234790486): Add the correct contents here. +</div> +
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_japanese_manage_user_dictionary_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_japanese_manage_user_dictionary_page.js new file mode 100644 index 0000000..8ce55ed --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_japanese_manage_user_dictionary_page.js
@@ -0,0 +1,59 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview 'os-settings-japanese-manage-user-dictionary-page' is a + * sub-page for editing the dictionary of words used for Japanese input + * methods. + */ + +import '../../settings_shared.css.js'; + +import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/cr_elements/i18n_behavior.js'; +import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {Route} from '../../router.js'; +import {GlobalScrollTargetBehavior, GlobalScrollTargetBehaviorInterface} from '../global_scroll_target_behavior.js'; +import {routes} from '../os_route.js'; + +import {getTemplate} from './os_japanese_manage_user_dictionary_page.html.js'; + +/** + * @constructor + * @extends {PolymerElement} + * @implements {I18nBehaviorInterface} + * @implements {GlobalScrollTargetBehaviorInterface} + */ +const OsSettingsJapaneseManageUserDictionaryPageElementBase = + mixinBehaviors([I18nBehavior, GlobalScrollTargetBehavior], PolymerElement); + +/** @polymer */ +class OsSettingsJapaneseManageUserDictionaryPageElement extends + OsSettingsJapaneseManageUserDictionaryPageElementBase { + static get is() { + return 'os-settings-japanese-manage-user-dictionary-page'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + /** + * Needed for GlobalScrollTargetBehavior. + * @type {!Route} + * @override + */ + subpageRoute: { + type: Object, + value: routes.OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY, + }, + }; + } +} + +customElements.define( + OsSettingsJapaneseManageUserDictionaryPageElement.is, + OsSettingsJapaneseManageUserDictionaryPageElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.html index 8aef9ab5..5238be1 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.html +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.html
@@ -82,4 +82,13 @@ <os-settings-edit-dictionary-page></os-settings-edit-dictionary-page> </settings-subpage> </template> + + <!-- "Japanese Manage User dictionary" sub-sub-page. --> + <template is="dom-if" route-path="/osLanguages/japaneseManageUserDictionary"> + <settings-subpage page-title="$i18n{japaneseManageUserDictionaryLabel}"> + <os-settings-japanese-manage-user-dictionary-page> + </os-settings-japanese-manage-user-dictionary-page> + </settings-subpage> + </template> + </settings-animated-pages>
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js index 8ad6355..eb6e028 100644 --- a/chrome/browser/resources/settings/chromeos/os_route.js +++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -328,6 +328,10 @@ r.OS_LANGUAGES_EDIT_DICTIONARY = createSubpage( r.OS_LANGUAGES_INPUT, routesMojomWebui.EDIT_DICTIONARY_SUBPAGE_PATH, Subpage.kEditDictionary); + r.OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY = createSubpage( + r.OS_LANGUAGES_INPUT, + routesMojomWebui.JAPANESE_MANAGE_USER_DICTIONARY_SUBPAGE_PATH, + Subpage.kJapaneseManageUserDictionary); r.OS_LANGUAGES_SMART_INPUTS = createSubpage( r.OS_LANGUAGES, routesMojomWebui.SMART_INPUTS_SUBPAGE_PATH, Subpage.kSmartInputs);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index 0a16d29..301548d 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -28,6 +28,7 @@ "chromeos/os_languages_page/input_page.js", "chromeos/os_languages_page/os_add_languages_dialog.js", "chromeos/os_languages_page/os_edit_dictionary_page.js", + "chromeos/os_languages_page/os_japanese_manage_user_dictionary_page.js", "chromeos/os_languages_page/os_languages_page_v2.js", "chromeos/os_languages_page/os_languages_section.js", "chromeos/os_languages_page/smart_inputs_page.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_routes.js b/chrome/browser/resources/settings/chromeos/os_settings_routes.js index 29f3417e..413beb7e 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_routes.js +++ b/chrome/browser/resources/settings/chromeos/os_settings_routes.js
@@ -74,6 +74,7 @@ * OS_ACCESSIBILITY: !Route, * OS_LANGUAGES: !Route, * OS_LANGUAGES_EDIT_DICTIONARY: !Route, + * OS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY: !Route, * OS_LANGUAGES_INPUT: !Route, * OS_LANGUAGES_INPUT_METHOD_OPTIONS: !Route, * OS_LANGUAGES_LANGUAGES: !Route,
diff --git a/chrome/browser/supervised_user/DIR_METADATA b/chrome/browser/supervised_user/DIR_METADATA index c0ebf85..7c567602 100644 --- a/chrome/browser/supervised_user/DIR_METADATA +++ b/chrome/browser/supervised_user/DIR_METADATA
@@ -1,3 +1,4 @@ -monorail { - component: "FamilyExperiences" -} \ No newline at end of file +# Chrome Browser +mixins: "//chrome/browser/supervised_user/android/COMMON_METADATA" +# ChromeOS specific +mixins: "//chrome/browser/supervised_user/chromeos/COMMON_METADATA"
diff --git a/chrome/browser/supervised_user/android/COMMON_METADATA b/chrome/browser/supervised_user/android/COMMON_METADATA new file mode 100644 index 0000000..285d50de --- /dev/null +++ b/chrome/browser/supervised_user/android/COMMON_METADATA
@@ -0,0 +1,14 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +# Chrome Kids team +team_email: "chrome-kids-eng@google.com" +os: ANDROID +monorail { + component: "FamilyExperiences > Browser" +} \ No newline at end of file
diff --git a/chrome/browser/supervised_user/chromeos/COMMON_METADATA b/chrome/browser/supervised_user/chromeos/COMMON_METADATA new file mode 100644 index 0000000..703e0f1 --- /dev/null +++ b/chrome/browser/supervised_user/chromeos/COMMON_METADATA
@@ -0,0 +1,15 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +# ChromeOS FamilyExperiences team +team_email: "cros-families-eng@google.com" +os: CHROME_OS +buganizer { + # ChromeOS > Software > Family > Parental controls + component_id: 1090157 +} \ No newline at end of file
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/DIR_METADATA b/chrome/browser/supervised_user/supervised_user_error_page/DIR_METADATA deleted file mode 100644 index d4229da..0000000 --- a/chrome/browser/supervised_user/supervised_user_error_page/DIR_METADATA +++ /dev/null
@@ -1,3 +0,0 @@ -monorail: { - component: "Services>SupervisedUser" -}
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn index 40c3028..fa6823aa 100644 --- a/chrome/browser/ui/android/omnibox/BUILD.gn +++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -425,6 +425,7 @@ "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java", + "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinderUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java", ] deps = [
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java index 74f3324d..819543e 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java
@@ -41,7 +41,7 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor; /** - * Tests for {@link BaseSuggestionViewProcessor}. + * Tests for {@link HeaderViewBinder}. */ @RunWith(BaseRobolectricTestRunner.class) public class HeaderViewBinderUnitTest {
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java index 24b8a88..39c6c67 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java
@@ -16,7 +16,6 @@ /** Container view for omnibox tail suggestions. */ public class TailSuggestionView extends TextView { private AlignmentManager mAlignmentManager; - private TextView mTextLine2; private int mFullTextWidth; private int mQueryTextWidth;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinderUnitTest.java new file mode 100644 index 0000000..6cb35012 --- /dev/null +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinderUnitTest.java
@@ -0,0 +1,85 @@ +// Copyright 2022 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.omnibox.suggestions.tail; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.view.ContextThemeWrapper; + +import androidx.annotation.ColorInt; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ContextUtils; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider; +import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; +import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable; +import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModelChangeProcessor; + +/** + * Tests for {@link TailSuggestionViewBinder}. + */ +@RunWith(BaseRobolectricTestRunner.class) +public class TailSuggestionViewBinderUnitTest { + private PropertyModel mModel; + private Context mContext; + + private TailSuggestionView mTailSuggestionView; + + @Before + public void setUp() { + mContext = new ContextThemeWrapper( + ContextUtils.getApplicationContext(), R.style.Theme_BrowserUI_DayNight); + + mTailSuggestionView = spy(new TailSuggestionView(mContext)); + + mModel = new PropertyModel(TailSuggestionViewProperties.ALL_KEYS); + PropertyModelChangeProcessor.create( + mModel, mTailSuggestionView, TailSuggestionViewBinder::bind); + } + + @Test + public void tailSuggestionView_setAlignmentManager() { + AlignmentManager alignmentManager = new AlignmentManager(); + + mModel.set(TailSuggestionViewProperties.ALIGNMENT_MANAGER, alignmentManager); + verify(mTailSuggestionView, times(1)).setAlignmentManager(alignmentManager); + } + + @Test + public void tailSuggestionView_setTailText() { + final SuggestionSpannable span = new SuggestionSpannable("test"); + + mModel.set(TailSuggestionViewProperties.TEXT, span); + verify(mTailSuggestionView, times(1)).setTailText(span); + } + + @Test + public void tailSuggestionView_setFullText() { + final String test = "test"; + + mModel.set(TailSuggestionViewProperties.FILL_INTO_EDIT, test); + verify(mTailSuggestionView, times(1)).setFullText(test); + } + + @Test + public void tailSuggestionView_setTextColor() { + final @BrandedColorScheme int colorScheme = BrandedColorScheme.LIGHT_BRANDED_THEME; + final @ColorInt int color = + OmniboxResourceProvider.getSuggestionPrimaryTextColor(mContext, colorScheme); + + mModel.set(SuggestionCommonProperties.COLOR_SCHEME, colorScheme); + verify(mTailSuggestionView, times(1)).setTextColor(color); + } +}
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 70e73e68..272b563 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1696,14 +1696,6 @@ Discard </message> - <!-- Download later --> - <message name="IDS_DOWNLOAD_DATE_TIME_PICKER_NEXT_TEXT" desc="The text for the positive button of the download date time picker dialog."> - Next - </message> - <message name="IDS_DOWNLOAD_LATER_PROMPT_ENABLED_TITLE" desc="A setting text to ask whether to show a dialog about when to download."> - Ask when to save files - </message> - <!-- Downloads location --> <message name="IDS_DOWNLOADS_LOCATION_SELECTOR_TITLE" desc="Title of the preference that allows the user to select which of the folders they would like to make the default location to save their downloads."> Download location @@ -2255,20 +2247,6 @@ =1 {1 download pending} other {# downloads pending}} </message> - <message name="IDS_DOWNLOAD_MESSAGE_MULTIPLE_DOWNLOAD_SCHEDULED" desc="Download message label describing that one or more downloads are scheduled"> - {FILE_COUNT, plural, - =1 {1 download scheduled} - other {# downloads scheduled}} - </message> - <message name="IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_WIFI" desc="Download message text describing that user can find about their download status from notifications."> - Download will start when on Wi-Fi - </message> - <message name="IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_DATE" desc="Download message text describing that the download was scheduled to start at a later date."> - Download will start on <ph name="date">%1$s<ex>Feb 28 2020</ex></ph>. - </message> - <message name="IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_TIME" desc="Download message text describing that the download was scheduled to start at a later time."> - Download will start at <ph name="time">%1$s<ex>8:30PM</ex></ph>. - </message> <message name="IDS_INCOGNITO_DOWNLOAD_MESSAGE_TITLE" desc="Download title displayed in a prompt message when the user downloads a file in Incognito mode."> Download file? @@ -2745,9 +2723,6 @@ <message name="IDS_DOWNLOAD_MANAGER_JUST_NOW" desc="Text on a label describing that the associated download event happened just now."> Just now </message> - <message name="IDS_DOWNLOAD_MANAGER_SCHEDULED_LATER" desc="Text on a label describing that the associated download is scheduled to start later."> - Scheduled for later - </message> <message name="IDS_DOWNLOAD_MANAGER_OFFLINE_HOME" desc="The title text on download home indicating that we are in offline mode."> Offline Home </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_DATE_TIME_PICKER_NEXT_TEXT.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_DATE_TIME_PICKER_NEXT_TEXT.png.sha1 deleted file mode 100644 index eb24acd..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_DATE_TIME_PICKER_NEXT_TEXT.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -4a9a742779890d13e4b916628bc2a6efc43e30ab \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_LATER_PROMPT_ENABLED_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_LATER_PROMPT_ENABLED_TITLE.png.sha1 deleted file mode 100644 index 699e153..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_LATER_PROMPT_ENABLED_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -3fb075cb87cc44916ff6929f20fa57fc22d24650 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_SCHEDULED_LATER.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_SCHEDULED_LATER.png.sha1 deleted file mode 100644 index 2e46edb..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MANAGER_SCHEDULED_LATER.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -37cf1e7cb53c553b9ec0ef63d08c45d5dabdf9fe \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_DATE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_DATE.png.sha1 deleted file mode 100644 index 34a6994..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_DATE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -ed07fd1d3c986ba70bc830fa6737c0d26f3074c8 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_TIME.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_TIME.png.sha1 deleted file mode 100644 index 4791936..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_TIME.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -0d24281949a4e8c12486695637602a6d1d4f6e35 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_WIFI.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_WIFI.png.sha1 deleted file mode 100644 index ba69021..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_DOWNLOAD_SCHEDULED_DESCRIPTION_ON_WIFI.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -ce725fe678c74d222f8e3d7906b5ea8c849a3e6f \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_MULTIPLE_DOWNLOAD_SCHEDULED.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_MULTIPLE_DOWNLOAD_SCHEDULED.png.sha1 deleted file mode 100644 index f0a8844..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_DOWNLOAD_MESSAGE_MULTIPLE_DOWNLOAD_SCHEDULED.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -795499cb3552abce6563e4ef6184487b3c1a7075 \ No newline at end of file
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.cc b/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.cc index 1a52bdb..28ca0e6 100644 --- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.cc +++ b/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.cc
@@ -4,9 +4,11 @@ #include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h" +#include "chrome/browser/ash/file_manager/fileapi_util.h" #include "chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.h" #include "chrome/browser/ui/app_list/search/files/file_suggest_util.h" #include "chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h" +#include "storage/browser/file_system/file_system_context.h" namespace app_list { @@ -17,7 +19,9 @@ FileSuggestKeyedService::FileSuggestKeyedService( Profile* profile, PersistentProto<RemovedResultsProto> proto) - : proto_(std::move(proto)) { + : profile_(profile), proto_(std::move(proto)) { + DCHECK(profile_); + proto_.RegisterOnRead( base::BindOnce(&FileSuggestKeyedService::OnRemovedSuggestionProtoReady, weak_factory_.GetWeakPtr())); @@ -68,27 +72,58 @@ } } +void FileSuggestKeyedService::RemoveSuggestionsAndNotify( + const std::vector<base::FilePath>& absolute_file_paths) { + if (!IsProtoInitialized()) + return; + + // Record the types of the removed suggestions. `observers_` should be + // notified of the updates on these types. + base::flat_set<FileSuggestionType> types_to_update; + + for (const auto& file_path : absolute_file_paths) { + DCHECK(file_path.IsAbsolute()); + + // Calculate the suggestion type based on `file_path`. + GURL crack_url; + const bool resolve_success = + file_manager::util::ConvertAbsoluteFilePathToFileSystemUrl( + profile_, file_path, file_manager::util::GetFileManagerURL(), + &crack_url); + DCHECK(resolve_success); + const storage::FileSystemURL& file_system_url = + file_manager::util::GetFileManagerFileSystemContext(profile_) + ->CrackURLInFirstPartyContext(crack_url); + DCHECK(file_system_url.is_valid()); + const FileSuggestionType type = + file_system_url.type() == storage::kFileSystemTypeDriveFs + ? FileSuggestionType::kDriveFile + : FileSuggestionType::kLocalFile; + + // Record the suggestion id to the storage proto's map. + // Note: We are using a map for its set capabilities; the map value is + // arbitrary. + const bool success = + proto_->mutable_removed_ids() + ->insert({CalculateSuggestionId(type, file_path), false}) + .second; + + // Skip the suggestion whose id is already in `proto_`. + if (success) + types_to_update.insert(type); + } + + proto_.StartWrite(); + + for (const auto& type : types_to_update) + OnSuggestionProviderUpdated(type); +} + PersistentProto<RemovedResultsProto>* FileSuggestKeyedService::GetProto( base::PassKey<RankerDelegate>) { return &proto_; } -void FileSuggestKeyedService::RemoveFileSuggestion( - FileSuggestionType type, - const std::string& suggestion_id) { - if (proto_.initialized()) { - // Record the string ID of `result` to the storage proto's map. - // Note: We are using a map for its set capabilities; the map value is - // arbitrary. - proto_->mutable_removed_ids()->insert({suggestion_id, false}); - proto_.StartWrite(); - - // Suggestions of `type` update because of a new removed suggestion. Notify - // clients of this update. - OnSuggestionProviderUpdated(type); - } -} - void FileSuggestKeyedService::AddObserver(Observer* observer) { observers_.AddObserver(observer); }
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h b/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h index b2294cf..6b373e5 100644 --- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h +++ b/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h
@@ -61,6 +61,12 @@ virtual void GetSuggestFileData(FileSuggestionType type, GetSuggestFileDataCallback callback); + // Persists the ids of the suggestions specified by `absolute_file_paths` so + // that the corresponding suggestions are not sent to service clients anymore. + // Also notifies observers of suggestion updates. Overridden for tests. + virtual void RemoveSuggestionsAndNotify( + const std::vector<base::FilePath>& absolute_file_paths); + // Used to expose `proto_` to app list so that the app list can query/remove // non-file result ids from `proto_`. // TODO(https://crbug.com/1368833): remove this function when the removed file @@ -68,11 +74,6 @@ // list's. PersistentProto<RemovedResultsProto>* GetProto(base::PassKey<RankerDelegate>); - // Persists `suggestion_id` so that the corresponding suggestion is not sent - // to service clients anymore. - void RemoveFileSuggestion(FileSuggestionType type, - const std::string& suggestion_id); - // Adds/Removes an observer. void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -116,6 +117,8 @@ base::ObserverList<Observer> observers_; + Profile* const profile_; + // Used to query/persis the removed result ids. NOTE: `proto_` contains // non-file ids. // TODO(https://crbug.com/1368833): `proto_` should only contain file ids
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc b/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc index cce6f615..ea7b11a 100644 --- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc +++ b/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc
@@ -5,11 +5,14 @@ #include <memory> #include "base/files/scoped_temp_dir.h" +#include "base/scoped_observation.h" #include "base/test/metrics/histogram_tester.h" #include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h" #include "chrome/browser/ui/app_list/search/files/file_suggest_test_util.h" #include "chrome/browser/ui/app_list/search/files/file_suggest_util.h" #include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h" +#include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.h" +#include "chrome/browser/ui/ash/holding_space/scoped_test_mount_point.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -17,6 +20,9 @@ #include "testing/gtest/include/gtest/gtest.h" namespace app_list { +// TODO(https://crbug.com/1370774): move `ScopedTestMountPoint` out of holding +// space to remove the dependency on holding space code. +using ash::holding_space::ScopedTestMountPoint; class FileSuggestKeyedServiceTest : public testing::Test { protected: @@ -63,6 +69,24 @@ FileSuggestKeyedServiceTest::SetUp(); file_suggest_service_ = static_cast<MockFileSuggestKeyedService*>( FileSuggestKeyedServiceFactory::GetInstance()->GetService(profile_)); + + // Initialize the local file mount point. + local_fs_mount_point_ = std::make_unique<ScopedTestMountPoint>( + /*name=*/"test_mount", storage::kFileSystemTypeLocal, + file_manager::VOLUME_TYPE_TESTING); + local_fs_mount_point_->Mount(profile_); + + // Initialize the drive file mount point. + drive_fs_mount_point_ = std::make_unique<ScopedTestMountPoint>( + /*name=*/"drivefs-delayed_mount", storage::kFileSystemTypeDriveFs, + file_manager::VOLUME_TYPE_GOOGLE_DRIVE); + drive_fs_mount_point_->Mount(profile_); + } + + void TearDown() override { + drive_fs_mount_point_.reset(); + local_fs_mount_point_.reset(); + FileSuggestKeyedServiceTest::TearDown(); } TestingProfile::TestingFactories GetTestingFactories() override { @@ -90,76 +114,148 @@ return suggestions; } + // Creates files and suggests these files through the file suggest keyed + // service. Returns paths to these files. + std::vector<base::FilePath> PrepareFileSuggestionsForType( + FileSuggestionType type, + size_t count) { + ScopedTestMountPoint* mount_point = nullptr; + switch (type) { + case FileSuggestionType::kDriveFile: + mount_point = drive_fs_mount_point_.get(); + break; + case FileSuggestionType::kLocalFile: + mount_point = local_fs_mount_point_.get(); + break; + } + + std::vector<base::FilePath> suggested_file_paths; + std::vector<FileSuggestData> suggestions; + for (size_t index = 0; index < count; ++index) { + suggested_file_paths.push_back(mount_point->CreateArbitraryFile()); + suggestions.emplace_back(type, suggested_file_paths.back(), + /*new_prediction_reason=*/absl::nullopt, + /*new_score=*/absl::nullopt); + } + file_suggest_service_->SetSuggestionsForType(type, suggestions); + return suggested_file_paths; + } + // Hosts the proto file. base::ScopedTempDir temp_dir_; // This test verifies the suggestion removal only. Therefore, a mock file // suggest keyed service is sufficient. MockFileSuggestKeyedService* file_suggest_service_ = nullptr; + + // The mount point for local files. + std::unique_ptr<ScopedTestMountPoint> local_fs_mount_point_; + + // The mount point for drive files. + std::unique_ptr<ScopedTestMountPoint> drive_fs_mount_point_; }; -// Verifies that a removed suggestion is not fetchable. -TEST_F(FileSuggestKeyedServiceRemoveTest, SuggestionRemoval) { - const base::FilePath path1("file1"); - const base::FilePath path2("file2"); - file_suggest_service_->SetSuggestionsForType( - /*type=*/FileSuggestionType::kDriveFile, - /*suggestions=*/std::vector<FileSuggestData>{ - {FileSuggestionType::kDriveFile, path1, - /*new_prediction_reason=*/absl::nullopt, - /*new_score=*/absl::nullopt}, - {FileSuggestionType::kDriveFile, path2, - /*new_prediction_reason=*/absl::nullopt, - /*new_score=*/absl::nullopt}}); +// Verifies removing drive file suggestions. +TEST_F(FileSuggestKeyedServiceRemoveTest, RemoveDriveFileSuggestions) { + const std::vector<base::FilePath> drive_file_suggestions = + PrepareFileSuggestionsForType(FileSuggestionType::kDriveFile, + /*count=*/2); + const base::FilePath& file_path_1 = drive_file_suggestions[0]; + const base::FilePath& file_path_2 = drive_file_suggestions[1]; absl::optional<std::vector<FileSuggestData>> suggestions = GetSuggestionsForType(FileSuggestionType::kDriveFile); - EXPECT_EQ(2u, suggestions->size()); - EXPECT_EQ("file1", suggestions->at(0).file_path.value()); - EXPECT_EQ("zero_state_drive://file1", suggestions->at(0).id); - EXPECT_EQ("file2", suggestions->at(1).file_path.value()); - EXPECT_EQ("zero_state_drive://file2", suggestions->at(1).id); + EXPECT_EQ(suggestions->size(), 2u); + EXPECT_EQ(suggestions->at(0).file_path.value(), file_path_1.value()); + EXPECT_EQ(suggestions->at(0).id, "zero_state_drive://" + file_path_1.value()); + EXPECT_EQ(suggestions->at(1).file_path.value(), file_path_2.value()); + EXPECT_EQ(suggestions->at(1).id, "zero_state_drive://" + file_path_2.value()); - file_suggest_service_->RemoveFileSuggestion( - /*type=*/FileSuggestionType::kDriveFile, - /*suggestion_id=*/"zero_state_drive://" + path1.value()); + MockFileSuggestKeyedServiceObserver observer_mocker; + base::ScopedObservation<FileSuggestKeyedService, + FileSuggestKeyedService::Observer> + scoped_observation(&observer_mocker); + scoped_observation.Observe(file_suggest_service_); + // The observer should be notified of the drive file suggestion update. + EXPECT_CALL(observer_mocker, + OnFileSuggestionUpdated(FileSuggestionType::kDriveFile)); + + file_suggest_service_->RemoveSuggestionsAndNotify( + /*absolute_file_paths=*/{{file_path_1}}); + + // Check the suggested files after suggestion removal. suggestions = GetSuggestionsForType(FileSuggestionType::kDriveFile); - EXPECT_EQ(1u, suggestions->size()); - EXPECT_EQ("file2", suggestions->at(0).file_path.value()); - EXPECT_EQ("zero_state_drive://file2", suggestions->at(0).id); + EXPECT_EQ(suggestions->size(), 1u); + EXPECT_EQ(suggestions->at(0).file_path.value(), file_path_2.value()); + EXPECT_EQ(suggestions->at(0).id, "zero_state_drive://" + file_path_2.value()); +} - const base::FilePath path3("file3"); - const base::FilePath path4("file4"); - file_suggest_service_->SetSuggestionsForType( - /*type=*/FileSuggestionType::kLocalFile, - /*suggestions=*/std::vector<FileSuggestData>{ - {FileSuggestionType::kLocalFile, path3, - /*new_prediction_reason=*/absl::nullopt, - /*new_score=*/absl::nullopt}, - {FileSuggestionType::kLocalFile, path4, - /*new_prediction_reason=*/absl::nullopt, - /*new_score=*/absl::nullopt}}); +// Verifies removing local file suggestions. +TEST_F(FileSuggestKeyedServiceRemoveTest, RemoveLocalFileSuggestions) { + const std::vector<base::FilePath> local_file_suggestions = + PrepareFileSuggestionsForType(FileSuggestionType::kLocalFile, + /*count=*/2); + const base::FilePath& file_path_1 = local_file_suggestions[0]; + const base::FilePath& file_path_2 = local_file_suggestions[1]; + + absl::optional<std::vector<FileSuggestData>> suggestions = + GetSuggestionsForType(FileSuggestionType::kLocalFile); + EXPECT_EQ(suggestions->size(), 2u); + EXPECT_EQ(suggestions->at(0).file_path.value(), file_path_1.value()); + EXPECT_EQ(suggestions->at(0).id, "zero_state_file://" + file_path_1.value()); + EXPECT_EQ(suggestions->at(1).file_path.value(), file_path_2.value()); + EXPECT_EQ(suggestions->at(1).id, "zero_state_file://" + file_path_2.value()); + + MockFileSuggestKeyedServiceObserver observer_mocker; + base::ScopedObservation<FileSuggestKeyedService, + FileSuggestKeyedService::Observer> + scoped_observation(&observer_mocker); + scoped_observation.Observe(file_suggest_service_); + + // The observer should be notified of the local file suggestion update. + EXPECT_CALL(observer_mocker, + OnFileSuggestionUpdated(FileSuggestionType::kLocalFile)); + + file_suggest_service_->RemoveSuggestionsAndNotify( + /*absolute_file_paths=*/{file_path_2}); + + // Check the suggested files after suggestion removal. suggestions = GetSuggestionsForType(FileSuggestionType::kLocalFile); - EXPECT_EQ(2u, suggestions->size()); - EXPECT_EQ("file3", suggestions->at(0).file_path.value()); - EXPECT_EQ("zero_state_file://file3", suggestions->at(0).id); - EXPECT_EQ("file4", suggestions->at(1).file_path.value()); - EXPECT_EQ("zero_state_file://file4", suggestions->at(1).id); + EXPECT_EQ(suggestions->size(), 1u); + EXPECT_EQ(suggestions->at(0).file_path.value(), file_path_1.value()); + EXPECT_EQ(suggestions->at(0).id, "zero_state_file://" + file_path_1.value()); +} - file_suggest_service_->RemoveFileSuggestion( - /*type=*/FileSuggestionType::kLocalFile, - /*suggestion_id=*/"zero_state_file://" + path3.value()); - suggestions = GetSuggestionsForType(FileSuggestionType::kLocalFile); - EXPECT_EQ(1u, suggestions->size()); - EXPECT_EQ("file4", suggestions->at(0).file_path.value()); - EXPECT_EQ("zero_state_file://file4", suggestions->at(0).id); +// Verifies removing drive and local file suggestions at the same time. +TEST_F(FileSuggestKeyedServiceRemoveTest, RemoveMixedFileSuggestions) { + const std::vector<base::FilePath> drive_file_suggestions = + PrepareFileSuggestionsForType(FileSuggestionType::kDriveFile, + /*count=*/1); + const std::vector<base::FilePath> local_file_suggestions = + PrepareFileSuggestionsForType(FileSuggestionType::kLocalFile, + /*count=*/1); - file_suggest_service_->RemoveFileSuggestion( - /*type=*/FileSuggestionType::kDriveFile, - /*suggestion_id=*/"zero_state_drive://" + path2.value()); - suggestions = GetSuggestionsForType(FileSuggestionType::kDriveFile); - EXPECT_TRUE(suggestions->empty()); + MockFileSuggestKeyedServiceObserver observer_mocker; + base::ScopedObservation<FileSuggestKeyedService, + FileSuggestKeyedService::Observer> + scoped_observation(&observer_mocker); + scoped_observation.Observe(file_suggest_service_); + + // The observer should be notified of the updates in drive and local file + // suggestions. + EXPECT_CALL(observer_mocker, + OnFileSuggestionUpdated(FileSuggestionType::kDriveFile)); + EXPECT_CALL(observer_mocker, + OnFileSuggestionUpdated(FileSuggestionType::kLocalFile)); + + file_suggest_service_->RemoveSuggestionsAndNotify( + /*absolute_file_paths=*/{drive_file_suggestions[0], + local_file_suggestions[0]}); + + // Check the suggested files after suggestion removal. + EXPECT_TRUE(GetSuggestionsForType(FileSuggestionType::kDriveFile)->empty()); + EXPECT_TRUE(GetSuggestionsForType(FileSuggestionType::kLocalFile)->empty()); } } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_util.cc b/chrome/browser/ui/app_list/search/files/file_suggest_util.cc index a586fd1..65d6b7a1 100644 --- a/chrome/browser/ui/app_list/search/files/file_suggest_util.cc +++ b/chrome/browser/ui/app_list/search/files/file_suggest_util.cc
@@ -25,7 +25,7 @@ } // namespace -// FileSuggestData ------------------------------------------------------- +// FileSuggestData ------------------------------------------------------------- FileSuggestData::FileSuggestData( FileSuggestionType new_type, @@ -34,7 +34,7 @@ absl::optional<float> new_score) : type(new_type), file_path(new_file_path), - id(GetPrefixFromSuggestionType(type) + file_path.value()), + id(CalculateSuggestionId(type, file_path)), prediction_reason(new_prediction_reason), score(new_score) {} @@ -46,4 +46,11 @@ FileSuggestData::~FileSuggestData() = default; +// Helper functions ------------------------------------------------------------ + +std::string CalculateSuggestionId(FileSuggestionType type, + const base::FilePath& file_path) { + return GetPrefixFromSuggestionType(type) + file_path.value(); +} + } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_util.h b/chrome/browser/ui/app_list/search/files/file_suggest_util.h index a79360d..0a52b53 100644 --- a/chrome/browser/ui/app_list/search/files/file_suggest_util.h +++ b/chrome/browser/ui/app_list/search/files/file_suggest_util.h
@@ -64,6 +64,10 @@ absl::optional<float> score; }; +// Calculates the id of a file suggestion specified by `type` and `file_path`. +std::string CalculateSuggestionId(FileSuggestionType type, + const base::FilePath& file_path); + } // namespace app_list #endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.cc b/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.cc index cfd78fa..39c9327 100644 --- a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.cc +++ b/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.cc
@@ -24,7 +24,14 @@ MockFileSuggestKeyedService::MockFileSuggestKeyedService( Profile* profile, PersistentProto<RemovedResultsProto> proto) - : app_list::FileSuggestKeyedService(profile, std::move(proto)) {} + : app_list::FileSuggestKeyedService(profile, std::move(proto)) { + ON_CALL(*this, RemoveSuggestionsAndNotify) + .WillByDefault( + [this](const std::vector<base::FilePath>& suggested_file_paths) { + FileSuggestKeyedService::RemoveSuggestionsAndNotify( + suggested_file_paths); + }); +} MockFileSuggestKeyedService::~MockFileSuggestKeyedService() = default;
diff --git a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h b/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h index 674ec82..16c8e3d 100644 --- a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h +++ b/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h" #include "chrome/browser/ui/app_list/search/files/file_suggest_util.h" +#include "testing/gmock/include/gmock/gmock.h" namespace content { class BrowserContext; @@ -38,6 +39,10 @@ // app_list::FileSuggestKeyedService: void GetSuggestFileData(app_list::FileSuggestionType type, GetSuggestFileDataCallback callback) override; + MOCK_METHOD(void, + RemoveSuggestionsAndNotify, + (const std::vector<base::FilePath>& suggested_file_paths), + (override)); void SetSuggestionsForType( app_list::FileSuggestionType type,
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc index a2ff62a..fa1ac7a 100644 --- a/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc +++ b/chrome/browser/ui/app_list/search/search_result_ranker/recurrence_ranker_util.cc
@@ -102,7 +102,7 @@ if (!bin_weights) return false; - for (const Value& bin_weight : bin_weights.value()->GetListDeprecated()) { + for (const Value& bin_weight : bin_weights.value()->GetList()) { const auto& bin = GetInt(&bin_weight, "bin"); const auto& weight = GetDouble(&bin_weight, "weight"); if (!bin || !weight) @@ -127,7 +127,7 @@ proto->set_learning_rate(learning_rate.value()); bool success = true; - for (const Value& predictor : predictors.value()->GetListDeprecated()) + for (const Value& predictor : predictors.value()->GetList()) success &= ConvertRecurrencePredictor(&predictor, proto->add_predictors()); return success; }
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc b/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc index 44bff98..ecd2e537 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc
@@ -19,6 +19,8 @@ #include "chrome/browser/ash/file_manager/fileapi_util.h" #include "chrome/browser/ash/file_manager/open_util.h" #include "chrome/browser/ash/file_manager/path_util.h" +#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h" +#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h" #include "chrome/browser/ui/ash/clipboard_util.h" #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h" #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h" @@ -302,6 +304,13 @@ service->AddPinnedFiles(file_system_urls); } +void HoldingSpaceClientImpl::RemoveFileSuggestions( + const std::vector<base::FilePath>& absolute_file_paths) { + app_list::FileSuggestKeyedServiceFactory::GetInstance() + ->GetService(profile_) + ->RemoveSuggestionsAndNotify(absolute_file_paths); +} + void HoldingSpaceClientImpl::ShowItemInFolder(const HoldingSpaceItem& item, SuccessCallback callback) { holding_space_metrics::RecordItemAction(
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_client_impl.h b/chrome/browser/ui/ash/holding_space/holding_space_client_impl.h index 4b36834..54dc228 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_client_impl.h +++ b/chrome/browser/ui/ash/holding_space/holding_space_client_impl.h
@@ -37,6 +37,8 @@ void OpenMyFiles(SuccessCallback callback) override; void PinFiles(const std::vector<base::FilePath>& file_paths) override; void PinItems(const std::vector<const HoldingSpaceItem*>& items) override; + void RemoveFileSuggestions( + const std::vector<base::FilePath>& absolute_file_paths) override; void ShowItemInFolder(const HoldingSpaceItem&, SuccessCallback) override; void UnpinItems(const std::vector<const HoldingSpaceItem*>& items) override;
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc index b5a7616..f5d5f92 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/components/arc/session/arc_service_manager.h" #include "ash/constants/ash_features.h" +#include "ash/public/cpp/holding_space/holding_space_client.h" #include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_controller.h" #include "ash/public/cpp/holding_space/holding_space_controller_observer.h" @@ -57,7 +58,6 @@ #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/test/async_file_test_helper.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/chromeos/styles/cros_styles.h" @@ -2997,6 +2997,39 @@ HoldingSpaceSuggestionsDelegateTest, /*enable_suggestion_feature=*/testing::Bool()); +// Verifies that suggestion removal through the holding space client works as +// expected. +TEST_P(HoldingSpaceSuggestionsDelegateTest, SuggestionRemoval) { + // Populate drive and local file suggestions. + const base::FilePath file_path_1 = mount_point()->CreateArbitraryFile(); + const base::FilePath file_path_2 = mount_point()->CreateArbitraryFile(); + GetFileSuggestKeyedService()->SetSuggestionsForType( + app_list::FileSuggestionType::kDriveFile, + /*suggestions=*/std::vector<app_list::FileSuggestData>{ + {app_list::FileSuggestionType::kDriveFile, file_path_1, + /*new_prediction_reason=*/absl::nullopt, absl::nullopt}}); + GetFileSuggestKeyedService()->SetSuggestionsForType( + app_list::FileSuggestionType::kLocalFile, + /*suggestions=*/std::vector<app_list::FileSuggestData>{ + {app_list::FileSuggestionType::kLocalFile, file_path_2, + /*new_prediction_reason=*/absl::nullopt, absl::nullopt}}); + task_environment()->FastForwardBy(base::Seconds(1)); + + const bool suggestion_feature_enabled = + features::IsHoldingSpaceSuggestionsEnabled(); + HoldingSpaceModel* model = HoldingSpaceController::Get()->model(); + EXPECT_EQ(GetSuggestionsInModel(model).size(), + suggestion_feature_enabled ? 2u : 0u); + + // Remove all suggestions through the holding space client. Verify that + // `HoldingSpaceClient::RemoveFileSuggestions()` is called. + HoldingSpaceClient* client = HoldingSpaceController::Get()->client(); + EXPECT_CALL(*GetFileSuggestKeyedService(), + RemoveSuggestionsAndNotify( + std::vector<base::FilePath>({file_path_1, file_path_2}))); + client->RemoveFileSuggestions({file_path_1, file_path_2}); +} + TEST_P(HoldingSpaceSuggestionsDelegateTest, VerifySuggestionsInModel) { const base::FilePath file_path_1 = mount_point()->CreateArbitraryFile();
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 18ae737..a385392 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -2296,7 +2296,7 @@ // Transfer the ownership of select file dialog so that the ref count is // released after the function returns. This is needed because the passed-in // data such as |file_info| and |params| could be owned by the dialog. - std::unique_ptr<ui::SelectFileDialog> dialog = std::move(select_file_dialog_); + scoped_refptr<ui::SelectFileDialog> dialog = std::move(select_file_dialog_); profile_->set_last_selected_directory(file_info.file_path.DirName());
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index b847b57..e80e3d1 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -1243,7 +1243,7 @@ std::unique_ptr<FindBarController> find_bar_controller_; // Dialog box used for opening and saving files. - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; // Helper which implements the ContentSettingBubbleModel interface. std::unique_ptr<BrowserContentSettingBubbleModelDelegate>
diff --git a/chrome/browser/ui/certificate_dialogs.cc b/chrome/browser/ui/certificate_dialogs.cc index 8909ffe7..668c0ea 100644 --- a/chrome/browser/ui/certificate_dialogs.cc +++ b/chrome/browser/ui/certificate_dialogs.cc
@@ -92,7 +92,7 @@ std::string GetCMSString(size_t start, size_t end) const; - std::unique_ptr<ui::SelectFileDialog> const select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> const select_file_dialog_; // The certificate hierarchy (leaf cert first). std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> cert_chain_list_;
diff --git a/chrome/browser/ui/chrome_select_file_policy_unittest.cc b/chrome/browser/ui/chrome_select_file_policy_unittest.cc index d0bfe62..50a42c7 100644 --- a/chrome/browser/ui/chrome_select_file_policy_unittest.cc +++ b/chrome/browser/ui/chrome_select_file_policy_unittest.cc
@@ -68,7 +68,7 @@ } private: - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; bool file_selection_initialisation_in_progress; };
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.cc b/chrome/browser/ui/global_media_controls/media_notification_service.cc index b8276e4..a5e530e0 100644 --- a/chrome/browser/ui/global_media_controls/media_notification_service.cc +++ b/chrome/browser/ui/global_media_controls/media_notification_service.cc
@@ -247,6 +247,14 @@ // If there exists a media session notification associated with // |web_contents|, hold onto the context for later use. context_ = std::move(context); + + // When a media session item is associated with a presentation request, we + // must show the origin associated with the request rather than that for + // the top frame. + std::string item_id = + GetActiveControllableSessionForWebContents(web_contents); + media_session_item_producer_->UpdateMediaItemSourceOrigin( + item_id, context_->presentation_request().frame_origin); } else if (presentation_request_notification_producer_) { // If there do not exist active notifications, pass |context| to // |presentation_request_notification_producer_| to create a dummy
diff --git a/chrome/browser/ui/passwords/settings/password_manager_porter.h b/chrome/browser/ui/passwords/settings/password_manager_porter.h index 220fce9a..54fe8af 100644 --- a/chrome/browser/ui/passwords/settings/password_manager_porter.h +++ b/chrome/browser/ui/passwords/settings/password_manager_porter.h
@@ -84,7 +84,7 @@ std::unique_ptr<password_manager::PasswordManagerExporter> exporter_; std::unique_ptr<password_manager::PasswordImporter> importer_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; raw_ptr<Profile> profile_; // We store |presenter_| and
diff --git a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.cc b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.cc index c61799f..699e322 100644 --- a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.cc +++ b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.cc
@@ -434,6 +434,7 @@ void PasswordChangeRunView::ClearPrompt() { DCHECK(body_); + focus_on_button_timer_->Stop(); body_->RemoveAllChildViews(); password_change_run_progress_->ResumeIconAnimation(); }
diff --git a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc index ec09aa5..2f961c60 100644 --- a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc +++ b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc
@@ -218,6 +218,20 @@ SimulateButtonClick(container->children()[0]); } +TEST_F(PasswordChangeRunViewTest, CreateBasePromptAndClickClearsFocusTimer) { + auto mock_timer = std::make_unique<base::MockOneShotTimer>(); + base::MockOneShotTimer* timer_ptr = mock_timer.get(); + view()->SetFocusOnButtonTimerForTest(std::move(mock_timer)); + std::vector<PromptChoice> choices = CreatePromptChoices(); + + view()->ShowBasePrompt(kDescription, choices); + EXPECT_TRUE(timer_ptr->IsRunning()); + + view()->ClearPrompt(); + // Clearing the prompt stops the timer. + EXPECT_FALSE(timer_ptr->IsRunning()); +} + TEST_F(PasswordChangeRunViewTest, CreateBasePromptWithoutButton) { // Show a prompt with no choices. view()->ShowBasePrompt({});
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc index a7df6b2b..befdd18 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
@@ -1188,17 +1188,8 @@ } // Test that remember by choice checkbox works for open PWA option. -// -// TODO(https://crbug.com/1361934): Fix timeouts under MSAN. -// TODO(https://crbug.com/1367375): Fix timeouts under ASAN. -#if (BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER)) || \ - defined(MEMORY_SANITIZER) -#define MAYBE_RememberOpenPWA DISABLED_RememberOpenPWA -#else -#define MAYBE_RememberOpenPWA RememberOpenPWA -#endif IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTestChromeOS, - MAYBE_RememberOpenPWA) { + RememberOpenPWA) { base::HistogramTester histogram_tester; GURL test_url(InScopeAppUrl()); @@ -1279,18 +1270,8 @@ // Simulates prerendering an app URL that the user has opted into always // launching an app window for. In this case, the prerender should be canceled // and the app shouldn't be opened. -// -// TODO(https://crbug.com/1361934): Fix timeouts under MSAN. -// TODO(https://crbug.com/1367375): Fix timeouts under ASAN. -#if (BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER)) || \ - defined(MEMORY_SANITIZER) -#define MAYBE_AppLaunchURLCancelsPrerendering \ - DISABLED_AppLaunchURLCancelsPrerendering -#else -#define MAYBE_AppLaunchURLCancelsPrerendering AppLaunchURLCancelsPrerendering -#endif IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewPrerenderingBrowserTestChromeOS, - MAYBE_AppLaunchURLCancelsPrerendering) { + AppLaunchURLCancelsPrerendering) { // Prerendering is currently limited to same-origin pages so we need to start // it from an arbitrary page on the same origin, rather than about:blank. const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html");
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc index f3a2923..d56c7aa 100644 --- a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc +++ b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
@@ -123,7 +123,8 @@ {feature_engagement::kIPHDesktopPwaInstallFeature, {}}}, #if BUILDFLAG(IS_CHROMEOS_ASH) { - {features::kWebAppsCrosapi, chromeos::features::kLacrosPrimary}, {} + features::kWebAppsCrosapi, + chromeos::features::kLacrosPrimary, } #else {}
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.cc b/chrome/browser/ui/views/select_file_dialog_extension.cc index 204a3500..4621521 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension.cc +++ b/chrome/browser/ui/views/select_file_dialog_extension.cc
@@ -71,14 +71,15 @@ public: static PendingDialog* GetInstance(); void Add(SelectFileDialogExtension::RoutingID id, - SelectFileDialogExtension* dialog); + scoped_refptr<SelectFileDialogExtension> dialog); void Remove(SelectFileDialogExtension::RoutingID id); - SelectFileDialogExtension* Find(SelectFileDialogExtension::RoutingID id); + scoped_refptr<SelectFileDialogExtension> Find( + SelectFileDialogExtension::RoutingID id); private: friend struct base::DefaultSingletonTraits<PendingDialog>; using Map = std::map<SelectFileDialogExtension::RoutingID, - raw_ptr<SelectFileDialogExtension>>; + scoped_refptr<SelectFileDialogExtension>>; Map map_; }; @@ -89,8 +90,8 @@ } void PendingDialog::Add(SelectFileDialogExtension::RoutingID id, - SelectFileDialogExtension* dialog) { - DCHECK(dialog); + scoped_refptr<SelectFileDialogExtension> dialog) { + DCHECK(dialog.get()); if (map_.find(id) == map_.end()) map_.insert(std::make_pair(id, dialog)); else @@ -101,7 +102,7 @@ map_.erase(id); } -SelectFileDialogExtension* PendingDialog::Find( +scoped_refptr<SelectFileDialogExtension> PendingDialog::Find( SelectFileDialogExtension::RoutingID id) { Map::const_iterator it = map_.find(id); if (it == map_.end()) @@ -255,12 +256,10 @@ SelectFileDialogExtension::Owner&&) = default; // static -std::unique_ptr<SelectFileDialogExtension> SelectFileDialogExtension::Create( +SelectFileDialogExtension* SelectFileDialogExtension::Create( Listener* listener, std::unique_ptr<ui::SelectFilePolicy> policy) { - // Using WrapUnique because the constructor is private. - return base::WrapUnique( - new SelectFileDialogExtension(listener, std::move(policy))); + return new SelectFileDialogExtension(listener, std::move(policy)); } SelectFileDialogExtension::SelectFileDialogExtension( @@ -304,9 +303,9 @@ RoutingID routing_id, const ui::SelectedFileInfo& file, int index) { - SelectFileDialogExtension* dialog = + scoped_refptr<SelectFileDialogExtension> dialog = PendingDialog::GetInstance()->Find(routing_id); - if (!dialog) + if (!dialog.get()) return; dialog->selection_type_ = SINGLE_FILE; dialog->selection_files_.clear(); @@ -318,9 +317,9 @@ void SelectFileDialogExtension::OnMultiFilesSelected( RoutingID routing_id, const std::vector<ui::SelectedFileInfo>& files) { - SelectFileDialogExtension* dialog = + scoped_refptr<SelectFileDialogExtension> dialog = PendingDialog::GetInstance()->Find(routing_id); - if (!dialog) + if (!dialog.get()) return; dialog->selection_type_ = MULTIPLE_FILES; dialog->selection_files_ = files; @@ -329,9 +328,9 @@ // static void SelectFileDialogExtension::OnFileSelectionCanceled(RoutingID routing_id) { - SelectFileDialogExtension* dialog = + scoped_refptr<SelectFileDialogExtension> dialog = PendingDialog::GetInstance()->Find(routing_id); - if (!dialog) + if (!dialog.get()) return; dialog->selection_type_ = CANCEL; dialog->selection_files_.clear(); @@ -563,5 +562,5 @@ // static bool SelectFileDialogExtension::PendingExists(RoutingID routing_id) { - return PendingDialog::GetInstance()->Find(routing_id) != nullptr; + return PendingDialog::GetInstance()->Find(routing_id).get() != nullptr; }
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.h b/chrome/browser/ui/views/select_file_dialog_extension.h index 8062b7a..b1982ff 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension.h +++ b/chrome/browser/ui/views/select_file_dialog_extension.h
@@ -44,7 +44,7 @@ SelectFileDialogExtension(const SelectFileDialogExtension&) = delete; SelectFileDialogExtension& operator=(SelectFileDialogExtension&) = delete; - static std::unique_ptr<SelectFileDialogExtension> Create( + static SelectFileDialogExtension* Create( ui::SelectFileDialog::Listener* listener, std::unique_ptr<ui::SelectFilePolicy> policy); @@ -116,8 +116,6 @@ bool show_android_picker_apps, bool use_media_store_filter = false); - ~SelectFileDialogExtension() override; - protected: // ui::SelectFileDialog: void SelectFileImpl(Type type, @@ -146,10 +144,11 @@ const std::string& id); void OnSystemDialogWillClose(); - // Use Create(). + // Object is ref-counted, use Create(). explicit SelectFileDialogExtension( SelectFileDialog::Listener* listener, std::unique_ptr<ui::SelectFilePolicy> policy); + ~SelectFileDialogExtension() override; // Invokes the appropriate file selection callback on our listener. void NotifyListener();
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc index 488586f..80c8abb 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc +++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -14,7 +14,6 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/logging.h" -#include "base/memory/ptr_util.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" @@ -168,8 +167,7 @@ void SetUp() override { // Create the dialog wrapper and listener objects. listener_ = std::make_unique<MockSelectFileDialogListener>(); - dialog_ = base::WrapUnique( - new SelectFileDialogExtension(listener_.get(), nullptr)); + dialog_ = new SelectFileDialogExtension(listener_.get(), nullptr); // One mount point will be needed. Files app looks for the "Downloads" // volume mount point by default, so use that. @@ -295,8 +293,8 @@ void TryOpeningSecondDialog(const gfx::NativeWindow& owning_window) { second_listener_ = std::make_unique<MockSelectFileDialogListener>(); - second_dialog_ = base::WrapUnique( - new SelectFileDialogExtension(second_listener_.get(), nullptr)); + second_dialog_ = + new SelectFileDialogExtension(second_listener_.get(), nullptr); // The dialog type is not relevant for this test but is required: use the // open file dialog type. @@ -343,10 +341,10 @@ base::FilePath downloads_dir_; std::unique_ptr<MockSelectFileDialogListener> listener_; - std::unique_ptr<SelectFileDialogExtension> dialog_; + scoped_refptr<SelectFileDialogExtension> dialog_; std::unique_ptr<MockSelectFileDialogListener> second_listener_; - std::unique_ptr<SelectFileDialogExtension> second_dialog_; + scoped_refptr<SelectFileDialogExtension> second_dialog_; bool use_file_type_filter_;
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_factory.cc b/chrome/browser/ui/views/select_file_dialog_extension_factory.cc index 8e8c501..87b7ea1 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension_factory.cc +++ b/chrome/browser/ui/views/select_file_dialog_extension_factory.cc
@@ -4,10 +4,7 @@ #include "chrome/browser/ui/views/select_file_dialog_extension_factory.h" -#include <memory> - #include "chrome/browser/ui/views/select_file_dialog_extension.h" -#include "ui/shell_dialogs/select_file_dialog.h" #include "ui/shell_dialogs/select_file_policy.h" SelectFileDialogExtensionFactory::SelectFileDialogExtensionFactory() { @@ -19,6 +16,5 @@ ui::SelectFileDialog* SelectFileDialogExtensionFactory::Create( ui::SelectFileDialog::Listener* listener, std::unique_ptr<ui::SelectFilePolicy> policy) { - return SelectFileDialogExtension::Create(listener, std::move(policy)) - .release(); + return SelectFileDialogExtension::Create(listener, std::move(policy)); }
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_unittest.cc b/chrome/browser/ui/views/select_file_dialog_extension_unittest.cc index 0e8dcac..2e808cb4 100644 --- a/chrome/browser/ui/views/select_file_dialog_extension_unittest.cc +++ b/chrome/browser/ui/views/select_file_dialog_extension_unittest.cc
@@ -7,8 +7,6 @@ #include <memory> #include "base/files/file_path.h" -#include "base/memory/ptr_util.h" -#include "base/test/scoped_feature_list.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/shell_dialogs/select_file_policy.h" #include "ui/shell_dialogs/selected_file_info.h" @@ -28,7 +26,7 @@ SelectFileDialogExtensionTest& operator=( const SelectFileDialogExtensionTest&) = delete; - static std::unique_ptr<SelectFileDialogExtension> CreateDialog( + static SelectFileDialogExtension* CreateDialog( ui::SelectFileDialog::Listener* listener) { SelectFileDialogExtension* dialog = new SelectFileDialogExtension(listener, nullptr); @@ -36,7 +34,7 @@ EXPECT_FALSE(SelectFileDialogExtension::PendingExists(kDefaultRoutingID)); dialog->AddPending(kDefaultRoutingID); EXPECT_TRUE(SelectFileDialogExtension::PendingExists(kDefaultRoutingID)); - return base::WrapUnique(dialog); + return dialog; } }; @@ -89,13 +87,13 @@ } private: - std::unique_ptr<SelectFileDialogExtension> dialog_; + scoped_refptr<SelectFileDialogExtension> dialog_; }; TEST_F(SelectFileDialogExtensionTest, FileSelected) { const int kFileIndex = 5; auto listener = std::make_unique<TestListener>(); - std::unique_ptr<SelectFileDialogExtension> dialog = + scoped_refptr<SelectFileDialogExtension> dialog = CreateDialog(listener.get()); // Simulate selecting a file. ui::SelectedFileInfo info; @@ -109,7 +107,7 @@ TEST_F(SelectFileDialogExtensionTest, FileSelectionCanceled) { auto listener = std::make_unique<TestListener>(); - std::unique_ptr<SelectFileDialogExtension> dialog = + scoped_refptr<SelectFileDialogExtension> dialog = CreateDialog(listener.get()); // Simulate cancelling the dialog. SelectFileDialogExtension::OnFileSelectionCanceled(kDefaultRoutingID);
diff --git a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc index 1c8bc10..bf54be3 100644 --- a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc +++ b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.cc
@@ -160,6 +160,8 @@ } AccessCodeCastHandler::~AccessCodeCastHandler() { + AccessCodeCastMetrics::RecordAccessCodeNotFoundCount( + access_code_not_found_count_); if (media_route_starter_) media_route_starter_->RemoveMediaSinkWithCastModesObserver(this); } @@ -232,6 +234,10 @@ access_code_cast::mojom::AddSinkResultCode add_sink_result, absl::optional<MediaSink::Id> sink_id) { DCHECK(sink_id || add_sink_result != AddSinkResultCode::OK); + + if (add_sink_result == AddSinkResultCode::ACCESS_CODE_NOT_FOUND) + access_code_not_found_count_++; + // Wait for OnResultsUpdated before triggering the |add_sink_callback_| since // we are not entirely sure the sink is ready to be casted to yet. if (add_sink_result != AddSinkResultCode::OK && add_sink_callback_) {
diff --git a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h index 08b6200..0c9cd23 100644 --- a/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h +++ b/chrome/browser/ui/webui/access_code_cast/access_code_cast_handler.h
@@ -141,6 +141,8 @@ AddSinkCallback add_sink_callback_; + int access_code_not_found_count_ = 0; + // The id of the media sink discovered from the access code; absl::optional<MediaSink::Id> sink_id_;
diff --git a/chrome/browser/ui/webui/certificates_handler.h b/chrome/browser/ui/webui/certificates_handler.h index 5716c35..4155153 100644 --- a/chrome/browser/ui/webui/certificates_handler.h +++ b/chrome/browser/ui/webui/certificates_handler.h
@@ -246,7 +246,7 @@ bool use_hardware_backed_; std::string file_data_; net::ScopedCERTCertificateList selected_cert_list_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; crypto::ScopedPK11Slot slot_; // Used in reading and writing certificate files.
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc index 6d3d82b2..76b9915 100644 --- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc +++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -667,7 +667,7 @@ base::StrCat({"log-", severity})); last_sent_event_id_ = log[i].id; } - if (!list.GetListDeprecated().empty()) { + if (!list.GetList().empty()) { MaybeCallJavascript("updateEventLog", std::move(list)); } } @@ -705,8 +705,8 @@ service_log_file_inode_ = response.first; last_sent_line_number_ = 0; } - if (!response.second.GetListDeprecated().empty()) { - last_sent_line_number_ += response.second.GetListDeprecated().size(); + if (!response.second.GetList().empty()) { + last_sent_line_number_ += response.second.GetList().size(); MaybeCallJavascript("updateServiceLog", std::move(response.second)); } service_log_file_is_processing_ = false;
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc index 9d39946..4349ee6 100644 --- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc +++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
@@ -399,7 +399,7 @@ void DeviceEmulatorMessageHandler::UpdatePowerSources( const base::Value::List& args) { CHECK(!args.empty() && args[0].is_list()); - base::Value::ConstListView sources = args[0].GetListDeprecated(); + const base::Value::List& sources = args[0].GetList(); power_manager::PowerSupplyProperties props = *fake_power_manager_client_->GetLastStatus();
diff --git a/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc b/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc index 14d0e84..f504ced 100644 --- a/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc +++ b/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc
@@ -115,7 +115,7 @@ } result += base::StringPrintf("Networks imported: %d\n", num_networks_imported); - if (certificates.GetListDeprecated().empty()) { + if (certificates.GetList().empty()) { if (!num_networks_imported) has_error = true; Respond(callback_id, result, has_error);
diff --git a/chrome/browser/ui/webui/family_link_user_internals/DIR_METADATA b/chrome/browser/ui/webui/family_link_user_internals/DIR_METADATA new file mode 100644 index 0000000..7c567602 --- /dev/null +++ b/chrome/browser/ui/webui/family_link_user_internals/DIR_METADATA
@@ -0,0 +1,4 @@ +# Chrome Browser +mixins: "//chrome/browser/supervised_user/android/COMMON_METADATA" +# ChromeOS specific +mixins: "//chrome/browser/supervised_user/chromeos/COMMON_METADATA"
diff --git a/chrome/browser/ui/webui/memory_internals_ui.cc b/chrome/browser/ui/webui/memory_internals_ui.cc index 16f3a069..f9bdcc07 100644 --- a/chrome/browser/ui/webui/memory_internals_ui.cc +++ b/chrome/browser/ui/webui/memory_internals_ui.cc
@@ -163,7 +163,7 @@ void SaveTraceFinished(bool success); - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; #if !BUILDFLAG(IS_ANDROID) raw_ptr<content::WebUI> web_ui_; // The WebUI that owns us. #endif
diff --git a/chrome/browser/ui/webui/net_export_ui.cc b/chrome/browser/ui/webui/net_export_ui.cc index 4537b72..463bb8a93 100644 --- a/chrome/browser/ui/webui/net_export_ui.cc +++ b/chrome/browser/ui/webui/net_export_ui.cc
@@ -156,7 +156,7 @@ net::NetLogCaptureMode capture_mode_; uint64_t max_log_file_size_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; base::WeakPtrFactory<NetExportMessageHandler> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h index 1d70797..3769946 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
@@ -195,7 +195,7 @@ base::TimeTicks background_images_request_start_time_; absl::optional<base::TimeTicks> one_google_bar_load_start_time_; raw_ptr<Profile> profile_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; raw_ptr<content::WebContents> web_contents_; base::Time ntp_navigation_start_time_; NTPUserDataLogger logger_;
diff --git a/chrome/browser/ui/webui/policy/policy_ui_handler.h b/chrome/browser/ui/webui/policy/policy_ui_handler.h index 5a70006..d512c18 100644 --- a/chrome/browser/ui/webui/policy/policy_ui_handler.h +++ b/chrome/browser/ui/webui/policy/policy_ui_handler.h
@@ -80,7 +80,7 @@ void WritePoliciesToJSONFile(const base::FilePath& path); - std::unique_ptr<ui::SelectFileDialog> export_policies_select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> export_policies_select_file_dialog_; std::unique_ptr<policy::PolicyValueAndStatusAggregator> policy_value_and_status_aggregator_;
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h index 9c8a564..c33c820 100644 --- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h +++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
@@ -84,7 +84,7 @@ const raw_ptr<content::WebContents> preview_web_contents_; // The underlying dialog object. Protected so unit tests can access it. - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; private: void PostPrintToPdfTask();
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc index fec946d..1804e21 100644 --- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
@@ -10,7 +10,8 @@ #include "base/bind.h" #include "base/callback_helpers.h" -#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/memory/ref_counted_memory.h" #include "base/run_loop.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/ui/browser_commands.h" @@ -76,9 +77,9 @@ ui::SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.resize(1); file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("pdf")); - select_file_dialog_ = base::WrapUnique(ui::CreateWinSelectFileDialog( + select_file_dialog_ = ui::CreateWinSelectFileDialog( this, nullptr /*policy already checked*/, - base::BindRepeating(&ExecuteCancelledSelectFileDialog))); + base::BindRepeating(&ExecuteCancelledSelectFileDialog)); select_file_dialog_->SelectFile( ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_filename, &file_type_info, 0, base::FilePath::StringType(),
diff --git a/chrome/browser/ui/webui/settings/ash/cups_printers_handler.h b/chrome/browser/ui/webui/settings/ash/cups_printers_handler.h index c31eecd..fd4acd64 100644 --- a/chrome/browser/ui/webui/settings/ash/cups_printers_handler.h +++ b/chrome/browser/ui/webui/settings/ash/cups_printers_handler.h
@@ -261,7 +261,7 @@ // that has been resolved in the lifetime of this object. std::map<std::string, PpdProvider::ResolvedPrintersList> resolved_printers_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; std::string webui_callback_id_; CupsPrintersManager* printers_manager_; std::unique_ptr<local_discovery::EndpointResolver> endpoint_resolver_;
diff --git a/chrome/browser/ui/webui/settings/ash/languages_section.cc b/chrome/browser/ui/webui/settings/ash/languages_section.cc index 7ef758a6..2f0f0b0f 100644 --- a/chrome/browser/ui/webui/settings/ash/languages_section.cc +++ b/chrome/browser/ui/webui/settings/ash/languages_section.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/ash/os_settings_features_util.h" #include "chrome/browser/ui/webui/settings/ash/search/search_tag_registry.h" +#include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom-forward.h" #include "chrome/browser/ui/webui/settings/languages_handler.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" @@ -293,6 +294,10 @@ IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_KEYMAP_STYLE_MOBILE}, {"inputMethodOptionsJapaneseKeymapStyleChromeOs", IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_KEYMAP_STYLE_CHROMEOS}, + {"inputMethodOptionsJapaneseManageUserDictionary", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY}, + {"inputMethodOptionsJapaneseManageUserDictionarySubtitle", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_MANAGE_USER_DICTIONARY_SUBTITLE}, {"inputMethodOptionsPinyinChinesePunctuation", IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_CHINESE_PUNCTUATION}, {"inputMethodOptionsPinyinDefaultChinese", @@ -448,6 +453,8 @@ {"languagesDictionaryDownloadRetryDescription", IDS_OS_SETTINGS_LANGUAGES_DICTIONARY_DOWNLOAD_RETRY_DESCRIPTION}, {"editDictionaryLabel", IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_LABEL}, + {"japaneseManageUserDictionaryLabel", + IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL}, {"editDictionaryDescription", IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_DESCRIPTION}, {"addDictionaryWordButtonLabel", @@ -601,6 +608,13 @@ mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, mojom::kEditDictionarySubpagePath); + // Japanese Manage User Dictionary + generator->RegisterNestedSubpage( + IDS_OS_SETTINGS_LANGUAGES_JAPANESE_MANAGE_USER_DICTIONARY_LABEL, + mojom::Subpage::kJapaneseManageUserDictionary, mojom::Subpage::kInput, + mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, + mojom::kJapaneseManageUserDictionarySubpagePath); + generator->RegisterNestedSetting(mojom::Setting::kAddLanguage, mojom::Subpage::kLanguages); generator->RegisterNestedSetting(mojom::Setting::kShowInputOptionsInShelf,
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom index b1c4a86d..42a76f1 100644 --- a/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom +++ b/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom
@@ -133,6 +133,7 @@ kLanguages = 1204, kInput = 1205, kEditDictionary = 1206, + kJapaneseManageUserDictionary = 1207, // Files section. kNetworkFileShares = 1300, @@ -256,6 +257,8 @@ const string kLanguagesSubpagePath = "osLanguages/languages"; const string kInputSubpagePath = "osLanguages/input"; const string kEditDictionarySubpagePath = "osLanguages/editDictionary"; +const string kJapaneseManageUserDictionarySubpagePath = + "osLanguages/japaneseManageUserDictionary"; // Files section. const string kFilesSectionPath = "files";
diff --git a/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc b/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc index 5efe740..e34e918 100644 --- a/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc +++ b/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc
@@ -105,6 +105,7 @@ chromeos::settings::mojom::kLanguagesSubpagePath, chromeos::settings::mojom::kInputSubpagePath, chromeos::settings::mojom::kEditDictionarySubpagePath, + chromeos::settings::mojom::kJapaneseManageUserDictionarySubpagePath, // Files section. chromeos::settings::mojom::kFilesSectionPath,
diff --git a/chrome/browser/ui/webui/settings/downloads_handler.h b/chrome/browser/ui/webui/settings/downloads_handler.h index 0f53fb1..98d92d8 100644 --- a/chrome/browser/ui/webui/settings/downloads_handler.h +++ b/chrome/browser/ui/webui/settings/downloads_handler.h
@@ -81,7 +81,7 @@ PrefChangeRegistrar pref_registrar_; - std::unique_ptr<ui::SelectFileDialog> select_folder_dialog_; + scoped_refptr<ui::SelectFileDialog> select_folder_dialog_; base::WeakPtrFactory<DownloadsHandler> weak_factory_{this}; };
diff --git a/chrome/browser/ui/webui/settings/import_data_handler.h b/chrome/browser/ui/webui/settings/import_data_handler.h index 5421834..26544eb 100644 --- a/chrome/browser/ui/webui/settings/import_data_handler.h +++ b/chrome/browser/ui/webui/settings/import_data_handler.h
@@ -76,7 +76,7 @@ bool import_did_succeed_{false}; bool importer_list_loaded_{false}; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; }; } // namespace settings
diff --git a/chrome/browser/ui/webui/signin/signin_utils.cc b/chrome/browser/ui/webui/signin/signin_utils.cc index 5bd644e..b2393ec 100644 --- a/chrome/browser/ui/webui/signin/signin_utils.cc +++ b/chrome/browser/ui/webui/signin/signin_utils.cc
@@ -4,56 +4,36 @@ #include "chrome/browser/ui/webui/signin/signin_utils.h" -#include <set> - -#include "base/bind.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" -#include "components/guest_view/browser/guest_view_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" - -namespace { - -bool AddWebContentsToSet(std::set<content::WebContents*>* frame_set, - const std::string& web_view_name, - content::WebContents* web_contents) { - auto* web_view = extensions::WebViewGuest::FromWebContents(web_contents); - if (web_view && web_view->name() == web_view_name) - frame_set->insert(web_contents); - return false; -} - -} // namespace namespace signin { content::RenderFrameHost* GetAuthFrame(content::WebContents* web_contents, const std::string& parent_frame_name) { - content::WebContents* auth_web_contents = - GetAuthFrameWebContents(web_contents, parent_frame_name); - return auth_web_contents ? auth_web_contents->GetPrimaryMainFrame() : nullptr; + content::RenderFrameHost* frame = nullptr; + web_contents->ForEachRenderFrameHostWithAction( + [&frame, &parent_frame_name](content::RenderFrameHost* rfh) { + auto* web_view = extensions::WebViewGuest::FromRenderFrameHost(rfh); + if (web_view && web_view->name() == parent_frame_name) { + DCHECK_EQ(web_view->GetGuestMainFrame(), rfh); + frame = rfh; + return content::RenderFrameHost::FrameIterationAction::kStop; + } + return content::RenderFrameHost::FrameIterationAction::kContinue; + }); + return frame; } -content::WebContents* GetAuthFrameWebContents( +extensions::WebViewGuest* GetAuthWebViewGuest( content::WebContents* web_contents, const std::string& parent_frame_name) { - std::set<content::WebContents*> frame_set; - auto* manager = guest_view::GuestViewManager::FromBrowserContext( - web_contents->GetBrowserContext()); - if (manager) { - manager->ForEachGuest(web_contents, - base::BindRepeating(&AddWebContentsToSet, &frame_set, - parent_frame_name)); - } - DCHECK_GE(1U, frame_set.size()); - if (!frame_set.empty()) - return *frame_set.begin(); - - return nullptr; + return extensions::WebViewGuest::FromRenderFrameHost( + GetAuthFrame(web_contents, parent_frame_name)); } Browser* GetDesktopBrowser(content::WebUI* web_ui) {
diff --git a/chrome/browser/ui/webui/signin/signin_utils.h b/chrome/browser/ui/webui/signin/signin_utils.h index c35ed4d..bb347e8 100644 --- a/chrome/browser/ui/webui/signin/signin_utils.h +++ b/chrome/browser/ui/webui/signin/signin_utils.h
@@ -18,6 +18,10 @@ class WebUI; } +namespace extensions { +class WebViewGuest; +} + namespace signin { // User choice when signing in. @@ -39,7 +43,7 @@ content::RenderFrameHost* GetAuthFrame(content::WebContents* web_contents, const std::string& parent_frame_name); -content::WebContents* GetAuthFrameWebContents( +extensions::WebViewGuest* GetAuthWebViewGuest( content::WebContents* web_contents, const std::string& parent_frame_name);
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc index c389831a..04ae47da 100644 --- a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc +++ b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc
@@ -118,7 +118,7 @@ std::set<feedback::PIIType> selected_pii_to_keep_; base::FilePath data_path_; std::unique_ptr<SupportToolHandler> handler_; - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; base::WeakPtrFactory<SupportToolMessageHandler> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/web_applications/web_app_utils.cc b/chrome/browser/web_applications/web_app_utils.cc index ad18015..298f833 100644 --- a/chrome/browser/web_applications/web_app_utils.cc +++ b/chrome/browser/web_applications/web_app_utils.cc
@@ -188,13 +188,17 @@ !ash::ProfileHelper::IsLockScreenAppProfile(profile)) { return false; } - // Disable Web Apps if running any kiosk app and kKioskEnableAppService is not - // enabled. auto* user_manager = user_manager::UserManager::Get(); - if (user_manager && user_manager->IsLoggedInAsAnyKioskApp() && - !base::FeatureList::IsEnabled(features::kKioskEnableAppService)) { + // Don't enable for Chrome App Kiosk sessions. + if (user_manager && user_manager->IsLoggedInAsKioskApp()) return false; - } + // Don't enable for ARC Kiosk sessions. + if (user_manager && user_manager->IsLoggedInAsArcKioskApp()) + return false; + // Don't enable for Web Kiosk if kKioskEnableAppService is disabled. + if (user_manager && user_manager->IsLoggedInAsWebKioskApp() && + !base::FeatureList::IsEnabled(features::kKioskEnableAppService)) + return false; #elif BUILDFLAG(IS_CHROMEOS_LACROS) if (!profile->IsMainProfile() && !g_skip_main_profile_check_for_testing) return false;
diff --git a/chrome/browser/web_applications/web_app_utils_unittest.cc b/chrome/browser/web_applications/web_app_utils_unittest.cc index f401c517..ab59b49 100644 --- a/chrome/browser/web_applications/web_app_utils_unittest.cc +++ b/chrome/browser/web_applications/web_app_utils_unittest.cc
@@ -252,6 +252,15 @@ base::test::ScopedFeatureList feature_list; feature_list.InitAndDisableFeature(features::kKioskEnableAppService); auto user_manager = std::make_unique<MockUserManager>(); + EXPECT_CALL(*user_manager, IsLoggedInAsWebKioskApp()) + .WillRepeatedly(testing::Return(true)); + user_manager::ScopedUserManager enabler(std::move(user_manager)); + EXPECT_FALSE(AreWebAppsEnabled(regular_profile)); + } + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kKioskEnableAppService); + auto user_manager = std::make_unique<MockUserManager>(); EXPECT_CALL(*user_manager, IsLoggedInAsArcKioskApp()) .WillOnce(testing::Return(true)); user_manager::ScopedUserManager enabler(std::move(user_manager)); @@ -262,8 +271,22 @@ EXPECT_CALL(*user_manager, IsLoggedInAsKioskApp()) .WillOnce(testing::Return(true)); user_manager::ScopedUserManager enabler(std::move(user_manager)); + EXPECT_FALSE(AreWebAppsEnabled(regular_profile)); + } + { + auto user_manager = std::make_unique<MockUserManager>(); + EXPECT_CALL(*user_manager, IsLoggedInAsWebKioskApp()) + .WillRepeatedly(testing::Return(true)); + user_manager::ScopedUserManager enabler(std::move(user_manager)); EXPECT_TRUE(AreWebAppsEnabled(regular_profile)); } + { + auto user_manager = std::make_unique<MockUserManager>(); + EXPECT_CALL(*user_manager, IsLoggedInAsArcKioskApp()) + .WillOnce(testing::Return(true)); + user_manager::ScopedUserManager enabler(std::move(user_manager)); + EXPECT_FALSE(AreWebAppsEnabled(regular_profile)); + } #endif }
diff --git a/chrome/browser/webapps/chrome_webapps_client.cc b/chrome/browser/webapps/chrome_webapps_client.cc index df6c5fa3..dee44b0e 100644 --- a/chrome/browser/webapps/chrome_webapps_client.cc +++ b/chrome/browser/webapps/chrome_webapps_client.cc
@@ -92,9 +92,10 @@ #if BUILDFLAG(IS_ANDROID) bool ChromeWebappsClient::IsInstallationInProgress( content::WebContents* web_contents, - const GURL& manifest_url) { + const GURL& manifest_url, + const GURL& manifest_id) { return WebApkInstallService::Get(web_contents->GetBrowserContext()) - ->IsInstallInProgress(manifest_url); + ->IsInstallInProgress(manifest_url, manifest_id); } bool ChromeWebappsClient::CanShowAppBanners(
diff --git a/chrome/browser/webapps/chrome_webapps_client.h b/chrome/browser/webapps/chrome_webapps_client.h index a8287a9..98d0d399 100644 --- a/chrome/browser/webapps/chrome_webapps_client.h +++ b/chrome/browser/webapps/chrome_webapps_client.h
@@ -29,7 +29,8 @@ content::WebContents* web_contents) override; #if BUILDFLAG(IS_ANDROID) bool IsInstallationInProgress(content::WebContents* web_contents, - const GURL& manifest_url) override; + const GURL& manifest_url, + const GURL& manifest_id) override; bool CanShowAppBanners(content::WebContents* web_contents) override; void OnWebApkInstallInitiatedFromAppMenu( content::WebContents* web_contents) override;
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index b3c8579..4eea11c 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1664819315-ffdf78dbb6597550a1acc2d2b9ee57ef4a49d441.profdata +chrome-linux-main-1664857638-4c1b0a36ea397a1ae2151d06d18fc74455377550.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index c66558e..a6075393 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1664798216-481a492bd03af5b88b90f22c35eac435b14edea9.profdata +chrome-mac-arm-main-1664819315-34a4cf7009d4c6f71f01d59b264c8857d33d762e.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 2ebae6f..cefff89 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1664819315-54e36189b4924d6893d21139a31bd1b9bd30cc96.profdata +chrome-mac-main-1664841456-3da53ffb56c67b1b7a8a3c50a5ec0546f638715b.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 31fdb755..e58ebff 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1664819315-b1f8ad9c5fcc78e5eee15c5b350cc39437e25b77.profdata +chrome-win32-main-1664841456-6e91453cac2e734626ffc2b01a75c5cf0f56a190.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 6d3bb8c83..63be3125 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1664819315-efa8f91214c7acd25fc7757678db8253373c9173.profdata +chrome-win64-main-1664841456-9235d616af2d3484228f317fc208f8f5a271db3f.profdata
diff --git a/chrome/renderer/cart/commerce_hint_agent.cc b/chrome/renderer/cart/commerce_hint_agent.cc index f7f40654..878bbc3 100644 --- a/chrome/renderer/cart/commerce_hint_agent.cc +++ b/chrome/renderer/cart/commerce_hint_agent.cc
@@ -636,8 +636,13 @@ if (!product_id_json_component.empty()) { script_string = "var idExtractionMap = " + product_id_json_component + ";\n" + script_string; + CommerceHeuristicsDataMetricsHelper::RecordProductIDExtractionPatternSource( + CommerceHeuristicsDataMetricsHelper::HeuristicsSource::FROM_COMPONENT); return WebString::FromUTF8(std::move(script_string)); } + CommerceHeuristicsDataMetricsHelper::RecordProductIDExtractionPatternSource( + CommerceHeuristicsDataMetricsHelper::HeuristicsSource:: + FROM_FEATURE_PARAMETER); const std::string id_extraction_map = kProductIdPatternMapping.Get().empty() ? ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
diff --git a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc index aec92c5e..5687c26 100644 --- a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc +++ b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc
@@ -590,6 +590,10 @@ "Commerce.Heuristics.CartExtractionScriptSource", int(CommerceHeuristicsDataMetricsHelper::HeuristicsSource::FROM_RESOURCE), 1); + WaitForUmaBucketCount("Commerce.Heuristics.ProductIDExtractionPatternSource", + int(CommerceHeuristicsDataMetricsHelper:: + HeuristicsSource::FROM_FEATURE_PARAMETER), + 1); ExpectUKMCount(ExtractionEntry::kEntryName, "ExtractionExecutionTime", 1); ExpectUKMCount(ExtractionEntry::kEntryName, "ExtractionLongestTaskTime", 1); ExpectUKMCount(ExtractionEntry::kEntryName, "ExtractionTotalTasksTime", 1); @@ -618,9 +622,10 @@ } extracted_results_promise = extractAllItems(document); )###"; + std::string product_id_json = "{\"foo.com\": \"test\"}"; bool is_populated = commerce_hint_service_->InitializeCommerceHeuristicsForTesting( - base::Version("0.0.0.1"), "{}", "{}", "", + base::Version("0.0.0.1"), "{}", "{}", std::move(product_id_json), std::move(extraction_script)); DCHECK(is_populated); @@ -639,6 +644,10 @@ int(CommerceHeuristicsDataMetricsHelper:: HeuristicsSource::FROM_COMPONENT), 1); + WaitForUmaBucketCount("Commerce.Heuristics.ProductIDExtractionPatternSource", + int(CommerceHeuristicsDataMetricsHelper:: + HeuristicsSource::FROM_COMPONENT), + 1); } #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/renderer/supervised_user/DIR_METADATA b/chrome/renderer/supervised_user/DIR_METADATA index d4229da..7c567602 100644 --- a/chrome/renderer/supervised_user/DIR_METADATA +++ b/chrome/renderer/supervised_user/DIR_METADATA
@@ -1,3 +1,4 @@ -monorail: { - component: "Services>SupervisedUser" -} +# Chrome Browser +mixins: "//chrome/browser/supervised_user/android/COMMON_METADATA" +# ChromeOS specific +mixins: "//chrome/browser/supervised_user/chromeos/COMMON_METADATA"
diff --git a/chrome/services/printing/pdf_to_emf_converter.cc b/chrome/services/printing/pdf_to_emf_converter.cc index c3ae5f3..69662df3 100644 --- a/chrome/services/printing/pdf_to_emf_converter.cc +++ b/chrome/services/printing/pdf_to_emf_converter.cc
@@ -72,7 +72,7 @@ } base::ReadOnlySharedMemoryRegion PdfToEmfConverter::RenderPdfPageToMetafile( - int page_number, + int page_index, bool postscript, float* scale_factor) { Emf metafile; @@ -108,7 +108,7 @@ base::ReadOnlySharedMemoryRegion invalid_emf_region; auto pdf_span = pdf_mapping_.GetMemoryAsSpan<const uint8_t>(); if (!chrome_pdf::RenderPDFPageToDC( - pdf_span, page_number, metafile.context(), + pdf_span, page_index, metafile.context(), pdf_render_settings_.dpi.width(), pdf_render_settings_.dpi.height(), pdf_render_settings_.area.x() - offset_x, pdf_render_settings_.area.y() - offset_y, @@ -132,11 +132,11 @@ return std::move(region_mapping.region); } -void PdfToEmfConverter::ConvertPage(uint32_t page_number, +void PdfToEmfConverter::ConvertPage(uint32_t page_index, ConvertPageCallback callback) { static constexpr float kInvalidScaleFactor = 0; base::ReadOnlySharedMemoryRegion invalid_emf_region; - if (page_number >= total_page_count_) { + if (page_index >= total_page_count_) { std::move(callback).Run(std::move(invalid_emf_region), kInvalidScaleFactor); return; } @@ -148,7 +148,7 @@ pdf_render_settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3_WITH_TYPE42_FONTS; base::ReadOnlySharedMemoryRegion emf_region = - RenderPdfPageToMetafile(page_number, postscript, &scale_factor); + RenderPdfPageToMetafile(page_index, postscript, &scale_factor); std::move(callback).Run(std::move(emf_region), scale_factor); }
diff --git a/chrome/services/printing/pdf_to_emf_converter.h b/chrome/services/printing/pdf_to_emf_converter.h index 02fa5f3..52cb8c8e 100644 --- a/chrome/services/printing/pdf_to_emf_converter.h +++ b/chrome/services/printing/pdf_to_emf_converter.h
@@ -26,7 +26,7 @@ private: // mojom::PdfToEmfConverter implementation. - void ConvertPage(uint32_t page_number, ConvertPageCallback callback) override; + void ConvertPage(uint32_t page_index, ConvertPageCallback callback) override; void SetPrintMode(); void LoadPdf(base::ReadOnlySharedMemoryRegion pdf_region);
diff --git a/chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom b/chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom index 954f82c..58a6e7d 100644 --- a/chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom +++ b/chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom
@@ -7,21 +7,21 @@ import "chrome/services/printing/public/mojom/pdf_render_settings.mojom"; import "mojo/public/mojom/base/shared_memory.mojom"; -// This set of interfaces is used to convert PDF files to EMF. -// Usage: -// - generate a PdfToEmfConverter by binding the PdfToEmfConverterFactory -// interface and calling PdfToEmfConverterFactory.CreateConverter(). This also -// returns the number of pages that will be generated. -// - call PdfToEmfConverter.ConvertPage() for each page to generate the EMF -// files. - +// Converts a PDF to EMF, page-by-page. interface PdfToEmfConverter { - ConvertPage(uint32 page_number) => + // Converts the page at `page_index` in the PDF. The PdfToEmfConverterFactory + // that created this PdfToEmfConverter returned how many pages are in PDF. + // For the given page, returns the converted EMF data, if successful, and the + // scale factor for that page. + ConvertPage(uint32 page_index) => (mojo_base.mojom.ReadOnlySharedMemoryRegion? emf_region, float scale_factor); }; +// Generates a PdfToEmfConverter, for converting a PDF to EMF. interface PdfToEmfConverterFactory { + // Sends the PDF data in `pdf_region`, along with the `render_settings` to + // use. Returns a PdfToEmfConverter and how many pages are in the PDF. CreateConverter(mojo_base.mojom.ReadOnlySharedMemoryRegion pdf_region, PdfRenderSettings render_settings) => (pending_remote<PdfToEmfConverter> converter, uint32 page_count);
diff --git a/chrome/test/data/extensions/api_test/file_system_provider/read_file/test.js b/chrome/test/data/extensions/api_test/file_system_provider/read_file/test.js index d73e5191..2f5d02d0 100644 --- a/chrome/test/data/extensions/api_test/file_system_provider/read_file/test.js +++ b/chrome/test/data/extensions/api_test/file_system_provider/read_file/test.js
@@ -88,19 +88,12 @@ var textToSend = TESTING_TEXT.substr(options.offset, options.length); var textToSendInChunks = textToSend.split(/(?= )/); - textToSendInChunks.forEach(function(item, index) { + textToSendInChunks.forEach((item, index) => { // Convert item (string) to an ArrayBuffer. - var reader = new FileReader(); - - reader.onload = function(e) { - onSuccess( - e.target.result, - index < textToSendInChunks.length - 1 /* hasMore */); - }; - - reader.readAsArrayBuffer(new Blob([item])); + onSuccess( + /*data=*/new TextEncoder().encode(item).buffer, + /*hasMore=*/index < textToSendInChunks.length - 1); }); - return; } if (filePath === '/' + TESTING_VANILLA_FOR_ABORT_FILE.name) {
diff --git a/chrome/test/data/extensions/api_test/file_system_provider/write_file/test.js b/chrome/test/data/extensions/api_test/file_system_provider/write_file/test.js index 14aa4a2..32c17280 100644 --- a/chrome/test/data/extensions/api_test/file_system_provider/write_file/test.js +++ b/chrome/test/data/extensions/api_test/file_system_provider/write_file/test.js
@@ -96,18 +96,19 @@ return; } - // Convert ArrayBuffer to string. - var reader = new FileReader(); - reader.onloadend = function(e) { - var oldContents = fileContents[filePath] || ''; - var newContents = oldContents.substr(0, options.offset) + reader.result + - oldContents.substr(options.offset + reader.result.length); - metadata.size = newContents.length; - fileContents[filePath] = newContents; - onSuccess(); - }; - - reader.readAsText(new Blob([options.data])); + // Create an array with enough space for new data. + const oldArray = new TextEncoder().encode(fileContents[filePath] || ''); + const newLength = + Math.max(oldArray.length, options.offset + options.data.byteLength); + const newArray = new Uint8Array(new ArrayBuffer(newLength)); + // Write existing data and new data. + newArray.set(oldArray, 0); + newArray.set(new Uint8Array(options.data), options.offset); + // Save the new file as text. + const newContents = new TextDecoder().decode(newArray); + fileContents[filePath] = newContents; + metadata.size = newContents.length; + onSuccess(); } /**
diff --git a/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js b/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js index 081b601..61c15e5 100644 --- a/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js +++ b/chrome/test/data/webui/settings/chromeos/network_summary_item_test.js
@@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://os-settings/chromeos/os_settings.js'; - +import {InternetPageBrowserProxyImpl} from 'chrome://os-settings/chromeos/os_settings.js'; import {InhibitReason} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {ConnectionStateType, DeviceStateType, NetworkType, PortalState} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; +import {TestInternetPageBrowserProxy} from './test_internet_page_browser_proxy.js'; + suite('NetworkSummaryItem', function() { /** @type {!NetworkSummaryItemElement|undefined} */ let netSummaryItem; @@ -250,9 +251,16 @@ }); suite('Portal', function() { + /** @type {?TestInternetPageBrowserProxy} */ + let browserProxy = null; + const testName = 'test_name'; + const testGuid = '0001'; function initWithPortalState(flagEnabled, portalState) { + browserProxy = new TestInternetPageBrowserProxy(); + netSummaryItem.browserProxy_ = browserProxy; + netSummaryItem.setProperties({ isCaptivePortalUI2022Enabled_: flagEnabled, deviceState: { @@ -262,7 +270,7 @@ }, activeNetworkState: { connectionState: ConnectionStateType.kPortal, - guid: '0001', + guid: testGuid, type: NetworkType.kWiFi, typeState: { wifi: { @@ -282,30 +290,56 @@ flush(); } - test('kPortal shows sign in', function() { - initWithPortalState(true /* flagEnabled */, PortalState.kPortal); - assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState') - .classList.contains('warning-message')); - assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState') - .classList.contains('network-state')); - assertEquals( - netSummaryItem.getNetworkStateText_(), - netSummaryItem.i18n('networkListItemSignIn')); - assertEquals(netSummaryItem.getTitleText_(), testName); - }); + test( + 'kPortal shows signin text and opens portal signin on click', + function() { + initWithPortalState(true /* flagEnabled */, PortalState.kPortal); + assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState') + .classList.contains('warning-message')); + assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState') + .classList.contains('network-state')); + assertEquals( + netSummaryItem.getNetworkStateText_(), + netSummaryItem.i18n('networkListItemSignIn')); + assertEquals(netSummaryItem.getTitleText_(), testName); - test('kProxyAuthRequired shows sign in', function() { - initWithPortalState( - true /* flagEnabled */, PortalState.kProxyAuthRequired); - assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState') - .classList.contains('warning-message')); - assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState') - .classList.contains('network-state')); - assertEquals( - netSummaryItem.getNetworkStateText_(), - netSummaryItem.i18n('networkListItemSignIn')); - assertEquals(netSummaryItem.getTitleText_(), testName); - }); + // Verify clicking network summary item will open portal signin + const networkSummaryItemRow = + netSummaryItem.shadowRoot.querySelector('#networkSummaryItemRow'); + assertTrue(!!networkSummaryItemRow); + networkSummaryItemRow.click(); + return browserProxy.whenCalled('showPortalSignin') + .then(function(guid) { + assertEquals(browserProxy.getCallCount('showPortalSignin'), 1); + assertEquals(testGuid, guid); + }); + }); + + test( + 'kProxyAuthRequired shows signin text and opens portal signin on click', + function() { + initWithPortalState( + true /* flagEnabled */, PortalState.kProxyAuthRequired); + assertTrue(netSummaryItem.shadowRoot.querySelector('#networkState') + .classList.contains('warning-message')); + assertFalse(netSummaryItem.shadowRoot.querySelector('#networkState') + .classList.contains('network-state')); + assertEquals( + netSummaryItem.getNetworkStateText_(), + netSummaryItem.i18n('networkListItemSignIn')); + assertEquals(netSummaryItem.getTitleText_(), testName); + + // Verify clicking network summary item will open portal signin + const networkSummaryItemRow = + netSummaryItem.shadowRoot.querySelector('#networkSummaryItemRow'); + assertTrue(!!networkSummaryItemRow); + networkSummaryItemRow.click(); + return browserProxy.whenCalled('showPortalSignin') + .then(function(guid) { + assertEquals(browserProxy.getCallCount('showPortalSignin'), 1); + assertEquals(testGuid, guid); + }); + }); test('kPortal does not show sign in when flag is disabled', function() { initWithPortalState(false /* flagEnabled */, PortalState.kPortal); @@ -317,6 +351,13 @@ netSummaryItem.getNetworkStateText_(), netSummaryItem.i18n('networkListItemSignIn')); assertNotEquals(netSummaryItem.getTitleText_(), testName); + + // Verify clicking network summary item does not open portal signin + const networkSummaryItemRow = + netSummaryItem.shadowRoot.querySelector('#networkSummaryItemRow'); + assertTrue(!!networkSummaryItemRow); + networkSummaryItemRow.click(); + assertEquals(browserProxy.getCallCount('showPortalSignin'), 0); }); test( @@ -332,6 +373,12 @@ netSummaryItem.getNetworkStateText_(), netSummaryItem.i18n('networkListItemSignIn')); assertNotEquals(netSummaryItem.getTitleText_(), testName); + // Verify clicking network summary item does not open portal signin + const networkSummaryItemRow = + netSummaryItem.shadowRoot.querySelector('#networkSummaryItemRow'); + assertTrue(!!networkSummaryItemRow); + networkSummaryItemRow.click(); + assertEquals(browserProxy.getCallCount('showPortalSignin'), 0); }); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/test_internet_page_browser_proxy.js b/chrome/test/data/webui/settings/chromeos/test_internet_page_browser_proxy.js index c02b6cc..8b800c5 100644 --- a/chrome/test/data/webui/settings/chromeos/test_internet_page_browser_proxy.js +++ b/chrome/test/data/webui/settings/chromeos/test_internet_page_browser_proxy.js
@@ -11,6 +11,7 @@ constructor() { super([ 'showCarrierAccountDetail', + 'showPortalSignin', 'showCellularSetupUI', 'configureThirdPartyVpn', 'addThirdPartyVpn', @@ -25,6 +26,11 @@ } /** @override */ + showPortalSignin(guid) { + this.methodCalled('showPortalSignin', guid); + } + + /** @override */ showCellularSetupUI(guid) { this.methodCalled('showCellularSetupUI'); }
diff --git a/chrome/test/ppapi/ppapi_test_select_file_dialog_factory.cc b/chrome/test/ppapi/ppapi_test_select_file_dialog_factory.cc index 686cff5..792c377 100644 --- a/chrome/test/ppapi/ppapi_test_select_file_dialog_factory.cc +++ b/chrome/test/ppapi/ppapi_test_select_file_dialog_factory.cc
@@ -5,7 +5,6 @@ #include "chrome/test/ppapi/ppapi_test_select_file_dialog_factory.h" #include "base/bind.h" -#include "base/memory/weak_ptr.h" #include "base/threading/thread_task_runner_handle.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/shell_dialogs/select_file_dialog.h" @@ -61,8 +60,8 @@ base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce( - &PPAPITestSelectFileDialog::RespondToFileSelectionRequest, - base::AsWeakPtr(this), params)); + &PPAPITestSelectFileDialog::RespondToFileSelectionRequest, this, + params)); } bool HasMultipleFileTypeChoicesImpl() override { return false; }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 401f5b8..0d7284b23 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -15113.0.0 \ No newline at end of file +15156.0.0 \ No newline at end of file
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc b/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc index 67e95115..6b9927b 100644 --- a/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc +++ b/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc
@@ -361,8 +361,8 @@ } void AudioDevicesPrefHandlerImpl::SaveDevicesMutePref() { - DictionaryPrefUpdate dict_update(local_state_, prefs::kAudioDevicesMute); - dict_update->GetDict() = device_mute_settings_.Clone(); + local_state_->SetDict(prefs::kAudioDevicesMute, + device_mute_settings_.Clone()); } void AudioDevicesPrefHandlerImpl::LoadDevicesVolumePref() { @@ -372,9 +372,8 @@ } void AudioDevicesPrefHandlerImpl::SaveDevicesVolumePref() { - DictionaryPrefUpdate dict_update(local_state_, - prefs::kAudioDevicesVolumePercent); - dict_update->GetDict() = device_volume_settings_.Clone(); + local_state_->SetDict(prefs::kAudioDevicesVolumePercent, + device_volume_settings_.Clone()); } void AudioDevicesPrefHandlerImpl::LoadDevicesGainPref() { @@ -384,9 +383,8 @@ } void AudioDevicesPrefHandlerImpl::SaveDevicesGainPref() { - DictionaryPrefUpdate dict_update(local_state_, - prefs::kAudioDevicesGainPercent); - dict_update->GetDict() = device_gain_settings_.Clone(); + local_state_->SetDict(prefs::kAudioDevicesGainPercent, + device_gain_settings_.Clone()); } void AudioDevicesPrefHandlerImpl::LoadDevicesStatePref() { @@ -396,8 +394,8 @@ } void AudioDevicesPrefHandlerImpl::SaveDevicesStatePref() { - DictionaryPrefUpdate dict_update(local_state_, prefs::kAudioDevicesState); - dict_update->GetDict() = device_state_settings_.Clone(); + local_state_->SetDict(prefs::kAudioDevicesState, + device_state_settings_.Clone()); } void AudioDevicesPrefHandlerImpl::LoadInputDevicesUserPriorityPref() { @@ -407,9 +405,8 @@ } void AudioDevicesPrefHandlerImpl::SaveInputDevicesUserPriorityPref() { - DictionaryPrefUpdate dict_update(local_state_, - prefs::kAudioInputDevicesUserPriority); - dict_update->GetDict() = input_device_user_priority_settings_.Clone(); + local_state_->SetDict(prefs::kAudioInputDevicesUserPriority, + input_device_user_priority_settings_.Clone()); } void AudioDevicesPrefHandlerImpl::LoadOutputDevicesUserPriorityPref() { @@ -419,9 +416,8 @@ } void AudioDevicesPrefHandlerImpl::SaveOutputDevicesUserPriorityPref() { - DictionaryPrefUpdate dict_update(local_state_, - prefs::kAudioOutputDevicesUserPriority); - dict_update->GetDict() = output_device_user_priority_settings_.Clone(); + local_state_->SetDict(prefs::kAudioOutputDevicesUserPriority, + output_device_user_priority_settings_.Clone()); } bool AudioDevicesPrefHandlerImpl::MigrateDevicesStatePref(
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc b/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc index ab9850d..8d866a5 100644 --- a/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc +++ b/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc
@@ -116,27 +116,27 @@ // are set when pref value sets up its internal state. std::string preset_key = GetPresetDeviceDeprecatedPrefKey(); { - DictionaryPrefUpdate update(pref_service_.get(), + ScopedDictPrefUpdate update(pref_service_.get(), prefs::kAudioDevicesState); - base::Value* pref = update.Get(); - base::Value state(base::Value::Type::DICTIONARY); - state.SetBoolKey("active", kPresetState.active); - state.SetBoolKey("activate_by_user", kPresetState.activate_by_user); - pref->SetKey(preset_key, std::move(state)); + base::Value::Dict& pref = update.Get(); + base::Value::Dict state; + state.Set("active", kPresetState.active); + state.Set("activate_by_user", kPresetState.activate_by_user); + pref.Set(preset_key, std::move(state)); } { - DictionaryPrefUpdate update(pref_service_.get(), + ScopedDictPrefUpdate update(pref_service_.get(), prefs::kAudioDevicesVolumePercent); - base::Value* pref = update.Get(); - pref->SetDoubleKey(preset_key, kPresetState.sound_level); + base::Value::Dict& pref = update.Get(); + pref.Set(preset_key, kPresetState.sound_level); } { - DictionaryPrefUpdate update(pref_service_.get(), + ScopedDictPrefUpdate update(pref_service_.get(), prefs::kAudioDevicesMute); - base::Value* pref = update.Get(); - pref->SetIntKey(preset_key, static_cast<int>(kPresetState.mute)); + base::Value::Dict& pref = update.Get(); + pref.Set(preset_key, static_cast<int>(kPresetState.mute)); } audio_pref_handler_ = new AudioDevicesPrefHandlerImpl(pref_service_.get());
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc index 72370b95..2e64d9bf 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.cc
@@ -317,56 +317,42 @@ } // namespace -// Allocate space for test api instance -base::raw_ptr<FakeUserDataAuthClient::TestApi> - FakeUserDataAuthClient::TestApi::instance_; - -FakeUserDataAuthClient::TestApi::TestApi( - base::raw_ptr<FakeUserDataAuthClient> client) { - DCHECK(client != nullptr); - client_ = client; -} - // static FakeUserDataAuthClient::TestApi* FakeUserDataAuthClient::TestApi::Get() { - if (instance_) { - return instance_; - } - // TestApi assumes that the FakeUserDataAuthClient singleton is initialized. if (FakeUserDataAuthClient::Get() == nullptr) { return nullptr; } - instance_ = new TestApi(FakeUserDataAuthClient::Get()); - return instance_; + static TestApi instance; + return &instance; } void FakeUserDataAuthClient::TestApi::SetServiceIsAvailable(bool is_available) { - service_is_available_ = is_available; + g_instance->service_is_available_ = is_available; if (!is_available) return; - client_->RunPendingWaitForServiceToBeAvailableCallbacks(); + g_instance->RunPendingWaitForServiceToBeAvailableCallbacks(); } void FakeUserDataAuthClient::TestApi::ReportServiceIsNotAvailable() { - DCHECK(!service_is_available_); - service_reported_not_available_ = true; - client_->RunPendingWaitForServiceToBeAvailableCallbacks(); + DCHECK(!g_instance->service_is_available_); + g_instance->service_reported_not_available_ = true; + g_instance->RunPendingWaitForServiceToBeAvailableCallbacks(); } void FakeUserDataAuthClient::TestApi::SetHomeEncryptionMethod( const cryptohome::AccountIdentifier& cryptohome_id, HomeEncryptionMethod method) { - auto user_it = client_->users_.find(cryptohome_id); - if (user_it == std::end(client_->users_)) { + auto user_it = g_instance->users_.find(cryptohome_id); + if (user_it == std::end(g_instance->users_)) { LOG(ERROR) << "User does not exist: " << cryptohome_id.account_id(); // TODO(crbug.com/1334538): Some existing tests rely on us creating the // user here, but new tests shouldn't. Eventually this should crash. user_it = - client_->users_.insert({cryptohome_id, UserCryptohomeState()}).first; + g_instance->users_.insert({cryptohome_id, UserCryptohomeState()}).first; } - DCHECK(user_it != std::end(client_->users_)); + DCHECK(user_it != std::end(g_instance->users_)); UserCryptohomeState& user_state = user_it->second; user_state.home_encryption_method = method; } @@ -375,8 +361,8 @@ const cryptohome::AccountIdentifier& account_id, const std::string& label, bool locked) { - auto user_it = client_->users_.find(account_id); - CHECK(user_it != client_->users_.end()) + auto user_it = g_instance->users_.find(account_id); + CHECK(user_it != g_instance->users_.end()) << "User does not exist: " << account_id.account_id(); UserCryptohomeState& user_state = user_it->second; @@ -394,14 +380,14 @@ void FakeUserDataAuthClient::TestApi::AddExistingUser( const cryptohome::AccountIdentifier& account_id) { const auto [user_it, was_inserted] = - client_->users_.insert({std::move(account_id), UserCryptohomeState()}); + g_instance->users_.insert({std::move(account_id), UserCryptohomeState()}); if (!was_inserted) { LOG(WARNING) << "User already exists: " << user_it->first.account_id(); return; } const absl::optional<base::FilePath> profile_dir = - client_->GetUserProfileDir(user_it->first); + g_instance->GetUserProfileDir(user_it->first); if (!profile_dir) { LOG(WARNING) << "User data directory has not been set, will not create " "user profile directory"; @@ -415,17 +401,17 @@ absl::optional<base::FilePath> FakeUserDataAuthClient::TestApi::GetUserProfileDir( const cryptohome::AccountIdentifier& account_id) const { - return client_->GetUserProfileDir(account_id); + return g_instance->GetUserProfileDir(account_id); } void FakeUserDataAuthClient::TestApi::AddKey( const cryptohome::AccountIdentifier& account_id, const cryptohome::Key& key) { - const auto user_it = client_->users_.find(account_id); - CHECK(user_it != std::end(client_->users_)) << "User doesn't exist"; + const auto user_it = g_instance->users_.find(account_id); + CHECK(user_it != std::end(g_instance->users_)) << "User doesn't exist"; UserCryptohomeState& user_state = user_it->second; const auto [factor_it, was_inserted] = user_state.auth_factors.insert( - KeyToFakeAuthFactor(key, TestApi::Get()->enable_auth_check_)); + KeyToFakeAuthFactor(key, g_instance->enable_auth_check_)); CHECK(was_inserted) << "Factor already exists"; } @@ -492,7 +478,7 @@ // TODO(crbug.com/1334538): We should get rid of mount_create_required_ // and instead check whether the user exists or not here. Tests would then // need to set up a user (or not). - if (TestApi::Get()->mount_create_required_ && !request.has_create()) { + if (mount_create_required_ && !request.has_create()) { reply.set_error(::user_data_auth::CryptohomeErrorCode:: CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND); return; @@ -551,8 +537,8 @@ CHECK_EQ(1, create_req.keys().size()) << "UserDataAuth::Mount called with `create` that does not contain " "precisely one key"; - user_state.auth_factors.insert(KeyToFakeAuthFactor( - create_req.keys()[0], TestApi::Get()->enable_auth_check_)); + user_state.auth_factors.insert( + KeyToFakeAuthFactor(create_req.keys()[0], enable_auth_check_)); } const bool is_ecryptfs = @@ -710,7 +696,7 @@ UserCryptohomeState& user_state = user_it->second; auto [new_label, new_factor] = - KeyToFakeAuthFactor(new_key, TestApi::Get()->enable_auth_check_); + KeyToFakeAuthFactor(new_key, enable_auth_check_); CHECK(clobber_if_exists || !user_state.auth_factors.contains(new_label)) << "Key exists, will not clobber: " << new_label; user_state.auth_factors[std::move(new_label)] = std::move(new_factor); @@ -781,7 +767,7 @@ new_key.mutable_data()->set_label(matched_factor_label); new_key.set_secret(request.secret()); const auto [new_label, new_factor] = - KeyToFakeAuthFactor(new_key, TestApi::Get()->enable_auth_check_); + KeyToFakeAuthFactor(new_key, enable_auth_check_); DCHECK_EQ(new_label, matched_factor_label); user_state.auth_factors[matched_factor_label] = new_factor; } @@ -808,7 +794,7 @@ dircrypto_migration_progress_ = 0; - if (TestApi::Get()->run_default_dircrypto_migration_) { + if (run_default_dircrypto_migration_) { dircrypto_migration_progress_timer_.Start( FROM_HERE, base::Milliseconds(kDircryptoMigrationUpdateIntervalMs), this, &FakeUserDataAuthClient::OnDircryptoMigrationProgressUpdated); @@ -842,7 +828,7 @@ GetSupportedKeyPoliciesCallback callback) { ::user_data_auth::GetSupportedKeyPoliciesReply reply; reply.set_low_entropy_credentials_supported( - TestApi::Get()->supports_low_entropy_credentials_); + supports_low_entropy_credentials_); ReturnProtobufMethodCallback(reply, std::move(callback)); } void FakeUserDataAuthClient::GetAccountDiskUsage( @@ -1256,8 +1242,7 @@ UserCryptohomeState& user_state = user_it->second; auto [new_label, new_factor] = AuthFactorWithInputToFakeAuthFactor( - request.auth_factor(), request.auth_input(), - TestApi::Get()->enable_auth_check_); + request.auth_factor(), request.auth_input(), enable_auth_check_); CHECK(!user_state.auth_factors.contains(new_label)) << "Key exists, will not clobber: " << new_label; user_state.auth_factors[std::move(new_label)] = std::move(new_factor); @@ -1310,7 +1295,7 @@ [&](const PasswordFactor& password_factor) { const auto& password_input = auth_input.password_input(); - if (TestApi::Get()->enable_auth_check_ && + if (enable_auth_check_ && password_input.secret() != password_factor.password) { reply.set_error( ::user_data_auth::CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED); @@ -1320,15 +1305,7 @@ [&](const PinFactor& pin_factor) { const auto& pin_input = auth_input.pin_input(); - if (pin_factor.locked) { - LOG(ERROR) << "PIN is locked"; - reply.set_error( - ::user_data_auth::CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED); - return; - } - - if (TestApi::Get()->enable_auth_check_ && - pin_input.secret() != pin_factor.pin) { + if (enable_auth_check_ && pin_input.secret() != pin_factor.pin) { reply.set_error( ::user_data_auth::CRYPTOHOME_ERROR_AUTHORIZATION_KEY_FAILED); return; @@ -1389,8 +1366,7 @@ // Update the fake auth factor according to the new secret. auto [new_label, new_factor] = AuthFactorWithInputToFakeAuthFactor( - request.auth_factor(), request.auth_input(), - TestApi::Get()->enable_auth_check_); + request.auth_factor(), request.auth_input(), enable_auth_check_); CHECK_EQ(new_label, request.auth_factor_label()); CHECK(user_state.auth_factors.contains(new_label)) << "Key does not exist: " << new_label; @@ -1460,11 +1436,9 @@ void FakeUserDataAuthClient::WaitForServiceToBeAvailable( chromeos::WaitForServiceToBeAvailableCallback callback) { - if (TestApi::Get()->service_is_available_ || - TestApi::Get()->service_reported_not_available_) { + if (service_is_available_ || service_reported_not_available_) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - TestApi::Get()->service_is_available_)); + FROM_HERE, base::BindOnce(std::move(callback), service_is_available_)); } else { pending_wait_for_service_to_be_available_callbacks_.push_back( std::move(callback)); @@ -1485,7 +1459,7 @@ const std::string& secret, bool wildcard_allowed, std::string* matched_factor_label) const { - if (!TestApi::Get()->enable_auth_check_) + if (!enable_auth_check_) return AuthResult::kAuthSuccess; const auto user_it = users_.find(account_id);
diff --git a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h index ffc4a77e..7c78ef4 100644 --- a/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h +++ b/chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h
@@ -29,16 +29,11 @@ kEcryptfs, }; + // The TestAPI of FakeUserDataAuth. Prefer to use `ash::CryptohomeMixin`, + // which exposes all the methods here and some additional ones. class COMPONENT_EXPORT(USERDATAAUTH_CLIENT) TestApi { public: - ~TestApi() = default; - - // Not copyable or movable. - TestApi(const TestApi&) = delete; - TestApi& operator=(const TestApi&) = delete; - TestApi(TestApi&&) = delete; - TestApi& operator=(TestApi&&) = delete; - + // Legacy method for tests that do not use `CryptohomeMixin`. static TestApi* Get(); // Sets whether dircrypto migration update should be run automatically. @@ -46,19 +41,20 @@ // progress updates on its own - a test that sets this will have to call // NotifyDircryptoMigrationProgress() for the progress to update. void set_run_default_dircrypto_migration(bool value) { - run_default_dircrypto_migration_ = value; + FakeUserDataAuthClient::Get()->run_default_dircrypto_migration_ = value; } // If set, next call to GetSupportedKeyPolicies() will tell caller that low // entropy credentials are supported. void set_supports_low_entropy_credentials(bool supports) { - supports_low_entropy_credentials_ = supports; + FakeUserDataAuthClient::Get()->supports_low_entropy_credentials_ = + supports; } // If enable_auth_check is true, then authentication requests actually check // the key. void set_enable_auth_check(bool enable_auth_check) { - enable_auth_check_ = enable_auth_check; + FakeUserDataAuthClient::Get()->enable_auth_check_ = enable_auth_check; } // Sets whether the Mount() call should fail when the |create| field is not @@ -66,7 +62,8 @@ // This allows to simulate the behavior during the new user profile // creation. void set_mount_create_required(bool mount_create_required) { - mount_create_required_ = mount_create_required; + FakeUserDataAuthClient::Get()->mount_create_required_ = + mount_create_required; } // Changes the behavior of WaitForServiceToBeAvailable(). This method runs @@ -104,38 +101,6 @@ // already exist). void AddKey(const cryptohome::AccountIdentifier& account_id, const cryptohome::Key& key); - - private: - friend class FakeUserDataAuthClient; - - explicit TestApi(base::raw_ptr<FakeUserDataAuthClient> client); - - // The singleton instance - static base::raw_ptr<FakeUserDataAuthClient::TestApi> instance_; - - // Do we run the dircrypto migration, as in, emit signals, when - // StartMigrateToDircrypto() is called? - bool run_default_dircrypto_migration_ = true; - - // If low entropy credentials are supported for the key. This is the value - // that GetSupportedKeyPolicies() returns. - bool supports_low_entropy_credentials_ = false; - - // If true, authentication requests actually check the key. - bool enable_auth_check_ = false; - - // If true, fails if |create| field is not provided - bool mount_create_required_ = false; - - // If set, we tell callers that service is available. - bool service_is_available_ = true; - - // If set, WaitForServiceToBeAvailable will run the callback, even if - // service is not available (instead of adding the callback to pending - // callback list). - bool service_reported_not_available_ = false; - - base::raw_ptr<FakeUserDataAuthClient> client_; }; // Represents the ongoing AuthSessions. @@ -431,6 +396,28 @@ // List of observers. base::ObserverList<Observer> observer_list_; + + // Do we run the dircrypto migration, as in, emit signals, when + // StartMigrateToDircrypto() is called? + bool run_default_dircrypto_migration_ = true; + + // If low entropy credentials are supported for the key. This is the value + // that GetSupportedKeyPolicies() returns. + bool supports_low_entropy_credentials_ = false; + + // If true, authentication requests actually check the key. + bool enable_auth_check_ = false; + + // If true, fails if |create| field is not provided + bool mount_create_required_ = false; + + // If set, we tell callers that service is available. + bool service_is_available_ = true; + + // If set, WaitForServiceToBeAvailable will run the callback, even if + // service is not available (instead of adding the callback to pending + // callback list). + bool service_reported_not_available_ = false; }; } // namespace ash
diff --git a/chromeos/ash/components/string_matching/prefix_matcher_new.cc b/chromeos/ash/components/string_matching/prefix_matcher_new.cc index 9bafa93..1bae69b 100644 --- a/chromeos/ash/components/string_matching/prefix_matcher_new.cc +++ b/chromeos/ash/components/string_matching/prefix_matcher_new.cc
@@ -14,8 +14,15 @@ #include "chromeos/ash/components/string_matching/tokenized_string.h" namespace ash::string_matching { +namespace { +using prefix_matcher_constants::kIsFrontOfTokenCharScore; +using prefix_matcher_constants::kIsPrefixCharScore; +using prefix_matcher_constants::kIsWeakHitCharScore; +using prefix_matcher_constants::kNoMatchScore; + MatchInfo::MatchInfo() = default; MatchInfo::~MatchInfo() = default; +} // namespace // TODO(crbug.com/1336160): Replace PrefixMatcher with PrefixMatcherNew // @@ -56,12 +63,19 @@ SentencePrefixMatch(sentence_match_info); MatchInfo token_match_info; TokenPrefixMatch(token_match_info); - relevance_ = - std::max(sentence_match_info.relevance, token_match_info.relevance); + + MatchInfo& better_match = + sentence_match_info.relevance >= token_match_info.relevance + ? sentence_match_info + : token_match_info; + relevance_ = better_match.relevance; + hits_ = better_match.hits; return relevance_ > 0.0; } void PrefixMatcherNew::SentencePrefixMatch(MatchInfo& sentence_match_info) { + // Since we are concatenating the tokens, we do not have whitespace + // separation, and so we have to be careful with index calculation later on. std::u16string query_sentence = base::StrCat(query_.tokens()); std::u16string text_sentence = base::StrCat(text_.tokens()); @@ -87,23 +101,34 @@ continue; } - // Update the relevance score and break the loop if the found match begins - // from the starting index of a token. + // Calculate the `relevance` score and `hits` and return if the found match + // begins from the starting index of a token. DCHECK(text_token_indexes.front() == matched_index); - if (matched_index == 0) - sentence_match_info.relevance = - constants::kIsPrefixCharScore * query_sentence.size(); - else { - sentence_match_info.relevance = - constants::kIsWeakHitCharScore * query_sentence.size(); - while (!text_token_indexes.empty() && - text_token_indexes.front() < - matched_index + query_sentence.size()) { - text_token_indexes.pop(); - sentence_match_info.relevance += constants::kIsFrontOfTokenCharScore - - constants::kIsWeakHitCharScore; - } + size_t text_pos = text_.tokens().size() - text_token_indexes.size(); + size_t text_sentence_end_pos = matched_index + query_sentence.size(); + + sentence_match_info.relevance = 0.0; + sentence_match_info.current_match.set_start( + text_.mappings()[text_pos].start()); + + while (!text_token_indexes.empty() && + text_token_indexes.front() < text_sentence_end_pos) { + // Text size may be smaller than the token size as prefix matching is + // allowed for the last token. + size_t text_size = + std::min(text_.tokens()[text_pos].size(), + text_sentence_end_pos - text_token_indexes.front()); + sentence_match_info.relevance += + matched_index == 0 ? kIsPrefixCharScore * text_size + : kIsFrontOfTokenCharScore + + kIsWeakHitCharScore * (text_size - 1); + sentence_match_info.current_match.set_end( + text_.mappings()[text_pos].start() + text_size); + + ++text_pos; + text_token_indexes.pop(); } + sentence_match_info.hits.push_back(sentence_match_info.current_match); return; } } @@ -155,30 +180,48 @@ ++matched_num; } - if (matched_num == num_query_token) + if (matched_num == num_query_token) { + DCHECK(token_match_info.current_match.IsValid()); + token_match_info.hits.push_back(token_match_info.current_match); return; + } } - token_match_info.relevance = constants::kNoMatchScore; + token_match_info.relevance = kNoMatchScore; } void PrefixMatcherNew::UpdateInfoForTokenPrefixMatch( size_t query_pos, size_t text_pos, MatchInfo& token_match_info) { - // TODO(crbug.com/1336160): Update the hits information. We concentrate on - // the correctness of the prefix matching and the relevance score in the - // first implement. The hits will be calculated and tested when prefix - // matcher is replaced in TokenizedStringMatch. - if (token_match_info.is_front && - (query_pos != token_match_info.last_query_pos + 1 || - text_pos != token_match_info.last_query_pos + 1)) { + const size_t hit_start_pos = text_.mappings()[text_pos].start(); + const size_t hit_end_pos = + text_.mappings()[text_pos].start() + query_.tokens()[query_pos].size(); + + // Update the hits information. + if (query_pos != token_match_info.last_query_pos + 1 || + text_pos != token_match_info.last_query_pos + 1) { token_match_info.is_front = false; + + // When it's not continuous matching and we have a valid `current_match`, + // push it `hits` and start a new match. + if (token_match_info.current_match.IsValid()) { + token_match_info.hits.push_back(token_match_info.current_match); + token_match_info.current_match = gfx::Range::InvalidRange(); + } } + // It's a continuous matching if the `current_match` is valid. + // Update only the end position if it's a continuous matching, and update both + // the start && end positions otherwise. + if (!token_match_info.current_match.IsValid()) + token_match_info.current_match.set_start(hit_start_pos); + token_match_info.current_match.set_end(hit_end_pos); + + // Update relevance score. token_match_info.relevance += token_match_info.is_front - ? constants::kIsPrefixCharScore * query_.tokens().at(query_pos).size() - : constants::kIsFrontOfTokenCharScore + - constants::kIsWeakHitCharScore * + ? kIsPrefixCharScore * query_.tokens().at(query_pos).size() + : kIsFrontOfTokenCharScore + + kIsWeakHitCharScore * (query_.tokens().at(query_pos).size() - 1); token_match_info.last_query_pos = query_pos; token_match_info.last_text_pos = text_pos;
diff --git a/chromeos/ash/components/string_matching/prefix_matcher_new.h b/chromeos/ash/components/string_matching/prefix_matcher_new.h index d88922f..4c3a41cd 100644 --- a/chromeos/ash/components/string_matching/prefix_matcher_new.h +++ b/chromeos/ash/components/string_matching/prefix_matcher_new.h
@@ -5,20 +5,20 @@ #ifndef CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_NEW_H_ #define CHROMEOS_ASH_COMPONENTS_STRING_MATCHING_PREFIX_MATCHER_NEW_H_ -#include "base/notreached.h" #include "chromeos/ash/components/string_matching/tokenized_string.h" +#include "ui/gfx/range/range.h" namespace ash::string_matching { // These are described in more detail in the .cc file. -namespace constants { +namespace prefix_matcher_constants { constexpr double kIsPrefixCharScore = 1.0; constexpr double kIsFrontOfTokenCharScore = 0.8; constexpr double kIsWeakHitCharScore = 0.6; constexpr double kNoMatchScore = 0.0; -} // namespace constants +} // namespace prefix_matcher_constants namespace { struct MatchInfo { @@ -31,8 +31,10 @@ MatchInfo(const MatchInfo&) = delete; MatchInfo& operator=(const MatchInfo&) = delete; - double relevance = constants::kNoMatchScore; + double relevance = prefix_matcher_constants::kNoMatchScore; Hits hits; + + gfx::Range current_match = gfx::Range::InvalidRange(); // The last query/text position that the relevance was updated. size_t last_query_pos = SIZE_MAX; size_t last_text_pos = SIZE_MAX; @@ -59,13 +61,7 @@ bool Match(); double relevance() const { return relevance_; } - // TODO(crbug.com/1336160): The hits_ has not yet been calculated. It will be - // implemented in the following CLs, and is not expected to be called at - // current stage. - const Hits& hits() const { - NOTREACHED(); - return hits_; - } + const Hits& hits() const { return hits_; } private: // Stops on the first full sentence prefix match and updates the relevance @@ -105,7 +101,9 @@ // last query token). void TokenPrefixMatch(MatchInfo& token_match_info); - // update the relevance score of token prefix based on the matched token. + // Update the relevance score of token prefix based on the matched token. This + // method can cope with full and partial token matches as it always update the + // `relevance` and `hits` according the query size. void UpdateInfoForTokenPrefixMatch(size_t query_pos, size_t text_pos, MatchInfo& token_match_info); @@ -113,7 +111,7 @@ const TokenizedString& query_; const TokenizedString& text_; - double relevance_ = constants::kNoMatchScore; + double relevance_ = prefix_matcher_constants::kNoMatchScore; Hits hits_; };
diff --git a/chromeos/ash/components/string_matching/prefix_matcher_new_unittest.cc b/chromeos/ash/components/string_matching/prefix_matcher_new_unittest.cc index 5c872e34..a55fede 100644 --- a/chromeos/ash/components/string_matching/prefix_matcher_new_unittest.cc +++ b/chromeos/ash/components/string_matching/prefix_matcher_new_unittest.cc
@@ -11,10 +11,10 @@ namespace { -using constants::kIsFrontOfTokenCharScore; -using constants::kIsPrefixCharScore; -using constants::kIsWeakHitCharScore; -using constants::kNoMatchScore; +using prefix_matcher_constants::kIsFrontOfTokenCharScore; +using prefix_matcher_constants::kIsPrefixCharScore; +using prefix_matcher_constants::kIsWeakHitCharScore; +using prefix_matcher_constants::kNoMatchScore; constexpr double kAbsError = 1e-5;
diff --git a/chromeos/ash/components/string_matching/tokenized_string_match.cc b/chromeos/ash/components/string_matching/tokenized_string_match.cc index dd0b5b9..a559758f 100644 --- a/chromeos/ash/components/string_matching/tokenized_string_match.cc +++ b/chromeos/ash/components/string_matching/tokenized_string_match.cc
@@ -10,7 +10,7 @@ #include "base/i18n/string_search.h" #include "base/strings/string_util.h" -#include "chromeos/ash/components/string_matching/prefix_matcher.h" +#include "chromeos/ash/components/string_matching/prefix_matcher_new.h" namespace ash::string_matching { @@ -41,12 +41,12 @@ const auto text_size = text_text.size(); if (query_size > 0 && query_size == text_size && base::EqualsCaseInsensitiveASCII(query_text, text_text)) { - hits_.push_back(gfx::Range(0, query_size)); + hits_.emplace_back(0, query_size); relevance_ = 1.0; return true; } - PrefixMatcher matcher(query, text); + PrefixMatcherNew matcher(query, text); if (matcher.Match()) { relevance_ = matcher.relevance(); hits_.assign(matcher.hits().begin(), matcher.hits().end()); @@ -60,8 +60,8 @@ query.text(), text.text(), &substr_match_start, &substr_match_length)) { relevance_ = kIsSubstringMultiplier * substr_match_length; - hits_.push_back(gfx::Range(substr_match_start, - substr_match_start + substr_match_length)); + hits_.emplace_back(substr_match_start, + substr_match_start + substr_match_length); } }
diff --git a/chromeos/ash/components/string_matching/tokenized_string_match_unittest.cc b/chromeos/ash/components/string_matching/tokenized_string_match_unittest.cc index b2046a2..b8aaa91 100644 --- a/chromeos/ash/components/string_matching/tokenized_string_match_unittest.cc +++ b/chromeos/ash/components/string_matching/tokenized_string_match_unittest.cc
@@ -59,21 +59,41 @@ const char* expect; } kTestCases[] = { {"ScratchPad", "pad", "Scratch[Pad]"}, - {"ScratchPad", "sp", "[S]cratch[P]ad"}, {"Chess2", "che", "[Che]ss2"}, - {"Chess2", "c2", "[C]hess[2]"}, - {"Cut the rope", "cut ro", "[Cu]t [t]he [ro]pe"}, - {"John Doe", "jdoe", "[J]ohn [Doe]"}, - {"John Doe", "johnd", "[John D]oe"}, + {"John Doe", "john d", "[John D]oe"}, + {"Cut the rope", "cut ro", "[Cut] the [ro]pe"}, {"Secure Shell", "she", "Secure [She]ll"}, {"Netflix", "flix", "Net[flix]"}, + {"John Doe", "johnd", "[John D]oe"}, + {"John Doe", "doe john", "[John] [Doe]"}, + {"John Doe", "doe joh", "[Joh]n [Doe]"}, }; TokenizedStringMatch match; - for (size_t i = 0; i < std::size(kTestCases); ++i) { - const std::u16string text(base::UTF8ToUTF16(kTestCases[i].text)); - EXPECT_TRUE(match.Calculate(base::UTF8ToUTF16(kTestCases[i].query), text)); - EXPECT_EQ(kTestCases[i].expect, MatchHit(text, match)); + for (auto& test_case : kTestCases) { + const std::u16string text(base::UTF8ToUTF16(test_case.text)); + EXPECT_TRUE(match.Calculate(base::UTF8ToUTF16(test_case.query), text)); + EXPECT_EQ(test_case.expect, MatchHit(text, match)); + } +} + +TEST(TokenizedStringMatchTest, AcronymMatchNotAllowed) { + struct { + const char* text; + const char* query; + const char* expect; + } kTestCases[] = { + {"ScratchPad", "sp", "ScratchPad"}, + {"Chess2", "c2", "Chess2"}, + {"John Doe", "jdoe", "John Doe"}, + {"hello John Doe", "jdoe", "hello John Doe"}, + }; + + TokenizedStringMatch match; + for (auto& test_case : kTestCases) { + const std::u16string text(base::UTF8ToUTF16(test_case.text)); + EXPECT_FALSE(match.Calculate(base::UTF8ToUTF16(test_case.query), text)); + EXPECT_EQ(test_case.expect, MatchHit(text, match)); } } @@ -89,13 +109,9 @@ {"Google Chrome", "goo", "goog"}, {"Google Chrome", "c", "ch"}, {"Google Chrome", "ch", "chr"}, - // Acronym match is better than something in the middle. - {"Google Chrome", "ch", "gc"}, - // Prefix match is better than middle match and acronym match. + // Prefix match is better than middle match. {"Google Chrome", "ch", "go"}, - {"Google Chrome", "gc", "go"}, // Substring match has the lowest score. - {"Google Chrome", "oo", "gc"}, {"Google Chrome", "oo", "go"}, {"Google Chrome", "oo", "ch"}, };
diff --git a/chromeos/ash/services/bluetooth_config/device_name_manager_impl.cc b/chromeos/ash/services/bluetooth_config/device_name_manager_impl.cc index 567f707..1078de4 100644 --- a/chromeos/ash/services/bluetooth_config/device_name_manager_impl.cc +++ b/chromeos/ash/services/bluetooth_config/device_name_manager_impl.cc
@@ -85,14 +85,11 @@ return; } - base::Value* device_id_to_nickname_map = - DictionaryPrefUpdate(local_state_, kDeviceIdToNicknameMapPrefName).Get(); - DCHECK(device_id_to_nickname_map) - << "Device ID to nickname map pref is unregistered."; + ScopedDictPrefUpdate update(local_state_, kDeviceIdToNicknameMapPrefName); BLUETOOTH_LOG(USER) << "Setting device nickname for " << device_id << " to " << nickname; - device_id_to_nickname_map->SetStringKey(device_id, nickname); + update->Set(device_id, nickname); NotifyDeviceNicknameChanged(device_id, nickname); device::RecordSetDeviceNickName(device::SetNicknameResult::kSuccess); @@ -105,20 +102,17 @@ return; } - base::Value* device_id_to_nickname_map = - DictionaryPrefUpdate(local_state_, kDeviceIdToNicknameMapPrefName).Get(); - DCHECK(device_id_to_nickname_map) - << "Device ID to nickname map pref is unregistered."; + ScopedDictPrefUpdate update(local_state_, kDeviceIdToNicknameMapPrefName); // Do nothing if no nickname exists for |device_id|. - if (!device_id_to_nickname_map->FindStringKey(device_id)) { + if (!update->Find(device_id)) { BLUETOOTH_LOG(ERROR) << "RemoveDeviceNickname for device failed because no " << "nickname exists for " << device_id; return; } BLUETOOTH_LOG(EVENT) << "Removing device nickname for " << device_id; - device_id_to_nickname_map->RemoveKey(device_id); + update->Remove(device_id); NotifyDeviceNicknameChanged(device_id, /*nickname=*/absl::nullopt); }
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index f5682a7..44e3f046 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -291,6 +291,9 @@ "lacros.Basic", "lacros.ShelfLaunch", "lacros.AppLauncherLaunch", + "lacros.AudioPinnedStream.play", + "mlservice.WebHandwritingRecognitionNotSupported.lacros", + "platform.PerfettoChromeConsumer.lacros", ] # To create filters to be used on specific builders add them like this:
diff --git a/components/access_code_cast/common/access_code_cast_metrics.cc b/components/access_code_cast/common/access_code_cast_metrics.cc index 78d9b32..826a5bfb 100644 --- a/components/access_code_cast/common/access_code_cast_metrics.cc +++ b/components/access_code_cast/common/access_code_cast_metrics.cc
@@ -10,6 +10,8 @@ AccessCodeCastMetrics::~AccessCodeCastMetrics() = default; // static +const char AccessCodeCastMetrics::kHistogramAccessCodeNotFoundCount[] = + "AccessCodeCast.Ui.AccessCodeNotFoundCount"; const char AccessCodeCastMetrics::kHistogramAddSinkResultNew[] = "AccessCodeCast.Discovery.AddSinkResult.New"; const char AccessCodeCastMetrics::kHistogramAddSinkResultRemembered[] = @@ -34,6 +36,15 @@ } // static +void AccessCodeCastMetrics::RecordAccessCodeNotFoundCount(int count) { + // Do not record if there were no incorrect codes. + if (count <= 0) + return; + + base::UmaHistogramCounts100(kHistogramAccessCodeNotFoundCount, count); +} + +// static void AccessCodeCastMetrics::RecordAddSinkResult( bool is_remembered, AccessCodeCastAddSinkResult result) {
diff --git a/components/access_code_cast/common/access_code_cast_metrics.h b/components/access_code_cast/common/access_code_cast_metrics.h index ad6a6db..9c95eec 100644 --- a/components/access_code_cast/common/access_code_cast_metrics.h +++ b/components/access_code_cast/common/access_code_cast_metrics.h
@@ -78,6 +78,7 @@ ~AccessCodeCastMetrics(); // UMA histogram names. + static const char kHistogramAccessCodeNotFoundCount[]; static const char kHistogramAddSinkResultNew[]; static const char kHistogramAddSinkResultRemembered[]; static const char kHistogramCastModeOnSuccess[]; @@ -91,6 +92,9 @@ static void OnCastSessionResult(int route_request_result_code, AccessCodeCastCastMode mode); + // Records the count of ACCESS_CODE_NOT_FOUND errors per instance of dialog. + static void RecordAccessCodeNotFoundCount(int count); + // Records the result of adding an access code sink. static void RecordAddSinkResult(bool is_remembered, AccessCodeCastAddSinkResult result);
diff --git a/components/access_code_cast/common/access_code_cast_metrics_unittest.cc b/components/access_code_cast/common/access_code_cast_metrics_unittest.cc index 3cdda4b1..16eb353 100644 --- a/components/access_code_cast/common/access_code_cast_metrics_unittest.cc +++ b/components/access_code_cast/common/access_code_cast_metrics_unittest.cc
@@ -95,6 +95,30 @@ "AccessCodeCast.Discovery.CastModeOnSuccess", 4); } +TEST(AccessCodeCastMetricsTest, RecordAccessCodeNotFoundCount) { + base::HistogramTester histogram_tester; + + AccessCodeCastMetrics::RecordAccessCodeNotFoundCount(0); + histogram_tester.ExpectTotalCount("AccessCodeCast.Ui.AccessCodeNotFoundCount", + 0); + + AccessCodeCastMetrics::RecordAccessCodeNotFoundCount(1); + histogram_tester.ExpectBucketCount( + "AccessCodeCast.Ui.AccessCodeNotFoundCount", 1, 1); + + AccessCodeCastMetrics::RecordAccessCodeNotFoundCount(100); + histogram_tester.ExpectBucketCount( + "AccessCodeCast.Ui.AccessCodeNotFoundCount", 100, 1); + + // Over 100 should be reported as 100. + AccessCodeCastMetrics::RecordAccessCodeNotFoundCount(500); + histogram_tester.ExpectBucketCount( + "AccessCodeCast.Ui.AccessCodeNotFoundCount", 100, 2); + + histogram_tester.ExpectTotalCount("AccessCodeCast.Ui.AccessCodeNotFoundCount", + 3); +} + TEST(AccessCodeCastMetricsTest, RecordDialogLoadTime) { base::HistogramTester histogram_tester;
diff --git a/components/account_id/account_id.cc b/components/account_id/account_id.cc index 25f05d1..bfa996b 100644 --- a/components/account_id/account_id.cc +++ b/components/account_id/account_id.cc
@@ -41,7 +41,7 @@ const std::string& user_email, const AccountType& account_type) : id_(id), user_email_(user_email), account_type_(account_type) { - DCHECK(user_email == gaia::CanonicalizeEmail(user_email)); + DCHECK_EQ(user_email, gaia::CanonicalizeEmail(user_email)); DCHECK(account_type != AccountType::UNKNOWN || id.empty()); DCHECK(account_type != AccountType::ACTIVE_DIRECTORY || !id.empty()); // Fail if e-mail looks similar to GaiaIdKey. @@ -162,6 +162,15 @@ } // static +AccountId AccountId::FromNonCanonicalEmail(const std::string& email, + const std::string& gaia_id, + const AccountType& account_type) { + DCHECK(!email.empty()); + return AccountId(gaia_id, gaia::CanonicalizeEmail(gaia::SanitizeEmail(email)), + account_type); +} + +// static AccountId AccountId::FromUserEmail(const std::string& email) { // TODO(alemate): DCHECK(!email.empty()); return AccountId(std::string() /* id */, email, AccountType::UNKNOWN);
diff --git a/components/account_id/account_id.h b/components/account_id/account_id.h index 734c1f5..1923288 100644 --- a/components/account_id/account_id.h +++ b/components/account_id/account_id.h
@@ -65,6 +65,9 @@ void SetUserEmail(const std::string& email); + static AccountId FromNonCanonicalEmail(const std::string& email, + const std::string& gaia_id, + const AccountType& account_type); // This method is to be used during transition period only. // AccountId with UNKNOWN AccountType; static AccountId FromUserEmail(const std::string& user_email);
diff --git a/components/autofill_assistant/browser/service/cup_unittest.cc b/components/autofill_assistant/browser/service/cup_unittest.cc index a142592..ed3baa8 100644 --- a/components/autofill_assistant/browser/service/cup_unittest.cc +++ b/components/autofill_assistant/browser/service/cup_unittest.cc
@@ -22,8 +22,8 @@ base::test::ScopedFeatureList scoped_feature_list_; void InitCupFeatures(bool enableSigning, bool enableVerifying) { - std::vector<base::Feature> enabled_features; - std::vector<base::Feature> disabled_features; + std::vector<base::test::FeatureRef> enabled_features; + std::vector<base::test::FeatureRef> disabled_features; if (enableSigning) { enabled_features.push_back(
diff --git a/components/autofill_assistant/browser/service/service_request_sender_impl_unittest.cc b/components/autofill_assistant/browser/service/service_request_sender_impl_unittest.cc index 137505c..398d392 100644 --- a/components/autofill_assistant/browser/service/service_request_sender_impl_unittest.cc +++ b/components/autofill_assistant/browser/service/service_request_sender_impl_unittest.cc
@@ -73,8 +73,8 @@ absl::optional<URLLoaderCompletionStatus> completion_status_ = absl::nullopt; void InitCupFeatures(bool enableSigning, bool enableVerifying) { - std::vector<base::Feature> enabled_features; - std::vector<base::Feature> disabled_features; + std::vector<base::test::FeatureRef> enabled_features; + std::vector<base::test::FeatureRef> disabled_features; if (enableSigning) { enabled_features.push_back(autofill_assistant::features::
diff --git a/components/autofill_assistant/browser/startup_util_unittest.cc b/components/autofill_assistant/browser/startup_util_unittest.cc index 6210ef6..19dbc39 100644 --- a/components/autofill_assistant/browser/startup_util_unittest.cc +++ b/components/autofill_assistant/browser/startup_util_unittest.cc
@@ -55,7 +55,7 @@ // Feature configurations to instantiate tests with. struct TestFeatureConfig { - std::vector<base::Feature> enabled_features; + std::vector<base::test::FeatureRef> enabled_features; }; // Shorthand for the full set of relevant features. @@ -104,8 +104,9 @@ {{kFullFeatureSet.begin(), kFullFeatureSet.end()}}}; // Custom output operator overloads to provide human-readable test outputs. -std::ostream& operator<<(std::ostream& out, const base::Feature& feature) { - out << feature.name; +std::ostream& operator<<(std::ostream& out, + const base::test::FeatureRef& feature) { + out << feature->name; return out; } @@ -150,7 +151,7 @@ public: void SetUp() override { StartupUtilTest::SetUp(); - std::vector<base::Feature> disabled_features; + std::vector<base::test::FeatureRef> disabled_features; for (const auto& feature : kFullFeatureSet) { if (!IsFeatureEnabled(feature)) { disabled_features.emplace_back(feature); @@ -166,7 +167,7 @@ void TearDown() override { scoped_feature_list_.reset(); } bool IsAnyFeatureSetEnabled( - const std::vector<std::vector<base::Feature>>& feature_sets) { + const std::vector<std::vector<base::test::FeatureRef>>& feature_sets) { for (const auto& features : feature_sets) { if (AreFeaturesEnabled(features)) { return true; @@ -175,9 +176,10 @@ return false; } - bool AreFeaturesEnabled(const std::vector<base::Feature>& features) const { + bool AreFeaturesEnabled( + const std::vector<base::test::FeatureRef>& features) const { for (const auto& feature : features) { - if (!IsFeatureEnabled(feature)) { + if (!IsFeatureEnabled(*feature)) { return false; } }
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd index fa21101..e139505 100644 --- a/components/browser_ui/strings/android/browser_ui_strings.grd +++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -196,10 +196,7 @@ <message name="IDS_DETAILS_LINK" desc="In 1) Settings > Clean up computer (desktop), a link to open details of incompatible applications. In 2) Settings > Lite mode (mobile), static title for data usage breakdown." meaning="Short for 'view details'. Link; static title."> Details </message> - <message name="IDS_CHANGE_LINK" desc="Any link text giving option to the user to edit some settings. [CHAR_LIMIT=20]"> - Change - </message> - <message name="IDS_DONE" desc="Label for a button to save a change or finish editing data. Used in multiple contexts. [CHAR_LIMIT=20]"> + <message name="IDS_DONE" desc="Label for a button to save a change or finish editing data. Used in multiple contexts. [CHAR_LIMIT=20]"> Done </message> <message name="IDS_DELETE" desc="Label for a delete button. Used in multiple contexts. [CHAR_LIMIT=20]">
diff --git a/components/commerce/core/commerce_heuristics_data_metrics_helper.cc b/components/commerce/core/commerce_heuristics_data_metrics_helper.cc index a286454..b2df27998 100644 --- a/components/commerce/core/commerce_heuristics_data_metrics_helper.cc +++ b/components/commerce/core/commerce_heuristics_data_metrics_helper.cc
@@ -35,3 +35,9 @@ base::UmaHistogramEnumeration("Commerce.Heuristics.SkipProductPatternSource", source); } + +void CommerceHeuristicsDataMetricsHelper:: + RecordProductIDExtractionPatternSource(HeuristicsSource source) { + base::UmaHistogramEnumeration( + "Commerce.Heuristics.ProductIDExtractionPatternSource", source); +}
diff --git a/components/commerce/core/commerce_heuristics_data_metrics_helper.h b/components/commerce/core/commerce_heuristics_data_metrics_helper.h index 2bbe591..d2775af 100644 --- a/components/commerce/core/commerce_heuristics_data_metrics_helper.h +++ b/components/commerce/core/commerce_heuristics_data_metrics_helper.h
@@ -42,6 +42,10 @@ // skip a product from the extraction results. Record the source of the // pattern data. static void RecordSkipProductPatternSource(HeuristicsSource source); + + // Gets called when we try to get the product ID extraction pattern. Record + // the source of the pattern data. + static void RecordProductIDExtractionPatternSource(HeuristicsSource source); }; #endif // COMPONENTS_COMMERCE_CORE_COMMERCE_HEURISTICS_DATA_METRICS_HELPER_H_
diff --git a/components/download/database/download_db_conversions_unittest.cc b/components/download/database/download_db_conversions_unittest.cc index 8e061ad..a16467d 100644 --- a/components/download/database/download_db_conversions_unittest.cc +++ b/components/download/database/download_db_conversions_unittest.cc
@@ -74,22 +74,7 @@ } // namespace class DownloadDBConversionsTest : public testing::Test, - public DownloadDBConversions { - public: - ~DownloadDBConversionsTest() override = default; - - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(features::kDownloadLater); - } - - protected: - base::test::ScopedFeatureList* scoped_feature_list() { - return &scoped_feature_list_; - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; + public DownloadDBConversions {}; TEST_F(DownloadDBConversionsTest, DownloadEntry) { // Entry with no fields.
diff --git a/components/download/database/proto/download_entry.proto b/components/download/database/proto/download_entry.proto index d55a8e1..74515b74 100644 --- a/components/download/database/proto/download_entry.proto +++ b/components/download/database/proto/download_entry.proto
@@ -48,6 +48,7 @@ } // Information about when to start the download, used by download later feature. +// Deprecated. message DownloadSchedule { optional int64 start_time = 1; } @@ -81,7 +82,7 @@ optional bool metered = 25; optional int64 bytes_wasted = 26; optional int32 auto_resume_count = 27; - optional DownloadSchedule download_schedule = 28; + optional DownloadSchedule download_schedule = 28; // // Deprecated. optional enterprise_connectors.DownloadItemRerouteInfo reroute_info = 29; optional int32 credentials_mode = 30; // network::mojom::CredentialsMode optional int64 range_request_from = 31;
diff --git a/components/download/public/common/auto_resumption_handler.cc b/components/download/public/common/auto_resumption_handler.cc index 7533670..b24c27de 100644 --- a/components/download/public/common/auto_resumption_handler.cc +++ b/components/download/public/common/auto_resumption_handler.cc
@@ -243,8 +243,6 @@ if (!has_actionable_downloads) { task_manager_->NotifyTaskFinished(kResumptionTaskType, false); - task_manager_->NotifyTaskFinished(DownloadTaskType::DOWNLOAD_LATER_TASK, - false); } if (!has_resumable_downloads) { @@ -300,8 +298,7 @@ if (!item || item->IsDangerous()) return false; - // Ignore downloads started a while ago. This doesn't include user scheduled - // downloads. + // Ignore downloads started a while ago. if (clock_->Now() - item->GetStartTime() > kAutoResumptionExpireInterval) { return false; }
diff --git a/components/download/public/common/auto_resumption_handler_unittest.cc b/components/download/public/common/auto_resumption_handler_unittest.cc index 1680af7..839ec0e 100644 --- a/components/download/public/common/auto_resumption_handler_unittest.cc +++ b/components/download/public/common/auto_resumption_handler_unittest.cc
@@ -36,8 +36,6 @@ const char kNow[] = "1 Sep 2020 01:00:00 GMT"; const DownloadTaskType kResumptionTaskType = DownloadTaskType::DOWNLOAD_AUTO_RESUMPTION_TASK; -const DownloadTaskType kDownloadLaterTaskType = - DownloadTaskType::DOWNLOAD_LATER_TASK; base::Time GetNow() { base::Time now; @@ -140,8 +138,6 @@ // Complete the download. EXPECT_CALL(*task_manager_, NotifyTaskFinished(kResumptionTaskType, _)); - EXPECT_CALL(*task_manager_, - NotifyTaskFinished(kDownloadLaterTaskType, false)); EXPECT_CALL(*task_manager_, UnscheduleTask(kResumptionTaskType)); SetDownloadState(item.get(), DownloadItem::COMPLETE, false, false); auto_resumption_handler_->OnDownloadUpdated(item.get()); @@ -161,8 +157,6 @@ // Remove the download. EXPECT_CALL(*task_manager_, NotifyTaskFinished(kResumptionTaskType, _)); - EXPECT_CALL(*task_manager_, - NotifyTaskFinished(kDownloadLaterTaskType, false)); SetDownloadState(item.get(), DownloadItem::COMPLETE, false, false); auto_resumption_handler_->OnDownloadRemoved(item.get()); task_runner_->FastForwardUntilNoTasksRemain(); @@ -193,8 +187,6 @@ // Finish item2. The task should now complete. EXPECT_CALL(*task_manager_, UnscheduleTask(kResumptionTaskType)); EXPECT_CALL(*task_manager_, NotifyTaskFinished(kResumptionTaskType, _)); - EXPECT_CALL(*task_manager_, - NotifyTaskFinished(kDownloadLaterTaskType, false)); SetDownloadState(item2.get(), DownloadItem::COMPLETE, false, false); auto_resumption_handler_->OnDownloadUpdated(item2.get()); task_runner_->FastForwardUntilNoTasksRemain();
diff --git a/components/download/public/common/download_features.cc b/components/download/public/common/download_features.cc index f2b6d9a..fc7ffef 100644 --- a/components/download/public/common/download_features.cc +++ b/components/download/public/common/download_features.cc
@@ -31,10 +31,6 @@ #endif ); -BASE_FEATURE(kDownloadLater, - "DownloadLater", - base::FEATURE_DISABLED_BY_DEFAULT); - #if BUILDFLAG(IS_ANDROID) BASE_FEATURE(kSmartSuggestionForLargeDownloads, "SmartSuggestionForLargeDownloads", @@ -82,10 +78,4 @@ } // namespace features -namespace switches { - -const char kDownloadLaterDebugOnWifi[] = "download-later-debug-on-wifi"; - -} // namespace switches - } // namespace download
diff --git a/components/download/public/common/download_features.h b/components/download/public/common/download_features.h index 5f2ae9ed..e774fec0 100644 --- a/components/download/public/common/download_features.h +++ b/components/download/public/common/download_features.h
@@ -12,14 +12,6 @@ namespace download { namespace features { -// The Finch parameter to control whether download later dialog should show the -// date time picker option. -constexpr char kDownloadLaterShowDateTimePicker[] = "show_date_time_picker"; - -// The Finch parameter to control the minimum download file size to show the -// download later dialog. -constexpr char kDownloadLaterMinFileSizeKb[] = "min_file_size_kb"; - // Whether offline content provider should be used for the downloads UI.. COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE( kUseDownloadOfflineContentProvider); @@ -30,9 +22,6 @@ // Whether a download can be handled by parallel jobs. COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE(kParallelDownloading); -// Whether to enable download later feature. -COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE(kDownloadLater); - #if BUILDFLAG(IS_ANDROID) // Whether download expiration date will be refreshed on resumption. COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE(kRefreshExpirationDate); @@ -70,14 +59,6 @@ COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE(kDownloadRange); } // namespace features -namespace switches { - -// If set, show the download later dialog without the requirement of being on -// cellular network. -COMPONENTS_DOWNLOAD_EXPORT extern const char kDownloadLaterDebugOnWifi[]; - -} // namespace switches - } // namespace download #endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_FEATURES_H_
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 951da8e..00ca2f5 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -12,7 +12,7 @@ import("//ui/base/ui_features.gni") assert(use_ozone) -assert(!is_chromeos_lacros) +assert(is_chromeos_ash) buildflag_header("buildflags") { header = "buildflags.h"
diff --git a/components/global_media_controls/BUILD.gn b/components/global_media_controls/BUILD.gn index 39c8c8e..8c8fccd 100644 --- a/components/global_media_controls/BUILD.gn +++ b/components/global_media_controls/BUILD.gn
@@ -35,6 +35,7 @@ public_deps = [ "//components/media_message_center", + "//components/url_formatter", "//services/media_session/public/cpp", "//services/media_session/public/mojom", "//ui/views",
diff --git a/components/global_media_controls/DEPS b/components/global_media_controls/DEPS index c185628b..9b4049d 100644 --- a/components/global_media_controls/DEPS +++ b/components/global_media_controls/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+components/media_message_center", "+components/strings", + "+components/url_formatter", "+components/vector_icons", "+media", "+mojo/public/cpp/bindings",
diff --git a/components/global_media_controls/public/media_session_item_producer.cc b/components/global_media_controls/public/media_session_item_producer.cc index d39738e..cff5781e 100644 --- a/components/global_media_controls/public/media_session_item_producer.cc +++ b/components/global_media_controls/public/media_session_item_producer.cc
@@ -427,6 +427,14 @@ std::move(callback)); } +void MediaSessionItemProducer::UpdateMediaItemSourceOrigin( + const std::string& id, + const url::Origin& origin) { + auto it = sessions_.find(id); + if (it != sessions_.end()) + it->second.item()->UpdatePresentationRequestOrigin(origin); +} + MediaSessionItemProducer::Session* MediaSessionItemProducer::GetSession( const std::string& id) { auto it = sessions_.find(id);
diff --git a/components/global_media_controls/public/media_session_item_producer.h b/components/global_media_controls/public/media_session_item_producer.h index 1eb303f..fcf7b75 100644 --- a/components/global_media_controls/public/media_session_item_producer.h +++ b/components/global_media_controls/public/media_session_item_producer.h
@@ -92,6 +92,12 @@ const std::string& id, base::RepeatingCallback<void(bool)> callback); + // Called when a media session item is associated with a presentation request + // as to show the origin associated with the request rather than that for the + // top frame. + void UpdateMediaItemSourceOrigin(const std::string& id, + const url::Origin& origin); + private: friend class MediaSessionItemProducerTest;
diff --git a/components/global_media_controls/public/media_session_notification_item.cc b/components/global_media_controls/public/media_session_notification_item.cc index 8e2aa33..682fc60a 100644 --- a/components/global_media_controls/public/media_session_notification_item.cc +++ b/components/global_media_controls/public/media_session_notification_item.cc
@@ -9,6 +9,8 @@ #include "base/time/time.h" #include "components/global_media_controls/public/constants.h" #include "components/media_message_center/media_notification_view.h" +#include "components/url_formatter/elide_url.h" +#include "components/url_formatter/url_formatter.h" #include "services/media_session/public/cpp/util.h" #include "services/media_session/public/mojom/media_controller.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h" @@ -87,7 +89,7 @@ // want to avoid sending the metadata twice is that metrics are recorded when // metadata is set and we don't want to double-count metrics. if (view_ && view_needs_metadata_update_ && !frozen_) - view_->UpdateWithMediaMetadata(session_metadata_); + view_->UpdateWithMediaMetadata(GetSessionMetadata()); view_needs_metadata_update_ = false; } @@ -116,6 +118,13 @@ } } +void MediaSessionNotificationItem::UpdatePresentationRequestOrigin( + const url::Origin& origin) { + optional_presentation_request_origin_ = origin; + if (view_ && !frozen_) + view_->UpdateWithMediaMetadata(GetSessionMetadata()); +} + void MediaSessionNotificationItem::MediaControllerImageChanged( media_session::mojom::MediaSessionImageType type, const SkBitmap& bitmap) { @@ -146,7 +155,7 @@ if (view_) { view_needs_metadata_update_ = false; view_->UpdateWithMediaSessionInfo(session_info_); - view_->UpdateWithMediaMetadata(session_metadata_); + view_->UpdateWithMediaMetadata(GetSessionMetadata()); view_->UpdateWithMediaActions(session_actions_); view_->UpdateWithMuteStatus(session_info_->muted); @@ -156,6 +165,8 @@ view_->UpdateWithMediaArtwork(*session_artwork_); if (session_favicon_.has_value()) view_->UpdateWithFavicon(*session_favicon_); + } else { + optional_presentation_request_origin_.reset(); } } @@ -253,6 +264,17 @@ media_controller_remote_.FlushForTesting(); // IN-TEST } +media_session::MediaMetadata MediaSessionNotificationItem::GetSessionMetadata() + const { + media_session::MediaMetadata data = session_metadata_; + if (optional_presentation_request_origin_.has_value()) { + data.source_title = url_formatter::FormatOriginForSecurityDisplay( + optional_presentation_request_origin_.value(), + url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS); + } + return data; +} + bool MediaSessionNotificationItem::ShouldShowNotification() const { // If the |is_controllable| bit is set in MediaSessionInfo then we should show // a media notification. @@ -311,7 +333,7 @@ if (view_) { view_needs_metadata_update_ = false; view_->UpdateWithMediaSessionInfo(session_info_); - view_->UpdateWithMediaMetadata(session_metadata_); + view_->UpdateWithMediaMetadata(GetSessionMetadata()); view_->UpdateWithMediaActions(session_actions_); view_->UpdateWithMuteStatus(session_info_->muted);
diff --git a/components/global_media_controls/public/media_session_notification_item.h b/components/global_media_controls/public/media_session_notification_item.h index 2dba17d5..469a31d 100644 --- a/components/global_media_controls/public/media_session_notification_item.h +++ b/components/global_media_controls/public/media_session_notification_item.h
@@ -19,6 +19,7 @@ #include "services/media_session/public/mojom/media_session.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/image/image_skia.h" +#include "url/origin.h" namespace media_message_center { class MediaNotificationView; @@ -79,6 +80,11 @@ void MediaSessionPositionChanged( const absl::optional<media_session::MediaPosition>& position) override; + // Called when a media session item is associated with a presentation request + // to show the origin associated with the request rather than that for the + // top frame. + void UpdatePresentationRequestOrigin(const url::Origin& origin); + // media_session::mojom::MediaControllerImageObserver: void MediaControllerImageChanged( media_session::mojom::MediaSessionImageType type, @@ -127,6 +133,8 @@ } private: + media_session::MediaMetadata GetSessionMetadata() const; + bool ShouldShowNotification() const; void MaybeUnfreeze(); @@ -161,6 +169,12 @@ media_session::MediaMetadata session_metadata_; + // When a media session item is associated with a presentation request, we + // must show the origin associated with the request rather than that for the + // top frame. So, in case of having a presentation request, this field is set + // to hold the origin of that presentation request. + absl::optional<url::Origin> optional_presentation_request_origin_; + base::flat_set<media_session::mojom::MediaSessionAction> session_actions_; absl::optional<media_session::MediaPosition> session_position_;
diff --git a/components/global_media_controls/public/media_session_notification_item_unittest.cc b/components/global_media_controls/public/media_session_notification_item_unittest.cc index ee6d278..3715e8e 100644 --- a/components/global_media_controls/public/media_session_notification_item_unittest.cc +++ b/components/global_media_controls/public/media_session_notification_item_unittest.cc
@@ -98,6 +98,31 @@ item().MediaSessionMetadataChanged(metadata); } +TEST_F(MediaSessionNotificationItemTest, + UpdateMetadataOriginWithPresentationRequestOrigin) { + media_session::MediaMetadata metadata; + metadata.source_title = u"source_title_test"; + + EXPECT_CALL(view(), UpdateWithMediaMetadata(metadata)).Times(1); + item().MediaSessionMetadataChanged(metadata); + + media_session::MediaMetadata updated_metadata; + updated_metadata.source_title = u"example.com"; + + EXPECT_CALL(view(), UpdateWithMediaMetadata(updated_metadata)).Times(2); + item().UpdatePresentationRequestOrigin( + url::Origin::Create(GURL("https://example.com"))); + // Make sure presentation request origin persists for the duration of the view + // despite the update of metadata. + item().MediaSessionMetadataChanged(metadata); + item().SetView(nullptr); + + // Make sure that presentation request origin was reset after the view is set + // to null in SetView(). + EXPECT_CALL(view(), UpdateWithMediaMetadata(metadata)).Times(1); + item().SetView(&view()); +} + TEST_F(MediaSessionNotificationItemTest, Freezing_DoNotUpdateImage) { SkBitmap image; image.allocN32Pixels(10, 10);
diff --git a/components/history_clusters/core/history_clusters_service.cc b/components/history_clusters/core/history_clusters_service.cc index fe24f9e..f36aec0 100644 --- a/components/history_clusters/core/history_clusters_service.cc +++ b/components/history_clusters/core/history_clusters_service.cc
@@ -157,7 +157,8 @@ base::Time begin_time, QueryClustersContinuationParams continuation_params, bool recluster, - QueryClustersCallback callback) { + QueryClustersCallback callback, + HistoryClustersServiceTaskGetMostRecentClusters::Source source) { if (ShouldNotifyDebugMessage()) { NotifyDebugMessage("HistoryClustersService::QueryClusters()"); NotifyDebugMessage( @@ -174,7 +175,7 @@ return std::make_unique<HistoryClustersServiceTaskGetMostRecentClusters>( weak_ptr_factory_.GetWeakPtr(), incomplete_visit_context_annotations_, backend_.get(), history_service_, clustering_request_source, begin_time, - continuation_params, recluster, std::move(callback)); + continuation_params, recluster, std::move(callback), source); } void HistoryClustersService::RepeatedlyUpdateClusters() { @@ -306,7 +307,9 @@ /*begin_time=*/base::Time(), std::make_unique<KeywordMap>(), std::make_unique<URLKeywordSet>(), &all_keywords_cache_, - &all_url_keywords_cache_)); + &all_url_keywords_cache_), + HistoryClustersServiceTaskGetMostRecentClusters::Source:: + kAllKeywordCacheRefresh); } else if ((base::Time::Now() - all_keywords_cache_timestamp_).InSeconds() > 10 && (base::Time::Now() - short_keyword_cache_timestamp_).InSeconds() > @@ -324,7 +327,9 @@ all_keywords_cache_timestamp_, std::make_unique<KeywordMap>(), std::make_unique<URLKeywordSet>(), &short_keyword_cache_, - &short_url_keywords_cache_)); + &short_url_keywords_cache_), + HistoryClustersServiceTaskGetMostRecentClusters::Source:: + kShortKeywordCacheRefresh); } } @@ -399,6 +404,12 @@ if (!continuation_params.exhausted_all_visits && (keyword_accumulator->size() < max_keyword_phrases || url_keyword_accumulator->size() < max_keyword_phrases)) { + const auto query_purpose = + cache == &all_keywords_cache_ + ? HistoryClustersServiceTaskGetMostRecentClusters::Source:: + kAllKeywordCacheRefresh + : HistoryClustersServiceTaskGetMostRecentClusters::Source:: + kShortKeywordCacheRefresh; cache_keyword_query_task_ = QueryClusters( ClusteringRequestSource::kKeywordCacheGeneration, begin_time, continuation_params, /*recluster=*/false, @@ -407,7 +418,8 @@ std::move(total_latency_timer), begin_time, // Pass on the accumulator sets to the next callback. std::move(keyword_accumulator), - std::move(url_keyword_accumulator), cache, url_cache)); + std::move(url_keyword_accumulator), cache, url_cache), + query_purpose); // Log this even if we go back for more clusters. base::UmaHistogramTimes(kKeywordCacheThreadTimeUmaName, populate_keywords_thread_timer.Elapsed());
diff --git a/components/history_clusters/core/history_clusters_service.h b/components/history_clusters/core/history_clusters_service.h index 9efbfe5..2ae92e1 100644 --- a/components/history_clusters/core/history_clusters_service.h +++ b/components/history_clusters/core/history_clusters_service.h
@@ -168,7 +168,8 @@ base::Time begin_time, QueryClustersContinuationParams continuation_params, bool recluster, - QueryClustersCallback callback); + QueryClustersCallback callback, + HistoryClustersServiceTaskGetMostRecentClusters::Source source); // Invokes `UpdateClusters()` after a short delay, then again periodically. // E.g., might invoke `UpdateClusters()` initially 5 minutes after startup,
diff --git a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc index 32f7d09..c391bcf 100644 --- a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc +++ b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.cc
@@ -18,6 +18,28 @@ #include "components/history_clusters/core/history_clusters_debug_jsons.h" #include "components/history_clusters/core/history_clusters_service.h" +namespace { + +std::string HistogramNameSlice( + history_clusters::HistoryClustersServiceTaskGetMostRecentClusters::Source + source) { + switch (source) { + case history_clusters::HistoryClustersServiceTaskGetMostRecentClusters:: + Source::kAllKeywordCacheRefresh: + return ".AllKeywordCacheRefresh"; + case history_clusters::HistoryClustersServiceTaskGetMostRecentClusters:: + Source::kShortKeywordCacheRefresh: + return ".ShortKeywordCacheRefresh"; + case history_clusters::HistoryClustersServiceTaskGetMostRecentClusters:: + Source::kWebUi: + return ".WebUI"; + default: + NOTREACHED(); + } +} + +} // namespace + namespace history_clusters { HistoryClustersServiceTaskGetMostRecentClusters:: @@ -30,7 +52,8 @@ base::Time begin_time, QueryClustersContinuationParams continuation_params, bool recluster, - QueryClustersCallback callback) + QueryClustersCallback callback, + Source source) : weak_history_clusters_service_(std::move(weak_history_clusters_service)), incomplete_visit_context_annotations_( incomplete_visit_context_annotations), @@ -40,7 +63,8 @@ begin_time_(begin_time), continuation_params_(continuation_params), recluster_(recluster), - callback_(std::move(callback)) { + callback_(std::move(callback)), + source_(source) { DCHECK(weak_history_clusters_service_); DCHECK(history_service_); Start(); @@ -75,8 +99,7 @@ // clusters, and current-day visits will never be pre-clustered, we // probably want to make sure they're optimal. So we should probably not // cluster at least the current day in isolation. - history_service_get_annotated_visits_to_cluster_start_time_ = - base::TimeTicks::Now(); + get_annotated_visits_to_cluster_start_time_ = base::TimeTicks::Now(); history_service_->ScheduleDBTask( FROM_HERE, std::make_unique<GetAnnotatedVisitsToCluster>( @@ -99,6 +122,18 @@ return; DCHECK(backend_); + const auto elapsed_time = + base::TimeTicks::Now() - get_annotated_visits_to_cluster_start_time_; + base::UmaHistogramTimes( + "History.Clusters.Backend.GetMostRecentClusters." + "GetAnnotatedVisitsToClusterLatency", + elapsed_time); + base::UmaHistogramTimes( + "History.Clusters.Backend.GetMostRecentClusters." + "GetAnnotatedVisitsToClusterLatency" + + HistogramNameSlice(source_), + elapsed_time); + if (weak_history_clusters_service_->ShouldNotifyDebugMessage()) { weak_history_clusters_service_->NotifyDebugMessage( "HistoryClustersServiceTaskGetMostRecentClusters::" @@ -116,11 +151,6 @@ GetDebugJSONForVisits(annotated_visits)); } - base::UmaHistogramTimes( - "History.Clusters.Backend.QueryAnnotatedVisitsLatency", - base::TimeTicks::Now() - - history_service_get_annotated_visits_to_cluster_start_time_); - if (annotated_visits.empty()) { // If there're no unclustered visits to cluster, then return persisted // clusters. @@ -129,7 +159,7 @@ } else { base::UmaHistogramCounts1000("History.Clusters.Backend.NumVisitsToCluster", static_cast<int>(annotated_visits.size())); - backend_get_clusters_start_time_ = base::TimeTicks::Now(); + get_model_clusters_start_time_ = base::TimeTicks::Now(); backend_->GetClusters( clustering_request_source_, base::BindOnce(&HistoryClustersServiceTaskGetMostRecentClusters:: @@ -145,9 +175,15 @@ if (!weak_history_clusters_service_) return; + const auto elapsed_time = + base::TimeTicks::Now() - get_model_clusters_start_time_; base::UmaHistogramTimes( - "History.Clusters.Backend.GetClustersLatency", - base::TimeTicks::Now() - backend_get_clusters_start_time_); + "History.Clusters.Backend.GetMostRecentClusters.ComputeClustersLatency", + elapsed_time); + base::UmaHistogramTimes( + "History.Clusters.Backend.GetMostRecentClusters.ComputeClustersLatency" + + HistogramNameSlice(source_), + elapsed_time); base::UmaHistogramCounts1000("History.Clusters.Backend.NumClustersReturned", clusters.size()); @@ -165,6 +201,7 @@ void HistoryClustersServiceTaskGetMostRecentClusters:: ReturnMostRecentPersistedClusters(base::Time exclusive_max_time) { if (GetConfig().persist_clusters_in_history_db && !recluster_) { + get_most_recent_persisted_clusters_start_time_ = base::TimeTicks::Now(); history_service_->GetMostRecentClusters( begin_time_, exclusive_max_time, GetConfig().max_persisted_clusters_to_fetch, @@ -183,6 +220,18 @@ if (!weak_history_clusters_service_) return; + const auto elapsed_time = + base::TimeTicks::Now() - get_most_recent_persisted_clusters_start_time_; + base::UmaHistogramTimes( + "History.Clusters.Backend.GetMostRecentClusters." + "GetMostRecentPersistedClustersLatency", + elapsed_time); + base::UmaHistogramTimes( + "History.Clusters.Backend.GetMostRecentClusters." + "GetMostRecentPersistedClustersLatency" + + HistogramNameSlice(source_), + elapsed_time); + if (GetConfig().persist_clusters_in_history_db && !recluster_ && weak_history_clusters_service_->ShouldNotifyDebugMessage()) { weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf(
diff --git a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h index ed213e2..b58cf6c 100644 --- a/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h +++ b/components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h
@@ -31,6 +31,15 @@ // callbacks. class HistoryClustersServiceTaskGetMostRecentClusters { public: + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class Source { + kAllKeywordCacheRefresh = 0, + kShortKeywordCacheRefresh = 1, + kWebUi = 2, + kMaxValue = kWebUi, + }; + HistoryClustersServiceTaskGetMostRecentClusters( base::WeakPtr<HistoryClustersService> weak_history_clusters_service, const IncompleteVisitMap incomplete_visit_context_annotations, @@ -40,7 +49,8 @@ base::Time begin_time, QueryClustersContinuationParams continuation_params, bool recluster, - QueryClustersCallback callback); + QueryClustersCallback callback, + Source source); ~HistoryClustersServiceTaskGetMostRecentClusters(); bool Done() { return done_; } @@ -107,11 +117,16 @@ // `OnGotMostRecentPersistedClusters()`. QueryClustersCallback callback_; + // Used for logging slices. + Source source_ = Source::kWebUi; // When `Start()` kicked off the request to fetch visits to cluster. - base::TimeTicks history_service_get_annotated_visits_to_cluster_start_time_; + base::TimeTicks get_annotated_visits_to_cluster_start_time_; // When `OnGotAnnotatedVisitsToCluster()` kicked off the request to cluster // the visits. - base::TimeTicks backend_get_clusters_start_time_; + base::TimeTicks get_model_clusters_start_time_; + // When `ReturnMostRecentPersistedClusters()` kicked off the request to get + // persisted clusters. + base::TimeTicks get_most_recent_persisted_clusters_start_time_; // Set to true when `callback_` is invoked, either with clusters or no // clusters.
diff --git a/components/history_clusters/core/history_clusters_service_task_update_clusters.cc b/components/history_clusters/core/history_clusters_service_task_update_clusters.cc index 0f74cde..920cbb30 100644 --- a/components/history_clusters/core/history_clusters_service_task_update_clusters.cc +++ b/components/history_clusters/core/history_clusters_service_task_update_clusters.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/bind.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/stringprintf.h" #include "components/history/core/browser/history_service.h" #include "components/history_clusters/core/clustering_backend.h" @@ -41,6 +42,7 @@ std::move(callback_).Run(); return; } + get_annotated_visits_to_cluster_start_time_ = base::TimeTicks::Now(); history_service_->ScheduleDBTask( FROM_HERE, std::make_unique<GetAnnotatedVisitsToCluster>( @@ -59,6 +61,13 @@ if (!weak_history_clusters_service_) return; + const auto elapsed_time = + base::TimeTicks::Now() - get_annotated_visits_to_cluster_start_time_; + base::UmaHistogramTimes( + "History.Clusters.Backend.UpdateClusters." + "GetAnnotatedVisitsToClusterLatency", + elapsed_time); + if (weak_history_clusters_service_->ShouldNotifyDebugMessage()) { weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf( "UPDATE CLUSTERS TASK - VISITS %zu:", annotated_visits.size())); @@ -72,6 +81,7 @@ std::move(callback_).Run(); return; } + get_model_clusters_start_time_ = base::TimeTicks::Now(); // Using `kKeywordCacheGeneration` as that only determines the task priority. backend_->GetClusters( ClusteringRequestSource::kKeywordCacheGeneration, @@ -88,18 +98,35 @@ if (!weak_history_clusters_service_) return; + const auto elapsed_time = + base::TimeTicks::Now() - get_model_clusters_start_time_; + base::UmaHistogramTimes( + "History.Clusters.Backend.UpdateClusters.ComputeClustersLatency", + elapsed_time); + if (weak_history_clusters_service_->ShouldNotifyDebugMessage()) { weak_history_clusters_service_->NotifyDebugMessage(base::StringPrintf( "UPDATE CLUSTERS TASK - CLUSTERS %zu:", clusters.size())); weak_history_clusters_service_->NotifyDebugMessage( GetDebugJSONForClusters(clusters)); } + persist_clusters_start_time_ = base::TimeTicks::Now(); continuation_params_ = continuation_params; history_service_->ReplaceClusters( old_cluster_ids, clusters, - base::BindOnce(&HistoryClustersServiceTaskUpdateClusters::Start, - weak_ptr_factory_.GetWeakPtr()), + base::BindOnce( + &HistoryClustersServiceTaskUpdateClusters::OnPersistedClusters, + weak_ptr_factory_.GetWeakPtr()), &task_tracker_); } +void HistoryClustersServiceTaskUpdateClusters::OnPersistedClusters() { + const auto elapsed_time = + base::TimeTicks::Now() - persist_clusters_start_time_; + base::UmaHistogramTimes( + "History.Clusters.Backend.UpdateClusters.PersistClustersLatency", + elapsed_time); + Start(); +} + } // namespace history_clusters
diff --git a/components/history_clusters/core/history_clusters_service_task_update_clusters.h b/components/history_clusters/core/history_clusters_service_task_update_clusters.h index 2a81625..6d48dfd 100644 --- a/components/history_clusters/core/history_clusters_service_task_update_clusters.h +++ b/components/history_clusters/core/history_clusters_service_task_update_clusters.h
@@ -50,11 +50,13 @@ // with clustered visits) and persist the newly created clusters: // Start() -> // GetAnnotatedVisitsToCluster() -> - // OnGotModelClusters() + // OnGotModelClusters() -> + // OnPersistedClusters() -> + // Start() - // Invoked during construction and after `OnGotModelClusters()` asyncly + // Invoked during construction and after `OnPersistedClusters()` asyncly // replaces clusters. Will asyncly request annotated visits from - // `GetAnnotatedVisitsToCluster`. May instead syncly invoke `callback_` if + // `GetAnnotatedVisitsToCluster()`. May instead syncly invoke `callback_` if // there's no `ClusteringBackend` or all visits are exhausted. void Start(); @@ -72,6 +74,10 @@ QueryClustersContinuationParams continuation_params, std::vector<history::Cluster> clusters); + // Invoked after `OnGotModelClusters()` asyncly persists clusters. Will syncly + // invoke `Start()` to initiate the next iteration. + void OnPersistedClusters(); + // Never nullptr. base::WeakPtr<HistoryClustersService> weak_history_clusters_service_; const IncompleteVisitMap incomplete_visit_context_annotations_; @@ -88,6 +94,14 @@ // Invoked after either `Start()` or `OnGotAnnotatedVisitsToCluster()`. base::OnceClosure callback_; + // When `Start()` kicked off the request to fetch visits to cluster. + base::TimeTicks get_annotated_visits_to_cluster_start_time_; + // When `OnGotAnnotatedVisitsToCluster()` kicked off the request to cluster + // the visits. + base::TimeTicks get_model_clusters_start_time_; + // When `OnGotModelClusters()` kicked off the request to persist the clusters. + base::TimeTicks persist_clusters_start_time_; + // Set to true when `callback_` is invoked, either with clusters or no // clusters. bool done_ = false;
diff --git a/components/history_clusters/core/history_clusters_service_unittest.cc b/components/history_clusters/core/history_clusters_service_unittest.cc index 4c27409..e27b5daf 100644 --- a/components/history_clusters/core/history_clusters_service_unittest.cc +++ b/components/history_clusters/core/history_clusters_service_unittest.cc
@@ -32,6 +32,7 @@ #include "components/history_clusters/core/config.h" #include "components/history_clusters/core/features.h" #include "components/history_clusters/core/history_clusters_db_tasks.h" +#include "components/history_clusters/core/history_clusters_service_task_get_most_recent_clusters.h" #include "components/history_clusters/core/history_clusters_service_test_api.h" #include "components/history_clusters/core/history_clusters_types.h" #include "components/history_clusters/core/history_clusters_util.h" @@ -255,7 +256,8 @@ loop.Quit(); clusters = clusters_temp; continuation_params = continuation_params_temp; - })); + }), + HistoryClustersServiceTaskGetMostRecentClusters::Source::kWebUi); // If we expect a clustering call, expect a request and return no clusters. if (expect_clustering_backend_call) { @@ -405,8 +407,8 @@ ClusteringRequestSource::kKeywordCacheGeneration, /*begin_time=*/base::Time(), /*continuation_params=*/{}, /*recluster=*/false, - base::DoNothing() // Only need to verify the correct request is sent - ); + base::DoNothing(), // Only need to verify the correct request is sent + HistoryClustersServiceTaskGetMostRecentClusters::Source::kWebUi); test_clustering_backend_->WaitForGetClustersCall(); history::BlockUntilHistoryProcessesPendingRequests(history_service_.get()); @@ -849,7 +851,8 @@ EXPECT_TRUE(cluster.keyword_to_data_map.empty()); run_loop_quit.Run(); - })); + }), + HistoryClustersServiceTaskGetMostRecentClusters::Source::kWebUi); AwaitAndVerifyTestClusteringBackendRequest(); @@ -881,7 +884,21 @@ histogram_tester.ExpectBucketCount( "History.Clusters.Backend.NumVisitsToCluster", 2, 1); histogram_tester.ExpectTotalCount( - "History.Clusters.Backend.GetClustersLatency", 1); + "History.Clusters.Backend.GetMostRecentClusters." + "ComputeClustersLatency", + 1); + histogram_tester.ExpectTotalCount( + "History.Clusters.Backend.GetMostRecentClusters." + "ComputeClustersLatency.WebUI", + 1); + histogram_tester.ExpectTotalCount( + "History.Clusters.Backend.GetMostRecentClusters." + "ComputeClustersLatency.AllKeywordCacheRefresh", + 0); + histogram_tester.ExpectTotalCount( + "History.Clusters.Backend.GetMostRecentClusters." + "GetMostRecentPersistedClustersLatency.ShortKeywordCacheRefresh", + 0); } TEST_F(HistoryClustersServiceTest, CompleteVisitContextAnnotationsIfReady) {
diff --git a/components/history_clusters/core/query_clusters_state.cc b/components/history_clusters/core/query_clusters_state.cc index 6af0e9f..1aba215 100644 --- a/components/history_clusters/core/query_clusters_state.cc +++ b/components/history_clusters/core/query_clusters_state.cc
@@ -83,7 +83,8 @@ /*begin_time=*/base::Time(), continuation_params_, recluster_, base::BindOnce(&QueryClustersState::OnGotRawClusters, weak_factory_.GetWeakPtr(), query_start_time, - std::move(callback))); + std::move(callback)), + HistoryClustersServiceTaskGetMostRecentClusters::Source::kWebUi); } void QueryClustersState::OnGotRawClusters(
diff --git a/components/offline_items_collection/core/BUILD.gn b/components/offline_items_collection/core/BUILD.gn index ababbba8..879bf12 100644 --- a/components/offline_items_collection/core/BUILD.gn +++ b/components/offline_items_collection/core/BUILD.gn
@@ -69,7 +69,6 @@ sources = [ "filtered_offline_item_observer_unittest.cc", "offline_content_aggregator_unittest.cc", - "offline_item_unittest.cc", "throttled_offline_content_provider_unittest.cc", ] @@ -97,7 +96,6 @@ "android/java/src/org/chromium/components/offline_items_collection/OfflineContentAggregatorBridge.java", "android/java/src/org/chromium/components/offline_items_collection/OfflineContentProvider.java", "android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java", - "android/java/src/org/chromium/components/offline_items_collection/OfflineItemSchedule.java", "android/java/src/org/chromium/components/offline_items_collection/OfflineItemShareInfo.java", "android/java/src/org/chromium/components/offline_items_collection/OfflineItemVisuals.java", "android/java/src/org/chromium/components/offline_items_collection/OpenParams.java",
diff --git a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java index e96c4ee..26f154827 100644 --- a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java +++ b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java
@@ -110,7 +110,6 @@ public int failState; @PendingState public int pendingState; - public OfflineItemSchedule schedule; public OfflineItem() { id = new ContentId(); @@ -151,7 +150,6 @@ clone.timeRemainingMs = timeRemainingMs; clone.failState = failState; clone.pendingState = pendingState; - if (schedule != null) clone.schedule = schedule.clone(); if (progress != null) { clone.progress = new Progress(progress.value, progress.max, progress.unit);
diff --git a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItemSchedule.java b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItemSchedule.java deleted file mode 100644 index 04d5e0d..0000000 --- a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItemSchedule.java +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.components.offline_items_collection; - -/** - * Java counter part of OfflineItemSchedule in native, see - * components/offline_items_collection/core/offline_item.h. - */ -public class OfflineItemSchedule { - /** - * Constructs a OfflineItemSchedule. - * @param onlyOnWifi See {@link #onlyOnWifi}. - * @param startTimeMs See {@link #startTimeMs}. - */ - public OfflineItemSchedule(boolean onlyOnWifi, long startTimeMs) { - this.onlyOnWifi = onlyOnWifi; - this.startTimeMs = startTimeMs; - } - - @Override - public OfflineItemSchedule clone() { - return new OfflineItemSchedule(onlyOnWifi, startTimeMs); - } - - /** - * Whether the offline item will be downloaded only on WIFI. - */ - public final boolean onlyOnWifi; - - /** - * The trigger time to download the offline item. Will not triggered at particular time if the - * value is 0. - */ - public final long startTimeMs; -}
diff --git a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java index 293e1da..d29c1b1a 100644 --- a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java +++ b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java
@@ -10,7 +10,6 @@ import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItemFilter; import org.chromium.components.offline_items_collection.OfflineItemProgressUnit; -import org.chromium.components.offline_items_collection.OfflineItemSchedule; import org.chromium.components.offline_items_collection.OfflineItemState; import org.chromium.components.offline_items_collection.PendingState; import org.chromium.components.offline_items_collection.UpdateDelta; @@ -57,7 +56,7 @@ boolean isResumable, boolean allowMetered, long receivedBytes, long progressValue, long progressMax, @OfflineItemProgressUnit int progressUnit, long timeRemainingMs, boolean isDangerous, boolean canRename, boolean ignoreVisuals, - double contentQualityScore, OfflineItemSchedule schedule) { + double contentQualityScore) { OfflineItem item = new OfflineItem(); item.id.namespace = nameSpace; item.id.id = id; @@ -93,7 +92,6 @@ item.canRename = canRename; item.ignoreVisuals = ignoreVisuals; item.contentQualityScore = contentQualityScore; - item.schedule = schedule; if (list != null) list.add(item); return item; @@ -111,10 +109,4 @@ updateDelta.visualsChanged = visualsChanged; return updateDelta; } - - @CalledByNative - private static OfflineItemSchedule createOfflineItemSchedule( - boolean onlyOnWifi, long startTimeMs) { - return new OfflineItemSchedule(onlyOnWifi, startTimeMs); - } }
diff --git a/components/offline_items_collection/core/android/native_java_unittests/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridgeUnitTest.java b/components/offline_items_collection/core/android/native_java_unittests/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridgeUnitTest.java index ca384aa..5207129 100644 --- a/components/offline_items_collection/core/android/native_java_unittests/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridgeUnitTest.java +++ b/components/offline_items_collection/core/android/native_java_unittests/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridgeUnitTest.java
@@ -31,15 +31,5 @@ Assert.assertEquals(OfflineItemState.COMPLETE, item.state); Assert.assertEquals(FailState.NO_FAILURE, item.failState); Assert.assertEquals(PendingState.NOT_PENDING, item.pendingState); - Assert.assertNull(item.schedule); - } - - @CalledByNative - public void testOfflineItemSchedule( - OfflineItem item, boolean expectedOnlyOnWifi, long expectedStartTime) { - Assert.assertNotNull(item); - Assert.assertNotNull(item.schedule); - Assert.assertEquals(expectedOnlyOnWifi, item.schedule.onlyOnWifi); - Assert.assertEquals(expectedStartTime, item.schedule.startTimeMs); } } \ No newline at end of file
diff --git a/components/offline_items_collection/core/android/offline_item_bridge.cc b/components/offline_items_collection/core/android/offline_item_bridge.cc index 51b7043..2d3eb80 100644 --- a/components/offline_items_collection/core/android/offline_item_bridge.cc +++ b/components/offline_items_collection/core/android/offline_item_bridge.cc
@@ -47,8 +47,7 @@ item.allow_metered, item.received_bytes, item.progress.value, item.progress.max.value_or(-1), static_cast<jint>(item.progress.unit), item.time_remaining_ms, item.is_dangerous, item.can_rename, - item.ignore_visuals, item.content_quality_score, - OfflineItemBridge::CreateOfflineItemSchedule(env, item.schedule)); + item.ignore_visuals, item.content_quality_score); } } // namespace @@ -84,19 +83,6 @@ update_delta.value().visuals_changed); } -// static -ScopedJavaLocalRef<jobject> OfflineItemBridge::CreateOfflineItemSchedule( - JNIEnv* env, - const absl::optional<OfflineItemSchedule>& schedule) { - if (!schedule.has_value()) - return ScopedJavaLocalRef<jobject>(); - - int64_t start_time_ms = - schedule->start_time.has_value() ? schedule->start_time->ToJavaTime() : 0; - return Java_OfflineItemBridge_createOfflineItemSchedule( - env, schedule->only_on_wifi, start_time_ms); -} - OfflineItemBridge::OfflineItemBridge() = default; } // namespace android
diff --git a/components/offline_items_collection/core/android/offline_item_bridge.h b/components/offline_items_collection/core/android/offline_item_bridge.h index efa4a3bc..beddbce 100644 --- a/components/offline_items_collection/core/android/offline_item_bridge.h +++ b/components/offline_items_collection/core/android/offline_item_bridge.h
@@ -35,11 +35,6 @@ JNIEnv* env, const absl::optional<UpdateDelta>& update_delta); - // Creates a Java OfflineItemSchedule. - static base::android::ScopedJavaLocalRef<jobject> CreateOfflineItemSchedule( - JNIEnv* env, - const absl::optional<OfflineItemSchedule>& schedule); - private: OfflineItemBridge(); };
diff --git a/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc b/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc index ce7cdc9f..d5082f3 100644 --- a/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc +++ b/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc
@@ -39,29 +39,6 @@ j_offline_item); } -// Verifies OfflineItemSchedule can be plumbed to Java correctly. -TEST_F(OfflineItemBridgeTest, OfflineItemSchedule) { - // OfflineItemSchedule only on wifi. - auto* env = AttachCurrentThread(); - OfflineItem item; - item.schedule = absl::make_optional<OfflineItemSchedule>( - true /*only_on_wifi*/, absl::nullopt); - auto j_offline_item = OfflineItemBridge::CreateOfflineItem(env, item); - Java_OfflineItemBridgeUnitTest_testOfflineItemSchedule( - env, j_test(), j_offline_item, true /*only_on_wifi*/, 0); - - // OfflineItemSchedule with specific start time. - auto start_time = base::Time::FromDeltaSinceWindowsEpoch(base::Days(1)); - item.schedule = absl::make_optional<OfflineItemSchedule>( - false /*only_on_wifi*/, start_time); - EXPECT_EQ(start_time, item.schedule->start_time); - EXPECT_FALSE(start_time.is_null()); - j_offline_item = OfflineItemBridge::CreateOfflineItem(env, item); - Java_OfflineItemBridgeUnitTest_testOfflineItemSchedule( - env, j_test(), j_offline_item, false /*only_on_wifi*/, - start_time.ToJavaTime()); -} - } // namespace } // namespace android } // namespace offline_items_collection
diff --git a/components/offline_items_collection/core/offline_item.cc b/components/offline_items_collection/core/offline_item.cc index 79e62e39..265371da 100644 --- a/components/offline_items_collection/core/offline_item.cc +++ b/components/offline_items_collection/core/offline_item.cc
@@ -31,24 +31,6 @@ } // ----------------------------------------------------------------------------- -// OfflineItemSchedule. -OfflineItemSchedule::OfflineItemSchedule(bool only_on_wifi, - absl::optional<base::Time> start_time) - : only_on_wifi(only_on_wifi), start_time(std::move(start_time)) {} - -OfflineItemSchedule::OfflineItemSchedule(const OfflineItemSchedule& other) = - default; - -OfflineItemSchedule& OfflineItemSchedule::operator=( - const OfflineItemSchedule& other) = default; - -OfflineItemSchedule::~OfflineItemSchedule() = default; - -bool OfflineItemSchedule::operator==(const OfflineItemSchedule& other) const { - return only_on_wifi == other.only_on_wifi && start_time == other.start_time; -} - -// ----------------------------------------------------------------------------- // OfflineItem. OfflineItem::Progress::Progress() : value(0), unit(OfflineItemProgressUnit::BYTES) {} @@ -124,8 +106,7 @@ received_bytes == offline_item.received_bytes && progress == offline_item.progress && time_remaining_ms == offline_item.time_remaining_ms && - is_dangerous == offline_item.is_dangerous && - schedule == offline_item.schedule; + is_dangerous == offline_item.is_dangerous; } OfflineItemVisuals::OfflineItemVisuals() = default;
diff --git a/components/offline_items_collection/core/offline_item.h b/components/offline_items_collection/core/offline_item.h index dc8fcf8..e957322 100644 --- a/components/offline_items_collection/core/offline_item.h +++ b/components/offline_items_collection/core/offline_item.h
@@ -42,25 +42,6 @@ bool operator<(const ContentId& content_id) const; }; -// Contains all the information to schedule the download of the offline item. -struct OfflineItemSchedule { - public: - OfflineItemSchedule(bool only_on_wifi, absl::optional<base::Time> start_time); - - OfflineItemSchedule(const OfflineItemSchedule& other); - OfflineItemSchedule& operator=(const OfflineItemSchedule& other); - ~OfflineItemSchedule(); - - bool operator==(const OfflineItemSchedule& other) const; - - // Whether the download should only happen on WIFI. - bool only_on_wifi; - - // Time to start downloading the offline item. Will be ignored if - // |only_on_wifi_| is true. - absl::optional<base::Time> start_time; -}; - // A Java counterpart will be generated for this enum. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.offline_items_collection enum class OfflineItemProgressUnit { @@ -235,9 +216,6 @@ // Whether the download might be dangerous and will require additional // validation from user. bool is_dangerous; - - // The criteria for when the offline item is likely to download. - absl::optional<OfflineItemSchedule> schedule; }; // Implemented for test-only. See test_support/offline_item_test_support.cc.
diff --git a/components/offline_items_collection/core/offline_item_unittest.cc b/components/offline_items_collection/core/offline_item_unittest.cc deleted file mode 100644 index 2de59fe..0000000 --- a/components/offline_items_collection/core/offline_item_unittest.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2020 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/offline_items_collection/core/offline_item.h" - -#include "base/time/time.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" - -namespace offline_items_collection { -namespace { - -TEST(OfflineItemTest, OfflineItemSchedule) { - OfflineItemSchedule schedule(true, absl::nullopt); - EXPECT_TRUE(schedule.only_on_wifi); - EXPECT_FALSE(schedule.start_time.has_value()); - - base::Time time = base::Time::Now(); - schedule = OfflineItemSchedule(false, time); - EXPECT_FALSE(schedule.only_on_wifi); - EXPECT_EQ(schedule.start_time, time); -} - -} // namespace -} // namespace offline_items_collection
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc index 48d143c0..12713a6 100644 --- a/components/omnibox/browser/autocomplete_result_unittest.cc +++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -1859,8 +1859,8 @@ {{OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam, "6"}}}, {omnibox::kMaxZeroSuggestMatches, {{OmniboxFieldTrial::kMaxZeroSuggestMatchesParam, "5"}}}}, - {{omnibox::kDynamicMaxAutocomplete, - omnibox::kRetainSuggestionsWithHeaders}}); + {omnibox::kDynamicMaxAutocomplete, + omnibox::kRetainSuggestionsWithHeaders}); const auto group_1 = omnibox::GROUP_PREVIOUS_SEARCH_RELATED; const auto group_2 = omnibox::GROUP_PREVIOUS_SEARCH_RELATED_ENTITY_CHIPS;
diff --git a/components/omnibox/browser/zero_suggest_cache_service.cc b/components/omnibox/browser/zero_suggest_cache_service.cc index de93f42..6f41a19 100644 --- a/components/omnibox/browser/zero_suggest_cache_service.cc +++ b/components/omnibox/browser/zero_suggest_cache_service.cc
@@ -4,6 +4,9 @@ #include "components/omnibox/browser/zero_suggest_cache_service.h" +#include "base/metrics/histogram_functions.h" +#include "base/trace_event/memory_usage_estimator.h" + ZeroSuggestCacheService::ZeroSuggestCacheService(size_t cache_size) : cache_(cache_size) {} @@ -19,6 +22,8 @@ const std::string& page_url, const std::string& response) { cache_.Put(page_url, response); + base::UmaHistogramCounts1M("Omnibox.ZeroSuggestProvider.CacheMemoryUsage", + base::trace_event::EstimateMemoryUsage(cache_)); for (auto& observer : observers_) { observer.OnZeroSuggestResponseUpdated(page_url, response);
diff --git a/components/omnibox/browser/zero_suggest_cache_service_unittest.cc b/components/omnibox/browser/zero_suggest_cache_service_unittest.cc index 1799274..beae794 100644 --- a/components/omnibox/browser/zero_suggest_cache_service_unittest.cc +++ b/components/omnibox/browser/zero_suggest_cache_service_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> +#include "base/test/metrics/histogram_tester.h" #include "testing/gtest/include/gtest/gtest.h" class FakeObserver : public ZeroSuggestCacheService::Observer { @@ -45,6 +46,31 @@ EXPECT_FALSE(cache_svc.IsCacheEmpty()); } +TEST(ZeroSuggestCacheServiceTest, StoreResponseRecordsMemoryUsageHistogram) { + base::HistogramTester histogram_tester; + ZeroSuggestCacheService cache_svc(1); + + const std::string page_url = "https://www.google.com"; + const std::string response = "foo"; + const std::string histogram = "Omnibox.ZeroSuggestProvider.CacheMemoryUsage"; + + cache_svc.StoreZeroSuggestResponse(page_url, response); + EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(page_url), response); + histogram_tester.ExpectTotalCount(histogram, 1); + + cache_svc.StoreZeroSuggestResponse(page_url, ""); + EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(page_url), ""); + histogram_tester.ExpectTotalCount(histogram, 2); + + cache_svc.StoreZeroSuggestResponse("", response); + EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(""), response); + histogram_tester.ExpectTotalCount(histogram, 3); + + cache_svc.StoreZeroSuggestResponse("", ""); + EXPECT_EQ(cache_svc.ReadZeroSuggestResponse(""), ""); + histogram_tester.ExpectTotalCount(histogram, 4); +} + TEST(ZeroSuggestCacheServiceTest, StoreResponseUpdatesExistingEntry) { ZeroSuggestCacheService cache_svc(1);
diff --git a/components/renderer_context_menu/context_menu_content_type.cc b/components/renderer_context_menu/context_menu_content_type.cc index 640d706..c3db998 100644 --- a/components/renderer_context_menu/context_menu_content_type.cc +++ b/components/renderer_context_menu/context_menu_content_type.cc
@@ -22,12 +22,9 @@ } // namespace ContextMenuContentType::ContextMenuContentType( - content::WebContents* web_contents, const content::ContextMenuParams& params, bool supports_custom_items) - : params_(params), - source_web_contents_(web_contents), - supports_custom_items_(supports_custom_items) {} + : params_(params), supports_custom_items_(supports_custom_items) {} ContextMenuContentType::~ContextMenuContentType() { }
diff --git a/components/renderer_context_menu/context_menu_content_type.h b/components/renderer_context_menu/context_menu_content_type.h index 31906cae..ee3d388 100644 --- a/components/renderer_context_menu/context_menu_content_type.h +++ b/components/renderer_context_menu/context_menu_content_type.h
@@ -9,10 +9,6 @@ #include "content/public/browser/context_menu_params.h" #include "ui/base/models/simple_menu_model.h" -namespace content { -class WebContents; -} - // ContextMenuContentType is a helper to decide which category/group of items // are relevant for a given WebContents and a context. // @@ -57,22 +53,16 @@ // Returns if |group| is enabled. virtual bool SupportsGroup(int group); - ContextMenuContentType(content::WebContents* web_contents, - const content::ContextMenuParams& params, + ContextMenuContentType(const content::ContextMenuParams& params, bool supports_custom_items); protected: const content::ContextMenuParams& params() const { return params_; } - content::WebContents* source_web_contents() const { - return source_web_contents_; - } - private: bool SupportsGroupInternal(int group); const content::ContextMenuParams params_; - const raw_ptr<content::WebContents> source_web_contents_; const bool supports_custom_items_; };
diff --git a/components/services/app_service/app_service_mojom_impl_unittest.cc b/components/services/app_service/app_service_mojom_impl_unittest.cc index 2d9a3dab..d691dd79 100644 --- a/components/services/app_service/app_service_mojom_impl_unittest.cc +++ b/components/services/app_service/app_service_mojom_impl_unittest.cc
@@ -15,10 +15,6 @@ #include "components/services/app_service/app_service_mojom_impl.h" #include "components/services/app_service/public/cpp/app_capability_access_cache.h" #include "components/services/app_service/public/cpp/features.h" -#include "components/services/app_service/public/cpp/intent.h" -#include "components/services/app_service/public/cpp/intent_filter_util.h" -#include "components/services/app_service/public/cpp/intent_test_util.h" -#include "components/services/app_service/public/cpp/intent_util.h" #include "components/services/app_service/public/cpp/preferred_app.h" #include "components/services/app_service/public/cpp/preferred_apps_list.h" #include "components/services/app_service/public/cpp/publisher_base.h" @@ -85,14 +81,9 @@ } for (const auto& app_id : app_ids) { known_app_ids_.push_back(app_id); - impl->RemovePreferredApp(app_type_, app_id); } } - bool AppHasSupportedLinksPreference(const std::string& app_id) { - return supported_link_apps_.find(app_id) != supported_link_apps_.end(); - } - std::string load_icon_app_id; private: @@ -110,15 +101,6 @@ apps::mojom::LaunchSource launch_source, apps::mojom::WindowInfoPtr window_info) override {} - void OnSupportedLinksPreferenceChanged(const std::string& app_id, - bool open_in_app) override { - if (open_in_app) { - supported_link_apps_.insert(app_id); - } else { - supported_link_apps_.erase(app_id); - } - } - void CallOnApps(apps::mojom::Subscriber* subscriber, std::vector<std::string>& app_ids, bool uninstall) { @@ -158,7 +140,6 @@ std::vector<std::string> known_app_ids_; std::set<std::string> apps_accessing_camera_; std::set<std::string> apps_accessing_microphone_; - std::set<std::string> supported_link_apps_; mojo::ReceiverSet<apps::mojom::Publisher> receivers_; mojo::RemoteSet<apps::mojom::Subscriber> subscribers_; }; @@ -195,17 +176,12 @@ return ss.str(); } - PreferredAppsList& PreferredApps() { return preferred_apps_; } - private: void OnApps(std::vector<apps::mojom::AppPtr> deltas, apps::mojom::AppType app_type, bool should_notify_initialized) override { for (const auto& delta : deltas) { app_ids_seen_.insert(delta->app_id); - if (delta->readiness == apps::mojom::Readiness::kUninstalledByUser) { - preferred_apps_.DeleteAppId(delta->app_id); - } } } @@ -219,29 +195,22 @@ } void OnPreferredAppsChanged( - apps::mojom::PreferredAppChangesPtr changes) override { - preferred_apps_.ApplyBulkUpdate( - ConvertMojomPreferredAppChangesToPreferredAppChanges(changes)); - } + apps::mojom::PreferredAppChangesPtr changes) override {} void InitializePreferredApps( std::vector<apps::mojom::PreferredAppPtr> mojom_preferred_apps) override { - preferred_apps_.Init( - ConvertMojomPreferredAppsToPreferredApps(mojom_preferred_apps)); } mojo::ReceiverSet<apps::mojom::Subscriber> receivers_; std::set<std::string> app_ids_seen_; AppCapabilityAccessCache cache_; - apps::PreferredAppsList preferred_apps_; }; class AppServiceMojomImplTest : public testing::Test { protected: AppServiceMojomImplTest() { scoped_feature_list_.InitWithFeatures( - {}, {kAppServicePreferredAppsWithoutMojom, - kAppServiceCapabilityAccessWithoutMojom}); + {}, {kAppServiceCapabilityAccessWithoutMojom}); } content::BrowserTaskEnvironment task_environment_; @@ -348,517 +317,4 @@ EXPECT_EQ("", sub1.AppIdsAccessingMicrophone()); } -TEST_F(AppServiceMojomImplTest, PreferredApps) { - // Test Initialize. - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - AppServiceMojomImpl impl(temp_dir_.GetPath()); - impl.GetPreferredAppsListForTesting().Init(); - - const char kAppId1[] = "abcdefg"; - const char kAppId2[] = "aaaaaaa"; - GURL filter_url = GURL("https://www.google.com/abc"); - auto intent_filter = apps_util::CreateIntentFilterForUrlScope(filter_url); - - impl.GetPreferredAppsListForTesting().AddPreferredApp( - kAppId1, ConvertMojomIntentFilterToIntentFilter(intent_filter)); - - // Add one subscriber. - FakeSubscriber sub0(&impl); - task_environment_.RunUntilIdle(); - EXPECT_EQ(sub0.PreferredApps().GetValue(), - impl.GetPreferredAppsListForTesting().GetValue()); - - // Add another subscriber. - FakeSubscriber sub1(&impl); - task_environment_.RunUntilIdle(); - EXPECT_EQ(sub1.PreferredApps().GetValue(), - impl.GetPreferredAppsListForTesting().GetValue()); - - FakePublisher pub0(&impl, apps::mojom::AppType::kArc, - std::vector<std::string>{kAppId1, kAppId2}); - task_environment_.RunUntilIdle(); - - // Test sync preferred app to all subscribers. - filter_url = GURL("https://www.abc.com/"); - GURL another_filter_url = GURL("https://www.test.com/"); - intent_filter = apps_util::CreateIntentFilterForUrlScope(filter_url); - auto another_intent_filter = - apps_util::CreateIntentFilterForUrlScope(another_filter_url); - - task_environment_.RunUntilIdle(); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(absl::nullopt, - sub1.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(another_filter_url)); - EXPECT_EQ(absl::nullopt, - sub1.PreferredApps().FindPreferredAppForUrl(another_filter_url)); - - impl.AddPreferredApp( - apps::mojom::AppType::kUnknown, kAppId2, intent_filter->Clone(), - apps_util::CreateIntentFromUrl(filter_url), /*from_publisher=*/true); - impl.AddPreferredApp(apps::mojom::AppType::kUnknown, kAppId2, - another_intent_filter->Clone(), - apps_util::CreateIntentFromUrl(another_filter_url), - /*from_publisher=*/true); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId2, sub0.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(kAppId2, sub1.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(kAppId2, - sub0.PreferredApps().FindPreferredAppForUrl(another_filter_url)); - EXPECT_EQ(kAppId2, - sub1.PreferredApps().FindPreferredAppForUrl(another_filter_url)); - - // Test that uninstall removes all the settings for the app. - pub0.UninstallApps(std::vector<std::string>{kAppId2}, &impl); - task_environment_.RunUntilIdle(); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(absl::nullopt, - sub1.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(another_filter_url)); - EXPECT_EQ(absl::nullopt, - sub1.PreferredApps().FindPreferredAppForUrl(another_filter_url)); - - impl.AddPreferredApp( - apps::mojom::AppType::kUnknown, kAppId2, intent_filter->Clone(), - apps_util::CreateIntentFromUrl(filter_url), /*from_publisher=*/true); - impl.AddPreferredApp(apps::mojom::AppType::kUnknown, kAppId2, - another_intent_filter->Clone(), - apps_util::CreateIntentFromUrl(another_filter_url), - /*from_publisher=*/true); - task_environment_.RunUntilIdle(); - - EXPECT_EQ(kAppId2, sub0.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(kAppId2, sub1.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(kAppId2, - sub0.PreferredApps().FindPreferredAppForUrl(another_filter_url)); - EXPECT_EQ(kAppId2, - sub1.PreferredApps().FindPreferredAppForUrl(another_filter_url)); -} - -// Tests that writing a preferred app value before the PreferredAppsList is -// initialized queues the write for after initialization. -TEST_F(AppServiceMojomImplTest, PreferredAppsWriteBeforeInit) { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - base::RunLoop run_loop_read; - AppServiceMojomImpl impl(temp_dir_.GetPath(), run_loop_read.QuitClosure()); - GURL filter_url("https://www.abc.com/"); - - std::string kAppId1 = "aaa"; - std::string kAppId2 = "bbb"; - - impl.AddPreferredApp(apps::mojom::AppType::kArc, kAppId1, - apps_util::CreateIntentFilterForMimeType("image/png"), - nullptr, - /*from_publisher=*/false); - - std::vector<apps::mojom::IntentFilterPtr> filters; - filters.push_back(apps_util::CreateIntentFilterForUrlScope(filter_url)); - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId2, - std::move(filters)); - - // Wait for the preferred apps list initialization to read from disk. - run_loop_read.Run(); - - // Both changes to the PreferredAppsList should have been applied. - std::vector<GURL> filesystem_urls( - {GURL("filesystem:chrome://foo/image.png")}); - std::vector<std::string> mime_types({"image/png"}); - ASSERT_EQ(kAppId1, - impl.GetPreferredAppsListForTesting().FindPreferredAppForIntent( - apps_util::MakeShareIntent(filesystem_urls, mime_types))); - ASSERT_EQ( - kAppId2, - impl.GetPreferredAppsListForTesting().FindPreferredAppForUrl(filter_url)); -} - -TEST_F(AppServiceMojomImplTest, PreferredAppsPersistency) { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - const char kAppId1[] = "abcdefg"; - GURL filter_url = GURL("https://www.google.com/abc"); - auto intent_filter = apps_util::CreateIntentFilterForUrlScope(filter_url); - { - base::RunLoop run_loop_read; - base::RunLoop run_loop_write; - AppServiceMojomImpl impl(temp_dir_.GetPath(), run_loop_read.QuitClosure(), - run_loop_write.QuitClosure()); - impl.FlushMojoCallsForTesting(); - run_loop_read.Run(); - impl.AddPreferredApp(apps::mojom::AppType::kUnknown, kAppId1, - intent_filter->Clone(), - apps_util::CreateIntentFromUrl(filter_url), - /*from_publisher=*/false); - run_loop_write.Run(); - impl.FlushMojoCallsForTesting(); - } - // Create a new impl to initialize preferred apps from the disk. - { - base::RunLoop run_loop_read; - AppServiceMojomImpl impl(temp_dir_.GetPath(), run_loop_read.QuitClosure()); - impl.FlushMojoCallsForTesting(); - run_loop_read.Run(); - EXPECT_EQ(kAppId1, - impl.GetPreferredAppsListForTesting().FindPreferredAppForUrl( - filter_url)); - } -} - -TEST_F(AppServiceMojomImplTest, PreferredAppsSetSupportedLinks) { - // Test Initialize. - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - AppServiceMojomImpl impl(temp_dir_.GetPath()); - impl.GetPreferredAppsListForTesting().Init(); - - const char kAppId1[] = "abcdefg"; - const char kAppId2[] = "hijklmn"; - const char kAppId3[] = "opqrstu"; - - auto intent_filter_a = - apps_util::CreateIntentFilterForUrlScope(GURL("https://www.a.com/")); - auto intent_filter_b = - apps_util::CreateIntentFilterForUrlScope(GURL("https://www.b.com/")); - auto intent_filter_c = - apps_util::CreateIntentFilterForUrlScope(GURL("https://www.c.com/")); - - FakeSubscriber sub0(&impl); - task_environment_.RunUntilIdle(); - - FakePublisher pub0(&impl, apps::mojom::AppType::kArc, - std::vector<std::string>{kAppId1, kAppId2, kAppId3}); - task_environment_.RunUntilIdle(); - - std::vector<apps::mojom::IntentFilterPtr> app_1_filters; - app_1_filters.push_back(intent_filter_a.Clone()); - app_1_filters.push_back(intent_filter_b.Clone()); - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId1, - std::move(app_1_filters)); - - std::vector<apps::mojom::IntentFilterPtr> app_2_filters; - app_2_filters.push_back(intent_filter_c.Clone()); - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId2, - std::move(app_2_filters)); - - task_environment_.RunUntilIdle(); - - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId1)); - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId2)); - EXPECT_FALSE(pub0.AppHasSupportedLinksPreference(kAppId3)); - - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.a.com/"))); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.b.com/"))); - EXPECT_EQ(kAppId2, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.c.com/"))); - - // App 3 overlaps with both App 1 and 2. Both previous apps should have all - // their supported link filters removed. - std::vector<apps::mojom::IntentFilterPtr> app_3_filters; - app_3_filters.push_back(intent_filter_b.Clone()); - app_3_filters.push_back(intent_filter_c.Clone()); - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId3, - std::move(app_3_filters)); - - task_environment_.RunUntilIdle(); - EXPECT_FALSE(pub0.AppHasSupportedLinksPreference(kAppId1)); - EXPECT_FALSE(pub0.AppHasSupportedLinksPreference(kAppId2)); - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId3)); - - EXPECT_EQ(absl::nullopt, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.a.com/"))); - EXPECT_EQ(kAppId3, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.b.com/"))); - EXPECT_EQ(kAppId3, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.c.com/"))); - - // Setting App 3 as preferred again should not change anything. - app_3_filters = std::vector<apps::mojom::IntentFilterPtr>(); - app_3_filters.push_back(intent_filter_b.Clone()); - app_3_filters.push_back(intent_filter_c.Clone()); - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId3, - std::move(app_3_filters)); - task_environment_.RunUntilIdle(); - - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId3)); - EXPECT_EQ(kAppId3, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.c.com/"))); - - impl.RemoveSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId3); - task_environment_.RunUntilIdle(); - - EXPECT_FALSE(pub0.AppHasSupportedLinksPreference(kAppId3)); - EXPECT_EQ(absl::nullopt, sub0.PreferredApps().FindPreferredAppForUrl( - GURL("https://www.c.com/"))); -} - -// Test that app with overlapped works properly. -TEST_F(AppServiceMojomImplTest, PreferredAppsOverlap) { - // Test Initialize. - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - AppServiceMojomImpl impl(temp_dir_.GetPath()); - impl.GetPreferredAppsListForTesting().Init(); - - const char kAppId1[] = "abcdefg"; - const char kAppId2[] = "hijklmn"; - - GURL filter_url_1 = GURL("https://www.google.com/abc"); - GURL filter_url_2 = GURL("http://www.google.com.au/abc"); - GURL filter_url_3 = GURL("https://www.abc.com/abc"); - - auto intent_filter_1 = apps_util::CreateIntentFilterForUrlScope(filter_url_1); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kScheme, filter_url_2.scheme(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_1); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kHost, filter_url_2.host(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_1); - - auto intent_filter_2 = apps_util::CreateIntentFilterForUrlScope(filter_url_3); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kScheme, filter_url_2.scheme(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_2); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kHost, filter_url_2.host(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_2); - - auto intent_filter_3 = apps_util::CreateIntentFilterForUrlScope(filter_url_1); - - FakeSubscriber sub0(&impl); - task_environment_.RunUntilIdle(); - - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_EQ(0U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(0U, sub0.PreferredApps().GetEntrySize()); - - impl.AddPreferredApp( - apps::mojom::AppType::kArc, kAppId1, intent_filter_1->Clone(), - apps_util::CreateIntentFromUrl(filter_url_1), /*from_publisher=*/true); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_EQ(1U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(1U, sub0.PreferredApps().GetEntrySize()); - - // Add preferred app with intent filter overlap with existing entry for - // another app will reset the preferred app setting for the other app. - impl.AddPreferredApp( - apps::mojom::AppType::kArc, kAppId2, intent_filter_2->Clone(), - apps_util::CreateIntentFromUrl(filter_url_1), /*from_publisher=*/true); - task_environment_.RunUntilIdle(); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(kAppId2, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(kAppId2, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_EQ(1U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(1U, sub0.PreferredApps().GetEntrySize()); -} - -// Test that app with overlapped supported links works properly. -TEST_F(AppServiceMojomImplTest, PreferredAppsOverlapSupportedLink) { - // Test Initialize. - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - AppServiceMojomImpl impl(temp_dir_.GetPath()); - impl.GetPreferredAppsListForTesting().Init(); - - const char kAppId1[] = "abcdefg"; - const char kAppId2[] = "hijklmn"; - - GURL filter_url_1 = GURL("https://www.google.com/abc"); - GURL filter_url_2 = GURL("http://www.google.com.au/abc"); - GURL filter_url_3 = GURL("https://www.abc.com/abc"); - - auto intent_filter_1 = apps_util::CreateIntentFilterForUrlScope(filter_url_1); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kScheme, filter_url_2.scheme(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_1); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kHost, filter_url_2.host(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_1); - - auto intent_filter_2 = apps_util::CreateIntentFilterForUrlScope(filter_url_3); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kScheme, filter_url_2.scheme(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_2); - apps_util::AddConditionValue( - apps::mojom::ConditionType::kHost, filter_url_2.host(), - apps::mojom::PatternMatchType::kLiteral, intent_filter_2); - - auto intent_filter_3 = apps_util::CreateIntentFilterForUrlScope(filter_url_1); - - std::vector<apps::mojom::IntentFilterPtr> app_1_filters; - app_1_filters.push_back(std::move(intent_filter_1)); - app_1_filters.push_back(std::move(intent_filter_2)); - std::vector<apps::mojom::IntentFilterPtr> app_2_filters; - app_2_filters.push_back(std::move(intent_filter_3)); - - FakeSubscriber sub0(&impl); - task_environment_.RunUntilIdle(); - - FakePublisher pub0(&impl, apps::mojom::AppType::kArc, - std::vector<std::string>{kAppId1, kAppId2}); - task_environment_.RunUntilIdle(); - - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_EQ(0U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(0U, sub0.PreferredApps().GetEntrySize()); - - // Test that add preferred app with overlapped filters for same app will - // add all entries. - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId1, - mojo::Clone(app_1_filters)); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId1)); - EXPECT_FALSE(pub0.AppHasSupportedLinksPreference(kAppId2)); - EXPECT_EQ(2U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(2U, sub0.PreferredApps().GetEntrySize()); - - // Test that add preferred app with another app that has overlapped filter - // will clear all entries from the original app. - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId2, - mojo::Clone(app_2_filters)); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId2, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_FALSE(pub0.AppHasSupportedLinksPreference(kAppId1)); - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId2)); - EXPECT_EQ(1U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(1U, sub0.PreferredApps().GetEntrySize()); - - // Test that setting back to app 1 works. - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId1, - mojo::Clone(app_1_filters)); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId1)); - EXPECT_FALSE(pub0.AppHasSupportedLinksPreference(kAppId2)); - EXPECT_EQ(2U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(2U, sub0.PreferredApps().GetEntrySize()); -} - -// Test that duplicated entry will not be added. -TEST_F(AppServiceMojomImplTest, PreferredAppsDuplicated) { - // Test Initialize. - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - AppServiceMojomImpl impl(temp_dir_.GetPath()); - impl.GetPreferredAppsListForTesting().Init(); - - const char kAppId1[] = "abcdefg"; - - GURL filter_url = GURL("https://www.google.com/abc"); - - auto intent_filter = apps_util::CreateIntentFilterForUrlScope(filter_url); - - FakeSubscriber sub0(&impl); - task_environment_.RunUntilIdle(); - - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(0U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(0U, sub0.PreferredApps().GetEntrySize()); - - impl.AddPreferredApp( - apps::mojom::AppType::kArc, kAppId1, intent_filter->Clone(), - apps_util::CreateIntentFromUrl(filter_url), /*from_publisher=*/true); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(1U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(1U, sub0.PreferredApps().GetEntrySize()); - - impl.AddPreferredApp( - apps::mojom::AppType::kArc, kAppId1, intent_filter->Clone(), - apps_util::CreateIntentFromUrl(filter_url), /*from_publisher=*/true); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url)); - EXPECT_EQ(1U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(1U, sub0.PreferredApps().GetEntrySize()); -} - -// Test that duplicated entry will not be added for supported links. -TEST_F(AppServiceMojomImplTest, PreferredAppsDuplicatedSupportedLink) { - // Test Initialize. - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - AppServiceMojomImpl impl(temp_dir_.GetPath()); - impl.GetPreferredAppsListForTesting().Init(); - - const char kAppId1[] = "abcdefg"; - - GURL filter_url_1 = GURL("https://www.google.com/abc"); - GURL filter_url_2 = GURL("http://www.google.com.au/abc"); - GURL filter_url_3 = GURL("https://www.abc.com/abc"); - - auto intent_filter_1 = apps_util::CreateIntentFilterForUrlScope(filter_url_1); - - auto intent_filter_2 = apps_util::CreateIntentFilterForUrlScope(filter_url_2); - - auto intent_filter_3 = apps_util::CreateIntentFilterForUrlScope(filter_url_3); - - std::vector<apps::mojom::IntentFilterPtr> app_1_filters; - app_1_filters.push_back(std::move(intent_filter_1)); - app_1_filters.push_back(std::move(intent_filter_2)); - app_1_filters.push_back(std::move(intent_filter_3)); - - FakeSubscriber sub0(&impl); - task_environment_.RunUntilIdle(); - - FakePublisher pub0(&impl, apps::mojom::AppType::kArc, - std::vector<std::string>{kAppId1}); - task_environment_.RunUntilIdle(); - - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(absl::nullopt, - sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_EQ(0U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(0U, sub0.PreferredApps().GetEntrySize()); - - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId1, - mojo::Clone(app_1_filters)); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId1)); - - EXPECT_EQ(3U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(3U, sub0.PreferredApps().GetEntrySize()); - - impl.SetSupportedLinksPreference(apps::mojom::AppType::kArc, kAppId1, - mojo::Clone(app_1_filters)); - task_environment_.RunUntilIdle(); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_1)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_2)); - EXPECT_EQ(kAppId1, sub0.PreferredApps().FindPreferredAppForUrl(filter_url_3)); - EXPECT_TRUE(pub0.AppHasSupportedLinksPreference(kAppId1)); - - EXPECT_EQ(3U, impl.GetPreferredAppsListForTesting().GetEntrySize()); - EXPECT_EQ(3U, sub0.PreferredApps().GetEntrySize()); -} - } // namespace apps
diff --git a/components/translate/ios/browser/BUILD.gn b/components/translate/ios/browser/BUILD.gn index 05a4f5d..f61c879 100644 --- a/components/translate/ios/browser/BUILD.gn +++ b/components/translate/ios/browser/BUILD.gn
@@ -9,8 +9,10 @@ sources = [ "ios_translate_driver.h", "ios_translate_driver.mm", - "js_translate_manager.h", - "js_translate_manager.mm", + "js_translate_web_frame_manager.h", + "js_translate_web_frame_manager.mm", + "js_translate_web_frame_manager_factory.h", + "js_translate_web_frame_manager_factory.mm", "language_detection_controller.h", "language_detection_controller.mm", "language_detection_model_service.h", @@ -19,6 +21,8 @@ "string_clipping_util.h", "translate_controller.h", "translate_controller.mm", + "translate_java_script_feature.h", + "translate_java_script_feature.mm", ] deps = [ @@ -47,13 +51,18 @@ visibility = [ ":browser" ] primary_script = "resources/translate_ios.js" sources = [ "resources/translate_ios.js" ] + + deps = [ + "//ios/web/public/js_messaging:gcrweb", + "//ios/web/public/js_messaging:util_scripts", + ] } source_set("unit_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ - "js_translate_manager_unittest.mm", + "js_translate_web_frame_manager_unittest.mm", "string_clipping_util_unittest.cc", "translate_controller_unittest.mm", ] @@ -64,6 +73,7 @@ "//base/test:test_support", "//components/language/ios/browser", "//components/resources", + "//ios/web/public/js_messaging", "//ios/web/public/test", "//ios/web/public/test:test_fixture", "//testing/gtest",
diff --git a/components/translate/ios/browser/ios_translate_driver.h b/components/translate/ios/browser/ios_translate_driver.h index 4e17775f..23cf1c8 100644 --- a/components/translate/ios/browser/ios_translate_driver.h +++ b/components/translate/ios/browser/ios_translate_driver.h
@@ -46,9 +46,6 @@ return language_detection_controller_.get(); } - TranslateController* translate_controller() { - return translate_controller_.get(); - } void OnLanguageModelFileAvailabilityChanged(bool available); // web::WebStateObserver methods. @@ -109,7 +106,6 @@ web::WebState* web_state_ = nullptr; base::WeakPtr<TranslateManager> translate_manager_; - std::unique_ptr<TranslateController> translate_controller_; std::unique_ptr<LanguageDetectionController> language_detection_controller_; LanguageDetectionModelService* language_detection_model_service_ = nullptr;
diff --git a/components/translate/ios/browser/ios_translate_driver.mm b/components/translate/ios/browser/ios_translate_driver.mm index 8fb3ce26..8b3a7e5 100644 --- a/components/translate/ios/browser/ios_translate_driver.mm +++ b/components/translate/ios/browser/ios_translate_driver.mm
@@ -19,7 +19,7 @@ #include "components/translate/core/common/translate_metrics.h" #include "components/translate/core/common/translate_util.h" #include "components/translate/core/language_detection/language_detection_model.h" -#import "components/translate/ios/browser/js_translate_manager.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager_factory.h" #import "components/translate/ios/browser/language_detection_controller.h" #include "components/translate/ios/browser/language_detection_model_service.h" #import "components/translate/ios/browser/translate_controller.h" @@ -75,13 +75,9 @@ web_state, language_detection_model, translate_manager_->translate_client()->GetPrefs()); - // Create the translate controller. - JsTranslateManager* js_translate_manager = - [[JsTranslateManager alloc] initWithWebState:web_state]; - translate_controller_ = - std::make_unique<TranslateController>(web_state, js_translate_manager); - - translate_controller_->set_observer(this); + TranslateController::CreateForWebState( + web_state, JSTranslateWebFrameManagerFactory::GetInstance()); + TranslateController::FromWebState(web_state)->set_observer(this); } IOSTranslateDriver::~IOSTranslateDriver() { @@ -166,13 +162,14 @@ source_language_ = source_lang; target_language_ = target_lang; pending_page_seq_no_ = page_seq_no; - translate_controller_->InjectTranslateScript(translate_script); + TranslateController::FromWebState(web_state_) + ->InjectTranslateScript(translate_script); } void IOSTranslateDriver::RevertTranslation(int page_seq_no) { if (page_seq_no != page_seq_no_) return; // The user navigated away. - translate_controller_->RevertTranslation(); + TranslateController::FromWebState(web_state_)->RevertTranslation(); } bool IOSTranslateDriver::IsIncognito() { @@ -260,7 +257,8 @@ std::string source = (source_language_ != kUnknownLanguageCode) ? source_language_ : kAutoDetectionLanguage; - translate_controller_->StartTranslation(source_language_, target_language_); + TranslateController::FromWebState(web_state_) + ->StartTranslation(source_language_, target_language_); } void IOSTranslateDriver::OnTranslateComplete(TranslateErrors error_type,
diff --git a/components/translate/ios/browser/js_translate_manager.h b/components/translate/ios/browser/js_translate_manager.h deleted file mode 100644 index ddc0391..0000000 --- a/components/translate/ios/browser/js_translate_manager.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2013 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_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_MANAGER_H_ -#define COMPONENTS_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_MANAGER_H_ - -#import <Foundation/Foundation.h> -#include <string> - -namespace web { -class WebState; -} // namespace web - -// Manager for the injection of the Translate JavaScript. -// Replicates functionality from TranslateAgent in -// chrome/renderer/translate/translate_agent.cc. -// JsTranslateManager injects the script in the page and calls it, but is not -// responsible for loading it or caching it. -@interface JsTranslateManager : NSObject - -- (instancetype)initWithWebState:(web::WebState*)web_state - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -// Injects the |translate_script| into the |web_state| passed in at -// initialization. -- (void)injectWithTranslateScript:(const std::string&)translate_script; - -// Starts translation of the page from |source| language to |target| language. -// Equivalent to TranslateAgent::StartTranslation(). -- (void)startTranslationFrom:(const std::string&)source - to:(const std::string&)target; - -// Reverts the translation. Assumes that no navigation happened since the page -// has been translated. -- (void)revertTranslation; - -// Returns the response to a XHR request that was proxied to the browser from -// javascript. See function __gCrWeb.translate.handleResponse. -// |URL| The original URL that was requested. -// |requestID| An ID for keeping track of inflight requests. -// |responeCode| The HTTP response code. -// |statusText| The status text associated with the response code, may be empty. -// |responseURL| The final URL from which the response originates. -// |responseText| The contents of the response. -- (void)handleTranslateResponseWithURL:(const std::string&)URL - requestID:(int)requestID - responseCode:(int)responseCode - statusText:(const std::string&)statusText - responseURL:(const std::string&)responseURL - responseText:(const std::string&)responseText; - -@end - -#endif // COMPONENTS_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_MANAGER_H_
diff --git a/components/translate/ios/browser/js_translate_manager.mm b/components/translate/ios/browser/js_translate_manager.mm deleted file mode 100644 index 157c51b..0000000 --- a/components/translate/ios/browser/js_translate_manager.mm +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "components/translate/ios/browser/js_translate_manager.h" - -#import <Foundation/Foundation.h> - -#include <memory> - -#include "base/check.h" -#include "base/mac/bundle_locations.h" -#include "base/strings/stringprintf.h" -#import "base/strings/sys_string_conversions.h" -#import "base/strings/utf_string_conversions.h" -#import "ios/web/public/web_state.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -// Returns an autoreleased string containing the JavaScript loaded from a -// bundled resource file with the given name (excluding extension). -NSString* GetPageScript(NSString* script_file_name) { - DCHECK(script_file_name); - NSString* path = - [base::mac::FrameworkBundle() pathForResource:script_file_name - ofType:@"js"]; - DCHECK(path) << "Script file not found: " - << base::SysNSStringToUTF8(script_file_name) << ".js"; - NSError* error = nil; - NSString* content = [NSString stringWithContentsOfFile:path - encoding:NSUTF8StringEncoding - error:&error]; - DCHECK(!error) << "Error fetching script: " - << base::SysNSStringToUTF8(error.description); - DCHECK(content); - return content; -} - -} // namespace - -@interface JsTranslateManager () -@property(nonatomic) web::WebState* web_state; -@property(nonatomic) bool injected; -@end - -@implementation JsTranslateManager - -- (instancetype)initWithWebState:(web::WebState*)web_state { - self = [super init]; - if (self) { - _web_state = web_state; - _injected = false; - } - return self; -} - -- (void)injectWithTranslateScript:(const std::string&)translate_script { - // Prepend translate_ios.js - NSString* translate_ios = GetPageScript(@"translate_ios"); - NSString* script = [translate_ios - stringByAppendingString:base::SysUTF8ToNSString(translate_script)]; - - // Reset translate state if previously injected. - if (_injected) { - NSString* resetScript = @"try {" - " cr.googleTranslate.revert();" - "} catch (e) {" - "}"; - script = [resetScript stringByAppendingString:script]; - } - - _injected = true; - - _web_state->ExecuteJavaScript(base::SysNSStringToUTF16(script)); -} - -- (void)startTranslationFrom:(const std::string&)source - to:(const std::string&)target { - std::string script = - base::StringPrintf("cr.googleTranslate.translate('%s','%s')", - source.c_str(), target.c_str()); - _web_state->ExecuteJavaScript(base::UTF8ToUTF16(script)); -} - -- (void)revertTranslation { - if (!_injected) - return; - - _web_state->ExecuteJavaScript(u"cr.googleTranslate.revert()"); -} - -- (void)handleTranslateResponseWithURL:(const std::string&)URL - requestID:(int)requestID - responseCode:(int)responseCode - statusText:(const std::string&)statusText - responseURL:(const std::string&)responseURL - responseText:(const std::string&)responseText { - DCHECK(_injected); - - // Return the response details to function defined in translate_ios.js. - std::string script = base::StringPrintf( - "__gCrWeb.translate.handleResponse('%s', %d, %d, '%s', '%s', '%s')", - URL.c_str(), requestID, responseCode, statusText.c_str(), - responseURL.c_str(), responseText.c_str()); - _web_state->ExecuteJavaScript(base::UTF8ToUTF16(script)); -} - -@end
diff --git a/components/translate/ios/browser/js_translate_manager_unittest.mm b/components/translate/ios/browser/js_translate_manager_unittest.mm deleted file mode 100644 index da76bd6..0000000 --- a/components/translate/ios/browser/js_translate_manager_unittest.mm +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "components/translate/ios/browser/js_translate_manager.h" - -#include "components/grit/components_resources.h" -#import "ios/web/public/test/web_test_with_web_state.h" -#import "testing/gtest_mac.h" -#include "ui/base/resource/resource_bundle.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace translate { -namespace { - -typedef web::WebTestWithWebState JsTranslateManagerTest; - -// Checks that cr.googleTranslate.libReady is available after the code has -// been injected in the page. -TEST_F(JsTranslateManagerTest, Inject) { - LoadHtml(@"<html></html>"); - JsTranslateManager* manager = - [[JsTranslateManager alloc] initWithWebState:web_state()]; - std::string script = - ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_TRANSLATE_JS); - [manager injectWithTranslateScript:script + "('DummyKey');"]; - - id result = ExecuteJavaScript(@"typeof cr.googleTranslate != 'undefined'"); - EXPECT_NSEQ(@YES, result); - - result = ExecuteJavaScript(@"cr.googleTranslate.libReady"); - EXPECT_NSEQ(@NO, result); -} - -} // namespace -} // namespace translate
diff --git a/components/translate/ios/browser/js_translate_web_frame_manager.h b/components/translate/ios/browser/js_translate_web_frame_manager.h new file mode 100644 index 0000000..5c75d14 --- /dev/null +++ b/components/translate/ios/browser/js_translate_web_frame_manager.h
@@ -0,0 +1,45 @@ +// Copyright 2022 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_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_WEB_FRAME_MANAGER_H_ +#define COMPONENTS_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_WEB_FRAME_MANAGER_H_ + +#import "ios/web/public/js_messaging/web_frame_user_data.h" + +namespace web { +class WebFrame; +} // namespace web + +class JSTranslateWebFrameManager + : public web::WebFrameUserData<JSTranslateWebFrameManager> { + public: + ~JSTranslateWebFrameManager() override; + + virtual void InjectTranslateScript(const std::string& script); + virtual void StartTranslation(const std::string& source, + const std::string& target); + virtual void RevertTranslation(); + virtual void HandleTranslateResponse(const std::string& url, + int request_id, + int response_code, + const std::string status_text, + const std::string& response_url, + const std::string& response_text); + + protected: + explicit JSTranslateWebFrameManager(web::WebFrame* web_frame); + + web::WebFrame* web_frame_ = nullptr; + + private: + friend class web::WebFrameUserData<JSTranslateWebFrameManager>; + friend class JSTranslateWebFrameManagerFactory; + friend class TestJSTranslateWebFrameManager; + + // Whether or not the translate script has been injected into the associated + // WebFrame. + bool injected_ = false; +}; + +#endif // COMPONENTS_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_WEB_FRAME_MANAGER_H_
diff --git a/components/translate/ios/browser/js_translate_web_frame_manager.mm b/components/translate/ios/browser/js_translate_web_frame_manager.mm new file mode 100644 index 0000000..ebe44d4 --- /dev/null +++ b/components/translate/ios/browser/js_translate_web_frame_manager.mm
@@ -0,0 +1,101 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "components/translate/ios/browser/js_translate_web_frame_manager.h" + +#import <Foundation/Foundation.h> + +#include "base/check.h" +#import "base/logging.h" +#include "base/mac/bundle_locations.h" +#include "base/strings/stringprintf.h" +#import "base/strings/sys_string_conversions.h" +#import "base/strings/utf_string_conversions.h" +#import "ios/web/public/js_messaging/web_frame.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +// Returns an autoreleased string containing the JavaScript loaded from a +// bundled resource file with the given name (excluding extension). +NSString* GetPageScript(NSString* script_file_name) { + DCHECK(script_file_name); + NSString* path = + [base::mac::FrameworkBundle() pathForResource:script_file_name + ofType:@"js"]; + DCHECK(path) << "Script file not found: " + << base::SysNSStringToUTF8(script_file_name) << ".js"; + NSError* error = nil; + NSString* content = [NSString stringWithContentsOfFile:path + encoding:NSUTF8StringEncoding + error:&error]; + DCHECK(!error) << "Error fetching script: " + << base::SysNSStringToUTF8(error.description); + DCHECK(content); + return content; +} + +} // namespace + +JSTranslateWebFrameManager::JSTranslateWebFrameManager(web::WebFrame* web_frame) + : web_frame_(web_frame) { + DCHECK(web_frame); +} + +JSTranslateWebFrameManager::~JSTranslateWebFrameManager() {} + +void JSTranslateWebFrameManager::InjectTranslateScript( + const std::string& translate_script) { + // Prepend translate_ios.js + NSString* translate_ios = GetPageScript(@"translate_ios"); + NSString* script = [translate_ios + stringByAppendingString:base::SysUTF8ToNSString(translate_script)]; + + // Reset translate state if previously injected. + if (injected_) { + NSString* resetScript = @"try {" + " cr.googleTranslate.revert();" + "} catch (e) {" + "}"; + script = [resetScript stringByAppendingString:script]; + } + + injected_ = true; + web_frame_->ExecuteJavaScript(base::SysNSStringToUTF16(script)); +} + +void JSTranslateWebFrameManager::StartTranslation(const std::string& source, + const std::string& target) { + std::string script = + base::StringPrintf("cr.googleTranslate.translate('%s','%s')", + source.c_str(), target.c_str()); + web_frame_->ExecuteJavaScript(base::UTF8ToUTF16(script)); +} + +void JSTranslateWebFrameManager::RevertTranslation() { + if (!injected_) + return; + + web_frame_->ExecuteJavaScript(u"cr.googleTranslate.revert()"); +} + +void JSTranslateWebFrameManager::HandleTranslateResponse( + const std::string& url, + int request_id, + int response_code, + const std::string status_text, + const std::string& response_url, + const std::string& response_text) { + DCHECK(injected_); + + // Return the response details to function defined in translate_ios.js. + std::string script = base::StringPrintf( + "__gCrWeb.translate.handleResponse('%s', %d, %d, '%s', '%s', '%s')", + url.c_str(), request_id, response_code, status_text.c_str(), + response_url.c_str(), response_text.c_str()); + web_frame_->ExecuteJavaScript(base::UTF8ToUTF16(script)); +}
diff --git a/components/translate/ios/browser/js_translate_web_frame_manager_factory.h b/components/translate/ios/browser/js_translate_web_frame_manager_factory.h new file mode 100644 index 0000000..0f0351e9 --- /dev/null +++ b/components/translate/ios/browser/js_translate_web_frame_manager_factory.h
@@ -0,0 +1,26 @@ +// Copyright 2022 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_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_WEB_FRAME_MANAGER_FACTORY_H_ +#define COMPONENTS_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_WEB_FRAME_MANAGER_FACTORY_H_ + +class JSTranslateWebFrameManager; + +namespace web { +class WebFrame; +} // namespace web + +class JSTranslateWebFrameManagerFactory { + public: + // static + static JSTranslateWebFrameManagerFactory* GetInstance(); + + virtual JSTranslateWebFrameManager* FromWebFrame(web::WebFrame* web_frame); + virtual void CreateForWebFrame(web::WebFrame* web_frame); + + protected: + ~JSTranslateWebFrameManagerFactory(); +}; + +#endif // COMPONENTS_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_WEB_FRAME_MANAGER_FACTORY_H_
diff --git a/components/translate/ios/browser/js_translate_web_frame_manager_factory.mm b/components/translate/ios/browser/js_translate_web_frame_manager_factory.mm new file mode 100644 index 0000000..736986a --- /dev/null +++ b/components/translate/ios/browser/js_translate_web_frame_manager_factory.mm
@@ -0,0 +1,31 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "components/translate/ios/browser/js_translate_web_frame_manager.h" + +#import "base/no_destructor.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager_factory.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// static +JSTranslateWebFrameManagerFactory* +JSTranslateWebFrameManagerFactory::GetInstance() { + static base::NoDestructor<JSTranslateWebFrameManagerFactory> instance; + return instance.get(); +} + +JSTranslateWebFrameManager* JSTranslateWebFrameManagerFactory::FromWebFrame( + web::WebFrame* web_frame) { + return JSTranslateWebFrameManager::FromWebFrame(web_frame); +} + +void JSTranslateWebFrameManagerFactory::CreateForWebFrame( + web::WebFrame* web_frame) { + JSTranslateWebFrameManager::CreateForWebFrame(web_frame); +} + +JSTranslateWebFrameManagerFactory::~JSTranslateWebFrameManagerFactory() {}
diff --git a/components/translate/ios/browser/js_translate_web_frame_manager_unittest.mm b/components/translate/ios/browser/js_translate_web_frame_manager_unittest.mm new file mode 100644 index 0000000..9760a5b --- /dev/null +++ b/components/translate/ios/browser/js_translate_web_frame_manager_unittest.mm
@@ -0,0 +1,137 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "components/translate/ios/browser/js_translate_web_frame_manager.h" + +#include "components/grit/components_resources.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager_factory.h" +#import "ios/web/public/js_messaging/web_frame.h" +#import "ios/web/public/js_messaging/web_frame_util.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#import "testing/gtest_mac.h" +#include "ui/base/resource/resource_bundle.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace translate { +namespace { + +typedef web::WebTestWithWebState JsTranslateWebFrameManagerTest; + +// Checks that cr.googleTranslate.libReady is available after the code has +// been injected in the page. +TEST_F(JsTranslateWebFrameManagerTest, Inject) { + LoadHtml(@"<html></html>"); + + id result = ExecuteJavaScript(@"typeof cr == 'undefined'"); + ASSERT_NSEQ(@YES, result); + + web::WebFrame* frame = web::GetMainFrame(web_state()); + JSTranslateWebFrameManager* manager = + JSTranslateWebFrameManagerFactory::GetInstance()->FromWebFrame(frame); + ASSERT_FALSE(manager); + + JSTranslateWebFrameManagerFactory::GetInstance()->CreateForWebFrame(frame); + manager = + JSTranslateWebFrameManagerFactory::GetInstance()->FromWebFrame(frame); + ASSERT_TRUE(manager); + + std::string script = + ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_TRANSLATE_JS); + manager->InjectTranslateScript(script + "('DummyKey');"); + + result = ExecuteJavaScript(@"typeof cr.googleTranslate != 'undefined'"); + EXPECT_NSEQ(@YES, result); + + result = ExecuteJavaScript(@"cr.googleTranslate.libReady"); + EXPECT_NSEQ(@NO, result); +} + +// Tests that injecting the translate script twice still leaves the translate +// lib ready. +TEST_F(JsTranslateWebFrameManagerTest, Reinject) { + LoadHtml(@"<html></html>"); + web::WebFrame* frame = web::GetMainFrame(web_state()); + JSTranslateWebFrameManagerFactory::GetInstance()->CreateForWebFrame(frame); + JSTranslateWebFrameManager* manager = + JSTranslateWebFrameManagerFactory::GetInstance()->FromWebFrame(frame); + ASSERT_TRUE(manager); + + std::string script = + ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_TRANSLATE_JS); + + manager->InjectTranslateScript(script + "('DummyKey');"); + manager->InjectTranslateScript(script + "('DummyKey');"); + + id result = ExecuteJavaScript(@"cr.googleTranslate.libReady"); + EXPECT_NSEQ(@NO, result); +} + +// Tests that starting translation calls the appropriate API. +TEST_F(JsTranslateWebFrameManagerTest, Translate) { + LoadHtml(@"<html></html>"); + web::WebFrame* frame = web::GetMainFrame(web_state()); + JSTranslateWebFrameManagerFactory::GetInstance()->CreateForWebFrame(frame); + JSTranslateWebFrameManager* manager = + JSTranslateWebFrameManagerFactory::GetInstance()->FromWebFrame(frame); + ASSERT_TRUE(manager); + + std::string script = + ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_TRANSLATE_JS); + + manager->InjectTranslateScript(script + "('DummyKey');"); + + ExecuteJavaScript(@"translationApiCalled = false;" + @"var originalTranslate = cr.googleTranslate.translate;" + @" cr.googleTranslate.translate = function() {" + @" translationApiCalled = true;" + @" return originalTranslate.apply(this, arguments);" + @"};"); + + id result = ExecuteJavaScript(@"translationApiCalled"); + EXPECT_NSEQ(@NO, result); + + manager->StartTranslation("en", "es"); + + result = ExecuteJavaScript(@"translationApiCalled"); + EXPECT_NSEQ(@YES, result); +} + +// Tests that reverting translation calls the appropriate API. +TEST_F(JsTranslateWebFrameManagerTest, Revert) { + LoadHtml(@"<html></html>"); + web::WebFrame* frame = web::GetMainFrame(web_state()); + JSTranslateWebFrameManagerFactory::GetInstance()->CreateForWebFrame(frame); + JSTranslateWebFrameManager* manager = + JSTranslateWebFrameManagerFactory::GetInstance()->FromWebFrame(frame); + ASSERT_TRUE(manager); + + std::string script = + ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_TRANSLATE_JS); + manager->InjectTranslateScript(script + "('DummyKey');"); + + ExecuteJavaScript(@"revertApiCalled = false;" + @"var originalRevert = cr.googleTranslate.revert;" + @" cr.googleTranslate.revert = function() {" + @" revertApiCalled = true;" + @" return originalRevert.apply(this, arguments);" + @"};"); + + id result = ExecuteJavaScript(@"revertApiCalled"); + EXPECT_NSEQ(@NO, result); + + manager->RevertTranslation(); + + result = ExecuteJavaScript(@"revertApiCalled"); + EXPECT_NSEQ(@YES, result); +} + +} // namespace +} // namespace translate
diff --git a/components/translate/ios/browser/resources/translate_ios.js b/components/translate/ios/browser/resources/translate_ios.js index 8b075c8a..d83f6c2 100644 --- a/components/translate/ios/browser/resources/translate_ios.js +++ b/components/translate/ios/browser/resources/translate_ios.js
@@ -6,44 +6,34 @@ * @fileoverview Translate script for iOS that is needed in addition to the * cross platform script translate.js. * - * TODO(crbug.com/659442): Enable checkTypes, checkVars errors for this file. - * @suppress {checkTypes, checkVars} */ -// Requires functions from base.js - -/** - * Namespace for this module. - */ -__gCrWeb.translate = {}; - -// Store message namespace object in a global __gCrWeb object referenced by a -// string, so it does not get renamed by closure compiler during the -// minification. -__gCrWeb['translate'] = __gCrWeb.translate; +import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js'; +import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js'; /** * Defines function to install callbacks on cr.googleTranslate. * See translate_script.cc for usage. */ -__gCrWeb.translate['installCallbacks'] = function() { +function installCallbacks() { /** * Sets a callback to inform host of the ready state of the translate element. */ cr.googleTranslate.readyCallback = function() { - __gCrWeb.message.invokeOnHost({ - 'command': 'translate.ready', - 'errorCode': cr.googleTranslate.errorCode, - 'loadTime': cr.googleTranslate.loadTime, - 'readyTime': cr.googleTranslate.readyTime}); + sendWebKitMessage('TranslateMessage', { + 'command': 'ready', + 'errorCode': cr.googleTranslate.errorCode, + 'loadTime': cr.googleTranslate.loadTime, + 'readyTime': cr.googleTranslate.readyTime, + }); }; /** * Sets a callback to inform host of the result of translation. */ cr.googleTranslate.resultCallback = function() { - __gCrWeb.message.invokeOnHost({ - 'command': 'translate.status', + sendWebKitMessage('TranslateMessage', { + 'command': 'status', 'errorCode': cr.googleTranslate.errorCode, 'pageSourceLanguage': cr.googleTranslate.sourceLang, 'translationTime': cr.googleTranslate.translationTime, @@ -54,11 +44,10 @@ * Sets a callback to inform host to download javascript. */ cr.googleTranslate.loadJavascriptCallback = function(url) { - __gCrWeb.message.invokeOnHost({ - 'command': 'translate.loadjavascript', - 'url': url}); + sendWebKitMessage( + 'TranslateMessage', {'command': 'loadjavascript', 'url': url}); }; -}; +} /** * Redefine XMLHttpRequest's open to capture request configurations. @@ -78,12 +67,6 @@ } /** - * Translate XMLHttpRequests still outstanding. - * @type {Array<XMLHttpRequest>} - */ -__gCrWeb.translate['xhrs'] = []; - -/** * Redefine XMLHttpRequest's send to call into the browser if it matches the * predefined translate security origin. * Only redefines once because this script may be injected multiple times. @@ -95,13 +78,14 @@ // the browser. Else, pass it through to the original implementation. // |securityOrigin| is predefined by translate_script.cc. if (this.savedUrl.startsWith(securityOrigin)) { - const length = __gCrWeb.translate['xhrs'].push(this); - __gCrWeb.message.invokeOnHost({ - 'command': 'translate.sendrequest', - 'method': this.savedMethod, - 'url': this.savedUrl, - 'body': body, - 'requestID': length - 1}); + const length = gCrWeb.translate.xhrs.push(this); + sendWebKitMessage('TranslateMessage', { + 'command': 'sendrequest', + 'method': this.savedMethod, + 'url': this.savedUrl, + 'body': body, + 'requestID': length - 1, + }); } else { this.realSend(body); } @@ -118,10 +102,10 @@ * @param {string} responseURL The url which the response was returned from. * @param {string} responseText The text received from the server. */ -__gCrWeb.translate['handleResponse'] = function( +function handleResponse( url, requestID, status, statusText, responseURL, responseText) { - // Retrive xhr object that's waiting for the response. - xhr = __gCrWeb.translate['xhrs'][requestID]; + // Retrieve xhr object that's waiting for the response. + xhr = gCrWeb.translate.xhrs[requestID]; // Configure xhr as it would have been if it was sent. Object.defineProperties(xhr, { @@ -136,5 +120,19 @@ xhr.onreadystatechange(); // Clean it up - delete __gCrWeb.translate['xhrs'][requestID]; + delete gCrWeb.translate.xhrs[requestID]; +} + +// Mark: Public API + +/** + * Translate XMLHttpRequests still outstanding. + * @type {Array<XMLHttpRequest>} + */ +const xhrs = []; + +gCrWeb.translate = { + installCallbacks, + handleResponse, + xhrs, };
diff --git a/components/translate/ios/browser/translate_controller.h b/components/translate/ios/browser/translate_controller.h index d99eab4..7793e40 100644 --- a/components/translate/ios/browser/translate_controller.h +++ b/components/translate/ios/browser/translate_controller.h
@@ -12,13 +12,14 @@ #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" +#include "base/values.h" #include "components/translate/core/common/translate_errors.h" #import "ios/web/public/web_state.h" #include "ios/web/public/web_state_observer.h" +#import "ios/web/public/web_state_user_data.h" #include "services/network/public/cpp/simple_url_loader.h" -@class JsTranslateManager; -class GURL; +class JSTranslateWebFrameManagerFactory; namespace web { class NavigationContext; @@ -28,7 +29,8 @@ // TranslateController controls the translation of the page, by injecting the // translate scripts and monitoring the status. -class TranslateController : public web::WebStateObserver { +class TranslateController : public web::WebStateObserver, + public web::WebStateUserData<TranslateController> { public: // Observer class to monitor the progress of the translation. class Observer { @@ -46,8 +48,6 @@ double translation_time) = 0; }; - TranslateController(web::WebState* web_state, JsTranslateManager* manager); - TranslateController(const TranslateController&) = delete; TranslateController& operator=(const TranslateController&) = delete; @@ -67,11 +67,20 @@ void StartTranslation(const std::string& source_language, const std::string& target_language); - // Changes the JsTranslateManager used by this TranslateController. - // Only used for testing. - void SetJsTranslateManagerForTesting(JsTranslateManager* manager); + // Called when a JavaScript command is received. + void OnJavascriptCommandReceived(const base::Value::Dict& payload); + + // Changes the JSTranslateWebFrameManagerFactory used by this + // TranslateController. Only used for testing. + void SetJsTranslateWebFrameManagerFactoryForTesting( + JSTranslateWebFrameManagerFactory* manager); private: + TranslateController(web::WebState* web_state, + JSTranslateWebFrameManagerFactory* js_manager_factory); + friend class web::WebStateUserData<TranslateController>; + WEB_STATE_USER_DATA_KEY_DECL(); + FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest, OnJavascriptCommandReceived); FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest, @@ -90,17 +99,12 @@ FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest, OnTranslateSendRequestWithBadMethod); - // Called when a JavaScript command is received. - bool OnJavascriptCommandReceived(const base::Value& command, - const GURL& url, - bool interacting, - web::WebFrame* sender_frame); // Methods to handle specific JavaScript commands. - // Return false if the command is invalid. - bool OnTranslateReady(const base::Value& command); - bool OnTranslateComplete(const base::Value& command); - bool OnTranslateLoadJavaScript(const base::Value& command); - bool OnTranslateSendRequest(const base::Value& command); + // The command is ignored if `payload` format is unexpected. + void OnTranslateReady(const base::Value::Dict& payload); + void OnTranslateComplete(const base::Value::Dict& payload); + void OnTranslateLoadJavaScript(const base::Value::Dict& payload); + void OnTranslateSendRequest(const base::Value::Dict& payload); // The callback when the script is fetched or a server error occurred. void OnScriptFetchComplete(std::unique_ptr<std::string> response_body); @@ -112,6 +116,10 @@ std::unique_ptr<std::string> response_body); // web::WebStateObserver implementation: + void WebFrameDidBecomeAvailable(web::WebState* web_state, + web::WebFrame* web_frame) override; + void WebFrameWillBecomeUnavailable(web::WebState* web_state, + web::WebFrame* web_frame) override; void WebStateDestroyed(web::WebState* web_state) override; void DidStartNavigation(web::WebState* web_state, web::NavigationContext* navigation_context) override; @@ -120,16 +128,16 @@ // WebStateDestroyed has been called. web::WebState* web_state_ = nullptr; + // The current main web frame of `web_state_`, if one exists. + web::WebFrame* main_web_frame_ = nullptr; + // Used to fetch translate requests. There may be multiple requests in flight. std::set<std::unique_ptr<network::SimpleURLLoader>> request_fetchers_; // Used to fetch additional scripts needed for translate. std::unique_ptr<network::SimpleURLLoader> script_fetcher_; - // Subscription for JS message. - base::CallbackListSubscription subscription_; - Observer* observer_; - __strong JsTranslateManager* js_manager_; + JSTranslateWebFrameManagerFactory* js_manager_factory_; base::WeakPtrFactory<TranslateController> weak_method_factory_; };
diff --git a/components/translate/ios/browser/translate_controller.mm b/components/translate/ios/browser/translate_controller.mm index 005ef2e9d..04a4e3e0 100644 --- a/components/translate/ios/browser/translate_controller.mm +++ b/components/translate/ios/browser/translate_controller.mm
@@ -15,7 +15,8 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "components/translate/core/common/translate_util.h" -#import "components/translate/ios/browser/js_translate_manager.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager_factory.h" #include "ios/web/public/browser_state.h" #include "ios/web/public/js_messaging/web_frame.h" #include "ios/web/public/navigation/navigation_context.h" @@ -35,16 +36,13 @@ namespace { -// Prefix for the translate javascript commands. Must be kept in sync with -// translate_ios.js. -const char kCommandPrefix[] = "translate"; - // Extracts a TranslateErrors value from `value` for the given `key`. Returns // absl::nullopt if the value is missing or not convertible to TranslateErrors. -absl::optional<TranslateErrors> FindTranslateErrorsKey(const base::Value& value, - base::StringPiece key) { +absl::optional<TranslateErrors> FindTranslateErrorsKey( + const base::Value::Dict& value, + base::StringPiece key) { // Does `value` contains a double value for `key`? - const absl::optional<double> found_value = value.FindDoubleKey(key); + const absl::optional<double> found_value = value.FindDouble(key); if (!found_value.has_value()) return absl::nullopt; @@ -70,20 +68,17 @@ } // anonymous namespace -TranslateController::TranslateController(web::WebState* web_state, - JsTranslateManager* manager) +WEB_STATE_USER_DATA_KEY_IMPL(TranslateController) + +TranslateController::TranslateController( + web::WebState* web_state, + JSTranslateWebFrameManagerFactory* js_manager_factory) : web_state_(web_state), observer_(nullptr), - js_manager_(manager), + js_manager_factory_(js_manager_factory), weak_method_factory_(this) { - DCHECK(js_manager_); DCHECK(web_state_); web_state_->AddObserver(this); - subscription_ = web_state_->AddScriptCommandCallback( - base::BindRepeating( - base::IgnoreResult(&TranslateController::OnJavascriptCommandReceived), - base::Unretained(this)), - kCommandPrefix); } TranslateController::~TranslateController() { @@ -95,84 +90,90 @@ void TranslateController::InjectTranslateScript( const std::string& translate_script) { - [js_manager_ injectWithTranslateScript:translate_script]; + if (!main_web_frame_) { + return; + } + + js_manager_factory_->FromWebFrame(main_web_frame_) + ->InjectTranslateScript(translate_script); } void TranslateController::RevertTranslation() { - [js_manager_ revertTranslation]; + if (!main_web_frame_) { + return; + } + + js_manager_factory_->FromWebFrame(main_web_frame_)->RevertTranslation(); } void TranslateController::StartTranslation(const std::string& source_language, const std::string& target_language) { - [js_manager_ startTranslationFrom:source_language to:target_language]; -} - -void TranslateController::SetJsTranslateManagerForTesting( - JsTranslateManager* manager) { - js_manager_ = manager; -} - -bool TranslateController::OnJavascriptCommandReceived( - const base::Value& command, - const GURL& page_url, - bool user_is_interacting, - web::WebFrame* sender_frame) { - if (!sender_frame->IsMainFrame()) { - // Translate is only supported on main frame. - return false; - } - const std::string* command_string = command.FindStringKey("command"); - if (!command_string) { - return false; + if (!main_web_frame_) { + return; } - if (*command_string == "translate.ready") - return OnTranslateReady(command); - if (*command_string == "translate.status") - return OnTranslateComplete(command); - if (*command_string == "translate.loadjavascript") - return OnTranslateLoadJavaScript(command); - if (*command_string == "translate.sendrequest") - return OnTranslateSendRequest(command); - - return false; + js_manager_factory_->FromWebFrame(main_web_frame_) + ->StartTranslation(source_language, target_language); } -bool TranslateController::OnTranslateReady(const base::Value& command) { +void TranslateController::SetJsTranslateWebFrameManagerFactoryForTesting( + JSTranslateWebFrameManagerFactory* manager) { + js_manager_factory_ = manager; +} + +void TranslateController::OnJavascriptCommandReceived( + const base::Value::Dict& payload) { + const std::string* command = payload.FindString("command"); + if (!command) { + return; + } + + if (*command == "ready") { + OnTranslateReady(payload); + } else if (*command == "status") { + OnTranslateComplete(payload); + } else if (*command == "loadjavascript") { + OnTranslateLoadJavaScript(payload); + } else if (*command == "sendrequest") { + OnTranslateSendRequest(payload); + } +} + +void TranslateController::OnTranslateReady(const base::Value::Dict& payload) { absl::optional<TranslateErrors> error_type = - FindTranslateErrorsKey(command, "errorCode"); + FindTranslateErrorsKey(payload, "errorCode"); if (!error_type.has_value()) - return false; + return; absl::optional<double> load_time; absl::optional<double> ready_time; if (*error_type == TranslateErrors::NONE) { - load_time = command.FindDoubleKey("loadTime"); - ready_time = command.FindDoubleKey("readyTime"); + load_time = payload.FindDouble("loadTime"); + ready_time = payload.FindDouble("readyTime"); if (!load_time.has_value() || !ready_time.has_value()) { - return false; + return; } } if (observer_) { observer_->OnTranslateScriptReady(*error_type, load_time.value_or(0.), ready_time.value_or(0.)); } - return true; } -bool TranslateController::OnTranslateComplete(const base::Value& command) { +void TranslateController::OnTranslateComplete( + const base::Value::Dict& payload) { absl::optional<TranslateErrors> error_type = - FindTranslateErrorsKey(command, "errorCode"); + FindTranslateErrorsKey(payload, "errorCode"); if (!error_type.has_value()) - return false; + return; const std::string* source_language = nullptr; absl::optional<double> translation_time; if (*error_type == TranslateErrors::NONE) { - source_language = command.FindStringKey("pageSourceLanguage"); - translation_time = command.FindDoubleKey("translationTime"); + source_language = payload.FindString("pageSourceLanguage"); + translation_time = payload.FindDouble("translationTime"); if (!source_language || !translation_time.has_value()) { - return false; + return; } } @@ -181,19 +182,18 @@ *error_type, source_language ? *source_language : std::string(), translation_time.value_or(0.)); } - return true; } -bool TranslateController::OnTranslateLoadJavaScript( - const base::Value& command) { - const std::string* url = command.FindStringKey("url"); +void TranslateController::OnTranslateLoadJavaScript( + const base::Value::Dict& payload) { + const std::string* url = payload.FindString("url"); if (!url) { - return false; + return; } GURL security_origin = translate::GetTranslateSecurityOrigin(); if (url->find(security_origin.spec()) || script_fetcher_) { - return false; + return; } auto resource_request = std::make_unique<network::ResourceRequest>(); @@ -205,31 +205,25 @@ web_state_->GetBrowserState()->GetURLLoaderFactory(), base::BindOnce(&TranslateController::OnScriptFetchComplete, base::Unretained(this))); - - return true; } -bool TranslateController::OnTranslateSendRequest(const base::Value& command) { - const std::string* method = command.FindStringKey("method"); - if (!method) { - return false; +void TranslateController::OnTranslateSendRequest( + const base::Value::Dict& payload) { + const std::string* method = payload.FindString("method"); + const std::string* url = payload.FindString("url"); + const std::string* body = payload.FindString("body"); + + if (!method || !url || !body) { + return; } - const std::string* url = command.FindStringKey("url"); - if (!url) { - return false; - } - const std::string* body = command.FindStringKey("body"); - if (!body) { - return false; - } - absl::optional<double> request_id = command.FindDoubleKey("requestID"); + absl::optional<double> request_id = payload.FindDouble("requestID"); if (!request_id.has_value()) { - return false; + return; } GURL security_origin = translate::GetTranslateSecurityOrigin(); if (url->find(security_origin.spec())) { - return false; + return; } auto request = std::make_unique<network::ResourceRequest>(); @@ -246,13 +240,12 @@ base::BindOnce(&TranslateController::OnRequestFetchComplete, base::Unretained(this), pair.first, *url, static_cast<int>(*request_id))); - return true; } void TranslateController::OnScriptFetchComplete( std::unique_ptr<std::string> response_body) { - if (response_body) { - web_state_->ExecuteJavaScript(base::UTF8ToUTF16(*response_body)); + if (main_web_frame_ && response_body) { + main_web_frame_->ExecuteJavaScript(base::UTF8ToUTF16(*response_body)); } script_fetcher_.reset(); } @@ -262,6 +255,10 @@ std::string url, int request_id, std::unique_ptr<std::string> response_body) { + if (!main_web_frame_) { + return; + } + const std::unique_ptr<network::SimpleURLLoader>& url_loader = *it; int response_code = 0; @@ -287,22 +284,37 @@ &escaped_response_text); std::string final_url = url_loader->GetFinalURL().spec(); - [js_manager_ handleTranslateResponseWithURL:url - requestID:request_id - responseCode:response_code - statusText:status_text - responseURL:final_url - responseText:escaped_response_text]; - + js_manager_factory_->FromWebFrame(main_web_frame_) + ->HandleTranslateResponse(url, request_id, response_code, status_text, + final_url, escaped_response_text); request_fetchers_.erase(it); } // web::WebStateObserver implementation. +void TranslateController::WebFrameDidBecomeAvailable(web::WebState* web_state, + web::WebFrame* web_frame) { + DCHECK_EQ(web_state_, web_state); + if (web_frame->IsMainFrame()) { + js_manager_factory_->CreateForWebFrame(web_frame); + main_web_frame_ = web_frame; + } +} + +void TranslateController::WebFrameWillBecomeUnavailable( + web::WebState* web_state, + web::WebFrame* web_frame) { + DCHECK_EQ(web_state_, web_state); + if (web_frame == main_web_frame_) { + main_web_frame_ = nullptr; + } +} + void TranslateController::WebStateDestroyed(web::WebState* web_state) { DCHECK_EQ(web_state_, web_state); web_state_->RemoveObserver(this); web_state_ = nullptr; + main_web_frame_ = nullptr; request_fetchers_.clear(); script_fetcher_.reset();
diff --git a/components/translate/ios/browser/translate_controller_unittest.mm b/components/translate/ios/browser/translate_controller_unittest.mm index a2a29ddd..7ffbfdb 100644 --- a/components/translate/ios/browser/translate_controller_unittest.mm +++ b/components/translate/ios/browser/translate_controller_unittest.mm
@@ -7,7 +7,8 @@ #include <memory> #include "base/values.h" -#import "components/translate/ios/browser/js_translate_manager.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager_factory.h" #include "ios/web/public/test/fakes/fake_browser_state.h" #include "ios/web/public/test/fakes/fake_web_frame.h" #import "ios/web/public/test/fakes/fake_web_state.h" @@ -20,7 +21,7 @@ #error "This file requires ARC support." #endif -#pragma mark - FakeJSTranslateManager +#pragma mark - FakeJSTranslateWebFrameManager namespace { @@ -46,50 +47,75 @@ std::string response_text; }; +class FakeJSTranslateWebFrameManager : public JSTranslateWebFrameManager { + public: + FakeJSTranslateWebFrameManager(web::WebFrame* web_frame) + : JSTranslateWebFrameManager(web_frame) {} + ~FakeJSTranslateWebFrameManager() override = default; + + void HandleTranslateResponse(const std::string& url, + int request_id, + int response_code, + const std::string status_text, + const std::string& response_url, + const std::string& response_text) override { + last_handle_response_params_ = + std::make_unique<HandleTranslateResponseParams>( + url, request_id, response_code, status_text, response_url, + response_text); + } + + HandleTranslateResponseParams* GetLastHandleResponseParams() { + return last_handle_response_params_.get(); + } + + private: + std::unique_ptr<HandleTranslateResponseParams> last_handle_response_params_; +}; + +class FakeJSTranslateWebFrameManagerFactory + : public JSTranslateWebFrameManagerFactory { + public: + FakeJSTranslateWebFrameManagerFactory() {} + ~FakeJSTranslateWebFrameManagerFactory() {} + + static FakeJSTranslateWebFrameManagerFactory* GetInstance() { + static base::NoDestructor<FakeJSTranslateWebFrameManagerFactory> instance; + return instance.get(); + } + + FakeJSTranslateWebFrameManager* FromWebFrame( + web::WebFrame* web_frame) override { + if (managers_.find(web_frame->GetFrameId()) == managers_.end()) { + managers_[web_frame->GetFrameId()] = + std::make_unique<FakeJSTranslateWebFrameManager>(web_frame); + } + return managers_[web_frame->GetFrameId()].get(); + } + + void CreateForWebFrame(web::WebFrame* web_frame) override { + // no-op, managers are created lazily in FromWebState + } + + private: + std::map<std::string, std::unique_ptr<FakeJSTranslateWebFrameManager>> + managers_; +}; + } // namespace -// Fake translate manager to store parameters passed to -// |handleTranslateResponseWithURL:...| -@interface FakeJSTranslateManager : JsTranslateManager - -@property(readonly) HandleTranslateResponseParams* lastHandleResponseParams; - -@end - -@implementation FakeJSTranslateManager { - std::unique_ptr<HandleTranslateResponseParams> _lastHandleResponseParams; -} - -- (HandleTranslateResponseParams*)lastHandleResponseParams { - return _lastHandleResponseParams.get(); -} - -- (void)handleTranslateResponseWithURL:(const std::string&)URL - requestID:(int)requestID - responseCode:(int)responseCode - statusText:(const std::string&)statusText - responseURL:(const std::string&)responseURL - responseText:(const std::string&)responseText { - _lastHandleResponseParams = std::make_unique<HandleTranslateResponseParams>( - URL, requestID, responseCode, statusText, responseURL, responseText); -} - -@end - namespace translate { class TranslateControllerTest : public PlatformTest, public TranslateController::Observer { protected: TranslateControllerTest() - : fake_web_state_(std::make_unique<web::FakeWebState>()), + : task_environment_(web::WebTaskEnvironment::Options::IO_MAINLOOP), + fake_web_state_(std::make_unique<web::FakeWebState>()), fake_browser_state_(std::make_unique<web::FakeBrowserState>()), fake_main_frame_(web::FakeWebFrame::Create(/*frame_id=*/"", /*is_main_frame=*/true, GURL())), - fake_iframe_(web::FakeWebFrame::Create(/*frame_id=*/"", - /*is_main_frame=*/false, - GURL())), error_type_(TranslateErrors::NONE), ready_time_(0), load_time_(0), @@ -97,11 +123,10 @@ on_script_ready_called_(false), on_translate_complete_called_(false) { fake_web_state_->SetBrowserState(fake_browser_state_.get()); - fake_js_translate_manager_ = - [[FakeJSTranslateManager alloc] initWithWebState:fake_web_state_.get()]; - translate_controller_ = std::make_unique<TranslateController>( - fake_web_state_.get(), fake_js_translate_manager_); - translate_controller_->set_observer(this); + TranslateController::CreateForWebState(fake_web_state_.get(), + &fake_translate_factory_); + TranslateController::FromWebState(fake_web_state_.get()) + ->set_observer(this); } // TranslateController::Observer methods. @@ -123,13 +148,15 @@ translation_time_ = translation_time; } + TranslateController* translate_controller() { + return TranslateController::FromWebState(fake_web_state_.get()); + } + web::WebTaskEnvironment task_environment_; std::unique_ptr<web::FakeWebState> fake_web_state_; std::unique_ptr<web::FakeBrowserState> fake_browser_state_; std::unique_ptr<web::FakeWebFrame> fake_main_frame_; - std::unique_ptr<web::FakeWebFrame> fake_iframe_; - FakeJSTranslateManager* fake_js_translate_manager_; - std::unique_ptr<TranslateController> translate_controller_; + FakeJSTranslateWebFrameManagerFactory fake_translate_factory_; TranslateErrors error_type_; double ready_time_; double load_time_; @@ -139,59 +166,36 @@ bool on_translate_complete_called_; }; -// Tests that OnJavascriptCommandReceived() returns false to malformed commands. -TEST_F(TranslateControllerTest, OnJavascriptCommandReceived) { - base::Value::Dict malformed_command; - EXPECT_FALSE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(malformed_command)), GURL("http://google.com"), - /*interacting*/ false, fake_main_frame_.get())); -} - -// Tests that OnJavascriptCommandReceived() returns false to iframe commands. -TEST_F(TranslateControllerTest, OnIFrameJavascriptCommandReceived) { - base::Value::Dict command; - command.Set("command", "translate.ready"); - command.Set("errorCode", - static_cast<double>(TranslateErrors::TRANSLATION_TIMEOUT)); - command.Set("loadTime", .0); - command.Set("readyTime", .0); - EXPECT_FALSE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting*/ false, fake_iframe_.get())); -} - // Tests that OnTranslateScriptReady() is called when a timeout message is // received from the JS side. TEST_F(TranslateControllerTest, OnTranslateScriptReadyTimeoutCalled) { base::Value::Dict command; - command.Set("command", "translate.ready"); + command.Set("command", "ready"); command.Set("errorCode", static_cast<double>(TranslateErrors::TRANSLATION_TIMEOUT)); command.Set("loadTime", .0); command.Set("readyTime", .0); - EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting*/ false, fake_main_frame_.get())); + translate_controller()->OnJavascriptCommandReceived( + base::Value::Dict(std::move(command))); EXPECT_TRUE(on_script_ready_called_); EXPECT_FALSE(on_translate_complete_called_); EXPECT_FALSE(error_type_ == TranslateErrors::NONE); } // Tests that OnTranslateScriptReady() is called with the right parameters when -// a |translate.ready| message is received from the JS side. +// a `ready` message is received from the JS side. TEST_F(TranslateControllerTest, OnTranslateScriptReadyCalled) { // Arbitrary values. double some_load_time = 23.1; double some_ready_time = 12.2; base::Value::Dict command; - command.Set("command", "translate.ready"); + command.Set("command", "ready"); command.Set("errorCode", static_cast<double>(TranslateErrors::NONE)); command.Set("loadTime", some_load_time); command.Set("readyTime", some_ready_time); - EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting*/ false, fake_main_frame_.get())); + translate_controller()->OnJavascriptCommandReceived( + base::Value::Dict(std::move(command))); EXPECT_TRUE(on_script_ready_called_); EXPECT_FALSE(on_translate_complete_called_); EXPECT_TRUE(error_type_ == TranslateErrors::NONE); @@ -200,20 +204,19 @@ } // Tests that OnTranslateComplete() is called with the right parameters when a -// |translate.status| message is received from the JS side. +// `status` message is received from the JS side. TEST_F(TranslateControllerTest, TranslationSuccess) { // Arbitrary values. std::string some_source_language("en"); double some_translation_time = 12.9; base::Value::Dict command; - command.Set("command", "translate.status"); + command.Set("command", "status"); command.Set("errorCode", static_cast<double>(TranslateErrors::NONE)); command.Set("pageSourceLanguage", some_source_language); command.Set("translationTime", some_translation_time); - EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting*/ false, fake_main_frame_.get())); + translate_controller()->OnJavascriptCommandReceived( + base::Value::Dict(std::move(command))); EXPECT_FALSE(on_script_ready_called_); EXPECT_TRUE(on_translate_complete_called_); EXPECT_TRUE(error_type_ == TranslateErrors::NONE); @@ -222,64 +225,73 @@ } // Tests that OnTranslateComplete() is called with the right parameters when a -// |translate.status| message is received from the JS side. +// `status` message is received from the JS side. TEST_F(TranslateControllerTest, TranslationFailure) { base::Value::Dict command; - command.Set("command", "translate.status"); + command.Set("command", "status"); command.Set("errorCode", static_cast<double>(TranslateErrors::INITIALIZATION_ERROR)); - EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting*/ false, fake_main_frame_.get())); + translate_controller()->OnJavascriptCommandReceived( + base::Value::Dict(std::move(command))); EXPECT_FALSE(on_script_ready_called_); EXPECT_TRUE(on_translate_complete_called_); EXPECT_FALSE(error_type_ == TranslateErrors::NONE); } -// Tests that OnTranslateLoadJavaScript() is called with the right parameters -// when a |translate.loadjavascript| message is received from the JS side. -TEST_F(TranslateControllerTest, OnTranslateLoadJavascript) { - base::Value::Dict command; - command.Set("command", "translate.loadjavascript"); - command.Set("url", "https://translate.googleapis.com/javascript.js"); - EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting=*/false, fake_main_frame_.get())); -} - // Tests that OnTranslateSendRequest() is called with the right parameters -// when a |translate.sendrequest| message is received from the JS side. +// when a `sendrequest` message is received from the JS side. TEST_F(TranslateControllerTest, OnTranslateSendRequestWithValidCommand) { + fake_web_state_->OnWebFrameDidBecomeAvailable(fake_main_frame_.get()); + base::Value::Dict command; - command.Set("command", "translate.sendrequest"); + command.Set("command", "sendrequest"); command.Set("method", "POST"); command.Set("url", "https://translate.googleapis.com/translate?key=abcd"); command.Set("body", "helloworld"); command.Set("requestID", .0); - EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting=*/false, fake_main_frame_.get())); + translate_controller()->OnJavascriptCommandReceived( + base::Value::Dict(std::move(command))); + task_environment_.RunUntilIdle(); + + HandleTranslateResponseParams* last_params = + fake_translate_factory_.FromWebFrame(fake_main_frame_.get()) + ->GetLastHandleResponseParams(); + ASSERT_TRUE(last_params); + EXPECT_EQ("https://translate.googleapis.com/translate?key=abcd", + last_params->URL); + EXPECT_EQ(0, last_params->request_ID); + EXPECT_EQ(net::HttpStatusCode::HTTP_BAD_REQUEST, last_params->response_code); + EXPECT_EQ("", last_params->status_text); + EXPECT_EQ("https://translate.googleapis.com/translate?key=abcd", + last_params->response_URL); + EXPECT_EQ("", last_params->response_text); } // Tests that OnTranslateSendRequest() rejects a bad url contained in the -// |translate.sendrequest| message received from Javascript. +// `sendrequest` message received from Javascript. TEST_F(TranslateControllerTest, OnTranslateSendRequestWithBadURL) { base::Value::Dict command; - command.Set("command", "translate.sendrequest"); + command.Set("command", "sendrequest"); command.Set("method", "POST"); command.Set("url", "https://badurl.example.com"); command.Set("body", "helloworld"); command.Set("requestID", .0); - EXPECT_FALSE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting=*/false, fake_main_frame_.get())); + translate_controller()->OnJavascriptCommandReceived( + base::Value::Dict(std::move(command))); + task_environment_.RunUntilIdle(); + HandleTranslateResponseParams* last_params = + fake_translate_factory_.FromWebFrame(fake_main_frame_.get()) + ->GetLastHandleResponseParams(); + ASSERT_FALSE(last_params); } // Tests that OnTranslateSendRequest() called with a bad method will eventually // cause the request to fail. TEST_F(TranslateControllerTest, OnTranslateSendRequestWithBadMethod) { + fake_web_state_->OnWebFrameDidBecomeAvailable(fake_main_frame_.get()); + base::Value::Dict command; - command.Set("command", "translate.sendrequest"); + command.Set("command", "sendrequest"); command.Set("method", "POST\r\nHost: other.example.com"); command.Set("url", "https://translate.googleapis.com/translate?key=abcd"); command.Set("body", "helloworld"); @@ -287,13 +299,13 @@ // The command will be accepted, but a bad method should cause the request to // fail shortly thereafter. - EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( - base::Value(std::move(command)), GURL("http://google.com"), - /*interacting=*/false, fake_main_frame_.get())); + translate_controller()->OnJavascriptCommandReceived( + base::Value::Dict(std::move(command))); task_environment_.RunUntilIdle(); HandleTranslateResponseParams* last_params = - fake_js_translate_manager_.lastHandleResponseParams; + fake_translate_factory_.FromWebFrame(fake_main_frame_.get()) + ->GetLastHandleResponseParams(); ASSERT_TRUE(last_params); EXPECT_EQ("https://translate.googleapis.com/translate?key=abcd", last_params->URL);
diff --git a/components/translate/ios/browser/translate_java_script_feature.h b/components/translate/ios/browser/translate_java_script_feature.h new file mode 100644 index 0000000..8e9d4f8 --- /dev/null +++ b/components/translate/ios/browser/translate_java_script_feature.h
@@ -0,0 +1,40 @@ +// Copyright 2022 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_TRANSLATE_IOS_BROWSER_TRANSLATE_JAVA_SCRIPT_FEATURE_H_ +#define COMPONENTS_TRANSLATE_IOS_BROWSER_TRANSLATE_JAVA_SCRIPT_FEATURE_H_ + +#include "base/no_destructor.h" +#include "ios/web/public/js_messaging/java_script_feature.h" + +namespace web { +class WebState; +} // namespace web + +namespace translate { + +// Feature which listens for translate messages from the injected scripts. +class TranslateJavaScriptFeature : public web::JavaScriptFeature { + public: + static TranslateJavaScriptFeature* GetInstance(); + + private: + friend class base::NoDestructor<TranslateJavaScriptFeature>; + + // web::JavaScriptFeature + absl::optional<std::string> GetScriptMessageHandlerName() const override; + void ScriptMessageReceived(web::WebState* web_state, + const web::ScriptMessage& message) override; + + TranslateJavaScriptFeature(); + ~TranslateJavaScriptFeature() override; + + TranslateJavaScriptFeature(const TranslateJavaScriptFeature&) = delete; + TranslateJavaScriptFeature& operator=(const TranslateJavaScriptFeature&) = + delete; +}; + +} // namespace translate + +#endif // COMPONENTS_TRANSLATE_IOS_BROWSER_TRANSLATE_JAVA_SCRIPT_FEATURE_H_
diff --git a/components/translate/ios/browser/translate_java_script_feature.mm b/components/translate/ios/browser/translate_java_script_feature.mm new file mode 100644 index 0000000..0317c92 --- /dev/null +++ b/components/translate/ios/browser/translate_java_script_feature.mm
@@ -0,0 +1,52 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "components/translate/ios/browser/translate_java_script_feature.h" + +#import "components/translate/ios/browser/translate_controller.h" +#import "ios/web/public/js_messaging/script_message.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +constexpr char kScriptMessageName[] = "TranslateMessage"; +} // namespace + +namespace translate { + +// static +TranslateJavaScriptFeature* TranslateJavaScriptFeature::GetInstance() { + static base::NoDestructor<TranslateJavaScriptFeature> instance; + return instance.get(); +} + +TranslateJavaScriptFeature::TranslateJavaScriptFeature() + : web::JavaScriptFeature( + ContentWorld::kPageContentWorld, + {/* The `translate_ios` script is injected on demand */ + /* by JSTranslateWebFrameManager. */}) {} + +TranslateJavaScriptFeature::~TranslateJavaScriptFeature() = default; + +absl::optional<std::string> +TranslateJavaScriptFeature::GetScriptMessageHandlerName() const { + return kScriptMessageName; +} + +void TranslateJavaScriptFeature::ScriptMessageReceived( + web::WebState* web_state, + const web::ScriptMessage& message) { + if (!message.is_main_frame() || !message.body() || + !message.body()->is_dict()) { + return; + } + + TranslateController* translate_controller = + TranslateController::FromWebState(web_state); + translate_controller->OnJavascriptCommandReceived(message.body()->GetDict()); +} + +} // namespace translate
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn index 3b9458c..a0d3cc2b 100644 --- a/components/vector_icons/BUILD.gn +++ b/components/vector_icons/BUILD.gn
@@ -90,7 +90,6 @@ "midi.icon", "midi_off.icon", "not_secure_warning.icon", - "notification_explore.icon", "notification_warning.icon", "notifications.icon", "notifications_off.icon",
diff --git a/components/vector_icons/notification_explore.icon b/components/vector_icons/notification_explore.icon deleted file mode 100644 index 008b747..0000000 --- a/components/vector_icons/notification_explore.icon +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 36, -PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF, -MOVE_TO, 0, 0, -R_H_LINE_TO, 36, -R_V_LINE_TO, 36, -H_LINE_TO, 0, -CLOSE, - -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0x1A, 0x73, 0xE8, -CIRCLE, 18, 18, 16.453, - -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF, -MOVE_TO, 9.05f, 9.05f, -R_CUBIC_TO, -1.59f, 1.59f, -0.13f, 5.7f, 1.99f, 7.82f, -R_LINE_TO, 9.81f, 9.81f, -R_LINE_TO, 5.84f, -5.84f, -R_LINE_TO, -9.81f, -9.81f, -R_CUBIC_TO, -2.12f, -2.12f, -6.23f, -3.58f, -7.82f, -1.99f, -CLOSE, - -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xAE, 0xCB, 0xFA, -MOVE_TO, 12.81f, 26.6f, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, -0.44f, -1.06f, -V_LINE_TO, 18.2f, -R_LINE_TO, 8.49f, 8.49f, -R_LINE_TO, -2.92f, 2.92f, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, -2.12f, 0, -R_LINE_TO, -3.01f, -3.01f, -CLOSE, - -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xAE, 0xCB, 0xFA, -MOVE_TO, 26.6f, 12.81f, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 0, -1.06f, -0.44f, -H_LINE_TO, 18.2f, -R_LINE_TO, 8.49f, 8.49f, -R_LINE_TO, 2.92f, -2.92f, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 0, 0, -2.12f, -R_LINE_TO, -3.01f, -3.01f, -CLOSE, - -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0x1A, 0x73, 0xE8, -CIRCLE, 13.03, 13.03, 1.688, - -NEW_PATH, -PATH_COLOR_ARGB, 0xFF, 0xAE, 0xCB, 0xFA, -MOVE_TO, 18.35f, 20.2f, -R_LINE_TO, 0.01f, 0.01f, -R_LINE_TO, 0.01f, 0.01f, -R_LINE_TO, 4.86f, 4.87f, -R_ARC_TO, 1.31f, 1.31f, 0, 1, 0, 1.87f, -1.85f, -R_LINE_TO, -4.94f, -4.94f, -R_LINE_TO, 0, 0, -R_ARC_TO, 1.31f, 1.31f, 0, 0, 0, -1.85f, 1.85f, -R_LINE_TO, 0, 0, -R_LINE_TO, 0.05f, 0.04f, -CLOSE
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 2cacbd6..a89d358 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -3175,7 +3175,8 @@ return; } - uint32_t usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ; + uint32_t usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | + gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE; if (requirements.generate_mipmap) usage |= gpu::SHARED_IMAGE_USAGE_MIPMAP; auto mailbox = skia_output_surface_->CreateSharedImage( @@ -3297,9 +3298,9 @@ if (it == available_render_pass_overlay_backings_.end()) { // Allocate the image for render pass overlay if there is no existing // available one. - constexpr auto kOverlayUsage = gpu::SHARED_IMAGE_USAGE_SCANOUT | - gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | - gpu::SHARED_IMAGE_USAGE_RASTER; + constexpr auto kOverlayUsage = + gpu::SHARED_IMAGE_USAGE_SCANOUT | gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | + gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE | gpu::SHARED_IMAGE_USAGE_RASTER; auto mailbox = skia_output_surface_->CreateSharedImage( buffer_format, buffer_size, color_space, kOverlayUsage, gpu::kNullSurfaceHandle);
diff --git a/components/viz/service/display_embedder/buffer_queue.cc b/components/viz/service/display_embedder/buffer_queue.cc index 4008ad7..6f2f0c6 100644 --- a/components/viz/service/display_embedder/buffer_queue.cc +++ b/components/viz/service/display_embedder/buffer_queue.cc
@@ -139,7 +139,8 @@ for (size_t i = 0; i < n; ++i) { const gpu::Mailbox mailbox = skia_output_surface_->CreateSharedImage( format, size_, color_space_, - gpu::SHARED_IMAGE_USAGE_SCANOUT | gpu::SHARED_IMAGE_USAGE_DISPLAY_READ, + gpu::SHARED_IMAGE_USAGE_SCANOUT | gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | + gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE, surface_handle_); DCHECK(!mailbox.IsZero());
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc index 6bdcbc3a7..908eb944 100644 --- a/components/viz/service/display_embedder/buffer_queue_unittest.cc +++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -158,7 +158,8 @@ EXPECT_CALL(*mock_skia_output_surface, CreateSharedImage(_, _, _, gpu::SHARED_IMAGE_USAGE_SCANOUT | - gpu::SHARED_IMAGE_USAGE_DISPLAY_READ, + gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | + gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE, _)) .WillOnce(Return(expected_mailbox)); EXPECT_CALL(*mock_skia_output_surface,
diff --git a/components/viz/service/display_embedder/output_presenter_fuchsia.cc b/components/viz/service/display_embedder/output_presenter_fuchsia.cc index fafe5ef9..0ac17ce5 100644 --- a/components/viz/service/display_embedder/output_presenter_fuchsia.cc +++ b/components/viz/service/display_embedder/output_presenter_fuchsia.cc
@@ -222,6 +222,7 @@ // Create PresenterImageFuchsia for each buffer in the collection. constexpr uint32_t image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | + gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE | gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_SCANOUT;
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc index 491881c..ee4616a 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.cc +++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -158,6 +158,7 @@ // static const uint32_t OutputPresenterGL::kDefaultSharedImageUsage = gpu::SHARED_IMAGE_USAGE_SCANOUT | gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | + gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE | gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT; // static
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 881e1c10..7e998a1 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -739,7 +739,8 @@ constexpr uint32_t kUsage = gpu::SHARED_IMAGE_USAGE_GLES2 | gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT | gpu::SHARED_IMAGE_USAGE_RASTER | - gpu::SHARED_IMAGE_USAGE_DISPLAY_READ; + gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | + gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE; gpu::Mailbox mailbox = gpu::Mailbox::GenerateForSharedImage(); SharedImageFormat si_format = SharedImageFormat::SinglePlane(resource_format);
diff --git a/components/webapps/browser/android/app_banner_manager_android.cc b/components/webapps/browser/android/app_banner_manager_android.cc index 15f8d8f..006f37bf 100644 --- a/components/webapps/browser/android/app_banner_manager_android.cc +++ b/components/webapps/browser/android/app_banner_manager_android.cc
@@ -578,8 +578,8 @@ // one is in flight for the current site. return WebappsUtils::IsWebApkInstalled(web_contents()->GetBrowserContext(), manifest().start_url) || - WebappsClient::Get()->IsInstallationInProgress(web_contents(), - manifest_url_); + WebappsClient::Get()->IsInstallationInProgress( + web_contents(), manifest_url_, manifest_id_); } void AppBannerManagerAndroid::ShowAmbientBadge() {
diff --git a/components/webapps/browser/android/shortcut_info.cc b/components/webapps/browser/android/shortcut_info.cc index a5c8980..8c90c5a 100644 --- a/components/webapps/browser/android/shortcut_info.cc +++ b/components/webapps/browser/android/shortcut_info.cc
@@ -103,7 +103,7 @@ scope = manifest.scope; - manifest_id = GetManifestId(manifest); + manifest_id = blink::GetIdFromManifest(manifest); // Set the display based on the manifest value, if any. if (manifest.display != DisplayMode::kUndefined) @@ -221,16 +221,4 @@ source = new_source; } -// static -GURL ShortcutInfo::GetManifestId(const blink::mojom::Manifest& manifest) { - if (manifest.id.has_value()) { - // Generate the formatted id by <start_url_origin>/<manifest_id>. - GURL manifest_id(manifest.start_url.DeprecatedGetOriginAsURL().spec() + - base::UTF16ToUTF8(manifest.id.value())); - DCHECK(manifest_id.is_valid()); - return manifest_id; - } - return manifest.start_url; -} - } // namespace webapps
diff --git a/components/webapps/browser/android/shortcut_info.h b/components/webapps/browser/android/shortcut_info.h index b07c15e..228a661 100644 --- a/components/webapps/browser/android/shortcut_info.h +++ b/components/webapps/browser/android/shortcut_info.h
@@ -136,9 +136,6 @@ // |splash_image_url| and |best_shortcut_icon_urls| if they are not empty std::set<GURL> GetWebApkIcons(); - // Generate the formatted id field from web manifest. - static GURL GetManifestId(const blink::mojom::Manifest& manifest); - GURL manifest_url; GURL url; GURL scope;
diff --git a/components/webapps/browser/banners/app_banner_manager.cc b/components/webapps/browser/banners/app_banner_manager.cc index 0264fe3..1912e31 100644 --- a/components/webapps/browser/banners/app_banner_manager.cc +++ b/components/webapps/browser/banners/app_banner_manager.cc
@@ -358,6 +358,7 @@ manifest_url_ = data.manifest_url; manifest_ = data.manifest.Clone(); + manifest_id_ = blink::GetIdFromManifest(manifest()); PerformInstallableChecks(); }
diff --git a/components/webapps/browser/banners/app_banner_manager.h b/components/webapps/browser/banners/app_banner_manager.h index 05dbbb0..00002ae 100644 --- a/components/webapps/browser/banners/app_banner_manager.h +++ b/components/webapps/browser/banners/app_banner_manager.h
@@ -356,6 +356,9 @@ // The URL of the manifest. GURL manifest_url_; + // The manifest id. + GURL manifest_id_; + // The URL of the primary icon. GURL primary_icon_url_;
diff --git a/components/webapps/browser/webapps_client.h b/components/webapps/browser/webapps_client.h index 5e9100cb..5752abd 100644 --- a/components/webapps/browser/webapps_client.h +++ b/components/webapps/browser/webapps_client.h
@@ -52,7 +52,8 @@ #if BUILDFLAG(IS_ANDROID) virtual bool IsInstallationInProgress(content::WebContents* web_contents, - const GURL& manifest_url) = 0; + const GURL& manifest_url, + const GURL& manifest_id) = 0; virtual bool CanShowAppBanners(content::WebContents* web_contents) = 0;
diff --git a/components/webrtc_logging/logging_unittest.cc b/components/webrtc_logging/logging_unittest.cc index 9522f5ea..0fd0c47b 100644 --- a/components/webrtc_logging/logging_unittest.cc +++ b/components/webrtc_logging/logging_unittest.cc
@@ -9,14 +9,17 @@ // We must include Chromium headers before including the overrides header // since webrtc's logging.h file may conflict with chromium. + #include "base/logging.h" -#include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "build/build_config.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/webrtc_overrides/rtc_base/logging.h" +namespace { + static const int kDefaultVerbosity = 0; static const char* AsString(rtc::LoggingSeverity severity) { @@ -36,11 +39,6 @@ } } -static bool ContainsString(const std::string& original, - const char* string_to_match) { - return original.find(string_to_match) != std::string::npos; -} - class WebRtcTextLogTest : public testing::Test { public: void SetUp() override { @@ -50,15 +48,6 @@ protected: bool Initialize(int verbosity_level) { - if (verbosity_level != kDefaultVerbosity) { - // Update the command line with specified verbosity level for this file. - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - std::ostringstream value_stream; - value_stream << "logging_unittest=" << verbosity_level; - const std::string& value = value_stream.str(); - command_line->AppendSwitchASCII("vmodule", value); - } - // The command line flags are parsed here and the log file name is set. logging::LoggingSettings settings; settings.logging_dest = logging::LOG_TO_FILE; @@ -68,6 +57,7 @@ if (!logging::InitLogging(settings)) { return false; } + logging::SetMinLogLevel(-verbosity_level); #if BUILDFLAG(USE_RUNTIME_VLOG) EXPECT_TRUE(VLOG_IS_ON(verbosity_level)); @@ -99,11 +89,16 @@ base::ReadFileToString(log_file_path_, &contents_of_file); // Make sure string contains the expected values. - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_ERROR))); - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_WARNING))); - EXPECT_FALSE(ContainsString(contents_of_file, AsString(rtc::LS_INFO))); - EXPECT_FALSE(ContainsString(contents_of_file, AsString(rtc::LS_VERBOSE))); - EXPECT_FALSE(ContainsString(contents_of_file, AsString(rtc::LS_SENSITIVE))); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr(AsString(rtc::LS_ERROR))); + EXPECT_THAT(contents_of_file, + ::testing::HasSubstr(AsString(rtc::LS_WARNING))); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr(AsString(rtc::LS_INFO)))); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr(AsString(rtc::LS_VERBOSE)))); + EXPECT_THAT( + contents_of_file, + ::testing::Not(::testing::HasSubstr(AsString(rtc::LS_SENSITIVE)))); } TEST_F(WebRtcTextLogTest, InfoConfiguration) { @@ -122,16 +117,23 @@ base::ReadFileToString(log_file_path_, &contents_of_file); // Make sure string contains the expected values. - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_ERROR))); - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_WARNING))); - EXPECT_FALSE(ContainsString(contents_of_file, AsString(rtc::LS_INFO))); - EXPECT_FALSE(ContainsString(contents_of_file, AsString(rtc::LS_VERBOSE))); - EXPECT_FALSE(ContainsString(contents_of_file, AsString(rtc::LS_SENSITIVE))); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr(AsString(rtc::LS_ERROR))); + EXPECT_THAT(contents_of_file, + ::testing::HasSubstr(AsString(rtc::LS_WARNING))); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr(AsString(rtc::LS_INFO)))); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr(AsString(rtc::LS_VERBOSE)))); + EXPECT_THAT( + contents_of_file, + ::testing::Not(::testing::HasSubstr(AsString(rtc::LS_SENSITIVE)))); // Also check that the log is proper. - EXPECT_TRUE(ContainsString(contents_of_file, "logging_unittest.cc")); - EXPECT_FALSE(ContainsString(contents_of_file, "logging.h")); - EXPECT_FALSE(ContainsString(contents_of_file, "logging.cc")); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr("logging_unittest.cc")); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr("logging.h"))); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr("logging.cc"))); } TEST_F(WebRtcTextLogTest, LogEverythingConfiguration) { @@ -152,14 +154,53 @@ base::ReadFileToString(log_file_path_, &contents_of_file); // Make sure string contains the expected values. - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_ERROR))); - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_WARNING))); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr(AsString(rtc::LS_ERROR))); + EXPECT_THAT(contents_of_file, + ::testing::HasSubstr(AsString(rtc::LS_WARNING))); #if BUILDFLAG(USE_RUNTIME_VLOG) - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_INFO))); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr(AsString(rtc::LS_INFO))); // RTC_LOG_E - EXPECT_TRUE(ContainsString(contents_of_file, strerror(kFakeError))); - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_VERBOSE))); - EXPECT_TRUE(ContainsString(contents_of_file, AsString(rtc::LS_SENSITIVE))); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr(strerror(kFakeError))); + EXPECT_THAT(contents_of_file, + ::testing::HasSubstr(AsString(rtc::LS_VERBOSE))); + EXPECT_THAT(contents_of_file, + ::testing::HasSubstr(AsString(rtc::LS_SENSITIVE))); #endif // BUILDFLAG(USE_RUNTIME_VLOG) } + +TEST_F(WebRtcTextLogTest, LogIf) { + ASSERT_TRUE(Initialize(2)); + + RTC_LOG_IF(LS_INFO, true) << "IfTrue"; + RTC_LOG_IF(LS_INFO, false) << "IfFalse"; + RTC_LOG_IF_F(LS_INFO, true) << "LogF"; + RTC_LOG_IF_F(LS_INFO, false) << "NoLogF"; + + RTC_DLOG_IF(LS_INFO, true) << "DebugIfTrue"; + RTC_DLOG_IF(LS_INFO, false) << "DebugIfFalse"; + RTC_DLOG_IF_F(LS_INFO, true) << "DebugLogF"; + RTC_DLOG_IF_F(LS_INFO, false) << "DebugNotLogF"; + + // Read file to string. + std::string contents_of_file; + base::ReadFileToString(log_file_path_, &contents_of_file); + + EXPECT_THAT(contents_of_file, ::testing::HasSubstr("IfTrue")); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr("IfFalse"))); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr(__FUNCTION__)); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr("LogF")); + EXPECT_THAT(contents_of_file, ::testing::Not(::testing::HasSubstr("NoLogF"))); + +#if RTC_DLOG_IS_ON + EXPECT_THAT(contents_of_file, ::testing::HasSubstr("DebugIfTrue")); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr("DebugIfFalse"))); + EXPECT_THAT(contents_of_file, ::testing::HasSubstr("DebugLogF")); + EXPECT_THAT(contents_of_file, + ::testing::Not(::testing::HasSubstr("DebugNoLogF"))); +#endif // RTC_DLOG_IF_ON +} + +} // namespace
diff --git a/content/browser/file_system_access/file_system_chooser.h b/content/browser/file_system_access/file_system_chooser.h index 8acae58..18f71a3 100644 --- a/content/browser/file_system_access/file_system_chooser.h +++ b/content/browser/file_system_access/file_system_chooser.h
@@ -107,7 +107,7 @@ base::ScopedClosureRunner fullscreen_block_ GUARDED_BY_CONTEXT(sequence_checker_); - std::unique_ptr<ui::SelectFileDialog> dialog_; + scoped_refptr<ui::SelectFileDialog> dialog_; }; } // namespace content
diff --git a/content/browser/resources/media/media_internals.js b/content/browser/resources/media/media_internals.js index 39e085b..9951deb6 100644 --- a/content/browser/resources/media/media_internals.js +++ b/content/browser/resources/media/media_internals.js
@@ -11,3 +11,16 @@ initialize(new Manager(new ClientRenderer())); const tabBox = document.querySelector('cr-tab-box'); tabBox.hidden = false; + +const _TabIndicies = { + '#players': 0, + '#audio': 1, + '#video-capture': 2, + '#audio-focus': 3, + '#cdms': 4, +}; + +const tabHash = window.location.hash.toLowerCase(); +if (tabHash in _TabIndicies) { + tabBox.setAttribute('selected-index', _TabIndicies[tabHash]); +}
diff --git a/content/browser/webrtc/webrtc_internals.h b/content/browser/webrtc/webrtc_internals.h index 83a660a6..1047945c 100644 --- a/content/browser/webrtc/webrtc_internals.h +++ b/content/browser/webrtc/webrtc_internals.h
@@ -234,7 +234,7 @@ base::Value::List get_user_media_requests_; // For managing select file dialog. - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; enum class SelectionType { kRtcEventLogs, kAudioDebugRecordings
diff --git a/content/test/gpu/gpu_tests/javascript/webgl_conformance_extension_harness_additional_script.js b/content/test/gpu/gpu_tests/javascript/webgl_conformance_extension_harness_additional_script.js new file mode 100644 index 0000000..aafb3cc5 --- /dev/null +++ b/content/test/gpu/gpu_tests/javascript/webgl_conformance_extension_harness_additional_script.js
@@ -0,0 +1,5 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +window.onload = function() { window._loaded = true; } \ No newline at end of file
diff --git a/content/test/gpu/gpu_tests/javascript/webgl_conformance_harness_script.js b/content/test/gpu/gpu_tests/javascript/webgl_conformance_harness_script.js new file mode 100644 index 0000000..1d5a081 --- /dev/null +++ b/content/test/gpu/gpu_tests/javascript/webgl_conformance_harness_script.js
@@ -0,0 +1,137 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +const HEARTBEAT_THROTTLE_MS = 5000; + +class WebSocketWrapper { + constructor() { + this.queued_messages = []; + this.throttle_timer = null; + this.last_heartbeat = null; + this.socket = null; + + this._sendDelayedHeartbeat = this._sendDelayedHeartbeat.bind(this); + } + + setWebSocket(s) { + this.socket = s; + for (let qm of this.queued_messages) { + s.send(qm); + } + } + + _sendMessage(message) { + if (this.socket === null) { + this.queued_messages.push(message); + } else { + this.socket.send(message); + } + } + + _sendHeartbeat() { + this._sendMessage('{"type": "TEST_HEARTBEAT"}'); + } + + _sendDelayedHeartbeat() { + this.throttle_timer = null; + this.last_heartbeat = +new Date(); + this._sendHeartbeat(); + } + + sendHeartbeatThrottled() { + const now = +new Date(); + // Heartbeat already scheduled. + if (this.throttle_timer !== null) { + // If we've already passed the point in time where the heartbeat should + // have been sent, cancel it and send it immediately. This helps in cases + // where we've scheduled one, but the test is doing so much work that + // the callback doesn't fire in a reasonable amount of time. + if (this.last_heartbeat !== null && + now - this.last_heartbeat >= HEARTBEAT_THROTTLE_MS) { + this._clearPendingHeartbeat(); + this.last_heartbeat = now; + this._sendHeartbeat(); + } + return; + } + + // Send a heartbeat immediately. + if (this.last_heartbeat === null || + now - this.last_heartbeat >= HEARTBEAT_THROTTLE_MS){ + this.last_heartbeat = now; + this._sendHeartbeat(); + return; + } + // Schedule a heartbeat for the future. + this.throttle_timer = setTimeout( + this._sendDelayedHeartbeat, HEARTBEAT_THROTTLE_MS); + } + + _clearPendingHeartbeat() { + if (this.throttle_timer !== null) { + clearTimeout(this.throttle_timer); + this.throttle_timer = null; + } + } + + sendTestFinished() { + this._clearPendingHeartbeat(); + this._sendMessage('{"type": "TEST_FINISHED"}'); + } +} + +if (window.parent.wrapper !== undefined) { + const wrapper = window.parent.wrapper; +} else { + const wrapper = new WebSocketWrapper(); + window.wrapper = wrapper; +} + +function connectWebsocket(port) { + let socket = new WebSocket('ws://127.0.0.1:' + port); + socket.addEventListener('open', () => { + wrapper.setWebSocket(socket); + }); +} + +var testHarness = {}; +testHarness._allTestSucceeded = true; +testHarness._messages = ''; +testHarness._failures = 0; +testHarness._finished = false; +testHarness._originalLog = window.console.log; + +testHarness.log = function(msg) { + wrapper.sendHeartbeatThrottled(); + testHarness._messages += msg + "\n"; + testHarness._originalLog.apply(window.console, [msg]); +} + +testHarness.reportResults = function(url, success, msg) { + wrapper.sendHeartbeatThrottled(); + testHarness._allTestSucceeded = testHarness._allTestSucceeded && !!success; + if(!success) { + testHarness._failures++; + if(msg) { + testHarness.log(msg); + } + } +}; +testHarness.notifyFinished = function(url) { + wrapper.sendTestFinished(); + testHarness._finished = true; +}; +testHarness.navigateToPage = function(src) { + var testFrame = document.getElementById("test-frame"); + testFrame.src = src; +}; + +window.webglTestHarness = testHarness; +window.parent.webglTestHarness = testHarness; +window.console.log = testHarness.log; +window.onerror = function(message, url, line) { + testHarness.reportResults(null, false, message); + testHarness.notifyFinished(null); +}; +window.quietMode = function() { return true; } \ No newline at end of file
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 4392a3ec..d03c0f5 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -212,6 +212,9 @@ crbug.com/891953 [ android ] WebglExtension_OVR_multiview2 [ Failure ] crbug.com/891953 [ linux display-server-wayland ] WebglExtension_OVR_multiview2 [ Failure ] +# Can take a rather long time to load, during which heartbeats aren't sent. +conformance2/sync/sync-webgl-specific.html [ Slow ] + # ======================== # Conformance expectations # ======================== @@ -412,6 +415,8 @@ crbug.com/1298619 [ mac passthrough angle-metal apple-angle-metal-renderer:-apple-m1 ] deqp/functional/gles3/occlusionquery_strict.html [ Failure ] crbug.com/angleproject/7397 [ mac passthrough angle-metal apple-angle-metal-renderer:-apple-m1 ] conformance2/renderbuffers/invalidate-framebuffer.html [ Failure ] +crbug.com/1363349 [ mac passthrough angle-metal ] conformance/glsl/bugs/complex-glsl-does-not-crash.html [ Slow ] + ###################################################################### # Mac failures (mainly OpenGL; some need to be reevaluated on Metal) # ######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 60939fd3..77d5908 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -526,6 +526,9 @@ crbug.com/982294 [ win debug passthrough nvidia ] conformance/uniforms/uniform-samplers-test.html [ RetryOnFailure ] +crbug.com/1364333 [ win debug angle-vulkan passthrough ] conformance/glsl/bugs/temp-expressions-should-not-crash.html [ Slow ] +crbug.com/1364333 [ win debug angle-vulkan passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-* [ Slow ] + #################### # Mac failures # #################### @@ -568,6 +571,7 @@ crbug.com/angleproject/5505 [ mac angle-metal passthrough ] conformance/ogles/GL/acos/acos_001_to_006.html [ Failure ] crbug.com/angleproject/5505 [ mac angle-metal passthrough ] conformance/ogles/GL/asin/asin_001_to_006.html [ Failure ] crbug.com/angleproject/6489 [ mac angle-metal passthrough ] conformance/ogles/GL/build/build_009_to_016.html [ Failure ] +crbug.com/1363349 [ mac passthrough angle-metal ] conformance/glsl/bugs/complex-glsl-does-not-crash.html [ Slow ] # Mac / Passthrough command decoder / Metal / Intel crbug.com/angleproject/4846 [ mac angle-metal passthrough intel ] conformance/rendering/rendering-stencil-large-viewport.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/util/websocket_server.py b/content/test/gpu/gpu_tests/util/websocket_server.py new file mode 100644 index 0000000..4df43e77 --- /dev/null +++ b/content/test/gpu/gpu_tests/util/websocket_server.py
@@ -0,0 +1,141 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Code to allow tests to communicate via a websocket server.""" + +import asyncio +import logging +import sys +import threading +from typing import Optional + +import websockets # pylint: disable=import-error +import websockets.server as ws_server # pylint: disable=import-error + +WEBSOCKET_PORT_TIMEOUT_SECONDS = 10 +WEBSOCKET_SETUP_TIMEOUT_SECONDS = 5 + +# The client (Chrome) should never be closing the connection. If it does, it's +# indicative of something going wrong like a renderer crash. +ClientClosedConnectionError = websockets.exceptions.ConnectionClosedOK + +# Alias for readability and so that users don't have to import asyncio. +WebsocketReceiveMessageTimeoutError = asyncio.TimeoutError + + +class WebsocketServer(): + def __init__(self): + """Server that abstracts the asyncio calls used under the hood. + + Only supports one active connection at a time. + """ + self.server_port = None + self.server_stopper = None + self.connection_stopper = None + self.websocket = None + self.port_set_event = threading.Event() + self.connection_received_event = threading.Event() + self.event_loop = None + self._server_thread = None + + def StartServer(self) -> None: + """Starts the websocket server on a separate thread.""" + assert self._server_thread is None, 'Server already running' + self._server_thread = _ServerThread(self) + self._server_thread.daemon = True + self._server_thread.start() + got_port = self.port_set_event.wait(WEBSOCKET_PORT_TIMEOUT_SECONDS) + if not got_port: + raise RuntimeError('Websocket server did not provide a port') + # Through some existing Telemetry magic, we don't need to set up port + # forwarding for remote platforms (ChromeOS/Android). We can provide the + # actual server port on these platforms and the page can connect just fine. + + def ClearCurrentConnection(self) -> None: + if self.connection_stopper: + self.connection_stopper.cancel() + try: + self.connection_stopper.exception() + except asyncio.CancelledError: + pass + self.connection_stopper = None + self.websocket = None + self.connection_received_event.clear() + + def WaitForConnection(self, timeout: Optional[int] = None) -> None: + if self.websocket: + return + timeout = timeout or WEBSOCKET_SETUP_TIMEOUT_SECONDS + self.connection_received_event.wait(timeout) + if not self.websocket: + raise RuntimeError('Websocket connection was not established') + + def StopServer(self) -> None: + self.ClearCurrentConnection() + if self.server_stopper: + self.server_stopper.cancel() + try: + self.server_stopper.exception() + except asyncio.CancelledError: + pass + self.server_stopper = None + self.server_port = None + + self._server_thread.join(5) + if self._server_thread.is_alive(): + logging.error( + 'Websocket server did not shut down properly - this might be ' + 'indicative of an issue in the test harness') + + def Send(self, message: str) -> None: + asyncio.run_coroutine_threadsafe(self.websocket.send(message), + self.event_loop) + + def Receive(self, timeout: int) -> str: + future = asyncio.run_coroutine_threadsafe( + asyncio.wait_for(self.websocket.recv(), timeout), self.event_loop) + try: + return future.result() + except asyncio.exceptions.TimeoutError as e: + raise WebsocketReceiveMessageTimeoutError( + 'Timed out after %d seconds waiting for websocket message' % + timeout) from e + + +class _ServerThread(threading.Thread): + def __init__(self, server_instance: WebsocketServer, *args, **kwargs): + super().__init__(*args, **kwargs) + self._server_instance = server_instance + + def run(self) -> None: + try: + asyncio.run(StartWebsocketServer(self._server_instance)) + except asyncio.CancelledError: + pass + except Exception as e: # pylint: disable=broad-except + sys.stdout.write('Server thread had an exception: %s\n' % e) + + +async def StartWebsocketServer(server_instance: WebsocketServer) -> None: + async def HandleWebsocketConnection( + websocket: ws_server.WebSocketServerProtocol) -> None: + # We only allow one active connection - if there are multiple, something is + # wrong. + assert server_instance.connection_stopper is None + assert server_instance.websocket is None + server_instance.connection_stopper = asyncio.Future() + # Keep our own reference in case the server clears its reference before the + # await finishes. + connection_stopper = server_instance.connection_stopper + server_instance.websocket = websocket + server_instance.connection_received_event.set() + await connection_stopper + + async with websockets.serve(HandleWebsocketConnection, '127.0.0.1', + 0) as server: + server_instance.event_loop = asyncio.get_running_loop() + server_instance.server_port = server.sockets[0].getsockname()[1] + server_instance.port_set_event.set() + server_instance.server_stopper = asyncio.Future() + server_stopper = server_instance.server_stopper + await server_stopper
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py index bd93557..4347cae 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
@@ -3,9 +3,11 @@ # found in the LICENSE file. import logging +import json import os import re import sys +import time from typing import Any, List, Optional, Set, Tuple import unittest @@ -14,54 +16,29 @@ from gpu_tests import gpu_helper from gpu_tests import gpu_integration_test from gpu_tests import webgl_test_util +from gpu_tests.util import websocket_server import gpu_path_util from telemetry.internal.platform import gpu_info as telemetry_gpu_info -conformance_harness_script = r""" - var testHarness = {}; - testHarness._allTestSucceeded = true; - testHarness._messages = ''; - testHarness._failures = 0; - testHarness._finished = false; - testHarness._originalLog = window.console.log; +JAVASCRIPT_DIR = os.path.join(gpu_path_util.GPU_DIR, 'gpu_tests', 'javascript') - testHarness.log = function(msg) { - testHarness._messages += msg + "\n"; - testHarness._originalLog.apply(window.console, [msg]); - } +WEBSOCKET_JAVASCRIPT_TIMEOUT_S = 30 +HEARTBEAT_TIMEOUT_S = 15 +ASAN_MULTIPLIER = 2 +SLOW_MULTIPLIER = 4 - testHarness.reportResults = function(url, success, msg) { - testHarness._allTestSucceeded = testHarness._allTestSucceeded && !!success; - if(!success) { - testHarness._failures++; - if(msg) { - testHarness.log(msg); - } - } - }; - testHarness.notifyFinished = function(url) { - testHarness._finished = true; - }; - testHarness.navigateToPage = function(src) { - var testFrame = document.getElementById("test-frame"); - testFrame.src = src; - }; +# Non-standard timeouts that can't be handled by a Slow expectation, likely due +# to being particularly long or not specific to a configuration. Try to use +# expectations first. +NON_STANDARD_HEARTBEAT_TIMEOUTS = {} - window.webglTestHarness = testHarness; - window.parent.webglTestHarness = testHarness; - window.console.log = testHarness.log; - window.onerror = function(message, url, line) { - testHarness.reportResults(null, false, message); - testHarness.notifyFinished(null); - }; - window.quietMode = function() { return true; } -""" - -extension_harness_additional_script = r""" - window.onload = function() { window._loaded = true; } -""" +# Non-standard timeouts for executing the JavaScript to establish the websocket +# connection. A test being in here implies that it starts doing a huge amount +# of work in JavaScript immediately, preventing execution of JavaScript via +# devtools as well. +NON_STANDARD_WEBSOCKET_JAVASCRIPT_TIMEOUTS = {} # cmp no longer exists in Python 3 def cmp(a: Any, b: Any) -> int: @@ -95,6 +72,12 @@ _verified_flags = False _original_environ = None + # Scripts read from file during process start up. + _conformance_harness_script = None + _extension_harness_additional_script = None + + websocket_server = None + @classmethod def Name(cls) -> str: return 'webgl_conformance' @@ -115,6 +98,13 @@ return { # crbug.com/1347970. 'conformance/textures/misc/texture-video-transparent.html', + # Specifically when using Metal, this test can be rather slow. When run + # in parallel, even a minute is not long enough for it to reliably run, + # as it does not properly send heartbeats (possibly due to a large + # amount of work being done). Instead of increasing the heartbeat + # timeout further, run it serially. Can potentially be removed depending + # on the response to crbug.com/1363349. + 'conformance/glsl/bugs/complex-glsl-does-not-crash.html', } @classmethod @@ -136,6 +126,17 @@ @classmethod def _SetClassVariablesFromOptions(cls, options: ct.ParsedCmdArgs) -> None: cls._webgl_version = int(options.webgl_conformance_version.split('.')[0]) + if not cls._conformance_harness_script: + with open( + os.path.join(JAVASCRIPT_DIR, + 'webgl_conformance_harness_script.js')) as f: + cls._conformance_harness_script = f.read() + if not cls._extension_harness_additional_script: + with open( + os.path.join( + JAVASCRIPT_DIR, + 'webgl_conformance_extension_harness_additional_script.js')) as f: + cls._extension_harness_additional_script = f.read() @classmethod def GenerateGpuTests(cls, options: ct.ParsedCmdArgs) -> ct.TestGenerator: @@ -342,10 +343,86 @@ self._verified_flags = True url = self.UrlOfStaticFilePath(test_path) self.tab.Navigate(url, script_to_evaluate_on_commit=harness_script) + self.tab.action_runner.EvaluateJavaScript( + 'connectWebsocket("%d")' % + WebGLConformanceIntegrationTest.websocket_server.server_port, + timeout=self._GetWebsocketJavaScriptTimeout()) + WebGLConformanceIntegrationTest.websocket_server.WaitForConnection() + + def _HandleMessageLoop(self, test_timeout: float) -> None: + start_time = time.time() + try: + while True: + response = WebGLConformanceIntegrationTest.websocket_server.Receive( + self._GetHeartbeatTimeout()) + response = json.loads(response) + response_type = response['type'] + + if time.time() - start_time > test_timeout: + raise RuntimeError( + 'Hit %.3f second global timeout, but page continued to send ' + 'messages over the websocket, i.e. was not due to a renderer ' + 'crash.' % test_timeout) + + if response_type == 'TEST_HEARTBEAT': + continue + if response_type == 'TEST_FINISHED': + break + raise RuntimeError('Received unknown message type %s' % response_type) + except websocket_server.WebsocketReceiveMessageTimeoutError: + logging.error( + 'Timed out waiting for websocket message, checking for hung renderer') + # Telemetry has some code to automatically crash the renderer and GPU + # processes if it thinks that the renderer is hung. So, execute some + # trivial JavaScript now to hit that code if we got the timeout because of + # a hung renderer. If we do detect a hung renderer, this will raise + # another exception and prevent the following line about the renderer not + # being hung from running. + self.tab.action_runner.EvaluateJavaScript('let somevar = undefined;', + timeout=5) + logging.error('Timeout does *not* appear to be due to a hung renderer') + raise + except websocket_server.ClientClosedConnectionError as e: + raise RuntimeError( + 'Detected closed websocket - likely caused by a renderer ' + 'crash') from e + finally: + WebGLConformanceIntegrationTest.websocket_server.ClearCurrentConnection() + + def _GetWebsocketJavaScriptTimeout(self) -> int: + # Most tests should be able to run JavaScript immediately after page load. + # However, some tests will do so much work that we're unable to actually + # run the JavaScript for quite a while. + return int( + NON_STANDARD_WEBSOCKET_JAVASCRIPT_TIMEOUTS.get( + self.shortName(), WEBSOCKET_JAVASCRIPT_TIMEOUT_S) * + self._GetTimeoutMultiplier()) + + def _GetHeartbeatTimeout(self) -> int: + return int( + NON_STANDARD_HEARTBEAT_TIMEOUTS.get(self.shortName(), + HEARTBEAT_TIMEOUT_S) * + self._GetTimeoutMultiplier()) + + def _GetTimeoutMultiplier(self) -> float: + # Parallel jobs increase load and can slow down test execution, so scale + # based on the number of jobs. Target 2x increase with 4 jobs. + multiplier = 1 + (self.child.jobs - 1) / 3.0 + if self.is_asan: + multiplier *= ASAN_MULTIPLIER + if self._IsSlowTest(): + multiplier *= SLOW_MULTIPLIER + return multiplier + + def _IsSlowTest(self) -> bool: + # We access the expectations directly instead of using + # self.GetExpectationsForTest since we need the raw results, but that method + # only returns the parsed results and whether the test should be retried. + expectation = self.child.expectations.expectations_for(self.shortName()) + return 'Slow' in expectation.raw_results def _CheckTestCompletion(self) -> None: - self.tab.action_runner.WaitForJavaScriptCondition( - 'webglTestHarness._finished', timeout=self._GetTestTimeout()) + self._HandleMessageLoop(self._GetTestTimeout()) if self._crash_count != self.browser.GetSystemInfo().gpu \ .aux_attributes['process_crash_count']: self.fail('GPU process crashed during test.\n' + @@ -354,12 +431,12 @@ self.fail(self._WebGLTestMessages(self.tab)) def _RunConformanceTest(self, test_path: str, _: WebGLTestArgs) -> None: - self._NavigateTo(test_path, conformance_harness_script) + self._NavigateTo(test_path, self._conformance_harness_script) self._CheckTestCompletion() def _RunExtensionCoverageTest(self, test_path: str, test_args: WebGLTestArgs) -> None: - self._NavigateTo(test_path, _GetExtensionHarnessScript()) + self._NavigateTo(test_path, self._GetExtensionHarnessScript()) self.tab.action_runner.WaitForJavaScriptCondition( 'window._loaded', timeout=self._GetTestTimeout()) context_type = 'webgl2' if test_args.webgl_version == 2 else 'webgl' @@ -374,7 +451,7 @@ self._CheckTestCompletion() def _RunExtensionTest(self, test_path: str, test_args: WebGLTestArgs) -> None: - self._NavigateTo(test_path, _GetExtensionHarnessScript()) + self._NavigateTo(test_path, self._GetExtensionHarnessScript()) self.tab.action_runner.WaitForJavaScriptCondition( 'window._loaded', timeout=self._GetTestTimeout()) context_type = 'webgl2' if test_args.webgl_version == 2 else 'webgl' @@ -391,6 +468,12 @@ timeout *= 2 return timeout + def _GetExtensionHarnessScript(self) -> str: + assert self._conformance_harness_script is not None + assert self._extension_harness_additional_script is not None + return (self._conformance_harness_script + + self._extension_harness_additional_script) + @classmethod def GenerateBrowserArgs(cls, additional_args: List[str]) -> List[str]: """Adds default arguments to |additional_args|. @@ -456,6 +539,11 @@ @classmethod def SetUpProcess(cls) -> None: super(WebGLConformanceIntegrationTest, cls).SetUpProcess() + # Logging every time a connection is opened/closed is spammy, so decrease + # the default log level. + logging.getLogger('websockets.server').setLevel(logging.WARNING) + cls.websocket_server = websocket_server.WebsocketServer() + cls.websocket_server.StartServer() cls.CustomizeBrowserArgs([]) cls.StartBrowser() # By setting multiple server directories, the root of the server @@ -468,6 +556,12 @@ webgl_test_util.extensions_relpath) ]) + @classmethod + def TearDownProcess(cls) -> None: + cls.websocket_server.StopServer() + cls.websocket_server = None + super(WebGLConformanceIntegrationTest, cls).TearDownProcess() + # Helper functions. @staticmethod @@ -614,10 +708,6 @@ return error_str -def _GetExtensionHarnessScript() -> str: - return conformance_harness_script + extension_harness_additional_script - - def load_tests(loader: unittest.TestLoader, tests: Any, pattern: Any) -> unittest.TestSuite: del loader, tests, pattern # Unused.
diff --git a/content/test/gpu/gpu_tests/webgpu_cts_integration_test.py b/content/test/gpu/gpu_tests/webgpu_cts_integration_test.py index 3978a17..cdb16e91 100644 --- a/content/test/gpu/gpu_tests/webgpu_cts_integration_test.py +++ b/content/test/gpu/gpu_tests/webgpu_cts_integration_test.py
@@ -2,22 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import asyncio import fnmatch import json -import logging import os import sys -import threading import time from typing import Any, Dict, List, Set import unittest -import websockets # pylint:disable=import-error -import websockets.server as ws_server # pylint: disable=import-error - from gpu_tests import common_typing as ct from gpu_tests import gpu_integration_test +from gpu_tests.util import websocket_server import gpu_path_util @@ -64,37 +59,6 @@ self.log_pieces = [] -async def StartWebsocketServer() -> None: - async def HandleWebsocketConnection( - websocket: ws_server.WebSocketServerProtocol) -> None: - # We only allow one active connection - if there are multiple, something is - # wrong. - assert WebGpuCtsIntegrationTest.connection_stopper is None - assert WebGpuCtsIntegrationTest.websocket is None - WebGpuCtsIntegrationTest.connection_stopper = asyncio.Future() - WebGpuCtsIntegrationTest.websocket = websocket - WebGpuCtsIntegrationTest.connection_received_event.set() - await WebGpuCtsIntegrationTest.connection_stopper - - async with websockets.serve(HandleWebsocketConnection, '127.0.0.1', - 0) as server: - WebGpuCtsIntegrationTest.event_loop = asyncio.get_running_loop() - WebGpuCtsIntegrationTest.server_port = server.sockets[0].getsockname()[1] - WebGpuCtsIntegrationTest.port_set_event.set() - WebGpuCtsIntegrationTest.server_stopper = asyncio.Future() - await WebGpuCtsIntegrationTest.server_stopper - - -class ServerThread(threading.Thread): - def run(self) -> None: - try: - asyncio.run(StartWebsocketServer()) - except asyncio.CancelledError: - pass - except Exception as e: # pylint:disable=broad-except - sys.stdout.write('Server thread had exception: %s\n' % e) - - class WebGpuCtsIntegrationTest(gpu_integration_test.GpuIntegrationTest): # Whether the test page has already been loaded. Caching this state here is # faster than checking the URL every time, and given how fast these tests are, @@ -113,14 +77,7 @@ total_tests_run = 0 - server_stopper = None - connection_stopper = None - server_port = None - websocket = None - port_set_event = None - connection_received_event = None - event_loop = None - _server_thread = None + websocket_server = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -171,24 +128,11 @@ super(WebGpuCtsIntegrationTest, cls).StartBrowser() @classmethod - def SetUpWebsocketServer(cls) -> None: - cls.port_set_event = threading.Event() - cls.connection_received_event = threading.Event() - cls._server_thread = ServerThread() - # Mark as a daemon so that the harness does not hang when shutting down if - # the thread fails to shut down properly. - cls._server_thread.daemon = True - cls._server_thread.start() - got_port = WebGpuCtsIntegrationTest.port_set_event.wait( - WEBSOCKET_PORT_TIMEOUT_SECONDS) - if not got_port: - raise RuntimeError('Server did not provide a port.') - - @classmethod def SetUpProcess(cls) -> None: super(WebGpuCtsIntegrationTest, cls).SetUpProcess() - cls.SetUpWebsocketServer() + cls.websocket_server = websocket_server.WebsocketServer() + cls.websocket_server.StartServer() browser_args = [ '--enable-unsafe-webgpu', '--disable-dawn-features=disallow_unsafe_apis', @@ -216,33 +160,9 @@ ]) @classmethod - def TearDownWebsocketServer(cls) -> None: - if cls.connection_stopper: - cls.connection_stopper.cancel() - try: - cls.connection_stopper.exception() - except asyncio.CancelledError: - pass - if cls.server_stopper: - cls.server_stopper.cancel() - try: - cls.server_stopper.exception() - except asyncio.CancelledError: - pass - cls.server_stopper = None - cls.connection_stopper = None - cls.server_port = None - cls.websocket = None - - cls._server_thread.join(5) - if cls._server_thread.is_alive(): - logging.error( - 'WebSocket server did not shut down properly - this might be ' - 'indicative of an issue in the test harness') - - @classmethod def TearDownProcess(cls) -> None: - cls.TearDownWebsocketServer() + cls.websocket_server.StopServer() + cls.websocket_server = None super(WebGpuCtsIntegrationTest, cls).TearDownProcess() @classmethod @@ -301,13 +221,12 @@ try: first_load = self._NavigateIfNecessary(test_path) - asyncio.run_coroutine_threadsafe( - WebGpuCtsIntegrationTest.websocket.send( - json.dumps({ - 'q': self._query, - 'w': self._run_in_worker - })), WebGpuCtsIntegrationTest.event_loop) - result = self.HandleMessageLoop(first_load=first_load) + WebGpuCtsIntegrationTest.websocket_server.Send( + json.dumps({ + 'q': self._query, + 'w': self._run_in_worker + })) + result = self.HandleMessageLoop(first_load) log_str = ''.join(result.log_pieces) status = result.status @@ -316,7 +235,7 @@ log_str) elif status == 'fail': self.fail(log_str) - except websockets.exceptions.ConnectionClosedOK as e: + except websocket_server.ClientClosedConnectionError as e: raise RuntimeError( 'Detected closed websocket - likely caused by renderer crash') from e except WebGpuMessageTimeoutError as e: @@ -401,10 +320,7 @@ while True: timeout = step_timeout * browser_timeout_multiplier try: - future = asyncio.run_coroutine_threadsafe( - asyncio.wait_for(WebGpuCtsIntegrationTest.websocket.recv(), - timeout), WebGpuCtsIntegrationTest.event_loop) - response = future.result() + response = WebGpuCtsIntegrationTest.websocket_server.Receive(timeout) response = json.loads(response) response_type = response['type'] @@ -447,7 +363,7 @@ else: raise WebGpuMessageProtocolError('Received unknown message type %s' % response_type) - except asyncio.TimeoutError as e: + except websocket_server.WebsocketReceiveMessageTimeoutError as e: self.HandleDurationTagOnFailure(message_state, global_timeout) raise WebGpuMessageTimeoutError( 'Timed out waiting %.3f seconds for a message. Message state: %s' % @@ -472,32 +388,18 @@ and JAVASCRIPT_DURATION not in self.additionalTags): self.additionalTags[JAVASCRIPT_DURATION] = '%.9fs' % test_timeout - @classmethod - def CleanUpExistingWebsocket(cls) -> None: - if cls.connection_stopper: - cls.connection_stopper.cancel() - try: - cls.connection_stopper.exception() - except asyncio.CancelledError: - pass - cls.connection_stopper = None - cls.websocket = None - cls.connection_received_event.clear() - def _NavigateIfNecessary(self, path: str) -> bool: if WebGpuCtsIntegrationTest._page_loaded: return False - WebGpuCtsIntegrationTest.CleanUpExistingWebsocket() + WebGpuCtsIntegrationTest.websocket_server.ClearCurrentConnection() url = self.UrlOfStaticFilePath(path) self.tab.Navigate(url) self.tab.action_runner.WaitForJavaScriptCondition( 'window.setupWebsocket != undefined') self.tab.action_runner.ExecuteJavaScript( - 'window.setupWebsocket("%s")' % WebGpuCtsIntegrationTest.server_port) - WebGpuCtsIntegrationTest.connection_received_event.wait( - WEBSOCKET_SETUP_TIMEOUT_SECONDS) - if not WebGpuCtsIntegrationTest.websocket: - raise RuntimeError('Websocket connection was not established.') + 'window.setupWebsocket("%s")' % + WebGpuCtsIntegrationTest.websocket_server.server_port) + WebGpuCtsIntegrationTest.websocket_server.WaitForConnection() WebGpuCtsIntegrationTest._page_loaded = True return True
diff --git a/device/gamepad/gamepad_device_linux.cc b/device/gamepad/gamepad_device_linux.cc index 05b4299..16d12c2 100644 --- a/device/gamepad/gamepad_device_linux.cc +++ b/device/gamepad/gamepad_device_linux.cc
@@ -12,6 +12,7 @@ #include <sys/ioctl.h> #include "base/callback_helpers.h" +#include "base/containers/fixed_flat_set.h" #include "base/posix/eintr_wrapper.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" @@ -262,12 +263,19 @@ } bool GamepadDeviceLinux::SupportsVibration() const { + static constexpr auto kNoVibration = base::MakeFixedFlatSet<GamepadId>({ + // The Xbox Adaptive Controller reports force feedback capability, but + // the device itself does not have any vibration actuators. + GamepadId::kMicrosoftProduct0b0a, + // SteelSeries Stratus Duo is XInput but does not support vibration. + GamepadId::kSteelSeriesProduct1430, + GamepadId::kSteelSeriesProduct1431, + }); + if (dualshock4_ || xbox_hid_ || hid_haptics_) return true; - // The Xbox Adaptive Controller reports force feedback capability, but the - // device itself does not have any vibration actuators. - if (gamepad_id_ == GamepadId::kMicrosoftProduct0b0a) + if (kNoVibration.contains(gamepad_id_)) return false; return supports_force_feedback_ && evdev_fd_.is_valid();
diff --git a/device/gamepad/gamepad_id_list.h b/device/gamepad/gamepad_id_list.h index ea97fdf..768e7511 100644 --- a/device/gamepad/gamepad_id_list.h +++ b/device/gamepad/gamepad_id_list.h
@@ -114,6 +114,8 @@ kSteelSeriesProduct1412 = 0x10381412, kSteelSeriesProduct1418 = 0x10381418, kSteelSeriesProduct1420 = 0x10381420, + kSteelSeriesProduct1430 = 0x10381430, + kSteelSeriesProduct1431 = 0x10381431, }; class DEVICE_GAMEPAD_EXPORT GamepadIdList {
diff --git a/device/gamepad/xbox_controller_mac.mm b/device/gamepad/xbox_controller_mac.mm index 7d603ae6..7d86fdb 100644 --- a/device/gamepad/xbox_controller_mac.mm +++ b/device/gamepad/xbox_controller_mac.mm
@@ -18,6 +18,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/check_op.h" +#include "base/containers/fixed_flat_set.h" #include "base/cxx17_backports.h" #include "base/location.h" #include "base/mac/foundation_util.h" @@ -586,8 +587,14 @@ } bool XboxControllerMac::SupportsVibration() const { - // The Xbox Adaptive Controller has no vibration actuators. - return gamepad_id_ != GamepadId::kMicrosoftProduct0b0a; + static constexpr auto kNoVibration = base::MakeFixedFlatSet<GamepadId>({ + // The Xbox Adaptive Controller has no vibration actuators. + GamepadId::kMicrosoftProduct0b0a, + // SteelSeries Stratus Duo is XInput but does not support vibration. + GamepadId::kSteelSeriesProduct1430, + GamepadId::kSteelSeriesProduct1431, + }); + return !kNoVibration.contains(gamepad_id_); } // static
diff --git a/device/gamepad/xbox_data_fetcher_mac.cc b/device/gamepad/xbox_data_fetcher_mac.cc index 71eca54..1cebdfb 100644 --- a/device/gamepad/xbox_data_fetcher_mac.cc +++ b/device/gamepad/xbox_data_fetcher_mac.cc
@@ -15,6 +15,7 @@ #include <limits> #include <string> +#include "base/containers/fixed_flat_set.h" #include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/strings/utf_string_conversions.h" @@ -25,17 +26,19 @@ namespace { // XboxDataFetcher recognizes the following devices connected over USB. -constexpr GamepadId kSupportedDeviceIds[]{ - GamepadId::kAmazonProduct041a, // Amazon Luna Controller - GamepadId::kMicrosoftProduct028e, // Xbox 360 - GamepadId::kMicrosoftProduct02d1, // Xbox One - GamepadId::kMicrosoftProduct02dd, // Xbox One, 2015 firmware - GamepadId::kMicrosoftProduct02e3, // Xbox Elite - GamepadId::kMicrosoftProduct02ea, // Xbox One S - GamepadId::kMicrosoftProduct0b00, // Xbox Elite 2 - GamepadId::kMicrosoftProduct0b0a, // Xbox Adaptive - GamepadId::kMicrosoftProduct0b12, // Xbox Series X -}; +constexpr auto kSupportedDeviceIds = base::MakeFixedFlatSet<GamepadId>({ + GamepadId::kAmazonProduct041a, // Amazon Luna Controller + GamepadId::kMicrosoftProduct028e, // Xbox 360 + GamepadId::kMicrosoftProduct02d1, // Xbox One + GamepadId::kMicrosoftProduct02dd, // Xbox One, 2015 firmware + GamepadId::kMicrosoftProduct02e3, // Xbox Elite + GamepadId::kMicrosoftProduct02ea, // Xbox One S + GamepadId::kMicrosoftProduct0b00, // Xbox Elite 2 + GamepadId::kMicrosoftProduct0b0a, // Xbox Adaptive + GamepadId::kMicrosoftProduct0b12, // Xbox Series X + GamepadId::kSteelSeriesProduct1430, // Stratus Duo receiver + GamepadId::kSteelSeriesProduct1431, // Stratus Duo +}); } // namespace
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h index 741fd09..f8b04f43 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.h +++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -145,6 +145,10 @@ // Returns spatial navigation status. bool IsSpatialNavigationEnabled() const; + base::WeakPtr<WebViewGuest> GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + private: explicit WebViewGuest(content::WebContents* owner_web_contents);
diff --git a/fuchsia_web/webengine/BUILD.gn b/fuchsia_web/webengine/BUILD.gn index 07068f3..759e134 100644 --- a/fuchsia_web/webengine/BUILD.gn +++ b/fuchsia_web/webengine/BUILD.gn
@@ -163,6 +163,7 @@ "//components/media_control/browser", "//components/media_control/renderer", "//components/memory_pressure", + "//components/network_session_configurator/common", "//components/on_load_script_injector/browser", "//components/on_load_script_injector/renderer", "//components/permissions",
diff --git a/fuchsia_web/webengine/browser/DEPS b/fuchsia_web/webengine/browser/DEPS index aafd36c..d5792f4 100644 --- a/fuchsia_web/webengine/browser/DEPS +++ b/fuchsia_web/webengine/browser/DEPS
@@ -7,6 +7,7 @@ "+components/keyed_service/content", "+components/keyed_service/core", "+components/on_load_script_injector/browser", + "+components/network_session_configurator/common/network_switches.h", "+components/permissions", "+components/profile_metrics", "+components/policy/content",
diff --git a/fuchsia_web/webengine/browser/web_engine_config.cc b/fuchsia_web/webengine/browser/web_engine_config.cc index 4ee4a76..c8ddcb2 100644 --- a/fuchsia_web/webengine/browser/web_engine_config.cc +++ b/fuchsia_web/webengine/browser/web_engine_config.cc
@@ -13,6 +13,7 @@ #include "base/values.h" #include "cc/base/switches.h" #include "components/embedder_support/switches.h" +#include "components/network_session_configurator/common/network_switches.h" #include "components/viz/common/features.h" #include "components/viz/common/switches.h" #include "content/public/common/content_switches.h" @@ -63,6 +64,7 @@ embedder_support::kOriginTrialDisabledTokens, switches::kDisableFeatures, switches::kDisableGpuWatchdog, + switches::kDisableQuic, switches::kDisableMipmapGeneration, // TODO(crbug.com/1082821): Remove this switch from the allow-list. switches::kEnableCastStreamingReceiver,
diff --git a/gpu/command_buffer/common/shared_image_usage.cc b/gpu/command_buffer/common/shared_image_usage.cc index d4cb913d..ca5c1d49 100644 --- a/gpu/command_buffer/common/shared_image_usage.cc +++ b/gpu/command_buffer/common/shared_image_usage.cc
@@ -25,6 +25,7 @@ {SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT, "Gles2FramebufferHint"}, {SHARED_IMAGE_USAGE_RASTER, "Raster"}, {SHARED_IMAGE_USAGE_DISPLAY_READ, "DisplayRead"}, + {SHARED_IMAGE_USAGE_DISPLAY_WRITE, "DisplayWrite"}, {SHARED_IMAGE_USAGE_SCANOUT, "Scanout"}, {SHARED_IMAGE_USAGE_OOP_RASTERIZATION, "OopRasterization"}, {SHARED_IMAGE_USAGE_WEBGPU, "Webgpu"},
diff --git a/gpu/command_buffer/common/shared_image_usage.h b/gpu/command_buffer/common/shared_image_usage.h index 214473a..ef41e973 100644 --- a/gpu/command_buffer/common/shared_image_usage.h +++ b/gpu/command_buffer/common/shared_image_usage.h
@@ -21,44 +21,46 @@ SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT = 1 << 1, // Image will be used in RasterInterface SHARED_IMAGE_USAGE_RASTER = 1 << 2, - // Image will be read inside Display Compositor + // Image will be read from inside Display Compositor SHARED_IMAGE_USAGE_DISPLAY_READ = 1 << 3, + // Image will be written to inside Display Compositor + SHARED_IMAGE_USAGE_DISPLAY_WRITE = 1 << 4, // Image will be used as a scanout buffer (overlay) - SHARED_IMAGE_USAGE_SCANOUT = 1 << 4, + SHARED_IMAGE_USAGE_SCANOUT = 1 << 5, // Image will be used in OOP rasterization. This flag is used on top of // SHARED_IMAGE_USAGE_RASTER to indicate that the client will only use // RasterInterface for OOP rasterization. TODO(backer): Eliminate once we can // CPU raster to SkImage via RasterInterface. - SHARED_IMAGE_USAGE_OOP_RASTERIZATION = 1 << 5, + SHARED_IMAGE_USAGE_OOP_RASTERIZATION = 1 << 6, // Image will be used by Dawn (for WebGPU) - SHARED_IMAGE_USAGE_WEBGPU = 1 << 6, + SHARED_IMAGE_USAGE_WEBGPU = 1 << 7, // Image will be used in a protected Vulkan context on Fuchsia. - SHARED_IMAGE_USAGE_PROTECTED = 1 << 7, + SHARED_IMAGE_USAGE_PROTECTED = 1 << 8, // Image may use concurrent read/write access. Used by single buffered canvas. // TODO(crbug.com/969114): This usage is currently not supported in GL/Vulkan // interop cases. - SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE = 1 << 8, + SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE = 1 << 9, // Image will be used for video decode acceleration on Chrome OS. - SHARED_IMAGE_USAGE_VIDEO_DECODE = 1 << 9, + SHARED_IMAGE_USAGE_VIDEO_DECODE = 1 << 10, // Image will be used as a WebGPU swapbuffer - SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE = 1 << 10, + SHARED_IMAGE_USAGE_WEBGPU_SWAP_CHAIN_TEXTURE = 1 << 11, // Image will be used by VideoToolbox on macOS. If this is set, then // GLImage::DisableInUseByWindowServer should be called on any GLImages that // use this SharedImage. - SHARED_IMAGE_USAGE_MACOS_VIDEO_TOOLBOX = 1 << 11, + SHARED_IMAGE_USAGE_MACOS_VIDEO_TOOLBOX = 1 << 12, // Image will be used with mipmap enabled - SHARED_IMAGE_USAGE_MIPMAP = 1 << 12, + SHARED_IMAGE_USAGE_MIPMAP = 1 << 13, // Image will be used for CPU Writes by client - SHARED_IMAGE_USAGE_CPU_WRITE = 1 << 13, + SHARED_IMAGE_USAGE_CPU_WRITE = 1 << 14, // Image will be used in RasterInterface with RawDraw. - SHARED_IMAGE_USAGE_RAW_DRAW = 1 << 14, + SHARED_IMAGE_USAGE_RAW_DRAW = 1 << 15, // Image will be used in RasterInterface for DelegatedCompositing. // TODO(crbug.com/1254033): this usage shall be removed after cc is able to // set a single (duplicated) fence for bunch of tiles instead of having the SI // framework creating fences for each single message when write access ends. - SHARED_IMAGE_USAGE_RASTER_DELEGATED_COMPOSITING = 1 << 15, + SHARED_IMAGE_USAGE_RASTER_DELEGATED_COMPOSITING = 1 << 16, // Image will be created on the high performance GPU if supported. - SHARED_IMAGE_USAGE_HIGH_PERFORMANCE_GPU = 1 << 16, + SHARED_IMAGE_USAGE_HIGH_PERFORMANCE_GPU = 1 << 17, // Start service side only usage flags after this entry. They must be larger // than `LAST_CLIENT_USAGE`. @@ -67,7 +69,7 @@ // Image will have pixels uploaded from CPU. The backing must implement // `UploadFromMemory()` if it supports this usage. Clients should specify // SHARED_IMAGE_USAGE_CPU_WRITE if they need to write pixels to the image. - SHARED_IMAGE_USAGE_CPU_UPLOAD = 1 << 17, + SHARED_IMAGE_USAGE_CPU_UPLOAD = 1 << 18, }; // Returns true if usage is a valid client usage.
diff --git a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc index 170ae37..aa6d4a85 100644 --- a/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/ahardwarebuffer_image_backing_factory.cc
@@ -558,8 +558,9 @@ // TODO(vikassoni): Also check gpu_preferences.enable_vulkan to figure out // if skia is using vulkan backing or GL backing. const bool use_gles2 = - (usage & (SHARED_IMAGE_USAGE_GLES2 | SHARED_IMAGE_USAGE_RASTER | - SHARED_IMAGE_USAGE_DISPLAY_READ)); + (usage & + (SHARED_IMAGE_USAGE_GLES2 | SHARED_IMAGE_USAGE_RASTER | + SHARED_IMAGE_USAGE_DISPLAY_READ | SHARED_IMAGE_USAGE_DISPLAY_WRITE)); // If usage flags indicated this backing can be used as a GL texture, then // do below gl related checks.
diff --git a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc index d529ad6f..0f845b5 100644 --- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
@@ -99,7 +99,8 @@ #endif SHARED_IMAGE_USAGE_GLES2 | SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT | SHARED_IMAGE_USAGE_RASTER | SHARED_IMAGE_USAGE_DISPLAY_READ | - SHARED_IMAGE_USAGE_OOP_RASTERIZATION | SHARED_IMAGE_USAGE_CPU_UPLOAD; + SHARED_IMAGE_USAGE_DISPLAY_WRITE | SHARED_IMAGE_USAGE_OOP_RASTERIZATION | + SHARED_IMAGE_USAGE_CPU_UPLOAD; if (usage & ~kSupportedUsages) return false;
diff --git a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc index af32a1df..64bf26d 100644 --- a/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/egl_image_backing_factory.cc
@@ -98,6 +98,7 @@ // Doesn't support contexts other than GL for OOPR Canvas if (gr_context_type != GrContextType::kGL && ((usage & SHARED_IMAGE_USAGE_DISPLAY_READ) || + (usage & SHARED_IMAGE_USAGE_DISPLAY_WRITE) || (usage & SHARED_IMAGE_USAGE_RASTER))) { return false; }
diff --git a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc index 7c0173ed..fd7a1066 100644 --- a/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/gl_image_backing_factory.cc
@@ -267,6 +267,7 @@ // Doesn't support contexts other than GL for OOPR Canvas if (gr_context_type != GrContextType::kGL && ((usage & SHARED_IMAGE_USAGE_DISPLAY_READ) || + (usage & SHARED_IMAGE_USAGE_DISPLAY_WRITE) || (usage & SHARED_IMAGE_USAGE_RASTER))) { return false; }
diff --git a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc index 29e2a60..37d479b7 100644 --- a/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/gl_texture_image_backing_factory.cc
@@ -156,6 +156,7 @@ // Doesn't support contexts other than GL for OOPR Canvas if (gr_context_type != GrContextType::kGL && ((usage & SHARED_IMAGE_USAGE_DISPLAY_READ) || + (usage & SHARED_IMAGE_USAGE_DISPLAY_WRITE) || (usage & SHARED_IMAGE_USAGE_RASTER))) { return false; }
diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc index b7c291c7..16fc445 100644 --- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc
@@ -191,7 +191,8 @@ } bool used_by_skia = (usage & SHARED_IMAGE_USAGE_RASTER) || - (usage & SHARED_IMAGE_USAGE_DISPLAY_READ); + (usage & SHARED_IMAGE_USAGE_DISPLAY_READ) || + (usage & SHARED_IMAGE_USAGE_DISPLAY_WRITE); bool used_by_vulkan = used_by_skia && gr_context_type == GrContextType::kVulkan; bool used_by_webgpu = usage & SHARED_IMAGE_USAGE_WEBGPU; @@ -220,9 +221,9 @@ // For now just use OzoneImageBacking for primary plane buffers. // TODO(crbug.com/1310026): When Vulkan/GL interop is supported on Fuchsia // OzoneImageBacking should be used for all scanout buffers. - constexpr uint32_t kPrimaryPlaneUsageFlags = SHARED_IMAGE_USAGE_DISPLAY_READ | - SHARED_IMAGE_USAGE_SCANOUT | - SHARED_IMAGE_USAGE_RASTER; + constexpr uint32_t kPrimaryPlaneUsageFlags = + SHARED_IMAGE_USAGE_DISPLAY_READ | SHARED_IMAGE_USAGE_DISPLAY_WRITE | + SHARED_IMAGE_USAGE_SCANOUT | SHARED_IMAGE_USAGE_RASTER; if (usage != kPrimaryPlaneUsageFlags || gmb_type != gfx::EMPTY_BUFFER) { return false; }
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 4046f05..e315de9 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
@@ -551,8 +551,9 @@ return true; // DISPLAY is for gpu composition and SCANOUT for overlays. - constexpr int kDisplayCompositorUsage = - SHARED_IMAGE_USAGE_DISPLAY_READ | SHARED_IMAGE_USAGE_SCANOUT; + constexpr int kDisplayCompositorUsage = SHARED_IMAGE_USAGE_DISPLAY_READ | + SHARED_IMAGE_USAGE_DISPLAY_WRITE | + SHARED_IMAGE_USAGE_SCANOUT; // Image is used on display compositor gpu thread if it's used by display // compositor and if display compositor runs on a separate thread. Image is
diff --git a/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc b/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc index 39aeff0..d47ac6e 100644 --- a/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc +++ b/gpu/command_buffer/service/shared_image/skia_vk_android_image_representation.cc
@@ -274,9 +274,9 @@ if (!vulkan_image_) return nullptr; - const uint32_t kSingleDeviceUsage = SHARED_IMAGE_USAGE_DISPLAY_READ | - SHARED_IMAGE_USAGE_RASTER | - SHARED_IMAGE_USAGE_OOP_RASTERIZATION; + const uint32_t kSingleDeviceUsage = + SHARED_IMAGE_USAGE_DISPLAY_READ | SHARED_IMAGE_USAGE_DISPLAY_WRITE | + SHARED_IMAGE_USAGE_RASTER | SHARED_IMAGE_USAGE_OOP_RASTERIZATION; // If SharedImage is used outside of current VkDeviceQueue we need to transfer // image back to it's original queue. Note, that for multithreading we use
diff --git a/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc b/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc index 88daa63..94b8d924 100644 --- a/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc +++ b/gpu/command_buffer/service/shared_image/skia_vk_ozone_image_representation.cc
@@ -241,9 +241,9 @@ if (!vulkan_image_) return nullptr; - const uint32_t kSingleDeviceUsage = SHARED_IMAGE_USAGE_DISPLAY_READ | - SHARED_IMAGE_USAGE_RASTER | - SHARED_IMAGE_USAGE_OOP_RASTERIZATION; + const uint32_t kSingleDeviceUsage = + SHARED_IMAGE_USAGE_DISPLAY_READ | SHARED_IMAGE_USAGE_DISPLAY_WRITE | + SHARED_IMAGE_USAGE_RASTER | SHARED_IMAGE_USAGE_OOP_RASTERIZATION; // If SharedImage is used outside of current VkDeviceQueue we need to transfer // image back to it's original queue. Note, that for multithreading we use
diff --git a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc index 72971194..6fcecd9 100644 --- a/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/wrapped_sk_image_backing_factory.cc
@@ -498,8 +498,9 @@ // Ignore for mipmap usage. usage &= ~SHARED_IMAGE_USAGE_MIPMAP; auto kWrappedSkImageUsage = - SHARED_IMAGE_USAGE_DISPLAY_READ | SHARED_IMAGE_USAGE_RASTER | - SHARED_IMAGE_USAGE_OOP_RASTERIZATION | SHARED_IMAGE_USAGE_CPU_UPLOAD; + SHARED_IMAGE_USAGE_DISPLAY_READ | SHARED_IMAGE_USAGE_DISPLAY_WRITE | + SHARED_IMAGE_USAGE_RASTER | SHARED_IMAGE_USAGE_OOP_RASTERIZATION | + SHARED_IMAGE_USAGE_CPU_UPLOAD; return (usage & kWrappedSkImageUsage) && !(usage & ~kWrappedSkImageUsage); }
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Pixel 4\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Pixel 4\051/properties.json" new file mode 100644 index 0000000..a47379d2 --- /dev/null +++ "b/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Pixel 4\051/properties.json"
@@ -0,0 +1,67 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Dawn Android arm DEPS Release (Pixel 4)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-dawn-archive", + "builder_group": "chromium.dawn", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_rel_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "config": "android", + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + }, + "run_tests_serially": true + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Dawn Android arm DEPS Release (Pixel 4)", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "dawn-android-arm-deps-rel", + "group": "tryserver.chromium.dawn" + } + ] + } + }, + "$build/reclient": { + "instance": "rbe-chromium-trusted", + "jobs": 500, + "metrics_project": "chromium-reclient-metrics" + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "chromium.dawn", + "recipe": "chromium" +} \ No newline at end of file
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm Release \050Pixel 4\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm Release \050Pixel 4\051/properties.json" new file mode 100644 index 0000000..f134011 --- /dev/null +++ "b/infra/config/generated/builders/ci/Dawn Android arm Release \050Pixel 4\051/properties.json"
@@ -0,0 +1,68 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Dawn Android arm Release (Pixel 4)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-dawn-archive", + "builder_group": "chromium.dawn", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_rel_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "config": "android", + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "dawn_top_of_tree", + "enable_reclient" + ], + "config": "chromium" + }, + "run_tests_serially": true + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Dawn Android arm Release (Pixel 4)", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-dawn-arm-rel", + "group": "tryserver.chromium.dawn" + } + ] + } + }, + "$build/reclient": { + "instance": "rbe-chromium-trusted", + "jobs": 500, + "metrics_project": "chromium-reclient-metrics" + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "chromium.dawn", + "recipe": "chromium" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTFuchsiaOfficial/properties.json b/infra/config/generated/builders/ci/ToTFuchsiaOfficial arm64/properties.json similarity index 100% rename from infra/config/generated/builders/ci/ToTFuchsiaOfficial/properties.json rename to infra/config/generated/builders/ci/ToTFuchsiaOfficial arm64/properties.json
diff --git a/infra/config/generated/builders/try/android-dawn-arm-rel/properties.json b/infra/config/generated/builders/try/android-dawn-arm-rel/properties.json new file mode 100644 index 0000000..95aee61 --- /dev/null +++ b/infra/config/generated/builders/try/android-dawn-arm-rel/properties.json
@@ -0,0 +1,64 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Dawn Android arm Release (Pixel 4)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-dawn-archive", + "builder_group": "chromium.dawn", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_rel_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "config": "android", + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "dawn_top_of_tree", + "enable_reclient" + ], + "config": "chromium" + }, + "run_tests_serially": true + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Dawn Android arm Release (Pixel 4)", + "project": "chromium" + } + ] + } + }, + "$build/goma": { + "enable_ats": true, + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite", + "v.gpu" + ] + }, + "builder_group": "tryserver.chromium.dawn", + "recipe": "chromium_trybot" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json b/infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json new file mode 100644 index 0000000..55588c60 --- /dev/null +++ b/infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json
@@ -0,0 +1,63 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "Dawn Android arm DEPS Release (Pixel 4)", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-dawn-archive", + "builder_group": "chromium.dawn", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "main_builder_rel_mb" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "config": "android", + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + }, + "run_tests_serially": true + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "Dawn Android arm DEPS Release (Pixel 4)", + "project": "chromium" + } + ] + } + }, + "$build/goma": { + "enable_ats": true, + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite", + "v.gpu" + ] + }, + "builder_group": "tryserver.chromium.dawn", + "recipe": "chromium_trybot" +} \ No newline at end of file
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index 824df8ab..be14a27 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -212,6 +212,21 @@ * [`//build/config/chromeos/.*`](https://cs.chromium.org/search?q=+file:build/config/chromeos/.*) * [`//chromeos/CHROMEOS_LKGM`](https://cs.chromium.org/chromium/src/chromeos/CHROMEOS_LKGM) +* [dawn-android-arm-deps-rel](https://ci.chromium.org/p/chromium/builders/try/dawn-android-arm-deps-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""dawn-android-arm-deps-rel"")) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+""dawn-android-arm-deps-rel"")) + + Path regular expressions: + * [`//content/test/gpu/.+`](https://cs.chromium.org/chromium/src/content/test/gpu/) + * [`//gpu/.+`](https://cs.chromium.org/chromium/src/gpu/) + * [`//testing/buildbot/chromium.dawn.json`](https://cs.chromium.org/search?q=+file:testing/buildbot/chromium.dawn.json) + * [`//third_party/blink/renderer/modules/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/modules/webgpu/) + * [`//third_party/blink/web_tests/external/wpt/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/external/wpt/webgpu/) + * [`//third_party/blink/web_tests/wpt_internal/webgpu/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/wpt_internal/webgpu/) + * [`//third_party/blink/web_tests/WebGPUExpectations`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/WebGPUExpectations) + * [`//third_party/dawn/.+`](https://cs.chromium.org/chromium/src/third_party/dawn/) + * [`//third_party/webgpu-cts/.+`](https://cs.chromium.org/chromium/src/third_party/webgpu-cts/) + * [`//tools/clang/scripts/update.py`](https://cs.chromium.org/search?q=+file:tools/clang/scripts/update.py) + * [`//ui/gl/features.gni`](https://cs.chromium.org/search?q=+file:ui/gl/features.gni) + * [dawn-linux-x64-deps-rel](https://ci.chromium.org/p/chromium/builders/try/dawn-linux-x64-deps-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""dawn-linux-x64-deps-rel"")) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+""dawn-linux-x64-deps-rel"")) Path regular expressions:
diff --git a/infra/config/generated/cq-usage/full.cfg b/infra/config/generated/cq-usage/full.cfg index 7240c87..e252d8e 100644 --- a/infra/config/generated/cq-usage/full.cfg +++ b/infra/config/generated/cq-usage/full.cfg
@@ -207,6 +207,22 @@ disable_reuse: true } builders { + name: "chromium/try/dawn-android-arm-deps-rel" + location_regexp: ".+/[+]/content/test/gpu/.+" + location_regexp: ".+/[+]/gpu/.+" + location_regexp: ".+/[+]/testing/buildbot/chromium.dawn.json" + location_regexp: ".+/[+]/third_party/blink/renderer/modules/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/external/wpt/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" + location_regexp: ".+/[+]/third_party/dawn/.+" + location_regexp: ".+/[+]/third_party/webgpu-cts/.+" + location_regexp: ".+/[+]/tools/clang/scripts/update.py" + location_regexp: ".+/[+]/ui/gl/features.gni" + location_regexp_exclude: ".+/[+]/docs/.+" + location_regexp_exclude: ".+/[+]/infra/config/.+" + } + builders { name: "chromium/try/dawn-linux-x64-deps-rel" location_regexp: ".+/[+]/content/test/gpu/.+" location_regexp: ".+/[+]/gpu/.+"
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index ee82cdca..19f444b6 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -534,6 +534,10 @@ includable_only: true } builders { + name: "chromium/try/android-dawn-arm-rel" + includable_only: true + } + builders { name: "chromium/try/android-deterministic-dbg" includable_only: true } @@ -1460,6 +1464,89 @@ disable_reuse: true } builders { + name: "chromium/try/dawn-android-arm-deps-rel" + location_regexp: ".+/[+]/content/test/gpu/.+" + location_regexp: ".+/[+]/gpu/.+" + location_regexp: ".+/[+]/testing/buildbot/chromium.dawn.json" + location_regexp: ".+/[+]/third_party/blink/renderer/modules/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/external/wpt/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+" + location_regexp: ".+/[+]/third_party/blink/web_tests/WebGPUExpectations" + location_regexp: ".+/[+]/third_party/dawn/.+" + location_regexp: ".+/[+]/third_party/webgpu-cts/.+" + location_regexp: ".+/[+]/tools/clang/scripts/update.py" + location_regexp: ".+/[+]/ui/gl/features.gni" + location_regexp_exclude: ".+/[+]/docs/.+" + location_regexp_exclude: ".+/[+]/infra/config/.+" + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "content/test/gpu/.+" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "gpu/.+" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "testing/buildbot/chromium.dawn.json" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "third_party/blink/renderer/modules/webgpu/.+" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "third_party/blink/web_tests/external/wpt/webgpu/.+" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "third_party/blink/web_tests/wpt_internal/webgpu/.+" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "third_party/blink/web_tests/WebGPUExpectations" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "third_party/dawn/.+" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "third_party/webgpu-cts/.+" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "tools/clang/scripts/update.py" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "ui/gl/features.gni" + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "docs/.+" + exclude: true + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "infra/config/.+" + exclude: true + } + } + builders { name: "chromium/try/dawn-linux-x64-deps-rel" location_regexp: ".+/[+]/content/test/gpu/.+" location_regexp: ".+/[+]/gpu/.+"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 8a83df7..611d15d 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -5333,6 +5333,174 @@ } } builders { + name: "Dawn Android arm DEPS Release (Pixel 4)" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "free_space:standard" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.gpu.ci" + dimensions: "ssd:0" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/ci/Dawn Android arm DEPS Release (Pixel 4)/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.dawn",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 10 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { + name: "Dawn Android arm Release (Pixel 4)" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "free_space:standard" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.gpu.ci" + dimensions: "ssd:0" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/ci/Dawn Android arm Release (Pixel 4)/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.dawn",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 10 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "Dawn Linux x64 Builder" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -19410,7 +19578,7 @@ } } builders { - name: "ToTFuchsiaOfficial" + name: "ToTFuchsiaOfficial arm64" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "cores:32" @@ -19436,7 +19604,7 @@ ' }' ' },' ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/ci/ToTFuchsiaOfficial/properties.json",' + ' "properties_file": "infra/config/generated/builders/ci/ToTFuchsiaOfficial arm64/properties.json",' ' "top_level_project": {' ' "ref": "refs/heads/main",' ' "repo": {' @@ -24648,6 +24816,10 @@ value: 10 } experiments { + key: "luci.buildbucket.omit_python2" + value: 100 + } + experiments { key: "luci.recipes.use_python3" value: 100 } @@ -56827,6 +56999,110 @@ } } builders { + name: "android-dawn-arm-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builder:android-dawn-arm-rel" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.try" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/try/android-dawn-arm-rel/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.dawn",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium_trybot"' + '}' + execution_timeout_secs: 14400 + expiration_secs: 7200 + grace_period { + seconds: 120 + } + caches { + name: "win_toolchain" + path: "win_toolchain" + } + build_numbers: YES + service_account: "chromium-try-gpu-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 20 + } + experiments { + key: "enable_weetbix_queries" + value: 100 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + experiments { + key: "weetbix.enable_weetbix_exonerations" + value: 100 + } + experiments { + key: "weetbix.retry_weak_exonerations" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "android-deterministic-dbg" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -64186,6 +64462,110 @@ } } builders { + name: "dawn-android-arm-deps-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builder:dawn-android-arm-deps-rel" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.try" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.dawn",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium_trybot"' + '}' + execution_timeout_secs: 14400 + expiration_secs: 7200 + grace_period { + seconds: 120 + } + caches { + name: "win_toolchain" + path: "win_toolchain" + } + build_numbers: YES + service_account: "chromium-try-gpu-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 20 + } + experiments { + key: "enable_weetbix_queries" + value: 100 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + experiments { + key: "weetbix.enable_weetbix_exonerations" + value: 100 + } + experiments { + key: "weetbix.retry_weak_exonerations" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "dawn-linux-x64-deps-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builder:dawn-linux-x64-deps-rel"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index 59ab3a7..c688c5a 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -1820,6 +1820,26 @@ short_name: "rel-ng" } builders { + name: "buildbucket/luci.chrome.ci/fuchsia-builder-perf-fyi" + category: "p/chrome|arm64" + short_name: "perf-bld" + } + builders { + name: "buildbucket/luci.chrome.ci/fuchsia-fyi-arm64-size" + category: "p/chrome|arm64" + short_name: "size" + } + builders { + name: "buildbucket/luci.chrome.ci/fuchsia-builder-perf-x64" + category: "p/chrome|x64" + short_name: "perf-bld" + } + builders { + name: "buildbucket/luci.chrome.ci/fuchsia-x64" + category: "p/chrome|x64" + short_name: "rel" + } + builders { name: "buildbucket/luci.chrome.ci/fuchsia-fyi-astro" category: "hardware" short_name: "ast" @@ -1850,55 +1870,50 @@ short_name: "sher" } builders { + name: "buildbucket/luci.chromium.ci/fuchsia-fyi-arm64-cfv2-script" + category: "fyi|arm64" + short_name: "cfv2" + } + builders { + name: "buildbucket/luci.chromium.ci/fuchsia-fyi-arm64-emu-arg" + category: "fyi|arm64" + short_name: "emu-arg" + } + builders { name: "buildbucket/luci.chromium.ci/fuchsia-fyi-arm64-rel" - category: "fyi" - short_name: "arm64" + category: "fyi|arm64" + short_name: "fyi-rel" } builders { - name: "buildbucket/luci.chromium.ci/ToTFuchsiaOfficial" - category: "fyi" - short_name: "clang-off" - } - builders { - name: "buildbucket/luci.chromium.ci/ToTFuchsia x64" - category: "fyi" - short_name: "clang-x64" + name: "buildbucket/luci.chromium.ci/fuchsia-fyi-cfv2-script" + category: "fyi|x64" + short_name: "cfv2" } builders { name: "buildbucket/luci.chromium.ci/fuchsia-code-coverage" - category: "fyi" + category: "fyi|x64" short_name: "cov" } builders { + name: "buildbucket/luci.chromium.ci/fuchsia-fyi-x64-rel" + category: "fyi|x64" + short_name: "fyi-rel" + } + builders { name: "buildbucket/luci.chromium.ci/fuchsia-fyi-x64-wst" - category: "fyi" + category: "fyi|x64" short_name: "work" } builders { - name: "buildbucket/luci.chromium.ci/fuchsia-fyi-x64-rel" - category: "fyi" + name: "buildbucket/luci.chromium.ci/ToTFuchsiaOfficial arm64" + category: "fyi|clang" + short_name: "arm64-off" + } + builders { + name: "buildbucket/luci.chromium.ci/ToTFuchsia x64" + category: "fyi|clang" short_name: "x64" } - builders { - name: "buildbucket/luci.chrome.ci/fuchsia-builder-perf-fyi" - category: "p/chrome|arm64" - short_name: "perf-bld" - } - builders { - name: "buildbucket/luci.chrome.ci/fuchsia-fyi-arm64-size" - category: "p/chrome|arm64" - short_name: "size" - } - builders { - name: "buildbucket/luci.chrome.ci/fuchsia-builder-perf-x64" - category: "p/chrome|x64" - short_name: "perf-bld" - } - builders { - name: "buildbucket/luci.chrome.ci/fuchsia-x64" - category: "p/chrome|x64" - short_name: "rel" - } header { oncalls { name: "Chromium" @@ -2693,6 +2708,9 @@ name: "buildbucket/luci.chromium.try/chromium_presubmit" } builders { + name: "buildbucket/luci.chromium.try/dawn-android-arm-deps-rel" + } + builders { name: "buildbucket/luci.chromium.try/dawn-linux-x64-deps-rel" } builders { @@ -6023,7 +6041,7 @@ short_name: "rel" } builders { - name: "buildbucket/luci.chromium.ci/ToTFuchsiaOfficial" + name: "buildbucket/luci.chromium.ci/ToTFuchsiaOfficial arm64" category: "ToT Fuchsia" short_name: "off" } @@ -6378,6 +6396,11 @@ refs: "regexp:refs/heads/main" manifest_name: "REVISION" builders { + name: "buildbucket/luci.chromium.ci/Dawn Android arm Release (Pixel 4)" + category: "ToT|Android" + short_name: "p4" + } + builders { name: "buildbucket/luci.chromium.ci/Dawn Linux x64 Builder" category: "ToT|Linux|Builder" short_name: "x64" @@ -6453,6 +6476,11 @@ short_name: "x64" } builders { + name: "buildbucket/luci.chromium.ci/Dawn Android arm DEPS Release (Pixel 4)" + category: "DEPS|Android" + short_name: "p4" + } + builders { name: "buildbucket/luci.chromium.ci/Dawn Linux x64 DEPS Builder" category: "DEPS|Linux|Builder" short_name: "x64" @@ -8130,7 +8158,7 @@ builders { name: "buildbucket/luci.chromium.ci/fuchsia-code-coverage" category: "code_coverage" - short_name: "fsa" + short_name: "fx" } builders { name: "buildbucket/luci.chromium.ci/ios-simulator-code-coverage" @@ -16169,6 +16197,9 @@ name: "buildbucket/luci.chromium.try/android-cronet-x86-rel-kitkat-tests" } builders { + name: "buildbucket/luci.chromium.try/android-dawn-arm-rel" + } + builders { name: "buildbucket/luci.chromium.try/android-deterministic-dbg" } builders { @@ -16376,6 +16407,9 @@ name: "buildbucket/luci.chromium.try/chromium_presubmit" } builders { + name: "buildbucket/luci.chromium.try/dawn-android-arm-deps-rel" + } + builders { name: "buildbucket/luci.chromium.try/dawn-linux-x64-deps-rel" } builders { @@ -17670,6 +17704,12 @@ id: "tryserver.chromium.dawn" name: "tryserver.chromium.dawn" builders { + name: "buildbucket/luci.chromium.try/android-dawn-arm-rel" + } + builders { + name: "buildbucket/luci.chromium.try/dawn-android-arm-deps-rel" + } + builders { name: "buildbucket/luci.chromium.try/dawn-linux-x64-deps-rel" } builders {
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index c7d1ee0..0297889 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -899,6 +899,26 @@ } } job { + id: "Dawn Android arm DEPS Release (Pixel 4)" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "Dawn Android arm DEPS Release (Pixel 4)" + } +} +job { + id: "Dawn Android arm Release (Pixel 4)" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "Dawn Android arm Release (Pixel 4)" + } +} +job { id: "Dawn Linux x64 Builder" realm: "ci" acl_sets: "ci" @@ -3065,13 +3085,13 @@ } } job { - id: "ToTFuchsiaOfficial" + id: "ToTFuchsiaOfficial arm64" realm: "ci" acl_sets: "ci" buildbucket { server: "cr-buildbucket.appspot.com" bucket: "ci" - builder: "ToTFuchsiaOfficial" + builder: "ToTFuchsiaOfficial arm64" } } job { @@ -7341,6 +7361,8 @@ triggers: "Comparison ios (reclient)(CQ)" triggers: "CrWinAsan" triggers: "CrWinAsan(dll)" + triggers: "Dawn Android arm DEPS Release (Pixel 4)" + triggers: "Dawn Android arm Release (Pixel 4)" triggers: "Dawn Linux x64 Builder" triggers: "Dawn Linux x64 DEPS Builder" triggers: "Dawn Mac x64 Builder" @@ -7438,7 +7460,7 @@ triggers: "ToTChromeOS" triggers: "ToTChromeOS (dbg)" triggers: "ToTFuchsia x64" - triggers: "ToTFuchsiaOfficial" + triggers: "ToTFuchsiaOfficial arm64" triggers: "ToTLinux" triggers: "ToTLinux (dbg)" triggers: "ToTLinuxASan"
diff --git a/infra/config/generated/sheriff-rotations/chromium.clang.txt b/infra/config/generated/sheriff-rotations/chromium.clang.txt index 116e2d9e..dff9a476 100644 --- a/infra/config/generated/sheriff-rotations/chromium.clang.txt +++ b/infra/config/generated/sheriff-rotations/chromium.clang.txt
@@ -13,7 +13,7 @@ ci/ToTChromeOS ci/ToTChromeOS (dbg) ci/ToTFuchsia x64 -ci/ToTFuchsiaOfficial +ci/ToTFuchsiaOfficial arm64 ci/ToTLinux ci/ToTLinux (dbg) ci/ToTLinuxASan
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star index ce0df148..56dc6af 100644 --- a/infra/config/subprojects/chromium/ci.star +++ b/infra/config/subprojects/chromium/ci.star
@@ -103,9 +103,8 @@ name = "sheriff.fuchsia", title = "Fuchsia Sheriff Console", ordering = { - "*type*": consoles.ordering(short_names = ["a64", "x64"]), - None: ["ci", "fuchsia ci", "hardware", "fyi"], - "chromium.fyi|13": "*type*", + None: ["ci", "fuchsia ci", "p/chrome", "hardware", "fyi"], + "fyi": ["arm64", "x64", "clang"], }, )
diff --git a/infra/config/subprojects/chromium/ci/chromium.clang.star b/infra/config/subprojects/chromium/ci/chromium.clang.star index b47c442..472e3b7 100644 --- a/infra/config/subprojects/chromium/ci/chromium.clang.star +++ b/infra/config/subprojects/chromium/ci/chromium.clang.star
@@ -226,14 +226,14 @@ consoles.console_view_entry( branch_selector = branches.MAIN, console_view = "sheriff.fuchsia", - category = "fyi", - short_name = "clang-x64", + category = "fyi|clang", + short_name = "x64", ), ], ) ci.builder( - name = "ToTFuchsiaOfficial", + name = "ToTFuchsiaOfficial arm64", console_view_entry = [ consoles.console_view_entry( category = "ToT Fuchsia", @@ -242,8 +242,8 @@ consoles.console_view_entry( branch_selector = branches.MAIN, console_view = "sheriff.fuchsia", - category = "fyi", - short_name = "clang-off", + category = "fyi|clang", + short_name = "arm64-off", ), ], )
diff --git a/infra/config/subprojects/chromium/ci/chromium.dawn.star b/infra/config/subprojects/chromium/ci/chromium.dawn.star index 44374d2..e6138e8 100644 --- a/infra/config/subprojects/chromium/ci/chromium.dawn.star +++ b/infra/config/subprojects/chromium/ci/chromium.dawn.star
@@ -98,6 +98,37 @@ cq_mirrors_console_view = "mirrors", ) +ci.gpu.linux_builder( + name = "Dawn Android arm DEPS Release (Pixel 4)", + branch_selector = branches.STANDARD_MILESTONE, + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + "enable_reclient", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "mb", + ], + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_rel_mb", + ), + build_gs_bucket = "chromium-dawn-archive", + run_tests_serially = True, + ), + console_view_entry = consoles.console_view_entry( + category = "DEPS|Android", + short_name = "p4", + ), + reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI, +) + ci.thin_tester( name = "Dawn Linux x64 DEPS Release (Intel UHD 630)", branch_selector = branches.STANDARD_MILESTONE, @@ -154,6 +185,37 @@ triggered_by = ["ci/Dawn Linux x64 DEPS Builder"], ) +ci.gpu.linux_builder( + name = "Dawn Android arm Release (Pixel 4)", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + "dawn_top_of_tree", + "enable_reclient", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "mb", + ], + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "main_builder_rel_mb", + ), + build_gs_bucket = "chromium-dawn-archive", + run_tests_serially = True, + ), + console_view_entry = consoles.console_view_entry( + category = "ToT|Android", + short_name = "p4", + ), + reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI, +) + ci.thin_tester( name = "Dawn Linux x64 Release (Intel UHD 630)", builder_spec = builder_config.builder_spec(
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 42a97a0d..ce60690 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -200,6 +200,12 @@ category = "fuchsia|arm64", short_name = "emu-arg", ), + consoles.console_view_entry( + branch_selector = branches.MAIN, + console_view = "sheriff.fuchsia", + category = "fyi|arm64", + short_name = "emu-arg", + ), ], notifies = ["cr-fuchsia-engprod"], os = os.LINUX_DEFAULT, @@ -215,8 +221,8 @@ consoles.console_view_entry( branch_selector = branches.MAIN, console_view = "sheriff.fuchsia", - category = "fyi", - short_name = "arm64", + category = "fyi|arm64", + short_name = "fyi-rel", ), ], notifies = ["cr-fuchsia"], @@ -249,6 +255,12 @@ category = "fuchsia|x64", short_name = "cfv2", ), + consoles.console_view_entry( + branch_selector = branches.MAIN, + console_view = "sheriff.fuchsia", + category = "fyi|x64", + short_name = "cfv2", + ), ], os = os.LINUX_DEFAULT, ) @@ -281,6 +293,12 @@ category = "fuchsia|arm64", short_name = "cfv2", ), + consoles.console_view_entry( + branch_selector = branches.MAIN, + console_view = "sheriff.fuchsia", + category = "fyi|arm64", + short_name = "cfv2", + ), ], os = os.LINUX_DEFAULT, ) @@ -295,8 +313,8 @@ consoles.console_view_entry( branch_selector = branches.MAIN, console_view = "sheriff.fuchsia", - category = "fyi", - short_name = "x64", + category = "fyi|x64", + short_name = "fyi-rel", ), ], notifies = ["cr-fuchsia"], @@ -313,7 +331,7 @@ consoles.console_view_entry( branch_selector = branches.MAIN, console_view = "sheriff.fuchsia", - category = "fyi", + category = "fyi|x64", short_name = "work", ), ], @@ -1825,12 +1843,12 @@ console_view_entry = [ consoles.console_view_entry( category = "code_coverage", - short_name = "fsa", + short_name = "fx", ), consoles.console_view_entry( branch_selector = branches.MAIN, console_view = "sheriff.fuchsia", - category = "fyi", + category = "fyi|x64", short_name = "cov", ), ],
diff --git a/infra/config/subprojects/chromium/ci/chromium.win.star b/infra/config/subprojects/chromium/ci/chromium.win.star index 3741d94..af36797 100644 --- a/infra/config/subprojects/chromium/ci/chromium.win.star +++ b/infra/config/subprojects/chromium/ci/chromium.win.star
@@ -348,7 +348,4 @@ ), executable = "recipe:swarming/deterministic_build", execution_timeout = 12 * time.hour, - - # TODO(https://crbug.com/1362440): remove this and use default value. - omit_python2 = False, )
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star b/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star index 124b69ce..d7d841b 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.dawn.star
@@ -28,6 +28,33 @@ ) try_.builder( + name = "dawn-android-arm-deps-rel", + branch_selector = branches.STANDARD_MILESTONE, + mirrors = [ + "ci/Dawn Android arm DEPS Release (Pixel 4)", + ], + main_list_view = "try", + tryjob = try_.job( + location_regexp = [ + ".+/[+]/content/test/gpu/.+", + ".+/[+]/gpu/.+", + ".+/[+]/testing/buildbot/chromium.dawn.json", + ".+/[+]/third_party/blink/renderer/modules/webgpu/.+", + ".+/[+]/third_party/blink/web_tests/external/wpt/webgpu/.+", + ".+/[+]/third_party/blink/web_tests/wpt_internal/webgpu/.+", + ".+/[+]/third_party/blink/web_tests/WebGPUExpectations", + ".+/[+]/third_party/dawn/.+", + ".+/[+]/third_party/webgpu-cts/.+", + ".+/[+]/tools/clang/scripts/update.py", + ".+/[+]/ui/gl/features.gni", + ], + ), + test_presentation = resultdb.test_presentation( + grouping_keys = ["status", "v.test_suite", "v.gpu"], + ), +) + +try_.builder( name = "dawn-linux-x64-deps-rel", branch_selector = branches.STANDARD_MILESTONE, mirrors = [ @@ -147,6 +174,16 @@ ) try_.builder( + name = "android-dawn-arm-rel", + mirrors = [ + "ci/Dawn Android arm Release (Pixel 4)", + ], + test_presentation = resultdb.test_presentation( + grouping_keys = ["status", "v.test_suite", "v.gpu"], + ), +) + +try_.builder( name = "linux-dawn-rel", mirrors = [ "ci/Dawn Linux x64 Builder",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star index f518e2a..6cb6871 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -333,9 +333,6 @@ check_for_flakiness = True, branch_selector = branches.STANDARD_MILESTONE, main_list_view = "try", - experiments = { - "luci.buildbucket.omit_python2": 100, - }, os = os.MAC_DEFAULT, ssd = None, xcode = xcode.x14main,
diff --git a/ios/chrome/browser/translate/translate_app_interface.mm b/ios/chrome/browser/translate/translate_app_interface.mm index a462111..0253f27 100644 --- a/ios/chrome/browser/translate/translate_app_interface.mm +++ b/ios/chrome/browser/translate/translate_app_interface.mm
@@ -14,7 +14,8 @@ #import "components/translate/core/common/language_detection_details.h" #import "components/translate/core/common/translate_switches.h" #import "components/translate/core/common/translate_util.h" -#import "components/translate/ios/browser/js_translate_manager.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager.h" +#import "components/translate/ios/browser/js_translate_web_frame_manager_factory.h" #import "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/translate/chrome_ios_translate_client.h" #import "ios/chrome/test/app/chrome_test_util.h" @@ -97,76 +98,89 @@ std::unique_ptr<FakeNetworkChangeNotifier> network_change_notifier_; }; -} // namespace +class FakeJSTranslateWebFrameManager : public JSTranslateWebFrameManager { + public: + FakeJSTranslateWebFrameManager(web::WebFrame* web_frame) + : JSTranslateWebFrameManager(web_frame) {} + ~FakeJSTranslateWebFrameManager() override = default; -#pragma mark - FakeJSTranslateManager + void InjectTranslateScript(const std::string& script) override { + // No need to set the `translate_script` JavaScript since it will never be + // used by this fake object. Instead just invoke host with 'translate.ready' + // followed by 'translate.status'. + base::Value translate_ready_dict(base::Value::Type::DICTIONARY); + translate_ready_dict.SetKey("command", base::Value("ready")); + translate_ready_dict.SetKey("errorCode", base::Value(0)); + translate_ready_dict.SetKey("loadTime", base::Value(0)); + translate_ready_dict.SetKey("readyTime", base::Value(0)); -// Fake translate manager to be used in tests so no network is needed. -// Translating the page just adds a 'Translated' button to the page, without -// changing the text. -@interface FakeJSTranslateManager : JsTranslateManager { - web::WebState* _webState; -} + std::vector<base::Value> translate_ready_params; + translate_ready_params.push_back(base::Value("TranslateMessage")); + translate_ready_params.push_back(std::move(translate_ready_dict)); + web_frame_->CallJavaScriptFunction("common.sendWebKitMessage", + translate_ready_params); -- (instancetype)initWithWebState:(web::WebState*)webState; + base::Value translate_status_dict(base::Value::Type::DICTIONARY); + translate_status_dict.SetKey("command", base::Value("status")); + translate_status_dict.SetKey("errorCode", base::Value(0)); + translate_status_dict.SetKey("pageSourceLanguage", base::Value("fr")); + translate_status_dict.SetKey("translationTime", base::Value(0)); -@end - -@implementation FakeJSTranslateManager - -- (instancetype)initWithWebState:(web::WebState*)webState { - if ((self = [super initWithWebState:webState])) { - _webState = webState; + std::vector<base::Value> translate_status_params; + translate_status_params.push_back(base::Value("TranslateMessage")); + translate_status_params.push_back(std::move(translate_status_dict)); + web_frame_->CallJavaScriptFunction("common.sendWebKitMessage", + translate_status_params); } - return self; -} -- (void)startTranslationFrom:(const std::string&)source - to:(const std::string&)target { - // Add a button with the 'Translated' label to the web page. - // The test can check it to determine if this method has been called. - _webState->ExecuteJavaScript( - u"myButton = document.createElement('button');" - u"myButton.setAttribute('id', 'translated-button');" - u"myButton.appendChild(document.createTextNode('Translated'));" - u"document.body.prepend(myButton);"); -} + void StartTranslation(const std::string& source, + const std::string& target) override { + // Add a button with the 'Translated' label to the web page. + // The test can check it to determine if this method has been called. + web_frame_->ExecuteJavaScript( + u"myButton = document.createElement('button');" + u"myButton.setAttribute('id', 'translated-button');" + u"myButton.appendChild(document.createTextNode('Translated'));" + u"document.body.prepend(myButton);"); + } -- (void)revertTranslation { - // Removes the button with 'translated-button' id from the web page, if any. - _webState->ExecuteJavaScript( - u"myButton = document.getElementById('translated-button');" - u"myButton.remove();"); -} + void RevertTranslation() override { + // Removes the button with 'translated-button' id from the web page, if any. + web_frame_->ExecuteJavaScript( + u"myButton = document.getElementById('translated-button');" + u"myButton.remove();"); + } +}; -- (void)injectWithTranslateScript:(const std::string&)translate_script { - // No need to set the `translate_script` JavaScript since it will never be - // used by this fake object. Instead just invoke host with 'translate.ready' - // followed by 'translate.status'. - base::Value translate_ready_dict(base::Value::Type::DICTIONARY); - translate_ready_dict.SetKey("command", base::Value("translate.ready")); - translate_ready_dict.SetKey("errorCode", base::Value(0)); - translate_ready_dict.SetKey("loadTime", base::Value(0)); - translate_ready_dict.SetKey("readyTime", base::Value(0)); +class FakeJSTranslateWebFrameManagerFactory + : public JSTranslateWebFrameManagerFactory { + public: + FakeJSTranslateWebFrameManagerFactory() {} + ~FakeJSTranslateWebFrameManagerFactory() {} - std::vector<base::Value> translate_ready_params; - translate_ready_params.push_back(std::move(translate_ready_dict)); - GetMainFrame(_webState)->CallJavaScriptFunction("message.invokeOnHost", - translate_ready_params); + static FakeJSTranslateWebFrameManagerFactory* GetInstance() { + static base::NoDestructor<FakeJSTranslateWebFrameManagerFactory> instance; + return instance.get(); + } - base::Value translate_status_dict(base::Value::Type::DICTIONARY); - translate_status_dict.SetKey("command", base::Value("translate.status")); - translate_status_dict.SetKey("errorCode", base::Value(0)); - translate_status_dict.SetKey("pageSourceLanguage", base::Value("fr")); - translate_status_dict.SetKey("translationTime", base::Value(0)); + JSTranslateWebFrameManager* FromWebFrame(web::WebFrame* web_frame) override { + if (managers_.find(web_frame->GetFrameId()) == managers_.end()) { + managers_[web_frame->GetFrameId()] = + std::make_unique<FakeJSTranslateWebFrameManager>(web_frame); + } + return managers_[web_frame->GetFrameId()].get(); + } - std::vector<base::Value> translate_status_params; - translate_status_params.push_back(std::move(translate_status_dict)); - GetMainFrame(_webState)->CallJavaScriptFunction("message.invokeOnHost", - translate_status_params); -} + void CreateForWebFrame(web::WebFrame* web_frame) override { + // no-op, managers are created lazily in FromWebState + } -@end + private: + std::map<std::string, std::unique_ptr<FakeJSTranslateWebFrameManager>> + managers_; +}; + +} // namespace #pragma mark - TranslateAppInterface @@ -246,15 +260,11 @@ } + (void)setUpFakeJSTranslateManagerInCurrentTab { - ChromeIOSTranslateClient* client = ChromeIOSTranslateClient::FromWebState( - chrome_test_util::GetCurrentWebState()); - translate::IOSTranslateDriver* driver = - static_cast<translate::IOSTranslateDriver*>(client->GetTranslateDriver()); - FakeJSTranslateManager* fakeJSTranslateManager = - [[FakeJSTranslateManager alloc] - initWithWebState:chrome_test_util::GetCurrentWebState()]; - driver->translate_controller()->SetJsTranslateManagerForTesting( - fakeJSTranslateManager); + translate::TranslateController* translate_controller = + translate::TranslateController::FromWebState( + chrome_test_util::GetCurrentWebState()); + translate_controller->SetJsTranslateWebFrameManagerFactoryForTesting( + FakeJSTranslateWebFrameManagerFactory::GetInstance()); } + (BOOL)shouldAutoTranslateFromLanguage:(NSString*)source
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/BUILD.gn b/ios/chrome/browser/ui/autofill/form_input_accessory/BUILD.gn index 0e6b2cae..ee9f6a1c 100644 --- a/ios/chrome/browser/ui/autofill/form_input_accessory/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/form_input_accessory/BUILD.gn
@@ -103,3 +103,20 @@ "//third_party/ocmock", ] } + +source_set("eg2_tests") { + configs += [ + "//build/config/compiler:enable_arc", + "//build/config/ios:xctest_config", + ] + testonly = true + sources = [ "branding_view_controller_egtest.mm" ] + deps = [ + "//base/test:test_support", + "//ios/chrome/browser/ui/autofill:eg_test_support+eg2", + "//ios/chrome/browser/ui/autofill:features", + "//ios/chrome/test/earl_grey:eg_test_support+eg2", + "//ios/testing/earl_grey:eg_test_support+eg2", + "//net:test_support", + ] +}
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/branding_view_controller.mm b/ios/chrome/browser/ui/autofill/form_input_accessory/branding_view_controller.mm index a0694e7..7c28937 100644 --- a/ios/chrome/browser/ui/autofill/form_input_accessory/branding_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/form_input_accessory/branding_view_controller.mm
@@ -19,12 +19,14 @@ constexpr CGFloat kLeadingInset = 10; // The scale used by the "pop" animation. constexpr CGFloat kAnimationScale = ((CGFloat)4) / 3; -// Wait time after the keyboard settles into placetwit to perform pop animation. +// Wait time after the keyboard settles into place to perform pop animation. constexpr base::TimeDelta kAnimationWaitTime = base::Milliseconds(200); // Time it takes the "pop" animation to perform. constexpr base::TimeDelta kTimeToAnimate = base::Milliseconds(400); // Minimum time interval between two animations. constexpr base::TimeDelta kMinTimeIntervalBetweenAnimations = base::Seconds(3); +// Accessibility ID of the view. +constexpr NSString* kBrandingButtonAXId = @"kBrandingButtonAXId"; } // namespace @interface BrandingViewController () @@ -69,6 +71,7 @@ } [button setImage:logo forState:UIControlStateNormal]; [button setImage:logo forState:UIControlStateHighlighted]; + button.accessibilityIdentifier = kBrandingButtonAXId; button.imageView.contentMode = UIViewContentModeScaleAspectFit; button.isAccessibilityElement = NO; // Prevents VoiceOver users from tap. button.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory/branding_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/form_input_accessory/branding_view_controller_egtest.mm new file mode 100644 index 0000000..007d6df9 --- /dev/null +++ b/ios/chrome/browser/ui/autofill/form_input_accessory/branding_view_controller_egtest.mm
@@ -0,0 +1,261 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "base/test/ios/wait_util.h" +#import "ios/chrome/browser/ui/autofill/autofill_app_interface.h" +#import "ios/chrome/browser/ui/autofill/features.h" +#import "ios/chrome/test/earl_grey/chrome_actions.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import "ios/chrome/test/earl_grey/chrome_matchers.h" +#import "ios/chrome/test/earl_grey/chrome_test_case.h" +#import "ios/testing/earl_grey/app_launch_manager.h" +#import "ios/testing/earl_grey/earl_grey_test.h" +#import "net/test/embedded_test_server/embedded_test_server.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using chrome_test_util::ButtonWithAccessibilityLabelId; +using chrome_test_util::ManualFallbackKeyboardIconMatcher; +using chrome_test_util::ManualFallbackPasswordIconMatcher; +using chrome_test_util::TapWebElementWithId; +using chrome_test_util::WebViewMatcher; + +namespace { +// HTML test page with form fields. +const char kFormHTMLFile[] = "/username_password_field_form.html"; +// The "username" field in the test page. +const char kFormElementUsername[] = "username"; + +// Save a set of credentials so that the manual fill password button is visible +// in keyboard accessories. +void EnableManualFillButtonForPassword() { + [AutofillAppInterface saveExamplePasswordForm]; +} + +// Save an address so that the manual fill address button is visible in keyboard +// accessories. +void EnableManualFillButtonForProfile() { + [AutofillAppInterface saveExampleProfile]; +} + +// Save a credit card information so that the manual fill credit card button is +// visible in keyboard accessories. +void EnableManualFillButtonForCreditCard() { + [AutofillAppInterface saveLocalCreditCard]; +} + +// Remove all saved passwords, credit cards and addresses so that no manual fill +// buttons will show in keyboard accessories. +void DisableManualFillButtons() { + [AutofillAppInterface clearPasswordStore]; + [AutofillAppInterface clearProfilesStore]; + [AutofillAppInterface clearCreditCardStore]; +} + +// Taps a form field to bring up the system keyboard. +void BringUpKeyboard() { + [[EarlGrey selectElementWithMatcher:WebViewMatcher()] + performAction:TapWebElementWithId(kFormElementUsername)]; +} + +// Check that the branding visibility matches the parameter `visibility`. +void CheckBrandingVisiblityWithDefaultTimeout(BOOL visibility) { + NSString* conditionDescription = visibility + ? @"Branding icon should be visible" + : @"Branding icon should be hidden"; + GREYCondition* visibilityCondition = [GREYCondition + conditionWithName:conditionDescription + block:^BOOL { + NSError* error; + [[EarlGrey + selectElementWithMatcher:grey_accessibilityID( + @"kBrandingButtonAXId")] + assertWithMatcher:visibility + ? grey_sufficientlyVisible() + : grey_notVisible() + error:&error]; + return error == nil; + }]; + BOOL success = [visibilityCondition + waitWithTimeout:base::test::ios::kWaitForUIElementTimeout.InSecondsF()]; + GREYAssertTrue(success, conditionDescription); +} + +} // namespace + +// Super class for integration Tests for Brandings View Controller. This class +// only defines setUp and tearDown methods; actual tests are implemented in +// subclasses with different feature flags. +@interface BrandingViewControllerTestCase : ChromeTestCase +@end + +@implementation BrandingViewControllerTestCase + +- (void)setUp { + [super setUp]; + GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); + GURL url = self.testServer->GetURL(kFormHTMLFile); + [ChromeEarlGrey loadURL:url]; + [ChromeEarlGrey waitForWebStateContainingText:"hello!"]; + DisableManualFillButtons(); +} + +- (void)tearDown { + DisableManualFillButtons(); + [super tearDown]; +} + +@end + +// BrandingViewControllerTestCases with flag enabled. +@interface BrandingViewControllerEnabledTestCase + : BrandingViewControllerTestCase +@end + +@implementation BrandingViewControllerEnabledTestCase + +- (AppLaunchConfiguration)appConfigurationForTestCase { + AppLaunchConfiguration config; + config.features_enabled.push_back(autofill::features::kAutofillBrandingIOS); + return config; +} + +// Tests that the branding is visible when some manual fill button is visible. +- (void)testSomeManualFillButtonsVisible { + EnableManualFillButtonForPassword(); + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(YES); +} + +// Tests that the branding is not visible when no manual fill button is visible. +- (void)testAllManualFillButtonsHidden { + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(NO); +} + +// Tests that the branding is not visible when some manual fill button is +// enabled then disabled before the keyboard is presented. +- (void)testEnableAndDisableManualFillButtonsBeforeKeyboardPresented { + EnableManualFillButtonForPassword(); + DisableManualFillButtons(); + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(NO); +} + +// Tests that the branding is visible when some manual fill button is enabled, +// disabled and re-enabled before the keyboard is presented. +- (void)testEnableDisableAndReenableManualFillButtonsBeforeKeyboardPresented { + EnableManualFillButtonForPassword(); + DisableManualFillButtons(); + EnableManualFillButtonForProfile(); + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(YES); +} + +// Tests that the branding is visible when some manual fill button is enabled, +// then disappears when the manual fill button is disabled. +- (void)testDisableManualFillButtonsDuringKeyboardPresenting { + EnableManualFillButtonForPassword(); + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(YES); + DisableManualFillButtons(); + CheckBrandingVisiblityWithDefaultTimeout(NO); +} + +// Tests that the branding is invisible until some manual fill button is +// enabled, then disappears when the manual fill button is disabled. +- (void)testEnableAndDisableManualFillButtonsDuringKeyboardPresenting { + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(NO); + EnableManualFillButtonForPassword(); + CheckBrandingVisiblityWithDefaultTimeout(YES); + DisableManualFillButtons(); + CheckBrandingVisiblityWithDefaultTimeout(NO); +} + +// Tests that the branding is visible even after one of the multiple manual fill +// buttons is disabled. +- (void)testEnableTwoManualFillButtonsAndDisableOneDuringKeyboardPresenting { + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(NO); + EnableManualFillButtonForPassword(); + EnableManualFillButtonForCreditCard(); + CheckBrandingVisiblityWithDefaultTimeout(YES); + // Hide manual fill button for password. + [AutofillAppInterface clearPasswordStore]; + CheckBrandingVisiblityWithDefaultTimeout(YES); + // Hide manual fill button for credit card. + [AutofillAppInterface clearCreditCardStore]; + CheckBrandingVisiblityWithDefaultTimeout(NO); +} + +// Tests that the branding is visible when the keyboard button is visible in the +// keyboard accessories, even if no manual fill buttons are visible. Note that +// this test is disabled on iPad since the keyboard button does not show there. +- (void)testDisableManualFillWhenKeyboardButtonPressed { + if ([ChromeEarlGrey isIPadIdiom]) { + EARL_GREY_TEST_DISABLED(@"Keyboard button does not exist on iPad."); + } + + EnableManualFillButtonForPassword(); + BringUpKeyboard(); + + CheckBrandingVisiblityWithDefaultTimeout(YES); + // Press the password button to display the keyboard button. + [[EarlGrey selectElementWithMatcher:ManualFallbackPasswordIconMatcher()] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + // Disable manual fill passwords; wait until the button is hidden. + DisableManualFillButtons(); + GREYCondition* passwordButtonCondition = [GREYCondition + conditionWithName:@"password button should be hidden" + block:^BOOL { + NSError* error; + [[EarlGrey selectElementWithMatcher: + ManualFallbackPasswordIconMatcher()] + assertWithMatcher:grey_notVisible() + error:&error]; + return error == nil; + }]; + BOOL passwordButtonHidden = [passwordButtonCondition + waitWithTimeout:base::test::ios::kWaitForUIElementTimeout.InSecondsF()]; + GREYAssertTrue(passwordButtonHidden, + @"Password button visible when no password is stored"); + // Check that keyboard button and the branding are still visible. + [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + CheckBrandingVisiblityWithDefaultTimeout(YES); + // Tap on the keyboard button to reset keyboard accessories. + [[EarlGrey selectElementWithMatcher:ManualFallbackKeyboardIconMatcher()] + performAction:grey_tap()]; + CheckBrandingVisiblityWithDefaultTimeout(NO); +} + +@end + +// BrandingViewControllerTestCases with flag disabled. +@interface BrandingViewControllerDisabledTestCase + : BrandingViewControllerTestCase +@end + +@implementation BrandingViewControllerDisabledTestCase + +- (AppLaunchConfiguration)appConfigurationForTestCase { + AppLaunchConfiguration config; + config.features_disabled.push_back(autofill::features::kAutofillBrandingIOS); + return config; +} + +// Tests that the branding is invisible when the autofill branding flag is +// disabled, regardless of the visibility of manual fill buttons. +- (void)testBrandingDisabled { + EnableManualFillButtonForPassword(); + BringUpKeyboard(); + CheckBrandingVisiblityWithDefaultTimeout(NO); +} + +@end
diff --git a/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm b/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm index 2060fbf3..5ca6a7eb 100644 --- a/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm +++ b/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm
@@ -105,7 +105,7 @@ const char kFrenchPageNoTranslateContent[] = "/frenchpagenotranslatecontent/"; const char kFrenchPageNoTranslateValue[] = "/frenchpagenotranslatevalue/"; const char kTranslateScriptPath[] = "/translatescript/"; -const char kTranslateScript[] = "Fake Translate Script"; +const char kTranslateScript[] = "Fake_Translate_Script"; // Body text for /languagepath/. const char kLanguagePathText[] = "Some text here.";
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn index 3af5ff3..43962db 100644 --- a/ios/chrome/browser/web/BUILD.gn +++ b/ios/chrome/browser/web/BUILD.gn
@@ -242,6 +242,7 @@ "//components/signin/public/identity_manager", "//components/strings", "//components/translate/core/browser", + "//components/translate/ios/browser", "//components/variations", "//components/variations/field_trial_config", "//components/variations/service",
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm index 3c72813..214ad237 100644 --- a/ios/chrome/browser/web/chrome_web_client.mm +++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -22,6 +22,7 @@ #import "components/password_manager/core/common/password_manager_features.h" #import "components/password_manager/ios/password_manager_java_script_feature.h" #import "components/strings/grit/components_strings.h" +#import "components/translate/ios/browser/translate_java_script_feature.h" #import "components/version_info/version_info.h" #import "ios/chrome/browser/application_context/application_context.h" #import "ios/chrome/browser/browser_about_rewriter.h" @@ -319,6 +320,7 @@ SearchEngineJavaScriptFeature::GetInstance()->SetDelegate( SearchEngineTabHelperFactory::GetInstance()); features.push_back(SearchEngineJavaScriptFeature::GetInstance()); + features.push_back(translate::TranslateJavaScriptFeature::GetInstance()); features.push_back(WebPerformanceMetricsJavaScriptFeature::GetInstance()); features.push_back(FollowJavaScriptFeature::GetInstance()); return features;
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn index 533fe53a..9e70037 100644 --- a/ios/chrome/test/earl_grey2/BUILD.gn +++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -87,6 +87,7 @@ "//ios/chrome/browser/prerender:eg2_tests", "//ios/chrome/browser/safe_browsing:eg2_tests", "//ios/chrome/browser/ui/autofill:eg2_tests", + "//ios/chrome/browser/ui/autofill/form_input_accessory:eg2_tests", "//ios/chrome/browser/ui/autofill/manual_fill:eg2_tests", "//ios/chrome/browser/ui/content_suggestions:eg2_tests", "//ios/chrome/browser/ui/context_menu:eg2_tests",
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 index 2d78b683..a307c83 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -ae27a5529fb60842fe82be77cd127fc14ff7c092 \ No newline at end of file +88c15d2f1723218400d0e3448c7967033dec0ed2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 index ab548f7c..e70c861 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -d8a56b16e50cddbb41f5fbcbaa33176be5eda5f0 \ No newline at end of file +94d42b75e07b538baaf4e669d8c87c0852200fb3 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index de4d0725..2066910 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -84d160783752dda2a2573b4a7ce0f0ad997cc9e2 \ No newline at end of file +a95a14769b23d417edfa804e0eee33bf9c3abdad \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 5be38d9..cb49ae3f 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -a43fb447f31e1d69e7309b25389cbed76188d233 \ No newline at end of file +8ac9d097ba66985336035ead04eafb47a241f40e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index fa802107..12a2310 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -363c850a87229f2a569307f609c16c002db1d4d5 \ No newline at end of file +8a1f696ed5608bb458390f8b3f0f5e717612ba80 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index c28f23d..86e8ac3a 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -ed1314852a5a4b905ae7b0cec19183840139715c \ No newline at end of file +972eda92fc206a014df2f013700e228c795d2a58 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 index 54bb13f..8a75089 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -82f190ef9d06c7d999113cfed9242e3a4e85befe \ No newline at end of file +c40f20f52596ee45c36d5421605da6356f299c83 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 index f915861..4219da1 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -3238623e1ea9ca62a4afbf17326f1b51941da66f \ No newline at end of file +522fb014d692dc93106a353b2b90a830acc830cb \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index f854259..2bcc59a06 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -989c60e7a5a2ed738221261927d31b3e3dcb781b \ No newline at end of file +3d63e6340c4573f8957d18a4661e39325ea68d67 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index 95d7f14..7c193f2 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -0eb26036d5fbf6ebe0b19655b444e6ee9b21f960 \ No newline at end of file +72bb9f5def44326486a666ec2d710afabe06e86e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index ab93706..ccaaa41 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -44e30b2f270804cc11f9bbc8e2b66f4c0a170a76 \ No newline at end of file +30a2ce12f63aefd58b56235c03d3832190b1e0f8 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 60a7fc4..ea58bf6 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -49da12fbdb4a5e3eaea4da2aaf2e4550a5bbc69d \ No newline at end of file +22b3c10b987784fb3fa8395a89ccd787c1a9e1f9 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index b8ff3e7..c0a8727 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -5351aaef8592acabb2f1d4b7395cc01dda16f7ac \ No newline at end of file +bfcfdd0125267d368a53970a4f4d83c4c7a46abe \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index cb996eaa..1ef672e 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -774625be2067d8e27bce9aa0315162f1501da78f \ No newline at end of file +a574c405f47773a49d2d5a1d5a439721c2eb94b8 \ No newline at end of file
diff --git a/ios/web_view/internal/web_view_web_client.mm b/ios/web_view/internal/web_view_web_client.mm index ca75a6b..fbbf967 100644 --- a/ios/web_view/internal/web_view_web_client.mm +++ b/ios/web_view/internal/web_view_web_client.mm
@@ -18,6 +18,7 @@ #import "components/security_interstitials/core/unsafe_resource.h" #include "components/ssl_errors/error_info.h" #include "components/strings/grit/components_strings.h" +#import "components/translate/ios/browser/translate_java_script_feature.h" #import "ios/components/security_interstitials/lookalikes/lookalike_url_container.h" #import "ios/components/security_interstitials/lookalikes/lookalike_url_error.h" #import "ios/components/security_interstitials/safe_browsing/safe_browsing_error.h" @@ -116,6 +117,7 @@ autofill::FormHandlersJavaScriptFeature::GetInstance(), autofill::SuggestionControllerJavaScriptFeature::GetInstance(), password_manager::PasswordManagerJavaScriptFeature::GetInstance(), + translate::TranslateJavaScriptFeature::GetInstance(), WebViewMessageHandlerJavaScriptFeature::GetInstance()}; }
diff --git a/net/base/schemeful_site.h b/net/base/schemeful_site.h index 5120fa4..a4449fc 100644 --- a/net/base/schemeful_site.h +++ b/net/base/schemeful_site.h
@@ -159,6 +159,9 @@ // in this case, and unfriend IsolationInfo. friend class IsolationInfo; + // Needed to create a bogus origin from a site. + friend class URLRequest; + // Needed because cookies do not account for scheme. friend class CookieMonster;
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 5c8f391..78067fa1 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -476,6 +476,14 @@ site_for_cookies_ = site_for_cookies; } +void URLRequest::set_isolation_info_from_network_anonymization_key( + const NetworkAnonymizationKey& network_anonymization_key) { + set_isolation_info(URLRequest::CreateIsolationInfoFromNetworkAnonymizationKey( + network_anonymization_key)); + + is_created_from_network_anonymization_key_ = true; +} + void URLRequest::set_first_party_url_policy( RedirectInfo::FirstPartyURLPolicy first_party_url_policy) { DCHECK(!is_pending_); @@ -624,6 +632,10 @@ void URLRequest::StartJob(std::unique_ptr<URLRequestJob> job) { DCHECK(!is_pending_); DCHECK(!job_); + if (is_created_from_network_anonymization_key_) { + DCHECK(load_flags_ & LOAD_DISABLE_CACHE); + DCHECK(!allow_credentials_); + } net_log_.BeginEvent(NetLogEventType::URL_REQUEST_START_JOB, [&] { return NetLogURLRequestStartParams( @@ -1161,6 +1173,48 @@ } } +IsolationInfo URLRequest::CreateIsolationInfoFromNetworkAnonymizationKey( + const NetworkAnonymizationKey& network_anonymization_key) { + if (!network_anonymization_key.IsFullyPopulated()) { + return IsolationInfo(); + } + + url::Origin top_frame_origin = + network_anonymization_key.GetTopFrameSite()->site_as_origin_; + + absl::optional<url::Origin> frame_origin; + if (NetworkAnonymizationKey::IsFrameSiteEnabled() && + network_anonymization_key.GetFrameSite().has_value()) { + // If frame site is set on the network anonymization key, use it to set the + // frame origin on the isolation info. + frame_origin = network_anonymization_key.GetFrameSite()->site_as_origin_; + } else if (NetworkAnonymizationKey::IsCrossSiteFlagSchemeEnabled() && + network_anonymization_key.GetIsCrossSite()) { + // If frame site is not set on the network anonymization key but we know + // that it is cross site to the top level site, create an empty origin to + // use as the frame origin for the isolation info. This should be cross site + // with the top level origin. + frame_origin = url::Origin(); + } else { + // If frame sit is not set on the network anonymization key and we don't + // know that it's cross site to the top level site, use the top frame site + // to set the frame origin. + frame_origin = top_frame_origin; + } + + const base::UnguessableToken* nonce = + network_anonymization_key.GetNonce() + ? &network_anonymization_key.GetNonce().value() + : nullptr; + + auto isolation_info = IsolationInfo::Create( + IsolationInfo::RequestType::kOther, top_frame_origin, + frame_origin.value(), SiteForCookies(), + /*party_context=*/absl::nullopt, nonce); + // TODO(crbug/1343856): DCHECK isolation info is fully populated. + return isolation_info; +} + ConnectionAttempts URLRequest::GetConnectionAttempts() const { if (job_) return job_->GetConnectionAttempts();
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index d8980db..6837095 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -269,6 +269,19 @@ void set_isolation_info(const IsolationInfo& isolation_info) { isolation_info_ = isolation_info; } + + // This will convert the passed NetworkAnonymizationKey to an IsolationInfo. + // This IsolationInfo mmay be assigned an inaccurate frame origin because the + // NetworkAnonymizationKey might not contain all the information to populate + // it. Additionally the NetworkAnonymizationKey uses sites which will be + // converted to origins when set on the IsolationInfo. If using this method it + // is required to skip the cache and not use credentials. Before starting the + // request, it must have the LoadFlag LOAD_DISABLE_CACHE set, and must be set + // to not allow credentials, to ensure that the inaccurate frame origin has no + // impact. The request will DCHECK otherwise. + void set_isolation_info_from_network_anonymization_key( + const NetworkAnonymizationKey& network_anonymization_key); + const IsolationInfo& isolation_info() const { return isolation_info_; } // Indicate whether SameSite cookies should be attached even though the @@ -539,6 +552,10 @@ // Access the LOAD_* flags modifying this request (see load_flags.h). int load_flags() const { return load_flags_; } + bool is_created_from_network_anonymization_key() const { + return is_created_from_network_anonymization_key_; + } + // Returns the Secure DNS Policy for the request. SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; } @@ -910,6 +927,11 @@ // checking. void RecordReferrerGranularityMetrics(bool request_is_same_origin) const; + // Creates a partial IsolationInfo with the information accessible from the + // NetworkAnonymiationKey. + net::IsolationInfo CreateIsolationInfoFromNetworkAnonymizationKey( + const NetworkAnonymizationKey& network_anonymization_key); + // Contextual information used for this request. Cannot be NULL. This contains // most of the dependencies which are shared between requests (disk cache, // cookie store, socket pool, etc.) @@ -972,6 +994,8 @@ // have been encountered, this will be the first error encountered. int status_ = OK; + bool is_created_from_network_anonymization_key_ = false; + // The HTTP response info, lazily initialized. HttpResponseInfo response_info_;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 0963563..e768a66 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -13109,6 +13109,246 @@ } } +TEST_F(URLRequestTest, SetIsolationInfoFromNakTripleNikTripleNak) { + base::test::ScopedFeatureList scoped_feature_list_; + std::vector<base::Feature> enabled_features = {}; + std::vector<base::Feature> disabled_features = { + net::features::kEnableDoubleKeyNetworkAnonymizationKey, + net::features::kForceIsolationInfoFrameOriginToTopLevelFrame, + net::features::kEnableCrossSiteFlagNetworkAnonymizationKey}; + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + + TestDelegate d; + SchemefulSite site_a = SchemefulSite(GURL("https://a.com/")); + SchemefulSite site_b = SchemefulSite(GURL("https://b.com/")); + base::UnguessableToken nak_nonce = base::UnguessableToken::Create(); + NetworkAnonymizationKey populated_cross_site_nak(site_a, site_b, true, + nak_nonce); + IsolationInfo expected_isolation_info_populated_cross_site_nak = + IsolationInfo::Create(IsolationInfo::RequestType::kOther, + url::Origin::Create(GURL("https://a.com/")), + url::Origin::Create(GURL("https://b.com/")), + SiteForCookies(), + /*party_context=*/absl::nullopt, &nak_nonce); + + NetworkAnonymizationKey populated_same_site_nak(site_a, site_a, false, + nak_nonce); + IsolationInfo expected_isolation_info_populated_same_site_nak = + IsolationInfo::Create(IsolationInfo::RequestType::kOther, + url::Origin::Create(GURL("https://a.com/")), + url::Origin::Create(GURL("https://a.com/")), + SiteForCookies(), + /*party_context=*/absl::nullopt, &nak_nonce); + + NetworkAnonymizationKey empty_nak; + GURL original_url("http://localhost"); + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->set_isolation_info_from_network_anonymization_key( + populated_cross_site_nak); + r->SetLoadFlags(LOAD_DISABLE_CACHE); + r->set_allow_credentials(false); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), + populated_cross_site_nak); + EXPECT_TRUE(r->isolation_info().IsEqualForTesting( + expected_isolation_info_populated_cross_site_nak)); + + r->set_isolation_info_from_network_anonymization_key(populated_same_site_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), + populated_same_site_nak); + EXPECT_TRUE(r->isolation_info().IsEqualForTesting( + expected_isolation_info_populated_same_site_nak)); + + r->set_isolation_info_from_network_anonymization_key(empty_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), empty_nak); + EXPECT_TRUE(r->isolation_info().IsEqualForTesting(net::IsolationInfo())); + r->Start(); + d.RunUntilComplete(); +} + +TEST_F(URLRequestTest, SetIsolationInfoFromNakDoubleNikDoubleNak) { + base::test::ScopedFeatureList scoped_feature_list_; + std::vector<base::Feature> enabled_features = { + net::features::kEnableDoubleKeyNetworkAnonymizationKey, + net::features::kForceIsolationInfoFrameOriginToTopLevelFrame}; + std::vector<base::Feature> disabled_features = { + net::features::kEnableCrossSiteFlagNetworkAnonymizationKey}; + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + + TestDelegate d; + SchemefulSite site_a = SchemefulSite(GURL("https://a.com/")); + SchemefulSite site_b = SchemefulSite(GURL("https://b.com/")); + base::UnguessableToken nak_nonce = base::UnguessableToken::Create(); + NetworkAnonymizationKey populated_cross_site_nak(site_a, site_b, true, + nak_nonce); + NetworkAnonymizationKey populated_same_site_nak(site_a, site_a, false, + nak_nonce); + // Frame site should be set to the top level sites value even though NAK is + // double keyed. + IsolationInfo expected_isolation_info_populated_same_site_nak = + IsolationInfo::Create(IsolationInfo::RequestType::kOther, + url::Origin::Create(GURL("https://a.com/")), + url::Origin::Create(GURL("https://a.com/")), + SiteForCookies(), + /*party_context=*/absl::nullopt, &nak_nonce); + NetworkAnonymizationKey empty_nak; + + GURL original_url("http://localhost"); + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->set_isolation_info_from_network_anonymization_key( + populated_cross_site_nak); + r->SetLoadFlags(LOAD_DISABLE_CACHE); + r->set_allow_credentials(false); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), + populated_cross_site_nak); + // We do not know the frame_site other than that it will be cross site. + EXPECT_EQ(r->isolation_info().top_frame_origin(), + url::Origin::Create(GURL("https://a.com/"))); + + r->set_isolation_info_from_network_anonymization_key(populated_same_site_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), + populated_same_site_nak); + EXPECT_TRUE(r->isolation_info().IsEqualForTesting( + expected_isolation_info_populated_same_site_nak)); + + r->set_isolation_info_from_network_anonymization_key(empty_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), empty_nak); + EXPECT_TRUE(r->isolation_info().IsEqualForTesting(net::IsolationInfo())); + r->Start(); + d.RunUntilComplete(); +} + +TEST_F(URLRequestTest, SetIsolationInfoFromNakTripleNikDoubleNak) { + base::test::ScopedFeatureList scoped_feature_list_; + std::vector<base::Feature> enabled_features = { + net::features::kEnableDoubleKeyNetworkAnonymizationKey}; + std::vector<base::Feature> disabled_features = { + net::features::kForceIsolationInfoFrameOriginToTopLevelFrame, + net::features::kEnableCrossSiteFlagNetworkAnonymizationKey}; + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + + TestDelegate d; + SchemefulSite site_a = SchemefulSite(GURL("https://a.com/")); + SchemefulSite site_b = SchemefulSite(GURL("https://b.com/")); + base::UnguessableToken nak_nonce = base::UnguessableToken::Create(); + NetworkAnonymizationKey populated_cross_site_nak(site_a, site_b, true, + nak_nonce); + NetworkAnonymizationKey populated_same_site_nak(site_a, site_a, false, + nak_nonce); + IsolationInfo expected_isolation_info_populated_same_site_nak = + IsolationInfo::Create(IsolationInfo::RequestType::kOther, + url::Origin::Create(GURL("https://a.com/")), + url::Origin::Create(GURL("https://a.com/")), + SiteForCookies(), + /*party_context=*/absl::nullopt, &nak_nonce); + NetworkAnonymizationKey empty_nak; + + GURL original_url("http://localhost"); + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->set_isolation_info_from_network_anonymization_key( + populated_cross_site_nak); + r->SetLoadFlags(LOAD_DISABLE_CACHE); + r->set_allow_credentials(false); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), + populated_cross_site_nak); + EXPECT_EQ(r->isolation_info().top_frame_origin(), + url::Origin::Create(GURL("https://a.com/"))); + // When double key is enabled for NAK but not for NIK, the frame site of the + // IsolationInfo will be set to the top level site. + EXPECT_EQ(r->isolation_info().frame_origin(), + url::Origin::Create(GURL("https://a.com/"))); + + r->set_isolation_info_from_network_anonymization_key(populated_same_site_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), + populated_same_site_nak); + EXPECT_TRUE(r->isolation_info().IsEqualForTesting( + expected_isolation_info_populated_same_site_nak)); + + r->set_isolation_info_from_network_anonymization_key(empty_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), empty_nak); + EXPECT_FALSE(r->isolation_info().top_frame_origin()); + EXPECT_FALSE(r->isolation_info().frame_origin()); + r->Start(); + d.RunUntilComplete(); +} + +TEST_F(URLRequestTest, + SetIsolationInfoFromNakTripleNikDoubleWithCrossSiteFlagNak) { + base::test::ScopedFeatureList scoped_feature_list_; + std::vector<base::Feature> enabled_features = { + net::features::kEnableDoubleKeyNetworkAnonymizationKey, + net::features::kEnableCrossSiteFlagNetworkAnonymizationKey}; + std::vector<base::Feature> disabled_features = { + net::features::kForceIsolationInfoFrameOriginToTopLevelFrame}; + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + + TestDelegate d; + SchemefulSite site_a = SchemefulSite(GURL("https://a.com/")); + SchemefulSite site_b = SchemefulSite(GURL("https://b.com/")); + base::UnguessableToken nak_nonce = base::UnguessableToken::Create(); + NetworkAnonymizationKey populated_cross_site_nak( + site_a, site_b, /*is_cross_site=*/true, nak_nonce); + NetworkAnonymizationKey populated_same_site_nak( + site_a, site_a, /*is_cross_site=*/false, nak_nonce); + + NetworkAnonymizationKey empty_nak; + GURL original_url("http://localhost"); + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + + r->set_isolation_info_from_network_anonymization_key( + populated_cross_site_nak); + r->SetLoadFlags(LOAD_DISABLE_CACHE); + r->set_allow_credentials(false); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE); + EXPECT_EQ(r->isolation_info().network_anonymization_key().ToDebugString(), + populated_cross_site_nak.ToDebugString()); + EXPECT_EQ(r->isolation_info().top_frame_origin(), + url::Origin::Create(GURL("https://a.com/"))); + // When double key is enabled for NAK but not for NIK, the frame site of the + // IsolationInfo will be set to the top level site. + EXPECT_TRUE(r->isolation_info().frame_origin()); + + r->set_isolation_info_from_network_anonymization_key(populated_same_site_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE); + EXPECT_EQ(r->isolation_info().network_anonymization_key().ToDebugString(), + populated_same_site_nak.ToDebugString()); + EXPECT_EQ(r->isolation_info().top_frame_origin(), + url::Origin::Create(GURL("https://a.com/"))); + // Cross site double keyed NAKs should set a cross site dummy origin on the + // IsolationInfo. + EXPECT_TRUE(r->isolation_info().frame_origin()); + + r->set_isolation_info_from_network_anonymization_key(empty_nak); + EXPECT_TRUE(r->is_created_from_network_anonymization_key()); + EXPECT_TRUE(r->load_flags() & LOAD_DISABLE_CACHE); + EXPECT_EQ(r->isolation_info().network_anonymization_key(), empty_nak); + EXPECT_FALSE(r->isolation_info().top_frame_origin()); + EXPECT_FALSE(r->isolation_info().frame_origin()); + + r->Start(); + d.RunUntilComplete(); +} + class URLRequestMaybeAsyncFirstPartySetsTest : public URLRequestTest, public testing::WithParamInterface<bool> {
diff --git a/pdf/pdf.cc b/pdf/pdf.cc index 0174755..ca1700f 100644 --- a/pdf/pdf.cc +++ b/pdf/pdf.cc
@@ -46,7 +46,7 @@ #if BUILDFLAG(IS_WIN) bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, HDC dc, int dpi_x, int dpi_y, @@ -67,7 +67,7 @@ gfx::Rect(bounds_origin_x, bounds_origin_y, bounds_width, bounds_height), fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds, autorotate, use_color, /*render_for_printing=*/true); - return engine_exports->RenderPDFPageToDC(pdf_buffer, page_number, settings, + return engine_exports->RenderPDFPageToDC(pdf_buffer, page_index, settings, dc); } @@ -99,15 +99,15 @@ absl::optional<gfx::SizeF> GetPDFPageSizeByIndex( base::span<const uint8_t> pdf_buffer, - int page_number) { + int page_index) { ScopedSdkInitializer scoped_sdk_initializer(/*enable_v8=*/true); chrome_pdf::PDFEngineExports* engine_exports = chrome_pdf::PDFEngineExports::Get(); - return engine_exports->GetPDFPageSizeByIndex(pdf_buffer, page_number); + return engine_exports->GetPDFPageSizeByIndex(pdf_buffer, page_index); } bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, void* bitmap_buffer, const gfx::Size& bitmap_size, const gfx::Size& dpi, @@ -120,8 +120,8 @@ options.keep_aspect_ratio, /*center_in_bounds=*/true, options.autorotate, options.use_color, options.render_device_type == RenderDeviceType::kPrinter); - return engine_exports->RenderPDFPageToBitmap(pdf_buffer, page_number, - settings, bitmap_buffer); + return engine_exports->RenderPDFPageToBitmap(pdf_buffer, page_index, settings, + bitmap_buffer); } std::vector<uint8_t> ConvertPdfPagesToNupPdf(
diff --git a/pdf/pdf.h b/pdf/pdf.h index 64e2da9d..40137c48 100644 --- a/pdf/pdf.h +++ b/pdf/pdf.h
@@ -49,7 +49,7 @@ // `pdf_buffer` is the buffer that contains the entire PDF document to be // rendered. -// `page_number` is the 0-based index of the page to be rendered. +// `page_index` is the 0-based index of the page to be rendered. // `dc` is the device context to render into. // `dpi_x` and `dpi_y` is the resolution. // `bounds_origin_x`, `bounds_origin_y`, `bounds_width` and `bounds_height` @@ -74,7 +74,7 @@ // `use_color` specifies color or grayscale. // Returns false if the document or the page number are not valid. bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, HDC dc, int dpi_x, int dpi_y, @@ -111,13 +111,12 @@ // Gets the dimensions of a specific page in a document. // `pdf_buffer` is the buffer that contains the entire PDF document to be // rendered. -// `page_number` is the page number that the function will get the dimensions -// of. +// `page_index` is the page number that the function will get the dimensions of. // Returns the size of the page in points, or nullopt if the document or the // page number are not valid. absl::optional<gfx::SizeF> GetPDFPageSizeByIndex( base::span<const uint8_t> pdf_buffer, - int page_number); + int page_index); enum class RenderDeviceType { kDisplay, @@ -141,14 +140,14 @@ // Renders PDF page into 4-byte per pixel BGRA color bitmap. // `pdf_buffer` is the buffer that contains the entire PDF document to be // rendered. -// `page_number` is the 0-based index of the page to be rendered. +// `page_index` is the 0-based index of the page to be rendered. // `bitmap_buffer` is the output buffer for bitmap. // `bitmap_size` is the size of the output bitmap. // `dpi` is the 2D resolution. // `options` is the options to render with. // Returns false if the document or the page number are not valid. bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, void* bitmap_buffer, const gfx::Size& bitmap_size, const gfx::Size& dpi,
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index 088bab2..d7fc9b7 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h
@@ -304,7 +304,7 @@ virtual bool HandleInputEvent(const blink::WebInputEvent& event) = 0; virtual void PrintBegin() = 0; virtual std::vector<uint8_t> PrintPages( - const std::vector<int>& page_numbers, + const std::vector<int>& page_index, const blink::WebPrintParams& print_params) = 0; virtual void PrintEnd() = 0; virtual void StartFind(const std::string& text, bool case_sensitive) = 0; @@ -508,7 +508,7 @@ #if BUILDFLAG(IS_WIN) // See the definition of RenderPDFPageToDC in pdf.cc for details. virtual bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, const RenderingSettings& settings, HDC dc) = 0; @@ -517,7 +517,7 @@ // See the definition of RenderPDFPageToBitmap in pdf.cc for details. virtual bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, const RenderingSettings& settings, void* bitmap_buffer) = 0; @@ -554,7 +554,7 @@ // See the definition of GetPDFPageSizeByIndex in pdf.cc for details. virtual absl::optional<gfx::SizeF> GetPDFPageSizeByIndex( base::span<const uint8_t> pdf_buffer, - int page_number) = 0; + int page_index) = 0; }; } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_engine_exports.cc b/pdf/pdfium/pdfium_engine_exports.cc index 82a319b9..8830270 100644 --- a/pdf/pdfium/pdfium_engine_exports.cc +++ b/pdf/pdfium/pdfium_engine_exports.cc
@@ -243,7 +243,7 @@ #if BUILDFLAG(IS_WIN) bool PDFiumEngineExports::RenderPDFPageToDC( base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, const RenderingSettings& settings, HDC dc) { ScopedUnsupportedFeature scoped_unsupported_feature( @@ -251,7 +251,7 @@ ScopedFPDFDocument doc = LoadPdfData(pdf_buffer); if (!doc) return false; - ScopedFPDFPage page(FPDF_LoadPage(doc.get(), page_number)); + ScopedFPDFPage page(FPDF_LoadPage(doc.get(), page_index)); if (!page) return false; @@ -319,7 +319,7 @@ bool PDFiumEngineExports::RenderPDFPageToBitmap( base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, const RenderingSettings& settings, void* bitmap_buffer) { ScopedUnsupportedFeature scoped_unsupported_feature( @@ -327,7 +327,7 @@ ScopedFPDFDocument doc = LoadPdfData(pdf_buffer); if (!doc) return false; - ScopedFPDFPage page(FPDF_LoadPage(doc.get(), page_number)); + ScopedFPDFPage page(FPDF_LoadPage(doc.get(), page_index)); if (!page) return false; @@ -403,9 +403,9 @@ if (max_page_width) { *max_page_width = 0; - for (int page_number = 0; page_number < page_count_local; page_number++) { + for (int page_index = 0; page_index < page_count_local; page_index++) { FS_SIZEF page_size; - if (FPDF_GetPageSizeByIndexF(doc.get(), page_number, &page_size) && + if (FPDF_GetPageSizeByIndexF(doc.get(), page_index, &page_size) && page_size.width > *max_page_width) { *max_page_width = page_size.width; } @@ -457,7 +457,7 @@ absl::optional<gfx::SizeF> PDFiumEngineExports::GetPDFPageSizeByIndex( base::span<const uint8_t> pdf_buffer, - int page_number) { + int page_index) { ScopedUnsupportedFeature scoped_unsupported_feature( ScopedUnsupportedFeature::kNoEngine); ScopedFPDFDocument doc = LoadPdfData(pdf_buffer); @@ -465,7 +465,7 @@ return absl::nullopt; FS_SIZEF size; - if (!FPDF_GetPageSizeByIndexF(doc.get(), page_number, &size)) + if (!FPDF_GetPageSizeByIndexF(doc.get(), page_index, &size)) return absl::nullopt; return gfx::SizeF(size.width, size.height);
diff --git a/pdf/pdfium/pdfium_engine_exports.h b/pdf/pdfium/pdfium_engine_exports.h index 3b1ee907..c6cc7f6 100644 --- a/pdf/pdfium/pdfium_engine_exports.h +++ b/pdf/pdfium/pdfium_engine_exports.h
@@ -27,13 +27,13 @@ #endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_WIN) bool RenderPDFPageToDC(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, const RenderingSettings& settings, HDC dc) override; void SetPDFUsePrintMode(int mode) override; #endif // BUILDFLAG(IS_WIN) bool RenderPDFPageToBitmap(base::span<const uint8_t> pdf_buffer, - int page_number, + int page_index, const RenderingSettings& settings, void* bitmap_buffer) override; std::vector<uint8_t> ConvertPdfPagesToNupPdf( @@ -55,7 +55,7 @@ int page_index) override; absl::optional<gfx::SizeF> GetPDFPageSizeByIndex( base::span<const uint8_t> pdf_buffer, - int page_number) override; + int page_index) override; }; } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_engine_exports_unittest.cc b/pdf/pdfium/pdfium_engine_exports_unittest.cc index c635b3d..342ec19 100644 --- a/pdf/pdfium/pdfium_engine_exports_unittest.cc +++ b/pdf/pdfium/pdfium_engine_exports_unittest.cc
@@ -66,9 +66,9 @@ int page_count; ASSERT_TRUE(GetPDFDocInfo(pdf_span, &page_count, nullptr)); ASSERT_EQ(2, page_count); - for (int page_number = 0; page_number < page_count; ++page_number) { + for (int page_index = 0; page_index < page_count; ++page_index) { absl::optional<gfx::SizeF> page_size = - GetPDFPageSizeByIndex(pdf_span, page_number); + GetPDFPageSizeByIndex(pdf_span, page_index); ASSERT_TRUE(page_size.has_value()); EXPECT_EQ(gfx::SizeF(200, 200), page_size.value()); } @@ -136,9 +136,9 @@ int page_count; ASSERT_TRUE(GetPDFDocInfo(output_pdf_span, &page_count, nullptr)); ASSERT_EQ(2, page_count); - for (int page_number = 0; page_number < page_count; ++page_number) { + for (int page_index = 0; page_index < page_count; ++page_index) { absl::optional<gfx::SizeF> page_size = - GetPDFPageSizeByIndex(output_pdf_span, page_number); + GetPDFPageSizeByIndex(output_pdf_span, page_index); ASSERT_TRUE(page_size.has_value()); EXPECT_EQ(gfx::SizeF(612, 792), page_size.value()); }
diff --git a/testing/buildbot/buildbot_json_magic_substitutions.py b/testing/buildbot/buildbot_json_magic_substitutions.py index 387313da..b5906e0 100644 --- a/testing/buildbot/buildbot_json_magic_substitutions.py +++ b/testing/buildbot/buildbot_json_magic_substitutions.py
@@ -128,6 +128,24 @@ return retval +def _GetGpusFromTestConfig(test_config): + """Generates all GPU dimension strings from a test config. + + Args: + test_config: A dict containing a configuration for a specific test on a + specific builder. + """ + dimensions = test_config.get('swarming', {}).get('dimension_sets', []) + assert dimensions + for d in dimensions: + # Split up multiple GPU/driver combinations if the swarming OR operator is + # being used. + if 'gpu' in d: + gpus = d['gpu'].split('|') + for gpu in gpus: + yield gpu + + def GPUParallelJobs(test_config, _, tester_config): """Substitutes the correct number of jobs for GPU tests. @@ -147,19 +165,26 @@ # Return --jobs=1 for Windows Intel bots running the WebGPU CTS # These bots can't handle parallel tests. See crbug.com/1353938. + # The load can also negatively impact WebGL tests, so reduce the number of + # jobs there. + # TODO(crbug.com/1349828): Try removing the Windows special casing once we + # swap which machines we're using. is_webgpu_cts = test_name.startswith('webgpu_cts') or test_config.get( 'telemetry_test_name') == 'webgpu_cts' - if os_type == 'win' and is_webgpu_cts: - dimensions = test_config.get('swarming', {}).get('dimension_sets', []) - assert dimensions - for d in dimensions: - # Split up multiple GPU/driver combinations if the swarming OR operator is - # being used. - if 'gpu' in d: - gpus = d['gpu'].split('|') - for gpu in gpus: - if gpu.startswith('8086'): - return ['--jobs=1'] + is_webgl_cts = 'webgl_conformance' in test_name or test_config.get( + 'telemetry_test_name') == 'webgl_conformance' + if os_type == 'win' and (is_webgl_cts or is_webgpu_cts): + for gpu in _GetGpusFromTestConfig(test_config): + if gpu.startswith('8086'): + if is_webgpu_cts: + return ['--jobs=1'] + return ['--jobs=2'] + # Similarly, the NVIDIA Macbooks are quite old and slow, so reduce the number + # of jobs there as well. + if os_type == 'mac' and is_webgl_cts: + for gpu in _GetGpusFromTestConfig(test_config): + if gpu.startswith('10de'): + return ['--jobs=3'] if os_type in ['lacros', 'linux', 'mac', 'win']: return ['--jobs=4']
diff --git a/testing/buildbot/buildbot_json_magic_substitutions_unittest.py b/testing/buildbot/buildbot_json_magic_substitutions_unittest.py index 46d981c..6ab65c91 100755 --- a/testing/buildbot/buildbot_json_magic_substitutions_unittest.py +++ b/testing/buildbot/buildbot_json_magic_substitutions_unittest.py
@@ -178,9 +178,9 @@ def testWebGPUCTSWindowsIntelSerialJobs(self): intel_config = CreateConfigWithGpus(['8086:device1-driver']) - nvidia_config = CreateConfigWithGpus(['10de:device1-driver']) + amd_config = CreateConfigWithGpus(['1002:device1-driver']) - for gpu_config in [intel_config, nvidia_config]: + for gpu_config in [intel_config, amd_config]: for name, telemetry_test_name in [('webgpu_cts', None), (None, 'webgpu_cts')]: is_intel = intel_config == gpu_config @@ -197,6 +197,48 @@ else: self.assertEqual(retval, ['--jobs=4']) + def testWebGLWindowsIntelParallelJobs(self): + intel_config = CreateConfigWithGpus(['8086:device1-driver']) + amd_config = CreateConfigWithGpus(['1002:device1-driver']) + + for gpu_config in [intel_config, amd_config]: + for name, telemetry_test_name in [('webgl_conformance', None), + (None, 'webgl_conformance')]: + is_intel = intel_config == gpu_config + c = gpu_config.copy() + if name: + c['name'] = name + if telemetry_test_name: + c['telemetry_test_name'] = telemetry_test_name + for os_type in ['lacros', 'linux', 'mac', 'win']: + retval = magic_substitutions.GPUParallelJobs(c, None, + {'os_type': os_type}) + if is_intel and os_type == 'win': + self.assertEqual(retval, ['--jobs=2']) + else: + self.assertEqual(retval, ['--jobs=4']) + + def testWebGLMacNvidiaParallelJobs(self): + amd_config = CreateConfigWithGpus(['1002:device1-driver']) + nvidia_config = CreateConfigWithGpus(['10de:device1-driver']) + + for gpu_config in [nvidia_config, amd_config]: + for name, telemetry_test_name in [('webgl_conformance', None), + (None, 'webgl_conformance')]: + is_nvidia = gpu_config == nvidia_config + c = gpu_config.copy() + if name: + c['name'] = name + if telemetry_test_name: + c['telemetry_test_name'] = telemetry_test_name + for os_type in ['lacros', 'linux', 'mac', 'win']: + retval = magic_substitutions.GPUParallelJobs(c, None, + {'os_type': os_type}) + if is_nvidia and os_type == 'mac': + self.assertEqual(retval, ['--jobs=3']) + else: + self.assertEqual(retval, ['--jobs=4']) + def CreateConfigWithDeviceTypes(device_types): dimension_sets = []
diff --git a/testing/buildbot/chromium.angle.json b/testing/buildbot/chromium.angle.json index 2eeb153..4b5523b 100644 --- a/testing/buildbot/chromium.angle.json +++ b/testing/buildbot/chromium.angle.json
@@ -1278,7 +1278,7 @@ "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--webgl-conformance-version=2.0.1", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -1317,7 +1317,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -1356,7 +1356,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -1394,7 +1394,7 @@ "-v", "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index e7a8212..2326ea6 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -9735,7 +9735,7 @@ } ] }, - "ToTFuchsiaOfficial": { + "ToTFuchsiaOfficial arm64": { "gtest_tests": [ { "merge": {
diff --git a/testing/buildbot/chromium.dawn.json b/testing/buildbot/chromium.dawn.json index e98336f..80eda59 100644 --- a/testing/buildbot/chromium.dawn.json +++ b/testing/buildbot/chromium.dawn.json
@@ -1,6 +1,8 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "Dawn Android arm DEPS Release (Pixel 4)": {}, + "Dawn Android arm Release (Pixel 4)": {}, "Dawn Linux x64 Builder": {}, "Dawn Linux x64 DEPS Builder": {}, "Dawn Linux x64 DEPS Release (Intel UHD 630)": {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 8d4f2ac..7b4718c 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -16609,7 +16609,7 @@ "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", "--webgl-conformance-version=2.0.1", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json", - "--jobs=4" + "--jobs=3" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -16651,7 +16651,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", - "--jobs=4" + "--jobs=3" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -16693,7 +16693,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough --force_high_performance_gpu", "--test-filter=conformance/rendering/gl-drawelements.html", - "--jobs=4" + "--jobs=3" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -19538,7 +19538,7 @@ "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--webgl-conformance-version=2.0.1", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -19577,7 +19577,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -19616,7 +19616,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -19654,7 +19654,7 @@ "-v", "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": {
diff --git a/testing/buildbot/tryserver.chromium.win.json b/testing/buildbot/tryserver.chromium.win.json index fd51341..30ffd20 100644 --- a/testing/buildbot/tryserver.chromium.win.json +++ b/testing/buildbot/tryserver.chromium.win.json
@@ -665,7 +665,7 @@ "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--webgl-conformance-version=2.0.1", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -744,7 +744,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -823,7 +823,7 @@ "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { @@ -900,7 +900,7 @@ "-v", "--stable-jobs", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu", - "--jobs=4" + "--jobs=2" ], "isolate_name": "telemetry_gpu_integration_test", "merge": {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 825c0af..9abf2b5 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1795,7 +1795,7 @@ 'gpu_telemetry_tests': 'gpu_fuchsia_telemetry_tests', }, }, - 'ToTFuchsiaOfficial': { + 'ToTFuchsiaOfficial arm64': { 'test_suites': { 'gtest_tests': 'fuchsia_web_engine_non_graphical_gtests', 'isolated_scripts': 'fuchsia_arm64_isolated_scripts', @@ -2149,6 +2149,28 @@ 'name': 'chromium.dawn', 'mixins': ['chromium-tester-service-account'], 'machines': { + 'Dawn Android arm DEPS Release (Pixel 4)': { + 'os_type': 'android', + 'browser_config': 'android-chromium', + 'mixins': [ + 'android_r', + 'has_native_resultdb_integration', + 'flame', + 'gpu-swarming-pool', + ], + 'test_suites': {}, + }, + 'Dawn Android arm Release (Pixel 4)': { + 'os_type': 'android', + 'browser_config': 'android-chromium', + 'mixins': [ + 'android_r', + 'has_native_resultdb_integration', + 'flame', + 'gpu-swarming-pool', + ], + 'test_suites': {}, + }, 'Dawn Linux x64 Builder' : {}, 'Dawn Linux x64 DEPS Builder' : {}, 'Dawn Linux x64 DEPS Release (Intel UHD 630)': {
diff --git a/third_party/blink/common/manifest/manifest_util.cc b/third_party/blink/common/manifest/manifest_util.cc index 9054288..58910fb 100644 --- a/third_party/blink/common/manifest/manifest_util.cc +++ b/third_party/blink/common/manifest/manifest_util.cc
@@ -6,6 +6,7 @@ #include "base/no_destructor.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "third_party/blink/public/common/manifest/manifest.h" #include "third_party/blink/public/common/permissions_policy/permissions_policy.h" #include "third_party/blink/public/mojom/manifest/capture_links.mojom.h" @@ -148,4 +149,15 @@ return absl::nullopt; } +GURL GetIdFromManifest(const mojom::Manifest& manifest) { + if (manifest.id.has_value()) { + // Generate the formatted id by <start_url_origin>/<manifest_id>. + GURL manifest_id(manifest.start_url.DeprecatedGetOriginAsURL().spec() + + base::UTF16ToUTF8(manifest.id.value())); + DCHECK(manifest_id.is_valid()); + return manifest_id; + } + return manifest.start_url; +} + } // namespace blink
diff --git a/third_party/blink/public/common/manifest/manifest_util.h b/third_party/blink/public/common/manifest/manifest_util.h index 736990c..39fd4763 100644 --- a/third_party/blink/public/common/manifest/manifest_util.h +++ b/third_party/blink/public/common/manifest/manifest_util.h
@@ -64,6 +64,9 @@ BLINK_COMMON_EXPORT absl::optional<mojom::ManifestLaunchHandler::ClientMode> ClientModeFromString(const std::string& client_mode); +// Returns the URL format manifest ID from the relative id. +BLINK_COMMON_EXPORT GURL GetIdFromManifest(const mojom::Manifest& manifest); + } // namespace blink #endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_MANIFEST_MANIFEST_UTIL_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record.cc b/third_party/blink/renderer/bindings/core/v8/module_record.cc index b9c473b..a75a2692 100644 --- a/third_party/blink/renderer/bindings/core/v8/module_record.cc +++ b/third_party/blink/renderer/bindings/core/v8/module_record.cc
@@ -25,7 +25,7 @@ ModuleRecordProduceCacheData::ModuleRecordProduceCacheData( v8::Isolate* isolate, - SingleCachedMetadataHandler* cache_handler, + CachedMetadataHandler* cache_handler, V8CodeCache::ProduceCacheOptions produce_cache_options, v8::Local<v8::Module> module) : cache_handler_(cache_handler),
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record.h b/third_party/blink/renderer/bindings/core/v8/module_record.h index b544272..a5ed9b4 100644 --- a/third_party/blink/renderer/bindings/core/v8/module_record.h +++ b/third_party/blink/renderer/bindings/core/v8/module_record.h
@@ -33,13 +33,13 @@ : public GarbageCollected<ModuleRecordProduceCacheData> { public: ModuleRecordProduceCacheData(v8::Isolate*, - SingleCachedMetadataHandler*, + CachedMetadataHandler*, V8CodeCache::ProduceCacheOptions, v8::Local<v8::Module>); void Trace(Visitor*) const; - SingleCachedMetadataHandler* CacheHandler() const { return cache_handler_; } + CachedMetadataHandler* CacheHandler() const { return cache_handler_; } V8CodeCache::ProduceCacheOptions GetProduceCacheOptions() const { return produce_cache_options_; } @@ -48,7 +48,7 @@ } private: - Member<SingleCachedMetadataHandler> cache_handler_; + Member<CachedMetadataHandler> cache_handler_; V8CodeCache::ProduceCacheOptions produce_cache_options_; TraceWrapperV8Reference<v8::UnboundModuleScript> unbound_script_; };
diff --git a/third_party/blink/renderer/bindings/core/v8/script_cache_consumer.h b/third_party/blink/renderer/bindings/core/v8/script_cache_consumer.h index a6593092..60583e3f 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_cache_consumer.h +++ b/third_party/blink/renderer/bindings/core/v8/script_cache_consumer.h
@@ -28,7 +28,7 @@ // completed. // // ScriptCacheConsumer works on unchecked CachedMetadata speculatively, before -// the source is available. If SingleCachedMetadataHandler::Check() fails later, +// the source is available. If CachedMetadataHandler::Check() fails later, // the CachedMetadata on the CachedMetadataHandler will be cleared, and the // result of this ScriptCacheConsumer will be dropped on TakeV8ConsumeTask() due // to a CachedMetadata mismatch.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc index 529d6dd..eef2a7f 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -727,7 +727,7 @@ // then we reset the code cache entry to just a timestamp, so this condition // will allow streaming the next time we load the resource. if (V8CodeCache::HasCodeCache(script_resource_->CacheHandler(), - SingleCachedMetadataHandler::kAllowUnchecked)) { + CachedMetadataHandler::kAllowUnchecked)) { // The resource has a code cache entry, so it's unnecessary to stream // and parse the code. // TODO(leszeks): Can we even reach this code path with data pipes?
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc index 4e16caa6..06bf9c4d 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -355,7 +355,7 @@ // script is loaded. V8TestingScope scope; - SingleCachedMetadataHandler* cache_handler = resource_->CacheHandler(); + CachedMetadataHandler* cache_handler = resource_->CacheHandler(); EXPECT_TRUE(cache_handler); cache_handler->DisableSendToPlatformForTesting(); // CodeCacheHost can be nullptr since we disabled sending data to
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc index 3da19f16..460fe003 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
@@ -46,7 +46,7 @@ } // Check previously stored timestamp. -bool IsResourceHotForCaching(const SingleCachedMetadataHandler* cache_handler) { +bool IsResourceHotForCaching(const CachedMetadataHandler* cache_handler) { static constexpr base::TimeDelta kHotHours = base::Hours(72); scoped_refptr<CachedMetadata> cached_metadata = cache_handler->GetCachedMetadata( @@ -65,8 +65,8 @@ } // namespace bool V8CodeCache::HasCodeCache( - const SingleCachedMetadataHandler* cache_handler, - SingleCachedMetadataHandler::GetCachedMetadataBehavior behavior) { + const CachedMetadataHandler* cache_handler, + CachedMetadataHandler::GetCachedMetadataBehavior behavior) { if (!cache_handler) return false; @@ -75,7 +75,7 @@ } std::unique_ptr<v8::ScriptCompiler::CachedData> V8CodeCache::CreateCachedData( - const SingleCachedMetadataHandler* cache_handler) { + const CachedMetadataHandler* cache_handler) { return V8CodeCache::CreateCachedData(GetCachedMetadata(cache_handler)); } @@ -89,8 +89,8 @@ } scoped_refptr<CachedMetadata> V8CodeCache::GetCachedMetadata( - const SingleCachedMetadataHandler* cache_handler, - SingleCachedMetadataHandler::GetCachedMetadataBehavior behavior) { + const CachedMetadataHandler* cache_handler, + CachedMetadataHandler::GetCachedMetadataBehavior behavior) { DCHECK(cache_handler); uint32_t code_cache_tag = V8CodeCache::TagForCodeCache(cache_handler); scoped_refptr<CachedMetadata> cached_metadata = @@ -113,7 +113,7 @@ V8CodeCache::ProduceCacheOptions, v8::ScriptCompiler::NoCacheReason> V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions cache_options, - const SingleCachedMetadataHandler* cache_handler, + const CachedMetadataHandler* cache_handler, size_t source_text_length, ScriptSourceLocationType source_location_type) { static const int kMinimalCodeLength = 1024; @@ -210,7 +210,7 @@ v8::Isolate* isolate, CodeCacheHost* code_cache_host, v8::Local<UnboundScript> unbound_script, - SingleCachedMetadataHandler* cache_handler, + CachedMetadataHandler* cache_handler, size_t source_text_length, const KURL& source_url, const TextPosition& source_start_position, @@ -271,7 +271,7 @@ void V8CodeCache::ProduceCache(v8::Isolate* isolate, CodeCacheHost* code_cache_host, v8::Local<v8::Script> script, - SingleCachedMetadataHandler* cache_handler, + CachedMetadataHandler* cache_handler, size_t source_text_length, const KURL& source_url, const TextPosition& source_start_position, @@ -296,19 +296,18 @@ } uint32_t V8CodeCache::TagForCodeCache( - const SingleCachedMetadataHandler* cache_handler) { + const CachedMetadataHandler* cache_handler) { return CacheTag(kCacheTagCode, cache_handler->Encoding()); } uint32_t V8CodeCache::TagForTimeStamp( - const SingleCachedMetadataHandler* cache_handler) { + const CachedMetadataHandler* cache_handler) { return CacheTag(kCacheTagTimeStamp, cache_handler->Encoding()); } // Store a timestamp to the cache as hint. -void V8CodeCache::SetCacheTimeStamp( - CodeCacheHost* code_cache_host, - SingleCachedMetadataHandler* cache_handler) { +void V8CodeCache::SetCacheTimeStamp(CodeCacheHost* code_cache_host, + CachedMetadataHandler* cache_handler) { uint64_t now_ms = base::TimeTicks::Now().since_origin().InMilliseconds(); cache_handler->ClearCachedMetadata(code_cache_host, CachedMetadataHandler::kClearLocally);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h index 7d758bd..aa67417 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h
@@ -48,16 +48,16 @@ kProduceCodeCache, }; - static uint32_t TagForCodeCache(const SingleCachedMetadataHandler*); - static uint32_t TagForTimeStamp(const SingleCachedMetadataHandler*); - static void SetCacheTimeStamp(CodeCacheHost*, SingleCachedMetadataHandler*); + static uint32_t TagForCodeCache(const CachedMetadataHandler*); + static uint32_t TagForTimeStamp(const CachedMetadataHandler*); + static void SetCacheTimeStamp(CodeCacheHost*, CachedMetadataHandler*); - // Returns true iff the SingleCachedMetadataHandler contains a code cache + // Returns true iff the CachedMetadataHandler contains a code cache // that can be consumed by V8. static bool HasCodeCache( - const SingleCachedMetadataHandler*, - SingleCachedMetadataHandler::GetCachedMetadataBehavior behavior = - SingleCachedMetadataHandler::kCrashIfUnchecked); + const CachedMetadataHandler*, + CachedMetadataHandler::GetCachedMetadataBehavior behavior = + CachedMetadataHandler::kCrashIfUnchecked); static std::tuple<v8::ScriptCompiler::CompileOptions, ProduceCacheOptions, @@ -67,23 +67,23 @@ ProduceCacheOptions, v8::ScriptCompiler::NoCacheReason> GetCompileOptions(mojom::blink::V8CacheOptions, - const SingleCachedMetadataHandler*, + const CachedMetadataHandler*, size_t source_text_length, ScriptSourceLocationType); static scoped_refptr<CachedMetadata> GetCachedMetadata( - const SingleCachedMetadataHandler* cache_handler, - SingleCachedMetadataHandler::GetCachedMetadataBehavior behavior = - SingleCachedMetadataHandler::kCrashIfUnchecked); + const CachedMetadataHandler* cache_handler, + CachedMetadataHandler::GetCachedMetadataBehavior behavior = + CachedMetadataHandler::kCrashIfUnchecked); static std::unique_ptr<v8::ScriptCompiler::CachedData> CreateCachedData( scoped_refptr<CachedMetadata>); static std::unique_ptr<v8::ScriptCompiler::CachedData> CreateCachedData( - const SingleCachedMetadataHandler*); + const CachedMetadataHandler*); static void ProduceCache(v8::Isolate*, CodeCacheHost*, v8::Local<v8::Script>, - SingleCachedMetadataHandler*, + CachedMetadataHandler*, size_t source_text_length, const KURL& source_url, const WTF::TextPosition& source_start_position,
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc index fe04a69..567b8b6 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -162,8 +162,7 @@ case v8::ScriptCompiler::kConsumeCodeCache: { // Compile a script, and consume a V8 cache that was generated previously. - SingleCachedMetadataHandler* cache_handler = - classic_script.CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script.CacheHandler(); ScriptCacheConsumer* cache_consumer = classic_script.CacheConsumer(); scoped_refptr<CachedMetadata> cached_metadata = V8CodeCache::GetCachedMetadata(cache_handler); @@ -318,7 +317,7 @@ case v8::ScriptCompiler::kConsumeCodeCache: { // Compile a script, and consume a V8 cache that was generated // previously. - SingleCachedMetadataHandler* cache_handler = params.CacheHandler(); + CachedMetadataHandler* cache_handler = params.CacheHandler(); DCHECK(cache_handler); cache_handler->DidUseCodeCache(); // TODO(leszeks): Add support for passing in ScriptCacheConsumer. @@ -417,7 +416,7 @@ namespace { void DelayedProduceCodeCacheTask(ScriptState* script_state, v8::Global<v8::Script> script, - SingleCachedMetadataHandler* cache_handler, + CachedMetadataHandler* cache_handler, size_t source_text_length, KURL source_url, TextPosition source_start_position) { @@ -496,7 +495,7 @@ v8::Local<v8::Script> script; - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); if (cache_handler) { cache_handler->Check( ExecutionContext::GetCodeCacheHostFromContext(execution_context),
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc index 151605f..7c6228f8 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc
@@ -60,14 +60,14 @@ : "http://bla.com/bla%d", counter_)); } - unsigned TagForCodeCache(SingleCachedMetadataHandler* cache_handler) const { + unsigned TagForCodeCache(CachedMetadataHandler* cache_handler) const { return V8CodeCache::TagForCodeCache(cache_handler); } - unsigned TagForTimeStamp(SingleCachedMetadataHandler* cache_handler) const { + unsigned TagForTimeStamp(CachedMetadataHandler* cache_handler) const { return V8CodeCache::TagForTimeStamp(cache_handler); } void SetCacheTimeStamp(CodeCacheHost* code_cache_host, - SingleCachedMetadataHandler* cache_handler) { + CachedMetadataHandler* cache_handler) { V8CodeCache::SetCacheTimeStamp(code_cache_host, cache_handler); } @@ -269,7 +269,7 @@ TEST_F(V8ScriptRunnerTest, codeOption) { V8TestingScope scope; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); ExecutionContext* execution_context = ExecutionContext::From(scope.GetScriptState()); SetCacheTimeStamp( @@ -294,7 +294,7 @@ V8TestingScope scope; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); // Set timestamp to simulate a warm run. - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); ExecutionContext* execution_context = ExecutionContext::From(scope.GetScriptState()); SetCacheTimeStamp( @@ -332,7 +332,7 @@ V8TestingScope scope; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); // Set timestamp to simulate a warm run. - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); ExecutionContext* execution_context = ExecutionContext::From(scope.GetScriptState()); SetCacheTimeStamp( @@ -378,7 +378,7 @@ blink::features::kDiscardCodeCacheAfterFirstUse); V8TestingScope scope; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); // Cold run - should set the timestamp. EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(), @@ -416,7 +416,7 @@ blink::features::kDiscardCodeCacheAfterFirstUse); V8TestingScope scope; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); // Cold run - should set the timestamp. EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(), @@ -455,7 +455,7 @@ blink::features::kDiscardCodeCacheAfterFirstUse); V8TestingScope scope; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); base::HistogramTester tester; HistogramCounter counter(tester); EXPECT_FALSE( @@ -469,7 +469,7 @@ blink::features::kDiscardCodeCacheAfterFirstUse); V8TestingScope scope; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); EXPECT_FALSE( cache_handler->GetCachedMetadata(TagForTimeStamp(cache_handler))); EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(), @@ -498,7 +498,7 @@ "codecachewithhashing"); code_cache_with_hashing_scheme_ = true; ClassicScript* classic_script = CreateScript(CreateResource(UTF8Encoding())); - SingleCachedMetadataHandler* cache_handler = classic_script->CacheHandler(); + CachedMetadataHandler* cache_handler = classic_script->CacheHandler(); EXPECT_TRUE(cache_handler->HashRequired()); // Cold run - should set the timestamp.
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index 8378863..e6b36d5 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -37,6 +37,7 @@ from .codegen_context import CodeGenContext from .codegen_expr import CodeGenExpr from .codegen_expr import expr_from_exposure +from .codegen_expr import expr_not from .codegen_expr import expr_or from .codegen_format import format_template as _format from .codegen_utils import component_export @@ -2087,6 +2088,20 @@ body = func_def.body if len(cg_context.constructor_group) == 1: + # The constructor callback is installed with + # v8::FunctionTemplate::SetCallHandler, where no way to control the + # installation context-by-context. So, we check the exposure and may + # throw a TypeError if not exposed. For the case of multiple overloads, + # the overload resolution is already exposure sensitive. + if cg_context.constructor.exposure.is_context_dependent(): + body.append( + CxxUnlikelyIfNode(cond=expr_not( + expr_from_exposure(cg_context.constructor.exposure)), + body=[ + T("${exception_state}.ThrowTypeError(" + "\"Illegal constructor\");"), + T("return;"), + ])) body.append(make_constructor_entry(cg_context)) body.append(EmptyNode()) @@ -5750,7 +5765,8 @@ FormatNode("${interface_function_template}->SetLength({});", entry.ctor_func_length), ] - if not entry.exposure_conditional.is_always_true: + if not (entry.exposure_conditional.is_always_true + or entry.is_context_dependent): nodes = [ CxxUnlikelyIfNode(cond=entry.exposure_conditional, body=nodes), ]
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index ad990bd4..d5244eea 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -55,6 +55,7 @@ #include "third_party/blink/renderer/core/css/container_query_data.h" #include "third_party/blink/renderer/core/css/container_query_evaluator.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_markup.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" @@ -199,6 +200,7 @@ #include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" +#include "third_party/blink/renderer/platform/language.h" #include "third_party/blink/renderer/platform/region_capture_crop_id.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/casting.h" @@ -8288,6 +8290,43 @@ style->SetProperty(property_id, value); } +void Element::MapLanguageAttributeToLocale(const AtomicString& value, + MutableCSSPropertyValueSet* style) { + if (!value.empty()) { + // Have to quote so the locale id is treated as a string instead of as a CSS + // keyword. + AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kWebkitLocale, + SerializeString(value)); + + // FIXME: Remove the following UseCounter code when we collect enough + // data. + UseCounter::Count(GetDocument(), WebFeature::kLangAttribute); + if (IsA<HTMLHtmlElement>(this)) + UseCounter::Count(GetDocument(), WebFeature::kLangAttributeOnHTML); + else if (IsA<HTMLBodyElement>(this)) + UseCounter::Count(GetDocument(), WebFeature::kLangAttributeOnBody); + String html_language = value.GetString(); + wtf_size_t first_separator = html_language.find('-'); + if (first_separator != kNotFound) + html_language = html_language.Left(first_separator); + String ui_language = DefaultLanguage(); + first_separator = ui_language.find('-'); + if (first_separator != kNotFound) + ui_language = ui_language.Left(first_separator); + first_separator = ui_language.find('_'); + if (first_separator != kNotFound) + ui_language = ui_language.Left(first_separator); + if (!DeprecatedEqualIgnoringCase(html_language, ui_language)) { + UseCounter::Count(GetDocument(), + WebFeature::kLangAttributeDoesNotMatchToUILocale); + } + } else { + // The empty string means the language is explicitly unknown. + AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kWebkitLocale, + CSSValueID::kAuto); + } +} + void Element::LogAddElementIfIsolatedWorldAndInDocument( const char element[], const QualifiedName& attr1) {
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index 9b348b0..ddb7194 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -1248,6 +1248,8 @@ void AddPropertyToPresentationAttributeStyle(MutableCSSPropertyValueSet*, CSSPropertyID, const CSSValue&); + void MapLanguageAttributeToLocale(const AtomicString&, + MutableCSSPropertyValueSet*); InsertionNotificationRequest InsertedInto(ContainerNode&) override; void RemovedFrom(ContainerNode&) override;
diff --git a/third_party/blink/renderer/core/events/mouse_event.cc b/third_party/blink/renderer/core/events/mouse_event.cc index 9d905e0..8f1f3806 100644 --- a/third_party/blink/renderer/core/events/mouse_event.cc +++ b/third_party/blink/renderer/core/events/mouse_event.cc
@@ -387,14 +387,14 @@ bool send_to_disabled_form_controls = RuntimeEnabledFeatures::SendMouseEventsDisabledFormControlsEnabled(); + if (!isTrusted()) + return dispatcher.Dispatch(); + if (send_to_disabled_form_controls && is_click && GetEventPath().DisabledFormControlExistsInPath()) { return DispatchEventResult::kCanceledBeforeDispatch; } - if (!isTrusted()) - return dispatcher.Dispatch(); - if (!send_to_disabled_form_controls && IsDisabledFormControl(&dispatcher.GetNode())) { if (GetEventPath().HasEventListenersInPath(type())) {
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 8d71a17..71885b1 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -336,6 +336,7 @@ visitor->Trace(lifecycle_observers_); visitor->Trace(fullscreen_video_elements_); visitor->Trace(pending_transform_updates_); + visitor->Trace(pending_opacity_updates_); } void LocalFrameView::ForAllChildViewsAndPlugins( @@ -5013,17 +5014,52 @@ return true; } -void LocalFrameView::UpdateAllPendingTransforms() { +bool LocalFrameView::UpdateAllPendingTransforms() { DCHECK(GetFrame().IsLocalRoot() || !IsAttached()); - ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) { + bool updated = false; + ForAllNonThrottledLocalFrameViews([&updated](LocalFrameView& frame_view) { if (frame_view.pending_transform_updates_) { for (const LayoutObject* object : *frame_view.pending_transform_updates_) { PaintPropertyTreeBuilder::DirectlyUpdateTransformMatrix(*object); + updated = true; } frame_view.pending_transform_updates_->clear(); } }); + return updated; } +void LocalFrameView::AddPendingOpacityUpdate(LayoutObject& object) { + if (!pending_opacity_updates_) { + pending_opacity_updates_ = + MakeGarbageCollected<HeapHashSet<Member<LayoutObject>>>(); + } + pending_opacity_updates_->insert(&object); +} + +bool LocalFrameView::RemovePendingOpacityUpdate(const LayoutObject& object) { + if (!pending_opacity_updates_) + return false; + auto it = pending_opacity_updates_->find(const_cast<LayoutObject*>(&object)); + if (it == pending_opacity_updates_->end()) + return false; + pending_opacity_updates_->erase(it); + return true; +} + +bool LocalFrameView::UpdateAllPendingOpacityUpdates() { + DCHECK(GetFrame().IsLocalRoot() || !IsAttached()); + bool updated = false; + ForAllNonThrottledLocalFrameViews([&updated](LocalFrameView& frame_view) { + if (frame_view.pending_opacity_updates_) { + for (const LayoutObject* object : *frame_view.pending_opacity_updates_) { + PaintPropertyTreeBuilder::DirectlyUpdateOpacityValue(*object); + updated = true; + } + frame_view.pending_opacity_updates_->clear(); + } + }); + return updated; +} } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 13997852..deef7ca 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -769,7 +769,11 @@ void AddPendingTransformUpdate(LayoutObject& object); bool RemovePendingTransformUpdate(const LayoutObject& object); - void UpdateAllPendingTransforms(); + bool UpdateAllPendingTransforms(); + + void AddPendingOpacityUpdate(LayoutObject& object); + bool RemovePendingOpacityUpdate(const LayoutObject& object); + bool UpdateAllPendingOpacityUpdates(); protected: void FrameRectsChanged(const gfx::Rect&) override; @@ -1176,7 +1180,9 @@ // possible, avoids needing to walk the tree to update them. See: // https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/paint/README.md#Transform-update-optimization // for more on the fast path + // TODO(yotha): unify these into one HeapHashMap. Member<HeapHashSet<Member<LayoutObject>>> pending_transform_updates_; + Member<HeapHashSet<Member<LayoutObject>>> pending_opacity_updates_; #if DCHECK_IS_ON() bool is_updating_descendant_dependent_flags_;
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index fe0cf970..e5b20be 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -30,7 +30,6 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_union_stringtreatnullasemptystring_trustedscript.h" #include "third_party/blink/renderer/core/css/css_color.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" -#include "third_party/blink/renderer/core/css/css_markup.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" @@ -92,7 +91,6 @@ #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" -#include "third_party/blink/renderer/platform/language.h" #include "third_party/blink/renderer/platform/text/bidi_resolver.h" #include "third_party/blink/renderer/platform/text/bidi_text_run.h" #include "third_party/blink/renderer/platform/text/text_run_iterator.h" @@ -277,44 +275,6 @@ CSSValueID::kSolid); } -void HTMLElement::MapLanguageAttributeToLocale( - const AtomicString& value, - MutableCSSPropertyValueSet* style) { - if (!value.empty()) { - // Have to quote so the locale id is treated as a string instead of as a CSS - // keyword. - AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kWebkitLocale, - SerializeString(value)); - - // FIXME: Remove the following UseCounter code when we collect enough - // data. - UseCounter::Count(GetDocument(), WebFeature::kLangAttribute); - if (IsA<HTMLHtmlElement>(this)) - UseCounter::Count(GetDocument(), WebFeature::kLangAttributeOnHTML); - else if (IsA<HTMLBodyElement>(this)) - UseCounter::Count(GetDocument(), WebFeature::kLangAttributeOnBody); - String html_language = value.GetString(); - wtf_size_t first_separator = html_language.find('-'); - if (first_separator != kNotFound) - html_language = html_language.Left(first_separator); - String ui_language = DefaultLanguage(); - first_separator = ui_language.find('-'); - if (first_separator != kNotFound) - ui_language = ui_language.Left(first_separator); - first_separator = ui_language.find('_'); - if (first_separator != kNotFound) - ui_language = ui_language.Left(first_separator); - if (!DeprecatedEqualIgnoringCase(html_language, ui_language)) { - UseCounter::Count(GetDocument(), - WebFeature::kLangAttributeDoesNotMatchToUILocale); - } - } else { - // The empty string means the language is explicitly unknown. - AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kWebkitLocale, - CSSValueID::kAuto); - } -} - bool HTMLElement::IsPresentationAttribute(const QualifiedName& name) const { if (name == html_names::kAlignAttr || name == html_names::kContenteditableAttr ||
diff --git a/third_party/blink/renderer/core/html/html_element.h b/third_party/blink/renderer/core/html/html_element.h index b4f7150..64e2f78 100644 --- a/third_party/blink/renderer/core/html/html_element.h +++ b/third_party/blink/renderer/core/html/html_element.h
@@ -239,8 +239,6 @@ bool IsStyledElement() const = delete; // This will catch anyone doing an unnecessary check. - void MapLanguageAttributeToLocale(const AtomicString&, - MutableCSSPropertyValueSet*); void ApplyAspectRatioToStyle(double width, double height, MutableCSSPropertyValueSet* style);
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 13e3e2e7..e73b051 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -3674,6 +3674,7 @@ if (GetFrameView()) { GetFrameView()->RemovePendingTransformUpdate(*this); + GetFrameView()->RemovePendingOpacityUpdate(*this); SetIsBackgroundAttachmentFixedObject(false); } }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc index 822eaac..2fc1494 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -2105,7 +2105,7 @@ #container { width: 150px; height: 60px; - overflow: hidden; + display: flow-root; } #float1 { width: 100px;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h index d6d9eeb..308f911 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -289,6 +289,8 @@ // Specify whether this will be the first fragment generated for the node. void SetIsFirstForNode(bool is_first) { is_first_for_node_ = is_first; } + void SetIsMonolithic(bool b) { is_monolithic_ = b; } + // Set how much of the block-size we've used so far for this box. This will be // the sum of the block-size of all previous fragments PLUS the one we're // building now. @@ -755,6 +757,7 @@ bool is_known_to_fit_in_fragmentainer_ = false; bool requires_content_before_breaking_ = false; bool is_block_size_for_fragmentation_clamped_ = false; + bool is_monolithic_ = true; bool is_first_for_node_ = true; bool did_break_self_ = false; bool has_inflow_child_break_inside_ = false;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h index 11d2e43..277eb8c 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h +++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -159,6 +159,7 @@ NGConstraintSpace copy = *this; DCHECK(copy.rare_data_); copy.rare_data_->block_direction_fragmentation_type = kFragmentNone; + copy.rare_data_->is_block_fragmentation_forced_off = true; return copy; } @@ -541,6 +542,12 @@ return BlockFragmentationType() != kFragmentNone; } + // Return true if the node actually participates in block fragmentation, that + // was disabled due to clipped overflow. + bool IsBlockFragmentationForcedOff() const { + return HasRareData() && rare_data_->is_block_fragmentation_forced_off; + } + // Return true if the document is paginated (for printing). bool IsPaginated() const { // TODO(layout-dev): This will not work correctly if establishing a nested @@ -878,6 +885,7 @@ hide_table_cell_if_empty(false), block_direction_fragmentation_type( static_cast<unsigned>(kFragmentNone)), + is_block_fragmentation_forced_off(false), requires_content_before_breaking(false), is_inside_balanced_columns(false), should_ignore_forced_breaks(false), @@ -907,6 +915,8 @@ hide_table_cell_if_empty(other.hide_table_cell_if_empty), block_direction_fragmentation_type( other.block_direction_fragmentation_type), + is_block_fragmentation_forced_off( + other.is_block_fragmentation_forced_off), requires_content_before_breaking( other.requires_content_before_breaking), is_inside_balanced_columns(other.is_inside_balanced_columns), @@ -989,6 +999,8 @@ hide_table_cell_if_empty != other.hide_table_cell_if_empty || block_direction_fragmentation_type != other.block_direction_fragmentation_type || + is_block_fragmentation_forced_off != + other.is_block_fragmentation_forced_off || requires_content_before_breaking != other.requires_content_before_breaking || is_inside_balanced_columns != other.is_inside_balanced_columns || @@ -1029,6 +1041,7 @@ is_pushed_by_floats || is_restricted_block_size_table_cell || hide_table_cell_if_empty || block_direction_fragmentation_type != kFragmentNone || + is_block_fragmentation_forced_off || requires_content_before_breaking || is_inside_balanced_columns || should_ignore_forced_breaks || is_in_column_bfc || min_break_appeal != kBreakAppealLastResort || @@ -1316,6 +1329,7 @@ unsigned hide_table_cell_if_empty : 1; unsigned block_direction_fragmentation_type : 2; + unsigned is_block_fragmentation_forced_off : 1; unsigned requires_content_before_breaking : 1; unsigned is_inside_balanced_columns : 1; unsigned should_ignore_forced_breaks : 1;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc b/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc index f19596e..37ab13d 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc
@@ -114,6 +114,31 @@ void NGFragmentRepeater::CloneChildFragments( const NGPhysicalBoxFragment& cloned_fragment) { + if (cloned_fragment.HasItems()) { + // Fragment items have already been cloned, but any atomic inlines were + // shallowly cloned. Deep-clone them now, if any. + for (auto& cloned_item : cloned_fragment.Items()->Items()) { + const NGPhysicalBoxFragment* child_box_fragment = + cloned_item.BoxFragment(); + if (!child_box_fragment) + continue; + const auto* child_layout_box = + DynamicTo<LayoutBox>(child_box_fragment->GetLayoutObject()); + if (!child_layout_box) { + // We don't need to clone non-atomic inlines. + DCHECK(child_box_fragment->GetLayoutObject()->IsLayoutInline()); + continue; + } + const NGLayoutResult* child_result = + GetClonableLayoutResult(*child_layout_box, *child_box_fragment); + child_result = Repeat(*child_result); + child_box_fragment = + &To<NGPhysicalBoxFragment>(child_result->PhysicalFragment()); + cloned_item.GetMutableForCloning().ReplaceBoxFragment( + *child_box_fragment); + } + } + for (NGLink& child : cloned_fragment.GetMutableForCloning().Children()) { if (const auto* child_box = DynamicTo<NGPhysicalBoxFragment>(child.fragment.Get())) { @@ -148,31 +173,6 @@ RemoveClonedResults(layout_box); } - if (cloned_fragment.HasItems()) { - // Fragment items have already been cloned, but any atomic inlines were - // shallowly cloned. Deep-clone them now, if any. - for (auto& cloned_item : cloned_fragment.Items()->Items()) { - const NGPhysicalBoxFragment* child_box_fragment = - cloned_item.BoxFragment(); - if (!child_box_fragment) - continue; - const auto* child_layout_box = - DynamicTo<LayoutBox>(child_box_fragment->GetLayoutObject()); - if (!child_layout_box) { - // We don't need to clone non-atomic inlines. - DCHECK(child_box_fragment->GetLayoutObject()->IsLayoutInline()); - continue; - } - const NGLayoutResult* child_result = - GetClonableLayoutResult(*child_layout_box, *child_box_fragment); - child_result = Repeat(*child_result); - child_box_fragment = - &To<NGPhysicalBoxFragment>(child_result->PhysicalFragment()); - cloned_item.GetMutableForCloning().ReplaceBoxFragment( - *child_box_fragment); - } - } - CloneChildFragments(cloned_fragment); // The first-for-node bit has also been cloned. But we're obviously not the
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc index b01a6b56..1f3b2fd3 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -320,6 +320,14 @@ // SetHasBlockFragmentation(), but we still need to resume layout correctly, // based on the previous break token. DCHECK(space.HasBlockFragmentation() || previous_break_token); + // If the node itself is monolithic, we shouldn't be here. + DCHECK(!node.IsMonolithic() || space.IsAnonymous()); + // If we turn off fragmentation on a non-monolithic node, we need to treat the + // resulting fragment as monolithic. This matters when it comes to determining + // the containing block of out-of-flow positioned descendants. + builder->SetIsMonolithic(!space.IsAnonymous() && + space.IsBlockFragmentationForcedOff()); + if (space.HasBlockFragmentation()) builder->SetHasBlockFragmentation(); builder->SetPreviousBreakToken(previous_break_token);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index 32b4bd22..66bc517 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -358,7 +358,8 @@ ConstHasRareDataFlag::encode(has_rare_data) | HasDescendantsForTablePartFlag::encode(false) | IsFragmentationContextRootFlag::encode( - builder->is_fragmentation_context_root_)), + builder->is_fragmentation_context_root_) | + IsMonolithicFlag::encode(builder->is_monolithic_)), const_num_children_(builder->children_.size()) { DCHECK(layout_object_); DCHECK(layout_object_->IsBoxModelObject());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h index 4920630..8a83fc3 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -405,6 +405,8 @@ return bit_field_.get<IsFragmentationContextRootFlag>(); } + bool IsMonolithic() const { return bit_field_.get<IsMonolithicFlag>(); } + #if DCHECK_IS_ON() void CheckSameForSimplifiedLayout(const NGPhysicalBoxFragment&, bool check_same_block_size) const; @@ -525,6 +527,8 @@ IsFirstForNodeFlag::DefineNextValue<bool, 1>; using IsFragmentationContextRootFlag = HasDescendantsForTablePartFlag::DefineNextValue<bool, 1>; + using IsMonolithicFlag = + IsFragmentationContextRootFlag::DefineNextValue<bool, 1>; bool ConstHasRareData() const { // Use get_concurrently because it can be called from a background thread in
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc index 75ff0e26..c4af9d8 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -543,6 +543,17 @@ *FragmentedOutOfFlowData()); } +bool NGPhysicalFragment::IsMonolithic() const { + // Line boxes are monolithic, except for line boxes that are just there to + // contain a block inside an inline, in which case the anonymous block child + // wrapper inside the line is breakable. + if (IsLineBox()) + return !IsBlockInInline(); + if (const auto* box_fragment = DynamicTo<NGPhysicalBoxFragment>(this)) + return box_fragment->IsMonolithic(); + return false; +} + const FragmentData* NGPhysicalFragment::GetFragmentData() const { const LayoutBox* box = DynamicTo<LayoutBox>(GetLayoutObject()); if (!box) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h index 608c4d9..8004025 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -388,18 +388,7 @@ // Return true if this fragment is monolithic, as far as block fragmentation // is concerned. - bool IsMonolithic() const { - // Line boxes are monolithic, except for line boxes that are just there to - // contain a block inside an inline, in which case the anonymous block child - // wrapper inside the line is breakable. - if (IsLineBox()) - return !IsBlockInInline(); - const LayoutObject* layout_object = GetLayoutObject(); - if (!layout_object || !IsBox() || !layout_object->IsBox()) - return false; - return To<LayoutBox>(layout_object)->GetNGPaginationBreakability() == - LayoutBox::kForbidBreaks; - } + bool IsMonolithic() const; // GetLayoutObject should only be used when necessary for compatibility // with LegacyLayout.
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h b/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h index 3bc47db..d950c2c 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h
@@ -32,7 +32,7 @@ ScriptSourceLocationType source_location_type, const ModuleType module_type, const ParkableString& source_text, - SingleCachedMetadataHandler* cache_handler, + CachedMetadataHandler* cache_handler, ScriptStreamer* script_streamer = nullptr, ScriptStreamer::NotStreamingReason not_streaming_reason = ScriptStreamer::NotStreamingReason::kStreamingDisabled) @@ -94,7 +94,7 @@ ScriptStreamer::NotStreamingReason::kStreamingDisabled); } - SingleCachedMetadataHandler* CacheHandler() const { return cache_handler_; } + CachedMetadataHandler* CacheHandler() const { return cache_handler_; } bool IsSafeToSendToAnotherThread() const { return is_isolated_; } @@ -139,7 +139,7 @@ mutable String isolated_source_text_; // |cache_handler_| is cleared when crossing thread boundaries. - Persistent<SingleCachedMetadataHandler> cache_handler_; + Persistent<CachedMetadataHandler> cache_handler_; // |script_streamer_| is cleared when crossing thread boundaries. Persistent<ScriptStreamer> script_streamer_;
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc index 3e3e74b..5e37d0b 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -116,7 +116,7 @@ ModuleType module_type, const ParkableString& source_text, const ResourceResponse& response, - SingleCachedMetadataHandler* cache_handler) { + CachedMetadataHandler* cache_handler) { HeapVector<Member<ConsoleMessage>> error_messages; const KURL response_url = response.ResponseUrl();
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h index efac190..3362881 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h
@@ -53,7 +53,7 @@ ModuleType module_type, const ParkableString& source_text, const ResourceResponse& response, - SingleCachedMetadataHandler* cache_handler); + CachedMetadataHandler* cache_handler); const Member<WorkerGlobalScope> global_scope_;
diff --git a/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc b/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc index 030aecd..4f7c978b 100644 --- a/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc +++ b/third_party/blink/renderer/core/loader/resource/resource_loader_code_cache_test.cc
@@ -235,25 +235,6 @@ EXPECT_FALSE(resource_->CodeCacheSize()); } -TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheInvalidInnerType) { - CommonSetup(); - - std::vector<uint8_t> cache_data{2, 3, 4, 5, 6}; - controller_->Respond( - base::Time(), - mojo_base::BigBuffer(MakeSerializedCodeCacheData( - cache_data, {}, 0, CachedMetadataHandler::kSingleEntryWithHash, - CachedMetadataHandler::kSourceKeyedMap))); - - // Nothing has changed yet because the content response hasn't arrived yet. - EXPECT_FALSE(resource_->CodeCacheSize()); - - loader_->DidReceiveResponse(WrappedResourceResponse(response_)); - - // The serialized metadata was rejected due to an invalid inner type. - EXPECT_FALSE(resource_->CodeCacheSize()); -} - TEST_F(ResourceLoaderCodeCacheTest, WebUICodeCacheHashCheckSuccess) { CommonSetup();
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.cc b/third_party/blink/renderer/core/loader/resource/script_resource.cc index 697201fe..538efa4 100644 --- a/third_party/blink/renderer/core/loader/resource/script_resource.cc +++ b/third_party/blink/renderer/core/loader/resource/script_resource.cc
@@ -257,7 +257,7 @@ return ""; } -SingleCachedMetadataHandler* ScriptResource::CacheHandler() { +CachedMetadataHandler* ScriptResource::CacheHandler() { return cached_metadata_handler_; } @@ -273,10 +273,10 @@ // It's safe to access unchecked cached metadata here, because the // ScriptCacheConsumer result will be ignored if the cached metadata // check fails later. - SingleCachedMetadataHandler::kAllowUnchecked)) { + CachedMetadataHandler::kAllowUnchecked)) { cache_consumer_ = MakeGarbageCollected<ScriptCacheConsumer>( - V8CodeCache::GetCachedMetadata( - CacheHandler(), SingleCachedMetadataHandler::kAllowUnchecked), + V8CodeCache::GetCachedMetadata(CacheHandler(), + CachedMetadataHandler::kAllowUnchecked), Url(), InspectorId()); AdvanceConsumeCacheState(ConsumeCacheState::kRunningOffThread); } else {
diff --git a/third_party/blink/renderer/core/loader/resource/script_resource.h b/third_party/blink/renderer/core/loader/resource/script_resource.h index bb3b86c..a899000e6 100644 --- a/third_party/blink/renderer/core/loader/resource/script_resource.h +++ b/third_party/blink/renderer/core/loader/resource/script_resource.h
@@ -40,11 +40,11 @@ namespace blink { +class CachedMetadataHandler; class FetchParameters; class KURL; class ResourceFetcher; class ScriptCachedMetadataHandler; -class SingleCachedMetadataHandler; // ScriptResource is a resource representing a JavaScript, either a classic or // module script. Based on discussions (crbug.com/1178198) ScriptResources are @@ -120,7 +120,7 @@ // not be used outside of the inspector. String TextForInspector() const; - SingleCachedMetadataHandler* CacheHandler(); + CachedMetadataHandler* CacheHandler(); mojom::blink::ScriptType GetInitialRequestScriptType() const { return initial_request_script_type_;
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.cc b/third_party/blink/renderer/core/mathml/mathml_element.cc index 0c935aa..74cb82e 100644 --- a/third_party/blink/renderer/core/mathml/mathml_element.cc +++ b/third_party/blink/renderer/core/mathml/mathml_element.cc
@@ -31,13 +31,14 @@ EqualIgnoringASCIICase(value, "rtl"); } -// Keywords from MathML3 and CSS font-size are skipped. +// Keywords from CSS font-size are skipped. static inline bool IsDisallowedMathSizeAttribute(const AtomicString& value) { return EqualIgnoringASCIICase(value, "medium") || value.EndsWith("large", kTextCaseASCIIInsensitive) || value.EndsWith("small", kTextCaseASCIIInsensitive) || EqualIgnoringASCIICase(value, "smaller") || - EqualIgnoringASCIICase(value, "larger"); + EqualIgnoringASCIICase(value, "larger") || + EqualIgnoringASCIICase(value, "math"); } bool MathMLElement::IsPresentationAttribute(const QualifiedName& name) const {
diff --git a/third_party/blink/renderer/core/mathml/mathml_operator_element.cc b/third_party/blink/renderer/core/mathml/mathml_operator_element.cc index b6b8a059..a6c7b719 100644 --- a/third_party/blink/renderer/core/mathml/mathml_operator_element.cc +++ b/third_party/blink/renderer/core/mathml/mathml_operator_element.cc
@@ -179,9 +179,10 @@ } else { if (!explicit_form) { // Step 3. - for (uint8_t fallback_form = MathMLOperatorDictionaryForm::kInfix; - fallback_form <= MathMLOperatorDictionaryForm::kPostfix; - fallback_form++) { + for (const auto& fallback_form : + {MathMLOperatorDictionaryForm::kInfix, + MathMLOperatorDictionaryForm::kPostfix, + MathMLOperatorDictionaryForm::kPrefix}) { if (fallback_form == form) continue; category = FindCategory(
diff --git a/third_party/blink/renderer/core/paint/README.md b/third_party/blink/renderer/core/paint/README.md index c13720a..af393b2 100644 --- a/third_party/blink/renderer/core/paint/README.md +++ b/third_party/blink/renderer/core/paint/README.md
@@ -462,9 +462,9 @@ from its containing self-painting layer to this layer, assuming that this layer needs all paint phases that its container self-painting layer needs. -### Transform update optimization +### Property tree update optimization -In specific cases of a transform update, we can directly update the property +In some specific cases of style updates, we can directly update the property tree without needing to run the property tree builder (Which requires a layout tree walk). During `PaintLayer::StyleDidChange` we check if this update meets the requirements for a quick update, and if so we add it to a list of pending @@ -472,9 +472,13 @@ changes can't be detected correctly). The updates are executed later in `PrePaintTreeWalk::WalkTree` using the -`LocalFrameView::UpdateAllPendingTransforms`. If at some point during pre-paint -we reach a node that has a pending update, we mark that node as needs full -update, and remove the pending update from the list. +the designated functions (For example - +`LocalFrameView::UpdateAllPendingTransforms`). If at some point during +pre-paint we reach a node that has a pending update, we mark that node as needs +full update, and remove the pending update from the list. + +Current updates that are checked for an optimized update are transform updates +and opacity updates. ### Hit test information recording
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc index 56b5a04..c6e446e2 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -981,6 +981,75 @@ EXPECT_FALSE(transform_node->transform_changed); } +// Same as the test above but for opacity changes +TEST_P(CompositingSimTest, FastPathOpacityUpdateFromStyle) { + InitializeWithHTML(R"HTML( + <!DOCTYPE html> + <style> + @keyframes animation { + 0% { opacity: 0.2; } + 100% { opacity: 0.8; } + } + #div { + opacity: 0.1; + width: 100px; + height: 100px; + /* + This causes the opacity to have an active animation, but because + the delay is so large, it will not have an effect for the duration + of this unit test. + */ + animation-name: animation; + animation-duration: 999s; + animation-delay: 999s; + } + </style> + <div id='div'></div> + )HTML"); + + Compositor().BeginFrame(); + + // Check the initial state of the blink effect node. + auto* div = GetElementById("div"); + auto* div_properties = + div->GetLayoutObject()->FirstFragment().PaintProperties(); + ASSERT_TRUE(div_properties); + EXPECT_NEAR(0.1, div_properties->Effect()->Opacity(), 0.001); + EXPECT_TRUE(div_properties->Effect()->HasActiveOpacityAnimation()); + EXPECT_FALSE(div->GetLayoutObject()->NeedsPaintPropertyUpdate()); + + // Check the initial state of the cc effect node. + auto* div_cc_layer = CcLayerByDOMElementId("div"); + auto effect_tree_index = div_cc_layer->effect_tree_index(); + const auto* effect_node = + GetPropertyTrees()->effect_tree().Node(effect_tree_index); + EXPECT_FALSE(effect_node->effect_changed); + EXPECT_FALSE(paint_artifact_compositor()->NeedsUpdate()); + EXPECT_NEAR(0.1, effect_node->opacity, 0.001); + + // Change the effect style and ensure the blink and cc effect nodes are + // not marked for a full update. + div->setAttribute(html_names::kStyleAttr, "opacity: 0.15"); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + EXPECT_FALSE(div->GetLayoutObject()->NeedsPaintPropertyUpdate()); + EXPECT_FALSE(paint_artifact_compositor()->NeedsUpdate()); + + // Continue to run the lifecycle to paint and ensure that updates are + // performed. + UpdateAllLifecyclePhasesExceptPaint(); + EXPECT_NEAR(0.15, div_properties->Effect()->Opacity(), 0.001); + EXPECT_NEAR(0.15, effect_node->opacity, 0.001); + EXPECT_TRUE(effect_node->effect_changed); + EXPECT_FALSE(div->GetLayoutObject()->NeedsPaintPropertyUpdate()); + EXPECT_FALSE(paint_artifact_compositor()->NeedsUpdate()); + EXPECT_TRUE(effect_node->effect_changed); + + // After a frame the |opacity_changed| value should be reset. + Compositor().BeginFrame(); + EXPECT_FALSE(effect_node->effect_changed); +} + TEST_P(CompositingSimTest, DirectSVGTransformPropertyUpdate) { InitializeWithHTML(R"HTML( <!doctype html>
diff --git a/third_party/blink/renderer/core/paint/cull_rect_updater.cc b/third_party/blink/renderer/core/paint/cull_rect_updater.cc index 81b2a0b..bf391597 100644 --- a/third_party/blink/renderer/core/paint/cull_rect_updater.cc +++ b/third_party/blink/renderer/core/paint/cull_rect_updater.cc
@@ -23,6 +23,8 @@ namespace { +bool g_is_overriding_cull_rects = false; + void SetLayerNeedsRepaintOnCullRectChange(PaintLayer& layer) { if (layer.PreviousPaintResult() == kMayBeClippedByCullRect || RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) { @@ -262,7 +264,10 @@ UpdateForDescendants(context, layer); } - layer.ClearNeedsCullRectUpdate(); + if (g_is_overriding_cull_rects) + layer.SetNeedsCullRectUpdate(); + else + layer.ClearNeedsCullRectUpdate(); } // "Children" in |force_update_children| means children in the containing block @@ -525,8 +530,7 @@ } OverriddenCullRectScope::OverriddenCullRectScope(PaintLayer& starting_layer, - const CullRect& cull_rect) - : starting_layer_(starting_layer) { + const CullRect& cull_rect) { if (!RuntimeEnabledFeatures::ScrollUpdateOptimizationsEnabled()) return; if (starting_layer.GetLayoutObject().GetFrame()->IsLocalRoot() && @@ -538,7 +542,9 @@ return; } - updated_ = true; + DCHECK(!g_is_overriding_cull_rects); + g_is_overriding_cull_rects = true; + starting_layer.SetNeedsCullRectUpdate(); CullRectUpdater(starting_layer).UpdateInternal(cull_rect); } @@ -546,8 +552,8 @@ OverriddenCullRectScope::~OverriddenCullRectScope() { if (!RuntimeEnabledFeatures::ScrollUpdateOptimizationsEnabled()) return; - if (updated_) - starting_layer_.SetNeedsCullRectUpdate(); + + g_is_overriding_cull_rects = false; } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/cull_rect_updater.h b/third_party/blink/renderer/core/paint/cull_rect_updater.h index ec9e37a6..11af4378 100644 --- a/third_party/blink/renderer/core/paint/cull_rect_updater.h +++ b/third_party/blink/renderer/core/paint/cull_rect_updater.h
@@ -85,16 +85,12 @@ // cull rect when leaving this scope. // TODO(crbug.com/1215251): Avoid repaint after the scope if the scope is used // to paint into a separate PaintController. -class OverriddenCullRectScope { +class CORE_EXPORT OverriddenCullRectScope { STACK_ALLOCATED(); public: OverriddenCullRectScope(PaintLayer&, const CullRect&); ~OverriddenCullRectScope(); - - private: - PaintLayer& starting_layer_; - bool updated_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/object_paint_properties.h b/third_party/blink/renderer/core/paint/object_paint_properties.h index d417496..7bc1c0b6 100644 --- a/third_party/blink/renderer/core/paint/object_paint_properties.h +++ b/third_party/blink/renderer/core/paint/object_paint_properties.h
@@ -321,6 +321,18 @@ std::move(transform_and_origin), animation_state); } + PaintPropertyChangeType DirectlyUpdateOpacity( + float opacity, + const EffectPaintPropertyNode::AnimationState& animation_state) { + // TODO(yotha): Remove this check once we make sure crbug.com/1370268 is + // fixed + DCHECK(effect_ != nullptr); + if (effect_ == nullptr) { + return PaintPropertyChangeType::kNodeAddedOrRemoved; + } + return effect_->DirectlyUpdateOpacity(opacity, animation_state); + } + private: // Return true if the property tree structure changes (an existing node was // deleted), and false otherwise. See the class-level comment ("update & clear
diff --git a/third_party/blink/renderer/core/paint/old_cull_rect_updater.h b/third_party/blink/renderer/core/paint/old_cull_rect_updater.h index 3ee16944..54f51c3 100644 --- a/third_party/blink/renderer/core/paint/old_cull_rect_updater.h +++ b/third_party/blink/renderer/core/paint/old_cull_rect_updater.h
@@ -75,7 +75,7 @@ // cull rect when leaving this scope. // TODO(crbug.com/1215251): Avoid repaint after the scope if the scope is used // to paint into a separate PaintController. -class OverriddenOldCullRectScope { +class CORE_EXPORT OverriddenOldCullRectScope { STACK_ALLOCATED(); public:
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 98c1f9e..9f30bbb 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -2456,9 +2456,18 @@ } } + bool needs_full_opacity_update = diff.OpacityChanged(); + if (needs_full_opacity_update) { + if (PaintPropertyTreeBuilder::ScheduleDeferredOpacityNodeUpdate( + GetLayoutObject())) { + needs_full_opacity_update = false; + SetNeedsDescendantDependentFlagsUpdate(); + } + } + // See also |LayoutObject::SetStyle| which handles these invalidations if a // PaintLayer is not present. - if (needs_full_transform_update || diff.OpacityChanged() || + if (needs_full_transform_update || needs_full_opacity_update || diff.ZIndexChanged() || diff.FilterChanged() || diff.CssClipChanged() || diff.BlendModeChanged() || diff.MaskChanged() || diff.CompositingReasonsChanged()) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc index c4a69f9..902e2af 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -6,6 +6,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" +#include "third_party/blink/renderer/core/paint/cull_rect_updater.h" +#include "third_party/blink/renderer/core/paint/old_cull_rect_updater.h" #include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h" #include "third_party/blink/renderer/platform/graphics/graphics_context.h" #include "third_party/blink/renderer/platform/testing/find_cc_layer.h" @@ -749,6 +751,40 @@ EXPECT_TRUE(html_layer.NeedsPaintPhaseDescendantOutlines()); } +TEST_P(PaintLayerPainterTest, PaintWithOverriddenCullRect) { + SetBodyInnerHTML(R"HTML( + <div id="stacking" style="opacity: 0.5; height: 200px;"> + <div id="absolute" style="position: absolute; height: 200px"></div> + </div> + )HTML"); + + auto& stacking = *GetPaintLayerByElementId("stacking"); + auto& absolute = *GetPaintLayerByElementId("absolute"); + EXPECT_EQ(gfx::Rect(0, 0, 800, 600), GetCullRect(stacking).Rect()); + EXPECT_EQ(gfx::Rect(0, 0, 800, 600), GetCullRect(absolute).Rect()); + EXPECT_EQ(kFullyPainted, stacking.PreviousPaintResult()); + EXPECT_EQ(kFullyPainted, absolute.PreviousPaintResult()); + { + OverriddenCullRectScope scope(stacking, + CullRect(gfx::Rect(0, 0, 100, 100))); + OverriddenOldCullRectScope old_scope(stacking, + CullRect(gfx::Rect(0, 0, 100, 100))); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), GetCullRect(stacking).Rect()); + EXPECT_EQ(gfx::Rect(0, 0, 100, 100), GetCullRect(absolute).Rect()); + PaintController controller(PaintController::kTransient); + GraphicsContext context(controller); + PaintLayerPainter(stacking).Paint(context); + } + UpdateAllLifecyclePhasesForTest(); + // Should restore the original status after OverridingCullRectScope. + EXPECT_EQ(gfx::Rect(0, 0, 800, 600), GetCullRect(stacking).Rect()); + EXPECT_EQ(gfx::Rect(0, 0, 800, 600), GetCullRect(absolute).Rect()); + EXPECT_EQ(kFullyPainted, stacking.PreviousPaintResult()); + EXPECT_EQ(kFullyPainted, absolute.PreviousPaintResult()); + EXPECT_FALSE(stacking.SelfOrDescendantNeedsRepaint()); + EXPECT_FALSE(absolute.SelfOrDescendantNeedsRepaint()); +} + class PaintLayerPainterPaintedOutputInvisibleTest : public PaintLayerPainterTest { protected:
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 5971312..23c1cbbb 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -851,6 +851,24 @@ } } +static void DirectlyUpdateCcOpacity(const LayoutObject& object, + ObjectPaintProperties& properties, + PaintPropertyChangeType& change_type) { + if (change_type == PaintPropertyChangeType::kChangedOnlySimpleValues && + properties.Effect()->HasDirectCompositingReasons()) { + if (auto* paint_artifact_compositor = + object.GetFrameView()->GetPaintArtifactCompositor()) { + bool updated = + paint_artifact_compositor->DirectlyUpdateCompositedOpacityValue( + *properties.Effect()); + if (updated) { + change_type = PaintPropertyChangeType::kChangedOnlyCompositedValues; + properties.Effect()->CompositorSimpleValuesUpdated(); + } + } + } +} + // TODO(dbaron): Remove this function when we can remove the // BackfaceVisibilityInteropEnabled() check, and have the caller use // CompositingReason::kDirectReasonsForTransformProperty directly. @@ -1446,6 +1464,9 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() { DCHECK(properties_); + // Since we're doing a full update, clear list of objects waiting for a + // deferred update + object_.GetFrameView()->RemovePendingOpacityUpdate(object_); const ComputedStyle& style = object_.StyleRef(); if (NeedsPaintPropertyUpdate()) { @@ -1557,25 +1578,7 @@ // If we have simple value change, which means opacity, we should try to // directly update it on the PaintArtifactCompositor in order to avoid // doing a full rebuild. - if (effective_change_type == - PaintPropertyChangeType::kChangedOnlySimpleValues && - properties_->Effect()->HasDirectCompositingReasons() && - // TODO(crbug.com/1253797): Due to the bug, we may create multiple - // cc effect nodes for one blink effect node of a fragmented object, - // and direct update would be incomplete in the case. - !object_.FirstFragment().NextFragment()) { - if (auto* paint_artifact_compositor = - object_.GetFrameView()->GetPaintArtifactCompositor()) { - bool updated = - paint_artifact_compositor->DirectlyUpdateCompositedOpacityValue( - *properties_->Effect()); - if (updated) { - effective_change_type = - PaintPropertyChangeType::kChangedOnlyCompositedValues; - properties_->Effect()->CompositorSimpleValuesUpdated(); - } - } - } + DirectlyUpdateCcOpacity(object_, *properties_, effective_change_type); OnUpdateEffect(effective_change_type); auto mask_direct_compositing_reasons = @@ -2927,7 +2930,8 @@ // |translation_2d_to_layout_shift_root_delta|) is updated properly. // See: ../paint/README.md#Transform-update-optimization for more on // optimized transform updates - if (object_.GetFrameView()->RemovePendingTransformUpdate(object_)) + if (object_.GetFrameView()->RemovePendingTransformUpdate(object_) || + object_.GetFrameView()->RemovePendingOpacityUpdate(object_)) object_.GetMutableForPainting().SetOnlyThisNeedsPaintPropertyUpdate(); if (box.Size() == box.PreviousSize()) @@ -4194,6 +4198,17 @@ return false; } +bool PaintPropertyTreeBuilder::ScheduleDeferredOpacityNodeUpdate( + LayoutObject& object) { + if (!base::FeatureList::IsEnabled(features::kFastPathPaintPropertyUpdates)) + return false; + if (CanDoDeferredOpacityNodeUpdate(object)) { + object.GetFrameView()->AddPendingOpacityUpdate(object); + return true; + } + return false; +} + // Fast-path for directly updating transforms. Returns true if successful. This // is similar to |FragmentPaintPropertyTreeBuilder::UpdateIndividualTransform|. void PaintPropertyTreeBuilder::DirectlyUpdateTransformMatrix( @@ -4252,6 +4267,34 @@ } } +void PaintPropertyTreeBuilder::DirectlyUpdateOpacityValue( + const LayoutObject& object) { + DCHECK(CanDoDeferredOpacityNodeUpdate(object)); + const ComputedStyle& style = object.StyleRef(); + + EffectPaintPropertyNode::AnimationState animation_state; + animation_state.is_running_opacity_animation_on_compositor = + style.IsRunningOpacityAnimationOnCompositor(); + animation_state.is_running_backdrop_filter_animation_on_compositor = + style.IsRunningBackdropFilterAnimationOnCompositor(); + + FragmentData* fragment_data = &object.GetMutableForPainting().FirstFragment(); + auto* properties = fragment_data->PaintProperties(); + auto effective_change_type = + properties->DirectlyUpdateOpacity(style.Opacity(), animation_state); + // If we have simple value change, which means opacity, we should try to + // directly update it on the PaintArtifactCompositor in order to avoid + // needing to run the property tree builder at all. + DirectlyUpdateCcOpacity(object, *properties, effective_change_type); + + if (effective_change_type >= + PaintPropertyChangeType::kChangedOnlySimpleValues) { + object.GetFrameView()->SetPaintArtifactCompositorNeedsUpdate( + PaintArtifactCompositorUpdateReason:: + kPaintPropertyTreeBuilderPaintPropertyChanged); + } +} + void PaintPropertyTreeBuilder::IssueInvalidationsAfterUpdate() { // We need to update property tree states of paint chunks. auto max_change = properties_changed_.Max(); @@ -4359,4 +4402,38 @@ return true; } +bool PaintPropertyTreeBuilder::CanDoDeferredOpacityNodeUpdate( + const LayoutObject& object) { + // If we already need a full update, do not do the direct update. + if (object.NeedsPaintPropertyUpdate() || + object.DescendantNeedsPaintPropertyUpdate()) { + return false; + } + + // In some cases where we need to remove the update, objects that are not + // boxes can cause a bug. (See SetNeedsPaintPropertyUpdateIfNeeded) + if (!object.IsBox()) + return false; + + // This fast path does not support iterating over each fragment, so do not + // run the fast path in the presence of fragmentation. + if (object.FirstFragment().NextFragment()) + return false; + + auto* properties = object.FirstFragment().PaintProperties(); + // Cannot directly update properties if they have not been created yet. + if (!properties || !properties->Effect()) + return false; + + // Descendant state depends on opacity being zero, so we can't do a direct + // update if it changes + bool old_opacity_is_zero = properties->Effect()->Opacity() == 0; + bool new_opacity_is_zero = object.Style()->Opacity() == 0; + if (old_opacity_is_zero != new_opacity_is_zero) { + return false; + } + + return true; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h index 0bcd685..66f00d2 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -371,8 +371,10 @@ } static void DirectlyUpdateTransformMatrix(const LayoutObject& object); + static void DirectlyUpdateOpacityValue(const LayoutObject& object); static bool ScheduleDeferredTransformNodeUpdate(LayoutObject& object); + static bool ScheduleDeferredOpacityNodeUpdate(LayoutObject& object); private: ALWAYS_INLINE void InitFragmentPaintProperties( @@ -410,6 +412,7 @@ bool IsInNGFragmentTraversal() const { return pre_paint_info_; } static bool CanDoDeferredTransformNodeUpdate(const LayoutObject& object); + static bool CanDoDeferredOpacityNodeUpdate(const LayoutObject& object); const LayoutObject& object_; NGPrePaintInfo* pre_paint_info_;
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc index ba1d707..8f11d0fe 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -1973,4 +1973,25 @@ EXPECT_EQ(200, div_properties->Transform()->Translation2D().x()); } +TEST_P(PaintPropertyTreeUpdateTest, + DirectOpacityUpdateSkipsPropertyTreeBuilder) { + SetBodyInnerHTML(R"HTML( + <div id='div' style="opacity:0.5"></div> + )HTML"); + + auto* div_properties = PaintPropertiesForElement("div"); + ASSERT_TRUE(div_properties); + EXPECT_EQ(0.5, div_properties->Effect()->Opacity()); + auto* div = GetDocument().getElementById("div"); + EXPECT_FALSE(div->GetLayoutObject()->NeedsPaintPropertyUpdate()); + + div->setAttribute(html_names::kStyleAttr, "opacity:0.8"); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + EXPECT_FALSE(div->GetLayoutObject()->NeedsPaintPropertyUpdate()); + + UpdateAllLifecyclePhasesExceptPaint(); + EXPECT_NEAR(0.8, div_properties->Effect()->Opacity(), 0.001); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index ce88af12..2e1ad9a1 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -78,6 +78,10 @@ ShowAllPropertyTrees(root_frame_view); #endif + if (root_frame_view.UpdateAllPendingTransforms() || + root_frame_view.UpdateAllPendingOpacityUpdates()) + needs_invalidate_chrome_client_ = true; + // If the page has anything changed, we need to inform the chrome client // so that the client will initiate repaint of the contents if needed (e.g. // when this page is embedded as a non-composited content of another page). @@ -85,7 +89,6 @@ if (auto* client = root_frame_view.GetChromeClient()) client->InvalidateContainer(); } - root_frame_view.UpdateAllPendingTransforms(); } void PrePaintTreeWalk::Walk(LocalFrameView& frame_view, @@ -449,9 +452,8 @@ // contained by the object participates in the current block fragmentation // context. If we're not participating in block fragmentation, the containing // fragment of an OOF fragment is always simply the parent. - const LayoutBox* box = DynamicTo<LayoutBox>(&object); if (!context.current_container.IsInFragmentationContext() || - (box && box->GetNGPaginationBreakability() == LayoutBox::kForbidBreaks)) { + (fragment && fragment->IsMonolithic())) { context.current_container.fragment = fragment; }
diff --git a/third_party/blink/renderer/core/script/classic_script.cc b/third_party/blink/renderer/core/script/classic_script.cc index 365ec96..aeb6df6 100644 --- a/third_party/blink/renderer/core/script/classic_script.cc +++ b/third_party/blink/renderer/core/script/classic_script.cc
@@ -77,7 +77,7 @@ const ScriptFetchOptions& fetch_options, ScriptSourceLocationType source_location_type, SanitizeScriptErrors sanitize_script_errors, - SingleCachedMetadataHandler* cache_handler, + CachedMetadataHandler* cache_handler, const TextPosition& start_position, ScriptStreamer::NotStreamingReason not_streaming_reason, InlineScriptStreamer* streamer) { @@ -156,7 +156,7 @@ const ScriptFetchOptions& fetch_options, ScriptSourceLocationType source_location_type, SanitizeScriptErrors sanitize_script_errors, - SingleCachedMetadataHandler* cache_handler, + CachedMetadataHandler* cache_handler, const TextPosition& start_position, ScriptStreamer* streamer, ScriptStreamer::NotStreamingReason not_streaming_reason,
diff --git a/third_party/blink/renderer/core/script/classic_script.h b/third_party/blink/renderer/core/script/classic_script.h index 62ba41c..8358921 100644 --- a/third_party/blink/renderer/core/script/classic_script.h +++ b/third_party/blink/renderer/core/script/classic_script.h
@@ -31,7 +31,7 @@ const ScriptFetchOptions&, ScriptSourceLocationType = ScriptSourceLocationType::kUnknown, SanitizeScriptErrors = SanitizeScriptErrors::kSanitize, - SingleCachedMetadataHandler* = nullptr, + CachedMetadataHandler* = nullptr, const TextPosition& start_position = TextPosition::MinimumPosition(), ScriptStreamer::NotStreamingReason = ScriptStreamer::NotStreamingReason::kInlineScript, @@ -62,7 +62,7 @@ const ScriptFetchOptions&, ScriptSourceLocationType, SanitizeScriptErrors, - SingleCachedMetadataHandler* = nullptr, + CachedMetadataHandler* = nullptr, const TextPosition& start_position = TextPosition::MinimumPosition(), ScriptStreamer* = nullptr, ScriptStreamer::NotStreamingReason = @@ -82,7 +82,7 @@ return sanitize_script_errors_; } - SingleCachedMetadataHandler* CacheHandler() const { return cache_handler_; } + CachedMetadataHandler* CacheHandler() const { return cache_handler_; } ScriptStreamer* Streamer() const { return streamer_; } ScriptStreamer::NotStreamingReason NotStreamingReason() const { @@ -120,7 +120,7 @@ const SanitizeScriptErrors sanitize_script_errors_; - const Member<SingleCachedMetadataHandler> cache_handler_; + const Member<CachedMetadataHandler> cache_handler_; const Member<ScriptStreamer> streamer_; const ScriptStreamer::NotStreamingReason not_streaming_reason_;
diff --git a/third_party/blink/renderer/core/script/module_script_test.cc b/third_party/blink/renderer/core/script/module_script_test.cc index fff9862..4d466f98 100644 --- a/third_party/blink/renderer/core/script/module_script_test.cc +++ b/third_party/blink/renderer/core/script/module_script_test.cc
@@ -57,7 +57,7 @@ }; ClassicScript* CreateClassicScript(const String& source_text, - SingleCachedMetadataHandler* cache_handler) { + CachedMetadataHandler* cache_handler) { return ClassicScript::Create(source_text, KURL(), KURL(), ScriptFetchOptions(), ScriptSourceLocationType::kInternal, @@ -86,7 +86,7 @@ static JSModuleScript* CreateJSModuleScript( Modulator* modulator, const String& source_text, - SingleCachedMetadataHandler* cache_handler) { + CachedMetadataHandler* cache_handler) { ModuleScriptCreationParams params( KURL("https://fox.url/script.js"), KURL("https://fox.url/"), ScriptSourceLocationType::kInline, ModuleType::kJavaScript, @@ -125,7 +125,7 @@ } static bool HandlerCachedMetadataWasDiscarded( - SingleCachedMetadataHandler* cache_handler) { + CachedMetadataHandler* cache_handler) { auto* handler = static_cast<ScriptCachedMetadataHandler*>(cache_handler); if (!handler) return false; @@ -157,7 +157,7 @@ auto sender = std::make_unique<MockCachedMetadataSender>(); MockCachedMetadataSender* sender_ptr = sender.get(); - SingleCachedMetadataHandler* cache_handler = + CachedMetadataHandler* cache_handler = MakeGarbageCollected<ScriptCachedMetadataHandler>(UTF8Encoding(), std::move(sender)); const uint32_t kTimeStampTag = V8CodeCache::TagForTimeStamp(cache_handler); @@ -277,7 +277,7 @@ auto sender = std::make_unique<MockCachedMetadataSender>(); MockCachedMetadataSender* sender_ptr = sender.get(); - SingleCachedMetadataHandler* cache_handler = + CachedMetadataHandler* cache_handler = MakeGarbageCollected<ScriptCachedMetadataHandler>(UTF8Encoding(), std::move(sender)); const uint32_t kTimeStampTag = V8CodeCache::TagForTimeStamp(cache_handler);
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc index 21c77a3..a525f22 100644 --- a/third_party/blink/renderer/core/svg/svg_element.cc +++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -657,6 +657,10 @@ if (params.name == html_names::kNonceAttr) { if (params.new_value != g_empty_atom) setNonce(params.new_value); + } else if (params.name.Matches(xml_names::kLangAttr)) { + PseudoStateChanged(CSSSelector::kPseudoLang); + } else if (params.name == svg_names::kLangAttr) { + PseudoStateChanged(CSSSelector::kPseudoLang); } const AtomicString& event_name = @@ -779,6 +783,10 @@ bool SVGElement::IsPresentationAttribute(const QualifiedName& name) const { if (const SVGAnimatedPropertyBase* property = PropertyFromAttribute(name)) return property->HasPresentationAttributeMapping(); + if (RuntimeEnabledFeatures::LangAttributeAwareSvgTextEnabled() && + (name.Matches(xml_names::kLangAttr) || name == svg_names::kLangAttr)) { + return true; + } return CssPropertyIdForSVGAttributeName(GetExecutionContext(), name) > CSSPropertyID::kInvalid; } @@ -789,8 +797,17 @@ MutableCSSPropertyValueSet* style) { CSSPropertyID property_id = CssPropertyIdForSVGAttributeName(GetExecutionContext(), name); - if (property_id > CSSPropertyID::kInvalid) + if (property_id > CSSPropertyID::kInvalid) { AddPropertyToPresentationAttributeStyle(style, property_id, value); + } else if (name.Matches(xml_names::kLangAttr)) { + if (RuntimeEnabledFeatures::LangAttributeAwareSvgTextEnabled()) + MapLanguageAttributeToLocale(value, style); + } else if (name == svg_names::kLangAttr) { + if (RuntimeEnabledFeatures::LangAttributeAwareSvgTextEnabled() && + !FastHasAttribute(xml_names::kLangAttr)) { + MapLanguageAttributeToLocale(value, style); + } + } } bool SVGElement::HaveLoadedRequiredResources() {
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index 25dc456..6ba31d2 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -332,9 +332,8 @@ // source text, settings object, response's url, the default classic script // fetch options, and muted errors. // TODO(crbug.com/1082086): Fix the base URL. - SingleCachedMetadataHandler* handler( - CreateWorkerScriptCachedMetadataHandler(complete_url, - std::move(cached_meta_data))); + CachedMetadataHandler* handler(CreateWorkerScriptCachedMetadataHandler( + complete_url, std::move(cached_meta_data))); ClassicScript* script = ClassicScript::Create( source_code, ClassicScript::StripFragmentIdentifier(complete_url), response_url /* base_url */, ScriptFetchOptions(), @@ -431,9 +430,8 @@ const v8_inspector::V8StackTraceId& stack_id) { DCHECK(!IsContextPaused()); - SingleCachedMetadataHandler* handler = - CreateWorkerScriptCachedMetadataHandler(script_url, - std::move(cached_meta_data)); + CachedMetadataHandler* handler = CreateWorkerScriptCachedMetadataHandler( + script_url, std::move(cached_meta_data)); // Cross-origin workers are disallowed, so use // SanitizeScriptErrors::kDoNotSanitize. Script* worker_script = ClassicScript::Create(
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index e63eb551..aad65f0 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -85,7 +85,7 @@ // use it because we don't create a CachedMetadtaHandler. Only service workers // override this method and provide a valid handler. We need to implement it // for Dedicated / Shared workers too so we can benefit from code caches. - virtual SingleCachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler( + virtual CachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler( const KURL& script_url, std::unique_ptr<Vector<uint8_t>> meta_data) { return nullptr;
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index 21c3339..19caac7 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -828,7 +828,7 @@ WorkerGlobalScope::importScripts(urls); } -SingleCachedMetadataHandler* +CachedMetadataHandler* ServiceWorkerGlobalScope::CreateWorkerScriptCachedMetadataHandler( const KURL& script_url, std::unique_ptr<Vector<uint8_t>> meta_data) {
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h index ab28f48..0df8cdd 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -346,7 +346,7 @@ private: void importScripts(const Vector<String>& urls) override; - SingleCachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler( + CachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler( const KURL& script_url, std::unique_ptr<Vector<uint8_t>> meta_data) override; void ExceptionThrown(ErrorEvent*) override;
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h b/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h index de7b986..07eca6d 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h +++ b/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h
@@ -17,8 +17,7 @@ class CachedMetadata; class ServiceWorkerGlobalScope; -class ServiceWorkerScriptCachedMetadataHandler - : public SingleCachedMetadataHandler { +class ServiceWorkerScriptCachedMetadataHandler : public CachedMetadataHandler { public: ServiceWorkerScriptCachedMetadataHandler( ServiceWorkerGlobalScope*,
diff --git a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc index 28a479bf..b23bab2 100644 --- a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc +++ b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc
@@ -42,18 +42,8 @@ } bool opacity_changed = opacity != other.opacity; bool opacity_change_is_simple = - opacity_changed && - // Opacity change is simple if - // - opacity doesn't change from or to 1, or - // - there was and is active opacity animation, or - // TODO(crbug.com/1285498): Optimize for will-change: opacity. - // The rule is because whether opacity is 1 affects whether the effect - // should create a render surface if there is no active opacity animation. - ((opacity != 1.f && other.opacity != 1.f) || - ((direct_compositing_reasons & - CompositingReason::kActiveOpacityAnimation) && - (other.direct_compositing_reasons & - CompositingReason::kActiveOpacityAnimation))); + IsOpacityChangeSimple(opacity, other.opacity, direct_compositing_reasons, + other.direct_compositing_reasons); if (opacity_changed && !opacity_change_is_simple) { DCHECK(!animation_state.is_running_opacity_animation_on_compositor); return PaintPropertyChangeType::kChangedOnlyValues; @@ -94,6 +84,19 @@ return PaintPropertyChangeType::kUnchanged; } +bool EffectPaintPropertyNode::State::IsOpacityChangeSimple( + float opacity, + float new_opacity, + CompositingReasons direct_compositing_reasons, + CompositingReasons new_direct_compositing_reasons) { + bool opacity_changed = opacity != new_opacity; + return opacity_changed && ((opacity != 1.f && new_opacity != 1.f) || + ((direct_compositing_reasons & + CompositingReason::kActiveOpacityAnimation) && + (new_direct_compositing_reasons & + CompositingReason::kActiveOpacityAnimation))); +} + const EffectPaintPropertyNode& EffectPaintPropertyNode::Root() { DEFINE_STATIC_REF(EffectPaintPropertyNode, root, base::AdoptRef(new EffectPaintPropertyNode( @@ -149,6 +152,40 @@ } } +PaintPropertyChangeType EffectPaintPropertyNode::State::ComputeOpacityChange( + float new_opacity, + const AnimationState& animation_state) const { + bool opacity_changed = opacity != new_opacity; + bool opacity_change_is_simple = State::IsOpacityChangeSimple( + opacity, new_opacity, direct_compositing_reasons, + direct_compositing_reasons); + if (opacity_changed && !opacity_change_is_simple) { + DCHECK(!animation_state.is_running_opacity_animation_on_compositor); + return PaintPropertyChangeType::kChangedOnlyValues; + } + + bool simple_values_changed = + opacity_change_is_simple && + !animation_state.is_running_opacity_animation_on_compositor; + if (simple_values_changed) { + return PaintPropertyChangeType::kChangedOnlySimpleValues; + } + if (opacity_changed) { + return PaintPropertyChangeType::kChangedOnlyCompositedValues; + } + return PaintPropertyChangeType::kUnchanged; +} + +PaintPropertyChangeType EffectPaintPropertyNode::DirectlyUpdateOpacity( + float opacity, + const AnimationState& animation_state) { + auto change = state_.ComputeOpacityChange(opacity, animation_state); + state_.opacity = opacity; + if (change != PaintPropertyChangeType::kUnchanged) + AddChanged(change); + return change; +} + gfx::RectF EffectPaintPropertyNode::MapRect(const gfx::RectF& rect) const { if (state_.filter.IsEmpty()) return rect;
diff --git a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h index e40a762..e98e719 100644 --- a/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h +++ b/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
@@ -132,6 +132,22 @@ PaintPropertyChangeType ComputeChange( const State& other, const AnimationState& animation_state) const; + + PaintPropertyChangeType ComputeOpacityChange( + float opacity, + const AnimationState& animation_state) const; + + // Opacity change is simple if + // - opacity doesn't change from or to 1, or + // - there was and is active opacity animation, or + // TODO(crbug.com/1285498): Optimize for will-change: opacity. + // The rule is because whether opacity is 1 affects whether the effect + // should create a render surface if there is no active opacity animation. + static bool IsOpacityChangeSimple( + float opacity, + float new_opacity, + CompositingReasons direct_compositing_reasons, + CompositingReasons new_direct_compositing_reasons); }; // This node is really a sentinel, and does not represent a real effect. @@ -157,6 +173,10 @@ return std::max(parent_changed, state_changed); } + PaintPropertyChangeType DirectlyUpdateOpacity( + float opacity, + const AnimationState& animation_state); + const EffectPaintPropertyNode& Unalias() const = delete; bool IsParentAlias() const = delete;
diff --git a/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h b/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h index 78027cb..f925846 100644 --- a/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h +++ b/third_party/blink/renderer/platform/loader/fetch/script_cached_metadata_handler.h
@@ -32,7 +32,7 @@ // the handler is rejected if e.g. the disk cache entry has been updated and the // handler refers to an older response. class PLATFORM_EXPORT ScriptCachedMetadataHandler - : public SingleCachedMetadataHandler { + : public CachedMetadataHandler { public: ScriptCachedMetadataHandler(const WTF::TextEncoding&, std::unique_ptr<CachedMetadataSender>);
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h index 96de614..b0590a0 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/cached_metadata_handler.h
@@ -82,11 +82,13 @@ // Enum for marking serialized cached metadatas so that the deserializers // do not conflict. enum CachedMetadataType : uint32_t { - kSingleEntry, // the metadata is a single CachedMetadata entry - kSourceKeyedMap, // the metadata is multiple CachedMetadata entries keyed - // by a source string. - kSingleEntryWithHash // the metadata is a content hash followed by a single - // CachedMetadata entry + kSingleEntry = 0, // the metadata is a single CachedMetadata entry + // This was used for inline code cache, but the feature was removed around + // 10/2022. + // kSourceKeyedMap = 1, // the metadata is multiple CachedMetadata + // entries keyed by a source string. + kSingleEntryWithHash = 2 // the metadata is a content hash followed by a + // single CachedMetadata entry }; virtual ~CachedMetadataHandler() = default; @@ -107,13 +109,6 @@ virtual size_t GetCodeCacheSize() const = 0; - protected: - CachedMetadataHandler() = default; -}; - -// A CachedMetadataHandler which stores one piece of metadata. -class SingleCachedMetadataHandler : public CachedMetadataHandler { - public: // Caches the given metadata in association with this resource and suggests // that the platform persist it. The dataTypeID is a pseudo-randomly chosen // identifier that is used to distinguish data generated by the caller. @@ -169,7 +164,7 @@ virtual void WillProduceCodeCache() {} protected: - SingleCachedMetadataHandler() = default; + CachedMetadataHandler() = default; bool disable_send_to_platform_for_testing_ = false; };
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc index f9efc9c9..a9b9a04e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.cc
@@ -175,8 +175,7 @@ NotifyCompletionIfAppropriate(); } -SingleCachedMetadataHandler* -WorkerMainScriptLoader::CreateCachedMetadataHandler() { +CachedMetadataHandler* WorkerMainScriptLoader::CreateCachedMetadataHandler() { // Currently we support the metadata caching only for HTTP family. if (!initial_request_url_.ProtocolIsInHTTPFamily() || !resource_response_.CurrentRequestUrl().ProtocolIsInHTTPFamily()) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h index f0210b5..b95560c 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h
@@ -29,10 +29,10 @@ namespace blink { +class CachedMetadataHandler; class FetchContext; class FetchParameters; class ResourceLoadInfoNotifierWrapper; -class SingleCachedMetadataHandler; class WorkerMainScriptLoaderClient; struct ResourceLoaderOptions; @@ -79,7 +79,7 @@ // Gets the raw data of the main script. SharedBuffer* Data() const { return data_.get(); } WTF::TextEncoding GetScriptEncoding() { return script_encoding_; } - SingleCachedMetadataHandler* CreateCachedMetadataHandler(); + CachedMetadataHandler* CreateCachedMetadataHandler(); virtual void Trace(Visitor*) const;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 5ee8e1f..2f202508 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1451,6 +1451,11 @@ settable_from_internals: true, }, { + name: "LangAttributeAwareSvgText", + base_feature: "LangAttributeAwareSvgText", + status: "stable", + }, + { // LayoutNG has been enabled in M76, but we still keep this flag for // testing. See web_tests/FlagExpectations/disable-layout-ng for more // details about running web tests with LayoutNG disabled. This flag also
diff --git a/third_party/blink/tools/blinkpy/common/checkout/git.py b/third_party/blink/tools/blinkpy/common/checkout/git.py index 6343c21..54fbc8e 100644 --- a/third_party/blink/tools/blinkpy/common/checkout/git.py +++ b/third_party/blink/tools/blinkpy/common/checkout/git.py
@@ -29,6 +29,7 @@ import logging import re +from typing import List from blinkpy.common.memoized import memoized from blinkpy.common.system.executive import Executive, ScriptError @@ -175,11 +176,43 @@ path = line[3:] yield line[0].strip(), line[1].strip(), path - def add_list(self, paths, return_exit_code=False): - return self.run(['add'] + paths, return_exit_code=return_exit_code) + def add_list(self, paths: List[str], return_exit_code: bool = False): + return self._run_chunked(['add'], + paths, + return_exit_code=return_exit_code) - def delete_list(self, paths): - return self.run(['rm', '-f'] + paths) + def delete_list(self, paths: List[str], ignore_unmatch: bool = False): + command = ['rm', '-f'] + if ignore_unmatch: + command.append('--ignore-unmatch') + return self._run_chunked(command, paths) + + def _run_chunked(self, + command: List[str], + paths: List[str], + chunk_size: int = 128, + **run_kwargs): + """Safely run `git` operations on an arbitrary number of paths. + + This helper transparently avoids command line length limitations on + Windows by splitting paths across multiple `git` invocations. This only + works for commands that can operate on a variable number of paths. + + Arguments: + command: The non-path arguments after `git` but before the paths. + paths: The paths to operate on. + chunk_size: The maximum number of paths to operate on at a time. The + default was picked heuristically. + + Returns: + The first truthy value returned by a `run` command. This is usually + stdout or a nonzero exit code. + """ + rv = 0 + for chunk_start in range(0, len(paths), chunk_size): + chunk = paths[chunk_start:chunk_start + chunk_size] + rv = rv or self.run(command + chunk, **run_kwargs) + return rv def move(self, origin, destination): return self.run(['mv', '-f', origin, destination])
diff --git a/third_party/blink/tools/blinkpy/common/checkout/git_mock.py b/third_party/blink/tools/blinkpy/common/checkout/git_mock.py index c68e9711..e11f23d 100644 --- a/third_party/blink/tools/blinkpy/common/checkout/git_mock.py +++ b/third_party/blink/tools/blinkpy/common/checkout/git_mock.py
@@ -87,7 +87,7 @@ def delete(self, path): return self.delete_list([path]) - def delete_list(self, paths): + def delete_list(self, paths, ignore_unmatch: bool = False): if not self._filesystem: return for path in paths:
diff --git a/third_party/blink/tools/blinkpy/common/system/filesystem.py b/third_party/blink/tools/blinkpy/common/system/filesystem.py index b34decb..fe87875 100644 --- a/third_party/blink/tools/blinkpy/common/system/filesystem.py +++ b/third_party/blink/tools/blinkpy/common/system/filesystem.py
@@ -160,7 +160,7 @@ return os.getcwd() def glob(self, path): - return glob.glob(path) + return glob.iglob(path, recursive=True) def isabs(self, path): return os.path.isabs(path)
diff --git a/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py b/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py index e0ca69f1..6c65b223 100644 --- a/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py +++ b/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
@@ -187,17 +187,18 @@ def glob(self, glob_string): # FIXME: This handles '*', but not '?', '[', or ']'. glob_string = re.escape(glob_string) - glob_string = glob_string.replace('\\*', '[^\\/]*') + '$' + glob_string = glob_string.replace('\\*\\*', '.*') + glob_string = glob_string.replace('\\*', '[^\\/]*') glob_string = glob_string.replace('\\/', '/') - path_filter = lambda path: re.match(glob_string, path) + path_filter = lambda path: re.fullmatch(glob_string, path) # We could use fnmatch.fnmatch, but that might not do the right thing on Windows. existing_files = [ path for path, contents in self.files.items() if contents is not None ] - return list(filter(path_filter, existing_files)) + list( - filter(path_filter, self.dirs)) + yield from filter(path_filter, existing_files) + yield from filter(path_filter, self.dirs) def isabs(self, path): return path.startswith(self.sep)
diff --git a/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py b/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py index 4587505..e10d5cf5 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py +++ b/third_party/blink/tools/blinkpy/tool/commands/update_metadata.py
@@ -13,6 +13,7 @@ import optparse import re from typing import ( + Collection, Iterable, Iterator, List, @@ -35,12 +36,23 @@ from blinkpy.web_tests.port.base import Port path_finder.bootstrap_wpt_imports() +from manifest import manifest from wptrunner import metadata, testloader, wpttest from wptrunner.wptmanifest.backends import conditional _log = logging.getLogger(__name__) +class TestPaths: + tests_path: str + metadata_path: str + manifest_path: str + url_base: Optional[str] + + +ManifestMap = Mapping[manifest.Manifest, TestPaths] + + class UpdateMetadata(Command): name = 'update-metadata' show_in_main_help = False # TODO(crbug.com/1299650): To be switched on. @@ -130,8 +142,9 @@ self._tool.builders, self.git_cl, can_trigger_jobs=(options.trigger_jobs and not options.dry_run)) - updater = MetadataUpdater.from_path_finder( - self._path_finder, + manifests = load_and_update_manifests(self._path_finder) + updater = MetadataUpdater.from_manifests( + manifests, self._explicit_include_patterns(options, args), overwrite_conditions=options.overwrite_conditions, disable_intermittent=options.disable_intermittent, @@ -150,6 +163,8 @@ stack.enter_context(self._io_pool) updater.collect_results( self.gather_reports(build_statuses, options.reports or [])) + self.remove_orphaned_metadata(manifests, + dry_run=options.dry_run) self.update_and_stage(updater, test_files, dry_run=options.dry_run) @@ -162,11 +177,42 @@ _log.error('%s', error) return 1 + def remove_orphaned_metadata(self, + manifests: ManifestMap, + dry_run: bool = False): + infrastructure_tests = self._path_finder.path_from_wpt_tests( + 'infrastructure') + for manifest, paths in manifests.items(): + allowlist = { + metadata.expected_path(paths['metadata_path'], test_path) + for _, test_path, _ in manifest + } + orphans = [] + glob = self._fs.join(paths['metadata_path'], '**', '*.ini') + for candidate in self._fs.glob(glob): + # Directory metadata are not supposed to correspond to any + # particular test, so do not remove them. Skip infrastructure + # test metadata as well, since they are managed by the upstream + # repository. + if (self._fs.basename(candidate) == '__dir__.ini' + or candidate.startswith(infrastructure_tests)): + continue + if candidate not in allowlist: + orphans.append(candidate) + + if orphans: + message = ( + 'Deleting %s:' % + grammar.pluralize('orphaned metadata file', len(orphans))) + self._log_metadata_paths(message, orphans) + if not dry_run: + # Ignore untracked files. + self.git.delete_list(orphans, ignore_unmatch=True) + def update_and_stage(self, updater: 'MetadataUpdater', test_files: List[metadata.TestFileData], - dry_run: bool = False, - chunk_size: int = 128): + dry_run: bool = False): test_files_to_stage = [] update_results = self._io_pool.map(updater.update, test_files) for i, (test_file, @@ -189,10 +235,7 @@ path for path in self._metadata_paths(test_files_to_stage) if path in unstaged_changes ] - # Stage the files in chunks to avoid a Windows command line length - # limit. The chunk size was picked heuristically. - for chunk_start in range(0, len(paths), chunk_size): - self.git.add_list(paths[chunk_start:chunk_start + chunk_size]) + self.git.add_list(paths) _log.info('Staged %s.', grammar.pluralize('metadata file', len(paths))) @@ -220,14 +263,23 @@ metadata_paths = set(self._metadata_paths(test_files)) uncommitted_metadata = uncommitted_changes & metadata_paths if uncommitted_metadata: - _log.error('Aborting: there are uncommitted metadata files:') - web_tests_root = self._path_finder.web_tests_dir() - for path in sorted(uncommitted_metadata): - rel_path = pathlib.Path(path).relative_to(web_tests_root) - _log.error(' %s', rel_path.as_posix()) + self._log_metadata_paths( + 'Aborting: there are uncommitted metadata files:', + uncommitted_metadata, + log=_log.error) raise UpdateAbortError('Please commit or reset these files ' 'to continue.') + def _log_metadata_paths(self, + message: str, + paths: Collection[str], + log=_log.warning): + log(message) + web_tests_root = self._path_finder.web_tests_dir() + for path in sorted(paths): + rel_path = pathlib.Path(path).relative_to(web_tests_root) + log(' %s', rel_path.as_posix()) + def _metadata_paths( self, test_files: List[metadata.TestFileData], @@ -376,40 +428,20 @@ self._dry_run = dry_run @classmethod - def from_path_finder( - cls, - finder: path_finder.PathFinder, - include: Optional[List[str]] = None, - **options, - ) -> 'MetadataUpdater': - """Construct a metadata updater from a path finder. + def from_manifests(cls, + manifests: ManifestMap, + include: Optional[List[str]] = None, + **options) -> 'MetadataUpdater': + """Construct a metadata updater from WPT manifests. Arguments: - finder: Path finder. Each WPT root is used as both the test and - metadata root. The manifest is read from `MANIFEST.json` at the - WPT root. include: A list of test patterns that are resolved into test IDs to update. The resolution works the same way as `wpt run`: - * Directories are expanded to include all children (e.g., - `a/` includes `a/b.html?c`). + * Directories are expanded to include all children (e.g., `a/` + includes `a/b.html?c`). * Test files are expanded to include all variants (e.g., `a.html` includes `a.html?b` and `a.html?c`). """ - # See: https://github.com/web-platform-tests/wpt/blob/merge_pr_35574/tools/wptrunner/wptrunner/testloader.py#L171-L199 - test_paths = {} - for rel_path_to_wpt_root, url_base in Port.WPT_DIRS.items(): - wpt_root = finder.path_from_web_tests(rel_path_to_wpt_root) - test_paths[url_base] = { - 'tests_path': - wpt_root, - 'metadata_path': - wpt_root, - 'manifest_path': - finder.path_from_web_tests(rel_path_to_wpt_root, - 'MANIFEST.json'), - } - manifests = testloader.ManifestLoader( - test_paths, force_manifest_update=True).load() # TODO(crbug.com/1299650): Validate the include list instead of silently # ignoring the bad test pattern. test_filter = testloader.TestFilter(manifests, include=include) @@ -419,10 +451,15 @@ # `testloader.TestLoader` API. Monkey-patching here is the cleanest # way to filter tests to be updated without loading more tests than # are necessary. - manifest.itertypes = _compose(test_filter, manifest.itertypes) - test_files.update( - metadata.create_test_tree(paths['metadata_path'], manifest)) - return MetadataUpdater(test_files, **options) + itertypes = manifest.itertypes + try: + manifest.itertypes = _compose(test_filter, manifest.itertypes) + test_files.update( + metadata.create_test_tree(paths['metadata_path'], + manifest)) + finally: + manifest.itertypes = itertypes + return cls(test_files, **options) def collect_results(self, reports: Iterable[io.TextIOBase]): """Parse and record test results.""" @@ -486,6 +523,31 @@ return lambda *args, **kwargs: f(g(*args, **kwargs)) +def load_and_update_manifests(finder: path_finder.PathFinder) -> ManifestMap: + """Load and update WPT manifests on disk by scanning the test root. + + Arguments: + finder: Path finder for constructing test paths (test root, metadata + root, and manifest path). + + See Also: + https://github.com/web-platform-tests/wpt/blob/merge_pr_35574/tools/wptrunner/wptrunner/testloader.py#L171-L199 + """ + test_paths = {} + for rel_path_to_wpt_root, url_base in Port.WPT_DIRS.items(): + wpt_root = finder.path_from_web_tests(rel_path_to_wpt_root) + test_paths[url_base] = { + 'tests_path': + wpt_root, + 'metadata_path': + wpt_root, + 'manifest_path': + finder.path_from_web_tests(rel_path_to_wpt_root, 'MANIFEST.json'), + } + return testloader.ManifestLoader(test_paths, + force_manifest_update=True).load() + + def _default_expected_by_type(): default_expected_by_type = {} for test_type, test_cls in wpttest.manifest_test_cls.items():
diff --git a/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py index 1ec57bd..c0bd2e5 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py +++ b/third_party/blink/tools/blinkpy/tool/commands/update_metadata_unittest.py
@@ -15,7 +15,11 @@ from blinkpy.common.net.rpc import Build, RPCError from blinkpy.common.system.log_testing import LoggingTestCase from blinkpy.tool.mock_tool import MockBlinkTool -from blinkpy.tool.commands.update_metadata import UpdateMetadata, MetadataUpdater +from blinkpy.tool.commands.update_metadata import ( + UpdateMetadata, + MetadataUpdater, + load_and_update_manifests, +) from blinkpy.web_tests.builder_list import BuilderList path_finder.bootstrap_wpt_imports() @@ -280,6 +284,10 @@ self.assertEqual(self.command.git_cl.calls, []) def test_execute_dry_run(self): + self.tool.filesystem.write_text_file( + self.finder.path_from_web_tests('external', 'wpt', 'dir', 'is', + 'orphaned.html.ini'), + '[orphaned.html]\n') files_before = dict(self.tool.filesystem.files) with self._patch_builtins(): exit_code = self.command.main(['--dry-run']) @@ -287,6 +295,8 @@ self.assertLog([ 'INFO: All builds finished.\n', 'INFO: Processing wptrunner report (1/1)\n', + 'WARNING: Deleting 1 orphaned metadata file:\n', + 'WARNING: external/wpt/dir/is/orphaned.html.ini\n', "INFO: Updated 'crash.html' (1/5, modified)\n", "INFO: Updated 'dir/multiglob.https.any.js' (2/5)\n", "INFO: Updated 'fail.html' (3/5)\n", @@ -381,6 +391,41 @@ 'WARNING: No reports to process.\n', ]) + def test_remove_orphaned_metadata(self): + """Verify that the tool removes orphaned metadata files. + + A metadata file is orphaned when its corresponding test no longer exists + in the manifest. + """ + self.tool.filesystem.write_text_file( + self.finder.path_from_web_tests('external', 'wpt', 'dir', 'is', + 'orphaned.html.ini'), + '[orphaned.html]\n') + self.tool.filesystem.write_text_file( + self.finder.path_from_web_tests('external', 'wpt', + 'infrastructure', 'metadata', + 'testdriver.html.ini'), + '[testdriver.html]\n') + self.tool.filesystem.write_text_file( + self.finder.path_from_web_tests('external', 'wpt', 'dir', 'is', + '__dir__.ini'), 'expected: FAIL\n') + with self._patch_builtins(): + manifests = load_and_update_manifests(self.finder) + self.command.remove_orphaned_metadata(manifests) + self.assertFalse( + self.tool.filesystem.exists( + self.finder.path_from_web_tests('external', 'wpt', 'dir', 'is', + 'orphaned.html.ini'))) + self.assertTrue( + self.tool.filesystem.exists( + self.finder.path_from_web_tests('external', 'wpt', 'dir', 'is', + '__dir__.ini'))) + self.assertTrue( + self.tool.filesystem.exists( + self.finder.path_from_web_tests('external', 'wpt', + 'infrastructure', 'metadata', + 'testdriver.html.ini'))) + class UpdateMetadataASTSerializationTest(BaseUpdateMetadataTest): """Verify the metadata ASTs are manipulated and written correctly. @@ -399,7 +444,8 @@ 'known_intermittent': [], } with self._patch_builtins(): - updater = MetadataUpdater.from_path_finder(self.finder, **options) + manifests = load_and_update_manifests(self.finder) + updater = MetadataUpdater.from_manifests(manifests, **options) for report in reports: report['run_info'] = { 'os': 'mac',
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 05b09c6..9fb727e 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -800,6 +800,11 @@ crbug.com/699040 external/wpt/svg/text/reftests/text-xml-space-001.svg [ Failure ] +# Content Shell on macOS doesn't work well for Han glyph selection for +# languages. Chrome works well. +crbug.com/1370460 [ Mac ] external/wpt/svg/text/reftests/lang-attribute.svg [ Failure ] +crbug.com/1370460 [ Mac ] external/wpt/svg/text/reftests/xml-lang-attribute.svg [ Failure ] + # WPT backgrounds and borders tests. Note that there are many more in NeverFixTests # that should be investigated (see crbug.com/780700) crbug.com/1242416 [ Linux ] external/wpt/css/CSS2/backgrounds/background-position-201.xht [ Failure Pass ] @@ -3935,9 +3940,6 @@ crbug.com/809935 external/wpt/css/css-fonts/variations/font-style-interpolation.html [ Skip Timeout ] crbug.com/626703 external/wpt/css/css-ui/text-overflow-011.html [ Crash Failure Pass ] -# <input disabled> does not fire click events after dispatchEvent -crbug.com/1115661 external/wpt/dom/events/Event-dispatch-click.html [ Timeout ] - crbug.com/1088280 [ Mac ] external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html [ Failure Timeout ] crbug.com/1088280 [ Win ] external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html [ Failure Timeout ] @@ -7186,3 +7188,6 @@ # Sheriff 2022-09-29 crbug.com/1368855 external/wpt/longtask-timing/containerNames.html [ Failure Pass ] crbug.com/1369642 [ Mac ] external/wpt/encoding/unsupported-labels.window.html [ Failure Timeout ] + +# Sheriff 2022-10-03 +crbug.com/1362405 css3/filters/effect-reference-hidpi.html [ Skip ]
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 c892757..9a09933 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
@@ -129155,6 +129155,35 @@ ] ], "gradient": { + "css-color-4-colors-default-to-oklab-gradient.html": [ + "c34521cbf2a7109bac0ddf34d7a8de439ab36fe8", + [ + null, + [ + [ + "/css/css-images/gradient/oklab-gradient-expected.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 1, + 2 + ], + [ + 0, + 24000 + ] + ] + ] + ] + } + ] + ], "gradient-eval-001.html": [ "98a9d9234588e5de74a66c09d638d1448814e3fd", [ @@ -129415,6 +129444,151 @@ ] } ] + ], + "legacy-color-gradient.html": [ + "8fe3ca83d8718fb622f3870c5fa10ee04b0c0862", + [ + null, + [ + [ + "/css/css-images/gradient/srgb-gradient-expected.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 1, + 2 + ], + [ + 0, + 24000 + ] + ] + ] + ] + } + ] + ], + "oklab-gradient.html": [ + "b520cbef126876113ac61cb29d912ba304004af1", + [ + null, + [ + [ + "/css/css-images/gradient/oklab-gradient-expected.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 1, + 2 + ], + [ + 0, + 24000 + ] + ] + ] + ] + } + ] + ], + "srgb-gradient.html": [ + "e27c637e22ebb12778d6036aac814e0f9c197dbd", + [ + null, + [ + [ + "/css/css-images/gradient/srgb-gradient-expected.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 1, + 2 + ], + [ + 0, + 24000 + ] + ] + ] + ] + } + ] + ], + "srgb-linear-gradient.html": [ + "fa2dd1a7a325668213643b4a09268017ec160060", + [ + null, + [ + [ + "/css/css-images/gradient/srgb-linear-gradient-expected.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 1, + 2 + ], + [ + 0, + 24000 + ] + ] + ] + ] + } + ] + ], + "xyz-gradient.html": [ + "fc7c9c470b97210e6074cd2d660a9c82cd661d82", + [ + null, + [ + [ + "/css/css-images/gradient/xyz-gradient-expected.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 1, + 2 + ], + [ + 0, + 24000 + ] + ] + ] + ] + } + ] ] }, "gradient-border-box.html": [ @@ -283093,7 +283267,25 @@ "gradient-eval-009-ref.html": [ "b4a36ff6d0e43b38d670472dd56a0eb44b31ea2c", [] - ] + ], + "resources": { + "oklab-gradient.png": [ + "9e52fd9b84ba9f16cdfba6fa1df67f17521c2ff5", + [] + ], + "srgb-gradient.png": [ + "1fc6660919a637c684be84236af5f1cf4bc07eaf", + [] + ], + "srgb-linear-gradient.png": [ + "e379a5df3e1b290befdde5d655ff9741839277fa", + [] + ], + "xyz-gradient.png": [ + "eb3ab7893663b01cac643f82da54405ce1bd541a", + [] + ] + } }, "gradient-border-box-ref.html": [ "5b219cea6c20ba46ebba7d7bb890af3923d90a54", @@ -333861,10 +334053,6 @@ "historical-expected.txt": [ "404b6a774fdba6fddf2b11f22b9fcfea15d4e18f", [] - ], - "idlharness.window-expected.txt": [ - "6cf7ce601efc1e30fcabe6b03e047c8394f4fa71", - [] ] }, "mediacapture-image": { @@ -338940,7 +339128,7 @@ [] ], "resource-loaders.js": [ - "92e57d0bde870864ac01730cca4d708ccea010cc", + "8bc1a77134cedc8db55cd4c2390ebf1da53d2db4", [] ], "resource-timing-content-length.py": [ @@ -392012,6 +392200,27 @@ {} ] ], + "flex-align-baseline-overflow-001.html": [ + "382112ed210b8563c73a4449847754ced0221cbb", + [ + null, + {} + ] + ], + "flex-align-baseline-overflow-002.html": [ + "d136159246b8801eb4e991396ad2806962add399", + [ + null, + {} + ] + ], + "flex-align-baseline-overflow-003.html": [ + "37d9ea26fde3fc1ac4418ed7e3ac54d52e3f629e", + [ + null, + {} + ] + ], "flex-align-baseline-table-001.html": [ "b90f840b10acaaac3af7adf4d91a1d3c30762019", [ @@ -395102,6 +395311,27 @@ {} ] ], + "grid-align-baseline-overflow-001.html": [ + "66f9eb1bcf059676465689f39cceffe43565ca84", + [ + null, + {} + ] + ], + "grid-align-baseline-overflow-002.html": [ + "b74dbf750be9bf2fbb9a1d964cd96b7c6ccc454b", + [ + null, + {} + ] + ], + "grid-align-baseline-overflow-003.html": [ + "569dd1ae37381f17ebe90381ad1826d82f196418", + [ + null, + {} + ] + ], "grid-align-baseline-table-001.html": [ "0cafef6ecca8fa1ce98c3ad69b9c4feb7c0569c7", [ @@ -397877,7 +398107,7 @@ ] ], "grid-shorthand.html": [ - "91995608dd9eda5cd8d99abe3454cd67e52e405b", + "9293d27631f4b3ea89c7015a73de322617890747", [ null, {} @@ -460393,6 +460623,13 @@ } ] ], + "defaultstatus.html": [ + "f683f130cd4a30c76514f3a3ea54d4feef5f90cb", + [ + null, + {} + ] + ], "document-attribute.window.js": [ "f13acdb8a3261410c0f3100fea49f1ba110ea9ab", [ @@ -512389,7 +512626,7 @@ ] ], "idlharness.window.js": [ - "c58e63ff12acefc73fc3cfa2f35836778696c827", + "970f3cd5c623261f0d5acc4e5fb14dfa2f732883", [ "mediacapture-fromelement/idlharness.window.html", { @@ -610173,6 +610410,36 @@ } }, "css-images": { + "gradient": { + "oklab-gradient-expected.html": [ + "ca2232e38096157847a2430e721f9eb73cf68185", + [ + null, + {} + ] + ], + "srgb-gradient-expected.html": [ + "49a402d68e668d924fbec150b367ba2188a67592", + [ + null, + {} + ] + ], + "srgb-linear-gradient-expected.html": [ + "b3984d7432d50e7235048ddb5396b5d1cae8c9af", + [ + null, + {} + ] + ], + "xyz-gradient-expected.html": [ + "0411ccff8c1be3e8d475b23900856c6d2a746504", + [ + null, + {} + ] + ] + }, "image-fit-001.xht": [ "169d55c0f2e9bf93fd9851f7fb43eb4493d14b39", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/overflow-clip-013.html b/third_party/blink/web_tests/external/wpt/css/css-break/overflow-clip-013.html new file mode 100644 index 0000000..31137b5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/overflow-clip-013.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1342107"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:1; column-fill:auto; width:100px; height:100px; background:green;"> + <div style="overflow:clip; height:100px;"> + <div style="height:200px;"> + <div style="height:100px;"></div> + <div style="position:relative;"> + <div style="position:absolute; width:100px; height:100px; background:red;"></div> + </div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand.html index 91995608dd..9293d276 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-shorthand.html
@@ -32,6 +32,19 @@ 'grid-auto-flow': 'row' }); +// This could theoretically be serialized as "auto-flow / 10px", +// but spec mandates the 'grid-template-*' form when the +// 'grid-auto-*' properties are all initial. +test_shorthand_value('grid', 'none / 10px', { + 'grid-template-rows': 'none', + 'grid-template-columns': '10px', + 'grid-template-areas': 'none', + + 'grid-auto-rows': 'auto', + 'grid-auto-columns': 'auto', + 'grid-auto-flow': 'row' +}); + test_shorthand_value('grid', 'fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))', { 'grid-template-rows': 'fit-content(calc(-0.5em + 10px))', 'grid-template-columns': 'fit-content(calc(0.5em + 10px))',
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/html5-tree/math-global-event-handlers.tentative.html b/third_party/blink/web_tests/external/wpt/mathml/relations/html5-tree/math-global-event-handlers.tentative.html index b7d569f..b924eefa 100644 --- a/third_party/blink/web_tests/external/wpt/mathml/relations/html5-tree/math-global-event-handlers.tentative.html +++ b/third_party/blink/web_tests/external/wpt/mathml/relations/html5-tree/math-global-event-handlers.tentative.html
@@ -4,6 +4,7 @@ <link rel="help" href="https://w3c.github.io/mathml-core/#dom-and-javascript"/> <link rel="help" href="https://html.spec.whatwg.org/multipage/#event-handler-idl-attributes"/> <link rel="help" href="https://html.spec.whatwg.org/multipage/#event-handler-content-attributes"/> +<meta name="timeout" content="long"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/resources/WebIDLParser.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/allowpaymentrequest/active-document-cross-origin.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/payment-request/allowpaymentrequest/active-document-cross-origin.https.sub.html.ini deleted file mode 100644 index 581f8bb..0000000 --- a/third_party/blink/web_tests/external/wpt/payment-request/allowpaymentrequest/active-document-cross-origin.https.sub.html.ini +++ /dev/null
@@ -1,4 +0,0 @@ -[active-document-cross-origin.https.sub.html] - [PaymentRequest <iframe allowpaymentrequest> in non-active document (cross-origin)] - expected: FAIL -
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/allowpaymentrequest/active-document-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/payment-request/allowpaymentrequest/active-document-same-origin.https.html.ini deleted file mode 100644 index 9420ee58..0000000 --- a/third_party/blink/web_tests/external/wpt/payment-request/allowpaymentrequest/active-document-same-origin.https.html.ini +++ /dev/null
@@ -1,4 +0,0 @@ -[active-document-same-origin.https.html] - [PaymentRequest <iframe allowpaymentrequest> in non-active document (same-origin)] - expected: FAIL -
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/onmerchantvalidation-attribute.https.html.ini b/third_party/blink/web_tests/external/wpt/payment-request/onmerchantvalidation-attribute.https.html.ini deleted file mode 100644 index c2d77067..0000000 --- a/third_party/blink/web_tests/external/wpt/payment-request/onmerchantvalidation-attribute.https.html.ini +++ /dev/null
@@ -1,13 +0,0 @@ -[onmerchantvalidation-attribute.https.html] - [onmerchantvalidation attribute and listeners both work] - expected: FAIL - - [Must have a onmerchantvalidation IDL attribute] - expected: FAIL - - [onmerchantvalidation attribute is a generic handler for "merchantvalidation"] - expected: FAIL - - [onmerchantvalidation attribute is a handler for MerchantValidationEvent] - expected: FAIL -
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/payment-request-canmakepayment-method-protection.https.html.ini b/third_party/blink/web_tests/external/wpt/payment-request/payment-request-canmakepayment-method-protection.https.html.ini deleted file mode 100644 index 86108c80..0000000 --- a/third_party/blink/web_tests/external/wpt/payment-request/payment-request-canmakepayment-method-protection.https.html.ini +++ /dev/null
@@ -1,4 +0,0 @@ -[payment-request-canmakepayment-method-protection.https.html] - [Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.] - expected: FAIL -
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-dynamic-ref.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-dynamic-ref.svg new file mode 100644 index 0000000..191adc0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-dynamic-ref.svg
@@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"> + <text> + <tspan x="10" y="100" font-size="90" fill="lime">Quick</tspan> + <tspan x="10" y="200" font-size="90">Brown</tspan> + <tspan x="10" y="300" font-size="90">Fox</tspan> + </text> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-dynamic.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-dynamic.svg new file mode 100644 index 0000000..d57b4dec --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-dynamic.svg
@@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" + class="reftest-wait"> + <metadata> + <title>Update of lang attribute should recalculate style</title> + <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#LangSpaceAttrs"/> + <h:link rel="match" href="lang-attribute-dynamic-ref.svg"/> + </metadata> + <style> +tspan:lang(ja) { fill: lime; } + </style> + <text> + <tspan x="10" y="100" font-size="90">Quick</tspan> + <tspan x="10" y="200" font-size="90">Brown</tspan> + <tspan x="10" y="300" font-size="90">Fox</tspan> + </text> + <script> +requestAnimationFrame(() => { + requestAnimationFrame(() => { + document.querySelectorAll('tspan')[0].setAttribute('lang', 'ja'); + document.documentElement.classList.remove('reftest-wait'); + }); +}); + </script> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-ref.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-ref.svg new file mode 100644 index 0000000..957cc24 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute-ref.svg
@@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"> + <text> + <tspan x="10" y="100" font-size="90">今骨直</tspan> + <tspan x="10" y="200" font-size="90">今骨直</tspan> + <tspan x="10" y="300" font-size="90">今骨直</tspan> + </text> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute.svg new file mode 100644 index 0000000..c619f825 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/lang-attribute.svg
@@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"> + <metadata> + <title>lang attribute should affect text rendering</title> + <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#LangSpaceAttrs"/> + <h:link rel="mismatch" href="lang-attribute-ref.svg"/> + </metadata> + <text> + <tspan x="10" y="100" font-size="90" lang="ja">今骨直</tspan> + <tspan x="10" y="200" font-size="90" lang="zh-CN">今骨直</tspan> + <tspan x="10" y="300" font-size="90" lang="zh-TW">今骨直</tspan> + </text> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/xml-lang-attribute-dynamic.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/xml-lang-attribute-dynamic.svg new file mode 100644 index 0000000..c604eb8c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/xml-lang-attribute-dynamic.svg
@@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" + class="reftest-wait"> + <metadata> + <title>Update of lang attribute should recalculate style</title> + <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#LangSpaceAttrs"/> + <h:link rel="match" href="lang-attribute-dynamic-ref.svg"/> + </metadata> + <style> +tspan:lang(ja) { fill: lime; } + </style> + <text> + <tspan x="10" y="100" font-size="90">Quick</tspan> + <tspan x="10" y="200" font-size="90">Brown</tspan> + <tspan x="10" y="300" font-size="90">Fox</tspan> + </text> + <script> +requestAnimationFrame(() => { + requestAnimationFrame(() => { + document.querySelectorAll('tspan')[0].setAttributeNS( + 'http://www.w3.org/XML/1998/namespace', 'xml:lang', 'ja'); + document.documentElement.classList.remove('reftest-wait'); + }); +}); + </script> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/reftests/xml-lang-attribute.svg b/third_party/blink/web_tests/external/wpt/svg/text/reftests/xml-lang-attribute.svg new file mode 100644 index 0000000..2e03716a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/text/reftests/xml-lang-attribute.svg
@@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"> + <metadata> + <title>xml:lang attribute should affect text rendering</title> + <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#LangSpaceAttrs"/> + <h:link rel="mismatch" href="lang-attribute-ref.svg"/> + </metadata> + + <text> + <tspan x="10" y="100" font-size="90" xml:lang="ja" lang="en">今骨直</tspan> + <tspan x="10" y="200" font-size="90" xml:lang="zh-CN">今骨直</tspan> + <tspan x="10" y="300" font-size="90" xml:lang="zh-TW">今骨直</tspan> + </text> +</svg>
diff --git a/third_party/blink/web_tests/fast/forms/mouseevent_disabled_form_control.html b/third_party/blink/web_tests/fast/forms/mouseevent_disabled_form_control.html index decbdf89..87d134c 100644 --- a/third_party/blink/web_tests/fast/forms/mouseevent_disabled_form_control.html +++ b/third_party/blink/web_tests/fast/forms/mouseevent_disabled_form_control.html
@@ -16,8 +16,7 @@ target.onclick = t.unreached_func("click should not fire on disabled element"); document.body.onclick = t.unreached_func("click should not fire on event path"); target.click(); - target.dispatchEvent(new MouseEvent('click', {capture: true, bubbles: true})); - }, 'Click should not fire'); + }, 'element.click() should not fire a click event.'); for (let eventName of eventList) { test((t) => {
diff --git a/third_party/blink/web_tests/printing/fixedpos-with-inline-block-expected.html b/third_party/blink/web_tests/printing/fixedpos-with-inline-block-expected.html new file mode 100644 index 0000000..dbc54e2 --- /dev/null +++ b/third_party/blink/web_tests/printing/fixedpos-with-inline-block-expected.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<script> + testRunner.setPrinting(); + internals.settings.setShouldPrintBackgrounds(true); +</script> +<style> + body { margin: 0; } +</style> +<div style="float:right; width:100px; height:100px; background:green;"></div> +<div style="break-after:page;"> + There should be two pages. Both pages should have a green square in the top + right corner. +</div> +<div style="float:right; width:100px; height:100px; background:green;"></div> +Page 2. Green square there? →
diff --git a/third_party/blink/web_tests/printing/fixedpos-with-inline-block.html b/third_party/blink/web_tests/printing/fixedpos-with-inline-block.html new file mode 100644 index 0000000..9dfd80a5 --- /dev/null +++ b/third_party/blink/web_tests/printing/fixedpos-with-inline-block.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<script> + testRunner.setPrinting(); + internals.settings.setShouldPrintBackgrounds(true); +</script> +<style> + body { margin: 0; } +</style> +<div style="position:fixed; right:0; top:0;"> + <div style="display:inline-block; vertical-align:top; width:100px; height:100px; background:green;"></div> +</div> +<div style="break-after:page;"> + There should be two pages. Both pages should have a green square in the top + right corner. +</div> +Page 2. Green square there? →
diff --git a/third_party/blink/web_tests/printing/page-overflow-inside-overflow-hidden-expected.html b/third_party/blink/web_tests/printing/page-overflow-inside-overflow-hidden-expected.html new file mode 100644 index 0000000..13445dd --- /dev/null +++ b/third_party/blink/web_tests/printing/page-overflow-inside-overflow-hidden-expected.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<script> + testRunner.setPrinting(); + internals.settings.setShouldPrintBackgrounds(true); +</script> +<div style="overflow:hidden; width:100px; height:100px; background:green;"> + <div style="height:5000px;"></div> +</div> +<p>There should be a green square above, and no red.</p>
diff --git a/third_party/blink/web_tests/printing/page-overflow-inside-overflow-hidden.html b/third_party/blink/web_tests/printing/page-overflow-inside-overflow-hidden.html new file mode 100644 index 0000000..3a4a304f --- /dev/null +++ b/third_party/blink/web_tests/printing/page-overflow-inside-overflow-hidden.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<script> + testRunner.setPrinting(); + internals.settings.setShouldPrintBackgrounds(true); +</script> +<div style="overflow:hidden; width:100px; height:100px; background:green;"> + <div style="height:5000px;"> + <div style="height:100px;"></div> + <div style="position:relative;"> + <div style="position:absolute; width:100px; height:100px; background:red;">FAIL</div> + </div> + </div> +</div> +<p>There should be a green square above, and no red.</p>
diff --git a/third_party/closure_compiler/externs/metrics_private.js b/third_party/closure_compiler/externs/metrics_private.js index ee69205..438d0e50 100644 --- a/third_party/closure_compiler/externs/metrics_private.js +++ b/third_party/closure_compiler/externs/metrics_private.js
@@ -1,4 +1,4 @@ -// Copyright 2020 The Chromium Authors +// Copyright 2022 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,7 +7,7 @@ // NOTE: The format of types has changed. 'FooType' is now // 'chrome.metricsPrivate.FooType'. // Please run the closure compiler before committing changes. -// See https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md +// See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md /** @fileoverview Externs generated from namespace: metricsPrivate */ @@ -147,7 +147,7 @@ */ chrome.metricsPrivate.recordSparseValueWithHashMetricName = function(metricName, value) {}; - /** +/** * Increments the count associated with the hash of |value| in the sparse * histogram defined by the |metricName| using base::PersistentHash(value). * @param {string} metricName
diff --git a/third_party/eigen3/README.chromium b/third_party/eigen3/README.chromium index 06ccd4a..433a409 100644 --- a/third_party/eigen3/README.chromium +++ b/third_party/eigen3/README.chromium
@@ -1,8 +1,8 @@ Name: Eigen Short Name: eigen3 URL: http://eigen.tuxfamily.org/ -Version: dceb779ecd822f55b4ae78f760371b0e08a889f2 -Date: 2022/09/23 +Version: b3bf8d6a13585ff248c079402654647d298de60b +Date: 2022/10/03 License: MPL 2 License File: LICENSE Security Critical: Yes
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index c6ce25b6..d2741b8 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-12-1-98-gb93f20ab7 -Revision: b93f20ab7ad610c986497243ca963ca79013411c +Version: VER-2-12-1-99-g8faf57dd1 +Revision: 8faf57dd17088c37fa947fd565870648bbdbad18 CPEPrefix: cpe:/a:freetype:freetype:2.11.1 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/tflite/README.chromium b/third_party/tflite/README.chromium index d9a15960..6a5f5eece 100644 --- a/third_party/tflite/README.chromium +++ b/third_party/tflite/README.chromium
@@ -1,8 +1,8 @@ Name: TensorFlow Lite Short Name: tflite URL: https://github.com/tensorflow/tensorflow -Version: e6ca8d5097646089651f009d93eec1e4597d2fbf -Date: 2022/09/27 +Version: da1ec73e06b2f1129aed8738ed3e530256899d07 +Date: 2022/10/03 License: Apache 2.0 License File: LICENSE Security Critical: Yes
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn index da6daca8..dc038853 100644 --- a/third_party/wayland-protocols/BUILD.gn +++ b/third_party/wayland-protocols/BUILD.gn
@@ -2,8 +2,19 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/sysroot.gni") import("//third_party/wayland/wayland_protocol.gni") +# This component mixes protocols from different sources. One of those sources +# is special: that is the wayland-protocols package which defines a set of +# standardised protocols. When using the system libwayland for the client, we +# should use the manifest files provided in the sysroot. +if (use_system_libwayland_client) { + standard_protocol_prefix = "${sysroot}/usr/share/wayland-protocols" +} else { + standard_protocol_prefix = "src" +} + # ATTENTION! Please keep these rules alphabetized! wayland_protocol("alpha_compositing_protocol") { @@ -23,7 +34,7 @@ } wayland_protocol("fullscreen_shell_protocol") { - sources = [ "src/unstable/fullscreen-shell/fullscreen-shell-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/fullscreen-shell/fullscreen-shell-unstable-v1.xml" ] } wayland_protocol("gaming_input_protocol") { @@ -39,15 +50,15 @@ } wayland_protocol("idle_inhibit_protocol") { - sources = [ "src/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml" ] } wayland_protocol("input_method_protocol") { - sources = [ "src/unstable/input-method/input-method-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/input-method/input-method-unstable-v1.xml" ] } wayland_protocol("input_timestamps_protocol") { - sources = [ "src/unstable/input-timestamps/input-timestamps-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/input-timestamps/input-timestamps-unstable-v1.xml" ] } wayland_protocol("keyboard_configuration_protocol") { @@ -59,15 +70,15 @@ } wayland_protocol("keyboard_shortcuts_inhibit_protocol") { - sources = [ "src/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml" ] } wayland_protocol("linux_dmabuf_protocol") { - sources = [ "src/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" ] } wayland_protocol("linux_explicit_synchronization_protocol") { - sources = [ "src/unstable/linux-explicit-synchronization/linux-explicit-synchronization-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/linux-explicit-synchronization/linux-explicit-synchronization-unstable-v1.xml" ] } wayland_protocol("notification_shell_protocol") { @@ -79,25 +90,23 @@ } wayland_protocol("pointer_constraints_protocol") { - sources = - [ "src/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" ] } wayland_protocol("pointer_gestures_protocol") { - sources = [ "src/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml" ] } wayland_protocol("presentation_time_protocol") { - sources = [ "src/stable/presentation-time/presentation-time.xml" ] + sources = [ "${standard_protocol_prefix}/stable/presentation-time/presentation-time.xml" ] } wayland_protocol("primary_selection_protocol") { - sources = - [ "src/unstable/primary-selection/primary-selection-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/primary-selection/primary-selection-unstable-v1.xml" ] } wayland_protocol("relative_pointer_protocol") { - sources = [ "src/unstable/relative-pointer/relative-pointer-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/relative-pointer/relative-pointer-unstable-v1.xml" ] } wayland_protocol("remote_shell_protocol") { @@ -124,7 +133,7 @@ } wayland_protocol("text_input_protocol") { - sources = [ "src/unstable/text-input/text-input-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/text-input/text-input-unstable-v1.xml" ] } wayland_protocol("touchpad_haptics_protocol") { @@ -132,7 +141,7 @@ } wayland_protocol("viewporter_protocol") { - sources = [ "src/stable/viewporter/viewporter.xml" ] + sources = [ "${standard_protocol_prefix}/stable/viewporter/viewporter.xml" ] } wayland_protocol("vsync_feedback_protocol") { @@ -148,27 +157,30 @@ } wayland_protocol("xdg_activation") { + # XDG activation has been introduced in wayland-protocols version 1.21, which + # is newer than 1.20 which is currently in the sysroot for Debian bullseye. + # That is why we cannot use the standard protocol prefix here. sources = [ "src/staging/xdg-activation/xdg-activation-v1.xml" ] } wayland_protocol("xdg_decoration_protocol") { - sources = [ "src/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml" ] } wayland_protocol("xdg_foreign") { sources = [ - "src/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml", - "src/unstable/xdg-foreign/xdg-foreign-unstable-v2.xml", + "${standard_protocol_prefix}/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml", + "${standard_protocol_prefix}/unstable/xdg-foreign/xdg-foreign-unstable-v2.xml", ] } wayland_protocol("xdg_output_protocol") { - sources = [ "src/unstable/xdg-output/xdg-output-unstable-v1.xml" ] + sources = [ "${standard_protocol_prefix}/unstable/xdg-output/xdg-output-unstable-v1.xml" ] } wayland_protocol("xdg_shell_protocol") { sources = [ - "src/stable/xdg-shell/xdg-shell.xml", - "src/unstable/xdg-shell/xdg-shell-unstable-v6.xml", + "${standard_protocol_prefix}/stable/xdg-shell/xdg-shell.xml", + "${standard_protocol_prefix}/unstable/xdg-shell/xdg-shell-unstable-v6.xml", ] }
diff --git a/third_party/wayland/BUILD.gn b/third_party/wayland/BUILD.gn index f7386d7..03a02b30 100644 --- a/third_party/wayland/BUILD.gn +++ b/third_party/wayland/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/config/linux/pkg_config.gni") +import("//build/config/sysroot.gni") import("//third_party/wayland/features.gni") import("//third_party/wayland/wayland_protocol.gni") import("//tools/generate_stubs/rules.gni") @@ -9,7 +10,11 @@ # This should be open to both system and non - system libwayland as wayland_stubs # also uses this. wayland_protocol("wayland_protocol_c") { - sources = [ "src/protocol/wayland.xml" ] + if (use_system_libwayland_client) { + sources = [ "${sysroot}/usr/share/wayland/wayland.xml" ] + } else { + sources = [ "src/protocol/wayland.xml" ] + } code_marshalling = true }
diff --git a/third_party/webrtc_overrides/rtc_base/logging.h b/third_party/webrtc_overrides/rtc_base/logging.h index 900fd8b..8a273bbb 100644 --- a/third_party/webrtc_overrides/rtc_base/logging.h +++ b/third_party/webrtc_overrides/rtc_base/logging.h
@@ -66,12 +66,20 @@ #define RTC_LOG_V(sev) DIAGNOSTIC_LOG(sev, NONE, 0) #undef RTC_LOG #define RTC_LOG(sev) DIAGNOSTIC_LOG(rtc::sev, NONE, 0) +// Log if condition evaluates to true. DIAGNOSTIC_LOG comes second in the +// expression so users can properly stream log message to the logger. +#define RTC_LOG_IF(sev, condition) \ + !(condition) ? (void)0 : DIAGNOSTIC_LOG(rtc::sev, NONE, 0) // The _F version prefixes the message with the current function name. #if defined(__GNUC__) && defined(_DEBUG) #define RTC_LOG_F(sev) RTC_LOG(sev) << __PRETTY_FUNCTION__ << ": " +#define RTC_LOG_IF_F(sev, condition) \ + RTC_LOG_IF(sev, condition) << __PRETTY_FUNCTION__ << ": " #else #define RTC_LOG_F(sev) RTC_LOG(sev) << __FUNCTION__ << ": " +#define RTC_LOG_IF_F(sev, condition) \ + RTC_LOG_IF(sev, condition) << __FUNCTION__ << ": " #endif #define RTC_LOG_E(sev, ctx, err, ...) \ @@ -108,8 +116,10 @@ #if RTC_DLOG_IS_ON #define RTC_DLOG(sev) RTC_LOG(sev) +#define RTC_DLOG_IF(sev, condition) RTC_LOG_IF(sev, condition) #define RTC_DLOG_V(sev) RTC_LOG_V(sev) #define RTC_DLOG_F(sev) RTC_LOG_F(sev) +#define RTC_DLOG_IF_F(sev, condition) RTC_LOG_IF_F(sev, condition) #else #define RTC_DLOG_EAT_STREAM_PARAMS(sev) \ (true ? true : ((void)(rtc::sev), true)) \ @@ -118,8 +128,10 @@ rtc::DiagnosticLogMessage(__FILE__, __LINE__, rtc::sev, \ rtc::ERRCTX_NONE, 0).stream() #define RTC_DLOG(sev) RTC_DLOG_EAT_STREAM_PARAMS(sev) +#define RTC_DLOG_IF(sev, condition) RTC_DLOG_EAT_STREAM_PARAMS(sev) #define RTC_DLOG_V(sev) RTC_DLOG_EAT_STREAM_PARAMS(sev) #define RTC_DLOG_F(sev) RTC_DLOG_EAT_STREAM_PARAMS(sev) +#define RTC_DLOG_IF_F(sev, condition) RTC_DLOG_EAT_STREAM_PARAMS(sev) #endif // Add operator<< for WebRTC types with the ToLogString method.
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 9db39ef2b..c49e28c3 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -197,7 +197,7 @@ 'ToTChromeOS': 'lacros_on_linux_tot_release', 'ToTChromeOS (dbg)': 'lacros_on_linux_tot_debug', 'ToTFuchsia x64': 'fuchsia_clang_tot_release_x64', - 'ToTFuchsiaOfficial': 'fuchsia_clang_tot_official_arm64', + 'ToTFuchsiaOfficial arm64': 'fuchsia_clang_tot_official_arm64', 'ToTLinux': 'clang_tot_linux_full_symbols_shared_release', 'ToTLinux (dbg)': 'clang_tot_shared_debug', 'ToTLinuxASan': 'clang_tot_asan_lsan_static_release', @@ -230,6 +230,9 @@ }, 'chromium.dawn': { + 'Dawn Android arm DEPS Release (Pixel 4)': 'dawn_tests_android_release_trybot_reclient', + 'Dawn Android arm Release (Pixel 4)': 'dawn_tests_android_release_trybot_reclient', + 'Dawn Linux x64 Builder': 'dawn_tests_with_desktop_gl_release_trybot_reclient', 'Dawn Linux x64 DEPS Builder': 'dawn_tests_with_desktop_gl_release_trybot_reclient', @@ -1119,6 +1122,8 @@ }, 'tryserver.chromium.dawn': { + 'android-dawn-arm-rel': 'dawn_tests_android_release_trybot', + 'dawn-android-arm-deps-rel': 'dawn_tests_android_release_trybot', 'dawn-linux-x64-deps-rel': 'dawn_tests_with_desktop_gl_release_trybot', 'dawn-mac-x64-deps-rel': 'dawn_tests_release_trybot_alloc_none', 'dawn-try-mac-amd-exp': 'dawn_tests_release_trybot_alloc_none', @@ -2468,6 +2473,14 @@ 'codesearch', 'android_without_codecs', 'static', 'goma', ], + 'dawn_tests_android_release_trybot': [ + 'dawn_tests', 'android', 'release_trybot_minimal_symbols', + ], + + 'dawn_tests_android_release_trybot_reclient': [ + 'dawn_tests', 'android', 'release_trybot_minimal_symbols_reclient', + ], + 'dawn_tests_asan_release_bot_dcheck_always_on_reclient': [ 'dawn_tests', 'asan', 'release_trybot_minimal_symbols_reclient', ],
diff --git a/tools/mb/mb_config_expectations/chromium.clang.json b/tools/mb/mb_config_expectations/chromium.clang.json index eb55dc9..b559349 100644 --- a/tools/mb/mb_config_expectations/chromium.clang.json +++ b/tools/mb/mb_config_expectations/chromium.clang.json
@@ -185,7 +185,7 @@ "target_os": "fuchsia" } }, - "ToTFuchsiaOfficial": { + "ToTFuchsiaOfficial arm64": { "gn_args": { "is_clang": true, "is_component_build": false,
diff --git a/tools/mb/mb_config_expectations/chromium.dawn.json b/tools/mb/mb_config_expectations/chromium.dawn.json index 2b692a3..953a0fc 100644 --- a/tools/mb/mb_config_expectations/chromium.dawn.json +++ b/tools/mb/mb_config_expectations/chromium.dawn.json
@@ -1,4 +1,34 @@ { + "Dawn Android arm DEPS Release (Pixel 4)": { + "gn_args": { + "dawn_enable_opengles": true, + "dcheck_always_on": true, + "debuggable_apks": false, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "symbol_level": 1, + "target_os": "android", + "use_dawn": true, + "use_remoteexec": true + } + }, + "Dawn Android arm Release (Pixel 4)": { + "gn_args": { + "dawn_enable_opengles": true, + "dcheck_always_on": true, + "debuggable_apks": false, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "symbol_level": 1, + "target_os": "android", + "use_dawn": true, + "use_remoteexec": true + } + }, "Dawn Linux x64 Builder": { "gn_args": { "dawn_enable_desktop_gl": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.dawn.json b/tools/mb/mb_config_expectations/tryserver.chromium.dawn.json index 8c68457..b5cdacd3 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.dawn.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.dawn.json
@@ -1,4 +1,34 @@ { + "android-dawn-arm-rel": { + "gn_args": { + "dawn_enable_opengles": true, + "dcheck_always_on": true, + "debuggable_apks": false, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "symbol_level": 1, + "target_os": "android", + "use_dawn": true, + "use_goma": true + } + }, + "dawn-android-arm-deps-rel": { + "gn_args": { + "dawn_enable_opengles": true, + "dcheck_always_on": true, + "debuggable_apks": false, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "symbol_level": 1, + "target_os": "android", + "use_dawn": true, + "use_goma": true + } + }, "dawn-linux-x64-deps-rel": { "gn_args": { "dawn_enable_desktop_gl": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b81ca70c..f21f536c 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -43534,11 +43534,23 @@ </enum> <enum name="FingerprintUnlockResult"> - <int value="0" label="Success"/> - <int value="1" label="Fingerprint auth not available"/> - <int value="2" label="Authentication is temporarily disabled"/> - <int value="3" label="Fingerprint match failed"/> - <int value="4" label="Fingerprint match is not of the the primary user"/> + <int value="0" label="Success"> + Successful fingerprint unlock occurred. + + FingerprintUnlockResult::kSuccess = 0 + </int> + <int value="1" label="Fingerprint auth not available"> + FingerprintUnlockResult::kFingerprintUnavailable = 1 + </int> + <int value="2" label="Authentication is temporarily disabled"> + FingerprintUnlockResult::kAuthTemporarilyDisabled = 2 + </int> + <int value="3" label="Fingerprint match failed"> + FingerprintUnlockResult::kMatchFailed = 3 + </int> + <int value="4" label="Fingerprint match is not of the the primary user"> + FingerprintUnlockResult::kMatchNotForPrimaryUser = 4 + </int> </enum> <enum name="FingerprintUpdaterReason"> @@ -74843,6 +74855,7 @@ <int value="1204" label="Languages"/> <int value="1205" label="Input"/> <int value="1206" label="Customize spell check"/> + <int value="1207" label="Manage user dictionary"/> <int value="1300" label="Network File Shares"/> <int value="1400" label="Printing Details"/> <int value="1500" label="Manage Accessibility"/> @@ -98201,6 +98214,9 @@ </enum> <enum name="TrustedWebActivityLocationErrorCode"> + <obsolete> + Deprecated 2022/10. + </obsolete> <int value="0" label="No error"/> <int value="1" label="Location Error"> Error when getting location from client app.
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml index 0efceb96..9f3c4c0 100644 --- a/tools/metrics/histograms/metadata/apps/histograms.xml +++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -1379,7 +1379,7 @@ </histogram> <histogram name="Apps.AppListFolder.ShowHide.AnimationSmoothness" units="%" - expires_after="2022-11-06"> + expires_after="2023-05-06"> <owner>tbarzic@chromium.org</owner> <owner>jamescook@chromium.org</owner> <owner>chromeos-launcher@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/commerce/histograms.xml b/tools/metrics/histograms/metadata/commerce/histograms.xml index 62af416..d809e20 100644 --- a/tools/metrics/histograms/metadata/commerce/histograms.xml +++ b/tools/metrics/histograms/metadata/commerce/histograms.xml
@@ -179,6 +179,21 @@ </summary> </histogram> +<histogram name="Commerce.Heuristics.ProductIDExtractionPatternSource" + enum="CommerceHeuristicsDataSource" expires_after="2023-02-19"> + <owner>yuezhanggg@chromium.org</owner> + <owner>wychen@chromium.org</owner> + <owner>chrome-shopping@google.com</owner> + <summary> + Product ID extraction pattern heuristics could come from Finch feature + parameter or component updater. This histogram is logged when we try to get + product ID extraction pattern to record from which source we are getting the + pattern. The action of getting product ID extraction is triggered every time + we try to load the cart extraction script for ChromeCart, which happens + after the user navigates to a cart page or updates the cart page. + </summary> +</histogram> + <histogram name="Commerce.Heuristics.SkipProductPatternSource" enum="CommerceHeuristicsDataSource" expires_after="2023-02-19"> <owner>yuezhanggg@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml index 5ac1c7d..33458fe 100644 --- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml +++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -625,6 +625,9 @@ <histogram name="TrustedWebActivity.LocationUpdateErrorCode" enum="TrustedWebActivityLocationErrorCode" expires_after="2022-10-23"> + <obsolete> + Deprecated 2022-09. no longer needed. + </obsolete> <owner>eirage@chromium.org</owner> <owner>peconn@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/fingerprint/histograms.xml b/tools/metrics/histograms/metadata/fingerprint/histograms.xml index 9525834..e299a0a7 100644 --- a/tools/metrics/histograms/metadata/fingerprint/histograms.xml +++ b/tools/metrics/histograms/metadata/fingerprint/histograms.xml
@@ -130,6 +130,12 @@ <owner>cros-lurs@google.com</owner> <summary> Counts the number of fingerprint attempts until successful screen unlock. + + A count of 0 means that the user unlocked the screen on the first attempt. + The maximum number of unlock attempts is governed by kMaximumUnlockAttempts, + such that this value must be less than the max. + + This is related to Fingerprint.Unlock.RecentAttemptsCountBeforeSuccess. </summary> </histogram> @@ -196,6 +202,12 @@ unlock. Recent attempts are defined as happening within 3 seconds from each others. The goal is to count intentional attempt to unlock the device and exclude incidental touches of the fingerprint sensor. + + A count of 0 means that the user unlocked the screen on the first attempt. + The maximum number of unlock attempts is governed by kMaximumUnlockAttempts, + such that this value must be less than the max. + + This is related to Fingerprint.Unlock.AttemptsCountBeforeSuccess. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index 4862409c..ada47801 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -355,7 +355,7 @@ <owner>chrome-owp-storage@google.com</owner> <component>UI>Browser>History</component> <summary> - Recorded after the user clicks clear data on the CleaerBrowsingData dialog, + Recorded after the user clicks clear data on the ClearBrowsingData dialog, but before the installed apps dialog is shown to the user. The value will be true if there are installed apps (and thus, the installed app dialog will be shown), and false otherwise. @@ -394,7 +394,7 @@ <owner>chrome-owp-storage@google.com</owner> <component>UI>Browser>History</component> <summary> - Recorded when we successfuly fetched important sites in the clear browsing + Recorded when we successfully fetched important sites in the clear browsing data screen. This is the number of sites that we think are important to the user. </summary> @@ -406,7 +406,7 @@ <owner>chrome-owp-storage@google.com</owner> <component>UI>Browser>History</component> <summary> - Recorded when we successfuly fetched installed apps in the clear browsing + Recorded when we successfully fetched installed apps in the clear browsing data screen. This is the number of apps that we think are important to the user and allow the users to exclude from clearing browsing data. </summary> @@ -519,7 +519,7 @@ </histogram> <histogram name="History.Clusters.Actions.FinalState.Number{Event}" - units="count" expires_after="2022-12-10"> + units="count" expires_after="2023-10-01"> <owner>mcrouse@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -536,7 +536,7 @@ <variant name="RelatedSearchesClicked" summary="related search links opened"/> <variant name="TogglesToBasicHistory" - summary="Tggles to from basic history UI"/> + summary="Toggles to from basic history UI"/> <variant name="VisibilityToggles" summary="Journeys UI toggles on/off"/> </token> </histogram> @@ -568,7 +568,7 @@ </histogram> <histogram name="History.Clusters.Actions.LinksOpened" units="links opened" - expires_after="2022-11-20"> + expires_after="2023-10-01"> <owner>manukh@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -653,7 +653,7 @@ </histogram> <histogram name="History.Clusters.Backend.ClusterSize.{ClusterStatistic}" - units="number visits" expires_after="M106"> + units="number visits" expires_after="2023-10-01"> <owner>mcrouse@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -699,17 +699,54 @@ </summary> </histogram> -<histogram name="History.Clusters.Backend.GetClustersLatency" units="ms" - expires_after="2023-03-26"> - <owner>mcrouse@chromium.org</owner> +<histogram + name="History.Clusters.Backend.GetMostRecentClusters.{Segment}{Source}" + units="ms" expires_after="2023-10-01"> + <owner>manukh@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> <summary> - Logs the latency of clustering visits performed by the on-device backend. - Logged when clusters have been calculated based on any request to cluster - visits, which could be triggered from several things, including loading the - journeys UI, putting a query in the journeys page, etc.. + Near startup and every 1 hour afterwards, unclustered visits are clustered, + and the clusters are persisted in the history DB. + + As needed, both fresh and persisted clusters are fetched. Clusters are + fetched for: a) displaying on the Journeys WebUI and b) generating keyword + caches to match with omnibox inputs and show journey chips or suggestions in + the omnibox. + + This histogram records the latency breakdown for fetching both fresh and + persisted clusters. See the similar + 'History.Clusters.Backend.UpdateClusters.*' histograms for the latency + breakdown for updating clusters. + + Recorded for every batch of fetched clusters; can be recorded more than once + per Journey WebUI load or keyword cache generations + + This slice records the time between the main thread requesting and receiving + {Segment}. Records {Source}. </summary> + <token key="Segment"> + <variant name="ComputeClustersLatency" summary="clusters from the model"/> + <variant name="GetAnnotatedVisitsToClusterLatency" + summary="annotated visits to cluster (which can include clustered, + unclustered, incomplete, and complete visits)"/> + <variant name="GetMostRecentPersistedClustersLatency" + summary="persisted clusters from the history DB"/> + </token> + <token key="Source"> + <variant name="" summary="all requests"/> + <variant name=".AllKeywordCacheRefresh" + summary="only requests for the all-keyword-cache which occurs about + once every 2 hours but can vary if e.g. the user isn't + interacting with the omnibox"/> + <variant name=".ShortKeywordCacheRefresh" + summary="only requests for the short-keyword cache which occurs up to + once every 10 seconds but can vary if e.g. the user isn't + interacting with the omnibox"/> + <variant name=".WebUI" + summary="only requests for the Journeys WebUI, either query-less or + query states, both on load and on scroll"/> + </token> </histogram> <histogram name="History.Clusters.Backend.KeywordCache.AllKeywordPhraseCount" @@ -829,7 +866,7 @@ <histogram name="History.Clusters.Backend.NumKeywordsPerCluster.{KeywordStatistic}" - units="number keywords" expires_after="2022-11-20"> + units="number keywords" expires_after="2023-10-01"> <owner>mcrouse@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -883,7 +920,7 @@ Logs the number of visits that were processed on the UI thread in a batch. Can be logged multiple times when a request to cluster visits is made, which could be triggered from several things, including loading the journeys UI, - putting a query in the journeys page, etc.. depending on how many visits + putting a query in the journeys page, etc... depending on how many visits were sent to the backend to cluster. </summary> </histogram> @@ -899,7 +936,7 @@ is performed on the UI thread. This does not include any thread hop or queuing delay. Can be logged multiple times when a request to cluster visits is made, which could be triggered from several things, including loading the - journeys UI, putting a query in the journeys page, etc.. depending on how + journeys UI, putting a query in the journeys page, etc... depending on how many visits were sent to the backend to cluster. </summary> </histogram> @@ -912,29 +949,51 @@ <summary> This histogram records the time taken (excluding queuing delay) to retrieve visits from the History database, which occurs on the History DB thread. - Logged once per request to cluster vists is made, which could be triggered + Logged once per request to cluster visits is made, which could be triggered from several things, including loading the journeys UI, putting a query in the journeys page, etc. </summary> </histogram> -<histogram name="History.Clusters.Backend.QueryAnnotatedVisitsLatency" - units="ms" expires_after="2023-02-12"> - <owner>sophiechang@chromium.org</owner> +<histogram name="History.Clusters.Backend.UpdateClusters.{Segment}" units="ms" + expires_after="2023-10-01"> + <owner>manukh@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> <summary> - This histogram records the total time taken (including queuing delay) from - which a request to retrieve vists from the History database took. Logged - once per request to cluster vists is made, which could be triggered from - several things, including loading the journeys UI, putting a query in the - journeys page, etc. + Near startup and every 1 hour afterwards, unclustered visits are clustered, + and the clusters are persisted in the history DB. + + As needed, both fresh and persisted clusters are fetched. Clusters are + fetched for: a) displaying on the Journeys WebUI and b) generating keyword + caches to match with omnibox inputs and show journey chips or suggestions in + the omnibox. + + This histogram records the latency breakdown for updating clusters. See the + similar 'History.Clusters.Backend.GetMostRecentClusters.*' histograms for + the latency breakdown for fetching clusters. + + Recorded for every batch of visits clustered; can be recorded more than once + every hour. + + This slice records the time between the main thread requesting and + {Segment}. </summary> + <token key="Segment"> + <variant name="ComputeClustersLatency" + summary="receiving clusters from the model"/> + <variant name="GetAnnotatedVisitsToClusterLatency" + summary="receiving annotated visits to cluster (which can include + clustered, unclustered, incomplete, and complete visits)"/> + <variant name="PersistClustersLatency" + summary="receiving acknowledgement for completion of persisting the + clusters to the history DB"/> + </token> </histogram> <histogram name="History.Clusters.Backend.WasClusterFiltered.{ClusterFilterReason}" - enum="BooleanFiltered" expires_after="2022-11-15"> + enum="BooleanFiltered" expires_after="2023-10-01"> <owner>mcrouse@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -952,7 +1011,7 @@ </histogram> <histogram name="History.Clusters.KeywordCache.Latency" units="ms" - expires_after="2022-07-24"> + expires_after="2023-10-01"> <owner>tommycli@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -961,10 +1020,19 @@ measured via the wall clock. Most of this time is not on the main thread. The total time spent populating the keywords cache will be: - History.Clusters.KeywordCache.Latency = (number of batches) * - (History.Clusters.Backend.QueryAnnotatedVisitsLatency + - History.Clusters.Backend.GetClustersLatency + - History.Clusters.KeywordCache.ThreadTime) + History.Clusters.KeywordCache.Latency = (number of batches) * ( + History.Clusters.Backend.GetMostRecentClusters.GetAnnotatedVisitsToClusterLatency.AllKeywordCacheRefresh + + + History.Clusters.Backend.GetMostRecentClusters.ComputeClustersLatency.AllKeywordCacheRefresh + + + History.Clusters.Backend.GetMostRecentClusters.GetMostRecentPersistedClustersLatency.AllKeywordCacheRefresh + + + History.Clusters.Backend.GetMostRecentClusters.GetAnnotatedVisitsToClusterLatency.ShortKeywordCacheRefresh + + + History.Clusters.Backend.GetMostRecentClusters.ComputeClustersLatency.ShortKeywordCacheRefresh + + + History.Clusters.Backend.GetMostRecentClusters.GetMostRecentPersistedClustersLatency.ShortKeywordCacheRefresh + + History.Clusters.KeywordCache.ThreadTime) </summary> </histogram> @@ -988,14 +1056,14 @@ <component>UI>Browser>Journeys</component> <summary> This histogram records the total time taken to convert and process visits in - in all history cluster available. This is recorded once after the - conversion, deduplication and sorting of the clusters. This is recorded - using the highest precision clock possible. Like most time measurements this - will not have the same behavior regarding system sleep on all platforms. See + all history cluster available. This is recorded once after the conversion, + deduplication and sorting of the clusters. This is recorded using the + highest precision clock possible. Like most time measurements this will not + have the same behavior regarding system sleep on all platforms. See bit.ly/chrome-clocks-and-sleep for more details. Since the measurement is taken after the operation is over it will be missing if the operation never completes. This can happen if the user or the system shuts down chrome - because of the unresponsiveness. A decidely imperfect strategy to evaluate + because of the unresponsiveness. A decidedly imperfect strategy to evaluate how often this happens is to compare total counts with another histogram that is recorded before the operation starts ("History.Clusters.Backend.GetClusterLatency"). Such analysis has @@ -1025,9 +1093,12 @@ between multiple UIs. Roughly, History.Clusters.ServiceLatency = - History.Clusters.Backend.QueryAnnotatedVisitsLatency + - History.Clusters.Backend.GetClustersLatency + - History.Clusters.ProcessClustersDuration + History.Clusters.Backend.GetMostRecentClusters.GetAnnotatedVisitsToClusterLatency.WebUI + + + History.Clusters.Backend.GetMostRecentClusters.ComputeClustersLatency.WebUI + + + History.Clusters.Backend.GetMostRecentClusters.GetMostRecentPersistedClustersLatency.WebUI + + History.Clusters.ProcessClustersDuration </summary> </histogram> @@ -1083,7 +1154,7 @@ </histogram> <histogram name="History.Clusters.UIActions.Cluster.{ClusterAction}" - units="index" expires_after="2022-08-25"> + units="index" expires_after="2023-10-01"> <owner>mahmadi@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -1105,7 +1176,7 @@ <histogram name="History.Clusters.UIActions.RelatedSearch.{RelatedSearchAction}" - units="index" expires_after="2022-08-25"> + units="index" expires_after="2023-10-01"> <owner>mahmadi@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -1121,7 +1192,7 @@ </histogram> <histogram name="History.Clusters.UIActions.ToggledVisibility" - enum="BooleanVisible" expires_after="2022-10-30"> + enum="BooleanVisible" expires_after="2023-10-01"> <owner>mahmadi@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -1133,7 +1204,7 @@ </histogram> <histogram name="History.Clusters.UIActions.{VisitType}Visit.{VisitAction}" - units="index" expires_after="2022-08-25"> + units="index" expires_after="2023-10-01"> <owner>mahmadi@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>UI>Browser>Journeys</component> @@ -1524,7 +1595,7 @@ <histogram name="History.GetFavIconFromDB" units="ms" expires_after="M79"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <component>UI>Browser>History</component> - <summary>Time to check the thumbnail database for an url's favicon.</summary> + <summary>Time to check the thumbnail database for a URL's favicon.</summary> </histogram> <histogram name="History.HistoryPageView" enum="HistoryPageView" @@ -1625,7 +1696,7 @@ <component>UI>Browser>History</component> <summary> Records the total time between when the in-memory url index is requested to - be built from the main thread, and when the request is succesfully finished + be built from the main thread, and when the request is successfully finished and reported back to the main thread. Failed cases are not recorded. From startup traces, we found that History initialization blocks the DB task @@ -1679,7 +1750,7 @@ Unique hostnames in History database urls table with last-visit times in the last 30 days. Metrics are logged on initialization of the History DB on 0.3% of starts. See also ExploreSites.MonthlyHostCount metric which is similar - but is reported on a elapsed time basis to help avoid bias toward more + but is reported on an elapsed time basis to help avoid bias toward more active users. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml index ffc8ccc..bac0e69d 100644 --- a/tools/metrics/histograms/metadata/omnibox/histograms.xml +++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -2171,8 +2171,27 @@ </summary> </histogram> +<histogram name="Omnibox.ZeroSuggestProvider.CacheMemoryUsage" units="Bytes" + expires_after="2023-09-30"> + <owner>mahmadi@chromium.org</owner> + <owner>chrome-omnibox-team@google.com</owner> + <summary> + Emitted in ZeroSuggestCacheService, records the estimated dynamically + allocated memory usage of the ZeroSuggestProvider cache every time the + prefetch or the non-prefetch zero-suggest response is stored in the cache on + eligible page load / page switch events and when the user has focused or + cleared the omnibox but has not typed in yet, respectively. Note that the + max number of responses stored in the cache is always capped. The cache size + can build up as more responses are stored. The cache size can also decrease + as responses are removed from the cache when suggestions are deleted from + the omnibox or when the user clears the browsing data. Hence, due to the + dynamic nature of the cache size, this histogram is recorded on every store + event as opposed to the cache destructor. + </summary> +</histogram> + <histogram name="Omnibox.ZeroSuggestProvider.Eligibility" - enum="ZeroSuggestEligibility" expires_after="2022-12-11"> + enum="ZeroSuggestEligibility" expires_after="2023-09-30"> <owner>mahmadi@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -2186,7 +2205,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestProvider.{ResultType}.{RequestType}" - enum="ZeroSuggestProviderEvent" expires_after="2022-12-11"> + enum="ZeroSuggestProviderEvent" expires_after="2023-09-30"> <owner>mahmadi@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -2207,7 +2226,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.NonPrefetch" - enum="OmniboxZeroSuggestRequests" expires_after="2022-12-11"> + enum="OmniboxZeroSuggestRequests" expires_after="2023-09-30"> <obsolete> Obsolete as of M105. </obsolete> @@ -2223,7 +2242,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.NonPrefetch.RoundTripTime" - units="ms" expires_after="2022-12-11"> + units="ms" expires_after="2023-09-30"> <obsolete> Obsolete as of M105. </obsolete> @@ -2238,7 +2257,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.Prefetch" - enum="OmniboxZeroSuggestRequests" expires_after="2022-12-11"> + enum="OmniboxZeroSuggestRequests" expires_after="2023-09-30"> <obsolete> Obsolete as of M105. </obsolete> @@ -2254,7 +2273,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.Prefetch.RoundTripTime" units="ms" - expires_after="2022-12-11"> + expires_after="2023-09-30"> <obsolete> Obsolete as of M105. </obsolete>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 92b4d9d..3e4b08f0 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -228,6 +228,18 @@ </summary> </histogram> +<histogram name="AccessCodeCast.Ui.AccessCodeNotFoundCount" units="instances" + expires_after="2023-03-12"> + <owner>bzielinski@google.com</owner> + <owner>cros-edu-eng@google.com</owner> + <summary> + The count of ACCESS_CODE_NOT_FOUND errors received while the + AccessCodeCastDialog is open, correlating to the number of times a user + typed an incorrect access code. Recorded after the dialog is closed. Logged + only on desktop platforms. + </summary> +</histogram> + <histogram name="AccessCodeCast.Ui.CastAttemptLength" units="ms" expires_after="2023-03-12"> <owner>bzielinski@google.com</owner> @@ -14039,7 +14051,7 @@ </histogram> <histogram name="TouchScreen.MissedTOUCHEVENTF_UP" enum="BooleanHit" - expires_after="2022-08-14"> + expires_after="2023-10-03"> <owner>girard@chromium.org</owner> <owner>input-dev@chromium.org</owner> <summary> @@ -14048,6 +14060,8 @@ TOUCHEVENTF_UP). Chromium generates a simulated event to maintain consistency/correctness. Only recorded on Windows. + Warning: This histogram was expired after M95, and resurrected in M108. + This workaround will be removed once usage drops off. See https://crbug.com/811273 for details. </summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index feb9541..224283c 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,16 +5,16 @@ "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "a4424c7c4b38ecc403042b12dbb96fd8fb7f00e5", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/099aff9404a0b944aa2d90a08a4e21655655e73e/trace_processor_shell.exe" + "hash": "61d0dbe93ee69ed61e5b397ecb71680e7bccc7d0", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/6b54769fde8e593a5ad7142596935d8198b511f1/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "77e3bc15e75534e1b377ade4a4afedd4e6548c46", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/099aff9404a0b944aa2d90a08a4e21655655e73e/trace_processor_shell" + "hash": "482fe6e201c0309c90dd65cccc479b8b31658b20", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/6b54769fde8e593a5ad7142596935d8198b511f1/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
diff --git a/ui/events/fuchsia/pointer_events_handler.cc b/ui/events/fuchsia/pointer_events_handler.cc index 001e1ed9..13e7c28 100644 --- a/ui/events/fuchsia/pointer_events_handler.cc +++ b/ui/events/fuchsia/pointer_events_handler.cc
@@ -8,6 +8,7 @@ #include <limits> #include <memory> +#include "base/fuchsia/fuchsia_logging.h" #include "base/logging.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" @@ -178,10 +179,11 @@ view_parameters.viewport_to_view_transform); // TODO(fxbug.dev/88580): Consider setting hover via // ui::TouchEvent::set_hovering(). - return TouchEvent(event_type, gfx::PointF(logical[0], logical[1]), - gfx::PointF(sample.position_in_viewport()[0], - sample.position_in_viewport()[1]), - timestamp, pointer_details); + gfx::PointF location(logical[0], logical[1]); + gfx::PointF root_location(sample.position_in_viewport()[0], + sample.position_in_viewport()[1]); + return TouchEvent(event_type, location, root_location, timestamp, + pointer_details); } // It returns a "draft" because the coordinates are logical. Later, @@ -282,7 +284,14 @@ PointerEventsHandler::PointerEventsHandler(fup::TouchSourceHandle touch_source, fup::MouseSourceHandle mouse_source) - : touch_source_(touch_source.Bind()), mouse_source_(mouse_source.Bind()) {} + : touch_source_(touch_source.Bind()), mouse_source_(mouse_source.Bind()) { + touch_source_.set_error_handler([](zx_status_t status) { + ZX_LOG(ERROR, status) << "fuchsia.ui.pointer.TouchSource disconnected."; + }); + mouse_source_.set_error_handler([](zx_status_t status) { + ZX_LOG(ERROR, status) << "fuchsia.ui.pointer.MouseSource disconnected."; + }); +} PointerEventsHandler::~PointerEventsHandler() = default;
diff --git a/ui/gfx/geometry/rect_conversions.h b/ui/gfx/geometry/rect_conversions.h index a16a070..8ac6907 100644 --- a/ui/gfx/geometry/rect_conversions.h +++ b/ui/gfx/geometry/rect_conversions.h
@@ -10,7 +10,9 @@ namespace gfx { -// Returns the smallest Rect that encloses the given RectF. +// Returns the smallest Rect that encloses the given RectF if possible. +// The returned Rect is larger than or equal to the input RectF, unless the +// the geometry values exceed int range and are clamped to int. GEOMETRY_EXPORT Rect ToEnclosingRect(const RectF& rect); // Similar to ToEnclosingRect(), but for each edge, if the distance between the @@ -21,7 +23,10 @@ GEOMETRY_EXPORT Rect ToEnclosingRectIgnoringError(const RectF& rect, float error); -// Returns the largest Rect that is enclosed by the given RectF. +// Returns the largest Rect that is enclosed by the given RectF if possible. +// The returned rect is smaller than or equal to the input rect, but if +// the input RectF is too small and no enclosed Rect exists, the returned +// rect is an empty Rect at |ToCeiledPoint(rect.origin())|. GEOMETRY_EXPORT Rect ToEnclosedRect(const RectF& rect); // Similar to ToEnclosedRect(), but for each edge, if the distance between the
diff --git a/ui/ozone/platform/scenic/scenic_window.cc b/ui/ozone/platform/scenic/scenic_window.cc index cf2036c..07685039 100644 --- a/ui/ozone/platform/scenic/scenic_window.cc +++ b/ui/ozone/platform/scenic/scenic_window.cc
@@ -54,35 +54,71 @@ view_ref_(std::move(properties.view_ref_pair.view_ref)), view_controller_(std::move(properties.view_controller)), event_dispatcher_(this), - scenic_session_(manager_->GetScenic()), - safe_presenter_(&scenic_session_), - view_(&scenic_session_, - std::move(std::move(properties.view_token)), - std::move(properties.view_ref_pair.control_ref), - CloneViewRef(), - "chromium window"), - node_(&scenic_session_), - input_node_(&scenic_session_), - render_node_(&scenic_session_), bounds_(delegate_->ConvertRectToPixels(properties.bounds)) { + { + // Send graphics and input endpoints to Scenic. The endpoints are dormant + // until the Session's Present call, at the bottom of this block. + fuchsia::ui::scenic::SessionEndpoints endpoints; + fuchsia::ui::scenic::SessionPtr session_ptr; + endpoints.set_session(session_ptr.NewRequest()); + fuchsia::ui::scenic::SessionListenerHandle listener_handle; + auto listener_request = listener_handle.NewRequest(); + endpoints.set_session_listener(std::move(listener_handle)); + fuchsia::ui::pointer::TouchSourceHandle touch_source; + endpoints.set_touch_source(touch_source.NewRequest()); + fuchsia::ui::pointer::MouseSourceHandle mouse_source; + endpoints.set_mouse_source(mouse_source.NewRequest()); + endpoints.set_view_ref_focused(view_ref_focused_.NewRequest()); + manager_->GetScenic()->CreateSessionT(std::move(endpoints), [] {}); + + // Set up pointer and focus event processors. + pointer_handler_.emplace(std::move(touch_source), std::move(mouse_source)); + pointer_handler_->StartWatching(base::BindRepeating( + &ScenicWindow::DispatchEvent, + // This is safe since |pointer_handler_| is a class member. + base::Unretained(this))); + + view_ref_focused_->Watch( + fit::bind_member(this, &ScenicWindow::OnViewRefFocusedWatchResult)); + view_ref_focused_.set_error_handler([](zx_status_t status) { + ZX_LOG(ERROR, status) << "Focus listener disconnected."; + }); + + // Set up GFX Session and scene resources. + scenic_session_.emplace(std::move(session_ptr), + std::move(listener_request)); + scenic_session_->set_error_handler( + fit::bind_member(this, &ScenicWindow::OnScenicError)); + scenic_session_->set_event_handler( + fit::bind_member(this, &ScenicWindow::OnScenicEvents)); + scenic_session_->SetDebugName("Chromium ScenicWindow"); + + view_.emplace(&scenic_session_.value(), + std::move(std::move(properties.view_token)), + std::move(properties.view_ref_pair.control_ref), + CloneViewRef(), "chromium window"); + + node_.emplace(&scenic_session_.value()); + + // Subscribe to metrics events from the node. Metrics events provide the + // device pixel ratio for the screen. + node_->SetEventMask(fuchsia::ui::gfx::kMetricsEventMask); + + // To receive metrics events on this node, attach it to the scene graph. + view_->AddChild(*node_); + + input_node_.emplace(&scenic_session_.value()); + render_node_.emplace(&scenic_session_.value()); + + safe_presenter_.emplace(&scenic_session_.value()); + safe_presenter_->QueuePresent(); + } + if (view_controller_) { view_controller_.set_error_handler( fit::bind_member(this, &ScenicWindow::OnViewControllerDisconnected)); } - scenic_session_.set_error_handler( - fit::bind_member(this, &ScenicWindow::OnScenicError)); - scenic_session_.set_event_handler( - fit::bind_member(this, &ScenicWindow::OnScenicEvents)); - scenic_session_.SetDebugName("Chromium ScenicWindow"); - - // Subscribe to metrics events from the node. These events are used to - // get the device pixel ratio for the screen. In order to receive metrics - // events on this node, we must also attach it to the scene graph. - node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask); - view_.AddChild(node_); - safe_presenter_.QueuePresent(); - delegate_->OnAcceleratedWidgetAvailable(window_id_); if (properties.enable_keyboard) { @@ -144,7 +180,7 @@ // Call Present2() to ensure that the scenic session commands are processed, // which is necessary to receive metrics event from Scenic. - safe_presenter_.QueuePresent(); + safe_presenter_->QueuePresent(); } void ScenicWindow::Hide() { @@ -269,7 +305,7 @@ void ScenicWindow::AttachSurfaceView( fuchsia::ui::views::ViewHolderToken token) { surface_view_holder_ = std::make_unique<scenic::ViewHolder>( - &scenic_session_, std::move(token), "chromium window surface"); + &scenic_session_.value(), std::move(token), "chromium window surface"); // Configure the ViewHolder not to be focusable, or hit-testable, to ensure // that it cannot receive input. @@ -280,10 +316,10 @@ surface_view_holder_->SetHitTestBehavior( fuchsia::ui::gfx::HitTestBehavior::kSuppress); - render_node_.DetachChildren(); - render_node_.AddChild(*surface_view_holder_); + render_node_->DetachChildren(); + render_node_->AddChild(*surface_view_holder_); - safe_presenter_.QueuePresent(); + safe_presenter_->QueuePresent(); } void ScenicWindow::DispatchEvent(ui::Event* event) { @@ -307,31 +343,31 @@ if (event.is_gfx()) { switch (event.gfx().Which()) { case fuchsia::ui::gfx::Event::kMetrics: { - if (event.gfx().metrics().node_id != node_.id()) + if (event.gfx().metrics().node_id != node_->id()) continue; OnViewMetrics(event.gfx().metrics().metrics); break; } case fuchsia::ui::gfx::Event::kViewPropertiesChanged: { - DCHECK(event.gfx().view_properties_changed().view_id == view_.id()); + DCHECK(event.gfx().view_properties_changed().view_id == view_->id()); OnViewProperties(event.gfx().view_properties_changed().properties); break; } case fuchsia::ui::gfx::Event::kViewAttachedToScene: { - DCHECK(event.gfx().view_attached_to_scene().view_id == view_.id()); + DCHECK(event.gfx().view_attached_to_scene().view_id == view_->id()); OnViewAttachedChanged(true); break; } case fuchsia::ui::gfx::Event::kViewDetachedFromScene: { - DCHECK(event.gfx().view_detached_from_scene().view_id == view_.id()); + DCHECK(event.gfx().view_detached_from_scene().view_id == view_->id()); OnViewAttachedChanged(false); // Detach the surface view. This is necessary to ensure that the // current content doesn't become visible when the view is attached // again. - render_node_.DetachChildren(); + render_node_->DetachChildren(); surface_view_holder_.reset(); - safe_presenter_.QueuePresent(); + safe_presenter_->QueuePresent(); // Destroy and recreate AcceleratedWidget. This will force the // compositor drop the current LayerTreeFrameSink together with the @@ -386,6 +422,14 @@ } } +void ScenicWindow::OnViewRefFocusedWatchResult( + fuchsia::ui::views::FocusState focus_state) { + delegate_->OnActivationChanged(focus_state.focused()); + + view_ref_focused_->Watch( + fit::bind_member(this, &ScenicWindow::OnViewRefFocusedWatchResult)); +} + void ScenicWindow::UpdateSize() { DCHECK_GT(device_pixel_ratio_, 0.0); DCHECK(view_properties_); @@ -406,18 +450,18 @@ // Translate the node by half of the view dimensions to put it in the center // of the view. - node_.SetTranslation(width / 2.0, height / 2.0, 0.f); + node_->SetTranslation(width / 2.0, height / 2.0, 0.f); // Scale the render node so that surface rect can always be 1x1. - render_node_.SetScale(width, height, 1.f); + render_node_->SetScale(width, height, 1.f); // Resize input node to cover the whole surface. - scenic::Rectangle window_rect(&scenic_session_, width, height); - input_node_.SetShape(window_rect); + scenic::Rectangle window_rect(&scenic_session_.value(), width, height); + input_node_->SetShape(window_rect); // This is necessary when using vulkan because ImagePipes are presented // separately and we need to make sure our sizes change is committed. - safe_presenter_.QueuePresent(); + safe_presenter_->QueuePresent(); PlatformWindowDelegate::BoundsChange bounds(old_origin != bounds_.origin()); bounds.system_ui_overlap = @@ -431,10 +475,10 @@ is_root_node_shown_ = should_show_root_node; if (should_show_root_node) { // Attach nodes to render content and receive input. - node_.AddChild(input_node_); - node_.AddChild(render_node_); + node_->AddChild(*input_node_); + node_->AddChild(*render_node_); } else { - node_.DetachChildren(); + node_->DetachChildren(); } } return is_root_node_shown_;
diff --git a/ui/ozone/platform/scenic/scenic_window.h b/ui/ozone/platform/scenic/scenic_window.h index 640f3f0..5eeecf96 100644 --- a/ui/ozone/platform/scenic/scenic_window.h +++ b/ui/ozone/platform/scenic/scenic_window.h
@@ -19,6 +19,7 @@ #include "ui/base/ime/fuchsia/keyboard_client.h" #include "ui/events/fuchsia/input_event_dispatcher.h" #include "ui/events/fuchsia/input_event_sink.h" +#include "ui/events/fuchsia/pointer_events_handler.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" @@ -111,6 +112,9 @@ // Called from OnScenicEvents() to handle focus change and input events. void OnInputEvent(const fuchsia::ui::input::InputEvent& event); + // Hanging gets from |view_ref_focused_|. + void OnViewRefFocusedWatchResult(fuchsia::ui::views::FocusState focus_state); + // Sizes the Scenic nodes based on the View dimensions, and device pixel // ratio, and signals the dimensions change to the window delegate. void UpdateSize(); @@ -148,23 +152,29 @@ fuchsia::ui::input3::KeyboardPtr keyboard_service_; std::unique_ptr<KeyboardClient> keyboard_client_; + // React to view-focus coming and going. + fuchsia::ui::views::ViewRefFocusedPtr view_ref_focused_; + + // Accept touch and mouse events. + absl::optional<PointerEventsHandler> pointer_handler_; + // Scenic session used for all drawing operations in this View. - scenic::Session scenic_session_; + absl::optional<scenic::Session> scenic_session_; // Used for safely queueing Present() operations on |scenic_session_|. - SafePresenter safe_presenter_; + absl::optional<SafePresenter> safe_presenter_; // The view resource in |scenic_session_|. - scenic::View view_; + absl::optional<scenic::View> view_; // Entity node for the |view_|. - scenic::EntityNode node_; + absl::optional<scenic::EntityNode> node_; // Node in |scenic_session_| for receiving input that hits within our View. - scenic::ShapeNode input_node_; + absl::optional<scenic::ShapeNode> input_node_; // Node in |scenic_session_| for rendering (hit testing disabled). - scenic::EntityNode render_node_; + absl::optional<scenic::EntityNode> render_node_; // Holds the View into which the GPU processes composites the window's // contents.
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc index 8696474b..16b10eae 100644 --- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc
@@ -6,7 +6,6 @@ #include <aura-shell-client-protocol.h> #include <xdg-decoration-unstable-v1-client-protocol.h> -#include <xdg-shell-client-protocol.h> #include <xdg-shell-unstable-v6-client-protocol.h> #include "base/logging.h" @@ -99,12 +98,16 @@ } static constexpr xdg_toplevel_listener xdg_toplevel_listener = { - &ConfigureTopLevel, - &CloseTopLevel, - // Since v4 - &ConfigureBounds, - // Since v5 - &WmCapabilities, + &ConfigureTopLevel, + &CloseTopLevel, +#if defined(XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) + // Since v4 + &ConfigureBounds, +#endif +#if defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) + // Since v5 + &WmCapabilities, +#endif }; if (!xdg_surface_wrapper_) @@ -338,6 +341,7 @@ surface->wayland_window_->OnCloseRequest(); } +#if defined(XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) // static void XDGToplevelWrapperImpl::ConfigureBounds(void* data, struct xdg_toplevel* xdg_toplevel, @@ -345,13 +349,16 @@ int32_t height) { NOTIMPLEMENTED_LOG_ONCE(); } +#endif +#if defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) // static void XDGToplevelWrapperImpl::WmCapabilities(void* data, struct xdg_toplevel* xdg_toplevel, struct wl_array* capabilities) { NOTIMPLEMENTED_LOG_ONCE(); } +#endif void XDGToplevelWrapperImpl::SetTopLevelDecorationMode( DecorationMode requested_mode) {
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h index ab11ae0..47d2e2e 100644 --- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
@@ -5,6 +5,7 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_XDG_TOPLEVEL_WRAPPER_IMPL_H_ #define UI_OZONE_PLATFORM_WAYLAND_HOST_XDG_TOPLEVEL_WRAPPER_IMPL_H_ +#include <xdg-shell-client-protocol.h> #include <memory> #include "base/memory/raw_ptr.h" @@ -72,13 +73,19 @@ int32_t height, struct wl_array* states); static void CloseTopLevel(void* data, struct xdg_toplevel* xdg_toplevel); + +#if defined(XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) static void ConfigureBounds(void* data, struct xdg_toplevel* xdg_toplevel, int32_t width, int32_t height); +#endif + +#if defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) static void WmCapabilities(void* data, struct xdg_toplevel* xdg_toplevel, struct wl_array* capabilities); +#endif // zxdg_decoration_listener static void ConfigureDecoration(
diff --git a/ui/ozone/platform/wayland/test/wayland_test.h b/ui/ozone/platform/wayland/test/wayland_test.h index 90454fe3..2a14045 100644 --- a/ui/ozone/platform/wayland/test/wayland_test.h +++ b/ui/ozone/platform/wayland/test/wayland_test.h
@@ -82,8 +82,9 @@ std::unique_ptr<WaylandScreen> screen_; std::unique_ptr<WaylandWindow> window_; gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget; - std::vector<base::Feature> enabled_features_{ui::kWaylandOverlayDelegation}; - std::vector<base::Feature> disabled_features_; + std::vector<base::test::FeatureRef> enabled_features_{ + ui::kWaylandOverlayDelegation}; + std::vector<base::test::FeatureRef> disabled_features_; private: bool initialized_ = false;
diff --git a/ui/shell_dialogs/base_shell_dialog_win.cc b/ui/shell_dialogs/base_shell_dialog_win.cc index b960f3fb..aa20fab4 100644 --- a/ui/shell_dialogs/base_shell_dialog_win.cc +++ b/ui/shell_dialogs/base_shell_dialog_win.cc
@@ -78,7 +78,6 @@ return run_state; } -// static void BaseShellDialogImpl::EndRun(std::unique_ptr<RunState> run_state) { if (run_state->owner) { DCHECK(IsRunningDialogForOwner(run_state->owner)); @@ -88,8 +87,7 @@ } } -// static -bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) { +bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const { return (owner && GetOwners().find(owner) != GetOwners().end()); }
diff --git a/ui/shell_dialogs/base_shell_dialog_win.h b/ui/shell_dialogs/base_shell_dialog_win.h index 7aec2865..404a117 100644 --- a/ui/shell_dialogs/base_shell_dialog_win.h +++ b/ui/shell_dialogs/base_shell_dialog_win.h
@@ -59,21 +59,21 @@ scoped_refptr<base::SingleThreadTaskRunner> dialog_task_runner; }; - // Cleans up after a dialog run. If the run_state has a valid HWND this makes - // sure that the window is enabled. This is essential because BeginRun - // aggressively guards against multiple modal dialogs per HWND. Must be called - // on the UI thread after the result of the dialog has been determined. - static void EndRun(std::unique_ptr<RunState> run_state); - - // Returns true if a modal shell dialog is currently active for the specified - // owner. Must be called on the UI thread. - static bool IsRunningDialogForOwner(HWND owner); - // Called at the beginning of a modal dialog run. Disables the owner window // and tracks it. Returns the dedicated single-threaded sequence that the // dialog will be run on. std::unique_ptr<RunState> BeginRun(HWND owner); + // Cleans up after a dialog run. If the run_state has a valid HWND this makes + // sure that the window is enabled. This is essential because BeginRun + // aggressively guards against multiple modal dialogs per HWND. Must be called + // on the UI thread after the result of the dialog has been determined. + void EndRun(std::unique_ptr<RunState> run_state); + + // Returns true if a modal shell dialog is currently active for the specified + // owner. Must be called on the UI thread. + bool IsRunningDialogForOwner(HWND owner) const; + private: typedef std::set<HWND> Owners;
diff --git a/ui/shell_dialogs/select_file_dialog.cc b/ui/shell_dialogs/select_file_dialog.cc index 0101272..6260f90 100644 --- a/ui/shell_dialogs/select_file_dialog.cc +++ b/ui/shell_dialogs/select_file_dialog.cc
@@ -86,14 +86,12 @@ } // static -std::unique_ptr<SelectFileDialog> SelectFileDialog::Create( +scoped_refptr<SelectFileDialog> SelectFileDialog::Create( Listener* listener, - std::unique_ptr<SelectFilePolicy> policy) { - if (dialog_factory_) { - return base::WrapUnique( - dialog_factory_->Create(listener, std::move(policy))); - } - return base::WrapUnique(CreateSelectFileDialog(listener, std::move(policy))); + std::unique_ptr<ui::SelectFilePolicy> policy) { + if (dialog_factory_) + return dialog_factory_->Create(listener, std::move(policy)); + return CreateSelectFileDialog(listener, std::move(policy)); } base::FilePath SelectFileDialog::GetShortenedFilePath( @@ -128,7 +126,6 @@ gfx::NativeWindow owning_window, void* params, const GURL* caller) { - CheckCalledOnValidSequence(); DCHECK(listener_); if (select_file_policy_.get() && @@ -139,8 +136,8 @@ // Post a task rather than calling FileSelectionCanceled directly to ensure // that the listener is called asynchronously. base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&SelectFileDialog::CancelFileSelection, - AsWeakPtr(), params)); + FROM_HERE, + base::BindOnce(&SelectFileDialog::CancelFileSelection, this, params)); return; } @@ -161,12 +158,9 @@ DCHECK(listener_); } -SelectFileDialog::~SelectFileDialog() { - CheckCalledOnValidSequence(); -} +SelectFileDialog::~SelectFileDialog() {} void SelectFileDialog::CancelFileSelection(void* params) { - CheckCalledOnValidSequence(); if (listener_) listener_->FileSelectionCanceled(params); }
diff --git a/ui/shell_dialogs/select_file_dialog.h b/ui/shell_dialogs/select_file_dialog.h index 5558f30..cff3cfc2 100644 --- a/ui/shell_dialogs/select_file_dialog.h +++ b/ui/shell_dialogs/select_file_dialog.h
@@ -11,8 +11,7 @@ #include "base/files/file_path.h" #include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/sequence_checker.h" +#include "base/memory/ref_counted.h" #include "ui/gfx/native_widget_types.h" #include "ui/shell_dialogs/base_shell_dialog.h" #include "ui/shell_dialogs/shell_dialogs_export.h" @@ -27,7 +26,7 @@ // Shows a dialog box for selecting a file or a folder. class SHELL_DIALOGS_EXPORT SelectFileDialog - : public base::SupportsWeakPtr<SelectFileDialog>, + : public base::RefCountedThreadSafe<SelectFileDialog>, public BaseShellDialog { public: enum Type { @@ -110,14 +109,14 @@ // // The lifetime of the Listener is not managed by this class. The calling // code should call always ListenerDestroyed() (on the base class - // BaseShellDialog) when the listener is destroyed. - static std::unique_ptr<SelectFileDialog> Create( + // BaseShellDialog) when the listener is destroyed since the SelectFileDialog + // is refcounted and uses a background thread. + static scoped_refptr<SelectFileDialog> Create( Listener* listener, std::unique_ptr<SelectFilePolicy> policy); SelectFileDialog(const SelectFileDialog&) = delete; SelectFileDialog& operator=(const SelectFileDialog&) = delete; - ~SelectFileDialog() override; // Holds information about allowed extensions on a file save dialog. struct SHELL_DIALOGS_EXPORT FileTypeInfo { @@ -212,8 +211,11 @@ bool HasMultipleFileTypeChoices(); protected: + friend class base::RefCountedThreadSafe<SelectFileDialog>; + explicit SelectFileDialog(Listener* listener, std::unique_ptr<SelectFilePolicy> policy); + ~SelectFileDialog() override; // Displays the actual file-selection dialog. // This is overridden in the platform-specific descendants of FileSelectDialog @@ -230,18 +232,15 @@ void* params, const GURL* caller) = 0; - // SelectFileDialog and each platform implementation should be accessed only - // in the main thread. Implementations often use background threads to - // interface with the system or for IO, but the SelectFileDialog uses - // unique_ptr and WeakPtr, which are only guaranteed to be valid in the thread - // that constructed it (main thread). - void CheckCalledOnValidSequence() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - } // The listener to be notified of selection completion. raw_ptr<Listener> listener_; private: + // Tests if the file selection dialog can be displayed by + // testing if the AllowFileSelectionDialogs-Policy is + // either unset or set to true. + bool CanOpenSelectFileDialog(); + // Informs the |listener_| that the file selection dialog was canceled. Moved // to a function for being able to post it to the message loop. void CancelFileSelection(void* params); @@ -249,8 +248,6 @@ // Returns true if the dialog has multiple file type choices. virtual bool HasMultipleFileTypeChoicesImpl() = 0; - SEQUENCE_CHECKER(sequence_checker_); - std::unique_ptr<SelectFilePolicy> select_file_policy_; };
diff --git a/ui/shell_dialogs/select_file_dialog_android.cc b/ui/shell_dialogs/select_file_dialog_android.cc index 7fe6118..4b2b8932d 100644 --- a/ui/shell_dialogs/select_file_dialog_android.cc +++ b/ui/shell_dialogs/select_file_dialog_android.cc
@@ -108,7 +108,6 @@ } void SelectFileDialogImpl::ListenerDestroyed() { - CheckCalledOnValidSequence(); listener_ = nullptr; } @@ -122,7 +121,6 @@ gfx::NativeWindow owning_window, void* params, const GURL* caller) { - CheckCalledOnValidSequence(); JNIEnv* env = base::android::AttachCurrentThread(); // The first element in the pair is a list of accepted types, the second
diff --git a/ui/shell_dialogs/select_file_dialog_lacros.cc b/ui/shell_dialogs/select_file_dialog_lacros.cc index 779803a8..2c3d56a 100644 --- a/ui/shell_dialogs/select_file_dialog_lacros.cc +++ b/ui/shell_dialogs/select_file_dialog_lacros.cc
@@ -7,7 +7,6 @@ #include <utility> #include "base/bind.h" -#include "base/memory/weak_ptr.h" #include "base/notreached.h" #include "chromeos/crosapi/mojom/select_file.mojom-shared.h" #include "chromeos/crosapi/mojom/select_file.mojom.h" @@ -122,7 +121,6 @@ gfx::NativeWindow owning_window, void* params, const GURL* caller) { - CheckCalledOnValidSequence(); params_ = params; crosapi::mojom::SelectFileOptionsPtr options = @@ -154,15 +152,13 @@ chromeos::LacrosService::Get() ->GetRemote<crosapi::mojom::SelectFile>() ->Select(std::move(options), - base::BindOnce(&SelectFileDialogLacros::OnSelected, - base::AsWeakPtr(this))); + base::BindOnce(&SelectFileDialogLacros::OnSelected, this)); } void SelectFileDialogLacros::OnSelected( crosapi::mojom::SelectFileResult result, std::vector<crosapi::mojom::SelectedFileInfoPtr> mojo_files, int file_type_index) { - CheckCalledOnValidSequence(); owning_shell_window_id_.clear(); if (!listener_) return;
diff --git a/ui/shell_dialogs/select_file_dialog_linux_kde.cc b/ui/shell_dialogs/select_file_dialog_linux_kde.cc index ce6ef04..b4b7704 100644 --- a/ui/shell_dialogs/select_file_dialog_linux_kde.cc +++ b/ui/shell_dialogs/select_file_dialog_linux_kde.cc
@@ -10,9 +10,6 @@ #include "base/callback_helpers.h" #include "base/command_line.h" #include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_refptr.h" -#include "base/memory/weak_ptr.h" #include "base/nix/mime_util_xdg.h" #include "base/nix/xdg_util.h" #include "base/process/launch.h" @@ -102,9 +99,6 @@ int exit_code; }; - using RefCountedKDialogOutputParams = - base::RefCountedData<KDialogOutputParams>; - // Get the filters from |file_types_| and concatenate them into // |filter_string|. std::string GetMimeTypeFilterString(); @@ -119,8 +113,8 @@ base::CommandLine* command_line); // Call KDialog on the FILE thread and return the results. - void CallKDialogOutput(const KDialogParams& params, - scoped_refptr<RefCountedKDialogOutputParams>); + std::unique_ptr<KDialogOutputParams> CallKDialogOutput( + const KDialogParams& params); // Notifies the listener that a single file was chosen. void FileSelected(const base::FilePath& path, void* params); @@ -157,23 +151,22 @@ // Common function for OnSelectSingleFileDialogResponse and // OnSelectSingleFolderDialogResponse. - void SelectSingleFileHelper( - void* params, - bool allow_folder, - scoped_refptr<RefCountedKDialogOutputParams> results); + void SelectSingleFileHelper(void* params, + bool allow_folder, + std::unique_ptr<KDialogOutputParams> results); void OnSelectSingleFileDialogResponse( gfx::AcceleratedWidget parent, void* params, - scoped_refptr<RefCountedKDialogOutputParams> results); + std::unique_ptr<KDialogOutputParams> results); void OnSelectMultiFileDialogResponse( gfx::AcceleratedWidget parent, void* params, - scoped_refptr<RefCountedKDialogOutputParams> results); + std::unique_ptr<KDialogOutputParams> results); void OnSelectSingleFolderDialogResponse( gfx::AcceleratedWidget parent, void* params, - scoped_refptr<RefCountedKDialogOutputParams> results); + std::unique_ptr<KDialogOutputParams> results); // Should be either DESKTOP_ENVIRONMENT_KDE3, KDE4, or KDE5. base::nix::DesktopEnvironment desktop_; @@ -385,9 +378,8 @@ return base::JoinString(filters, "|"); } -void SelectFileDialogLinuxKde::CallKDialogOutput( - const KDialogParams& params, - scoped_refptr<RefCountedKDialogOutputParams> results) { +std::unique_ptr<SelectFileDialogLinuxKde::KDialogOutputParams> +SelectFileDialogLinuxKde::CallKDialogOutput(const KDialogParams& params) { DCHECK(pipe_task_runner_->RunsTasksInCurrentSequence()); base::CommandLine::StringVector cmd_vector; cmd_vector.push_back(kKdialogBinary); @@ -396,11 +388,13 @@ params.parent, params.file_operation, params.multiple_selection, &command_line); - // Get output from KDialog - base::GetAppOutputWithExitCode(command_line, &results->data.output, - &results->data.exit_code); - if (!results->data.output.empty()) - results->data.output.erase(results->data.output.size() - 1); + auto results = std::make_unique<KDialogOutputParams>(); + // Get output from KDialog + base::GetAppOutputWithExitCode(command_line, &results->output, + &results->exit_code); + if (!results->output.empty()) + results->output.erase(results->output.size() - 1); + return results; } void SelectFileDialogLinuxKde::GetKDialogCommandLine( @@ -481,20 +475,17 @@ int title_message_id = (type == SELECT_UPLOAD_FOLDER) ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE : IDS_SELECT_FOLDER_DIALOG_TITLE; - scoped_refptr<RefCountedKDialogOutputParams> results = - base::MakeRefCounted<RefCountedKDialogOutputParams>(); - pipe_task_runner_->PostTaskAndReply( + pipe_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce( - &SelectFileDialogLinuxKde::CallKDialogOutput, base::AsWeakPtr(this), + &SelectFileDialogLinuxKde::CallKDialogOutput, this, KDialogParams( "--getexistingdirectory", GetTitle(title, title_message_id), default_path.empty() ? *last_opened_path() : default_path, parent, - false, false), - results), + false, false)), base::BindOnce( - &SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse, - base::AsWeakPtr(this), parent, params, results)); + &SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse, this, + parent, params)); } void SelectFileDialogLinuxKde::CreateFileOpenDialog( @@ -502,20 +493,17 @@ const base::FilePath& default_path, gfx::AcceleratedWidget parent, void* params) { - scoped_refptr<RefCountedKDialogOutputParams> results = - base::MakeRefCounted<RefCountedKDialogOutputParams>(); - pipe_task_runner_->PostTaskAndReply( + pipe_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce( - &SelectFileDialogLinuxKde::CallKDialogOutput, base::AsWeakPtr(this), + &SelectFileDialogLinuxKde::CallKDialogOutput, this, KDialogParams( "--getopenfilename", GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE), default_path.empty() ? *last_opened_path() : default_path, parent, - true, false), - results), + true, false)), base::BindOnce( - &SelectFileDialogLinuxKde::OnSelectSingleFileDialogResponse, - base::AsWeakPtr(this), parent, params, results)); + &SelectFileDialogLinuxKde::OnSelectSingleFileDialogResponse, this, + parent, params)); } void SelectFileDialogLinuxKde::CreateMultiFileOpenDialog( @@ -523,19 +511,16 @@ const base::FilePath& default_path, gfx::AcceleratedWidget parent, void* params) { - scoped_refptr<RefCountedKDialogOutputParams> results = - base::MakeRefCounted<RefCountedKDialogOutputParams>(); - pipe_task_runner_->PostTaskAndReply( + pipe_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce( - &SelectFileDialogLinuxKde::CallKDialogOutput, base::AsWeakPtr(this), + &SelectFileDialogLinuxKde::CallKDialogOutput, this, KDialogParams( "--getopenfilename", GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE), default_path.empty() ? *last_opened_path() : default_path, parent, - true, true), - results), + true, true)), base::BindOnce(&SelectFileDialogLinuxKde::OnSelectMultiFileDialogResponse, - base::AsWeakPtr(this), parent, params, results)); + this, parent, params)); } void SelectFileDialogLinuxKde::CreateSaveAsDialog( @@ -543,33 +528,30 @@ const base::FilePath& default_path, gfx::AcceleratedWidget parent, void* params) { - scoped_refptr<RefCountedKDialogOutputParams> results = - base::MakeRefCounted<RefCountedKDialogOutputParams>(); - pipe_task_runner_->PostTaskAndReply( + pipe_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce( - &SelectFileDialogLinuxKde::CallKDialogOutput, base::AsWeakPtr(this), + &SelectFileDialogLinuxKde::CallKDialogOutput, this, KDialogParams( "--getsavefilename", GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE), default_path.empty() ? *last_saved_path() : default_path, parent, - true, false), - results), + true, false)), base::BindOnce( - &SelectFileDialogLinuxKde::OnSelectSingleFileDialogResponse, - base::AsWeakPtr(this), parent, params, results)); + &SelectFileDialogLinuxKde::OnSelectSingleFileDialogResponse, this, + parent, params)); } void SelectFileDialogLinuxKde::SelectSingleFileHelper( void* params, bool allow_folder, - scoped_refptr<RefCountedKDialogOutputParams> results) { - VLOG(1) << "[kdialog] SingleFileResponse: " << results->data.output; - if (results->data.exit_code || results->data.output.empty()) { + std::unique_ptr<KDialogOutputParams> results) { + VLOG(1) << "[kdialog] SingleFileResponse: " << results->output; + if (results->exit_code || results->output.empty()) { FileNotSelected(params); return; } - base::FilePath path(results->data.output); + base::FilePath path(results->output); if (allow_folder) { FileSelected(path, params); return; @@ -584,7 +566,7 @@ void SelectFileDialogLinuxKde::OnSelectSingleFileDialogResponse( gfx::AcceleratedWidget parent, void* params, - scoped_refptr<RefCountedKDialogOutputParams> results) { + std::unique_ptr<KDialogOutputParams> results) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); parents_.erase(parent); SelectSingleFileHelper(params, false, std::move(results)); @@ -593,7 +575,7 @@ void SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse( gfx::AcceleratedWidget parent, void* params, - scoped_refptr<RefCountedKDialogOutputParams> results) { + std::unique_ptr<KDialogOutputParams> results) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); parents_.erase(parent); SelectSingleFileHelper(params, true, std::move(results)); @@ -602,20 +584,20 @@ void SelectFileDialogLinuxKde::OnSelectMultiFileDialogResponse( gfx::AcceleratedWidget parent, void* params, - scoped_refptr<RefCountedKDialogOutputParams> results) { + std::unique_ptr<KDialogOutputParams> results) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - VLOG(1) << "[kdialog] MultiFileResponse: " << results->data.output; + VLOG(1) << "[kdialog] MultiFileResponse: " << results->output; parents_.erase(parent); - if (results->data.exit_code || results->data.output.empty()) { + if (results->exit_code || results->output.empty()) { FileNotSelected(params); return; } std::vector<base::FilePath> filenames_fp; for (const base::StringPiece& line : - base::SplitStringPiece(results->data.output, "\n", base::KEEP_WHITESPACE, + base::SplitStringPiece(results->output, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { base::FilePath path(line); if (CallDirectoryExistsOnUIThread(path))
diff --git a/ui/shell_dialogs/select_file_dialog_linux_portal.cc b/ui/shell_dialogs/select_file_dialog_linux_portal.cc index d1c0e41..b7f6e65 100644 --- a/ui/shell_dialogs/select_file_dialog_linux_portal.cc +++ b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
@@ -7,7 +7,6 @@ #include "base/containers/contains.h" #include "base/functional/bind.h" #include "base/logging.h" -#include "base/memory/weak_ptr.h" #include "base/no_destructor.h" #include "base/notreached.h" #include "base/strings/string_piece.h" @@ -202,13 +201,11 @@ gfx::NativeWindow owning_window, void* params, const GURL* caller) { - CheckCalledOnValidSequence(); - auto info = base::MakeRefCounted<DialogInfo>( base::BindOnce(&SelectFileDialogLinuxPortal::CompleteOpenOnMainThread, - base::AsWeakPtr(this)), + this), base::BindOnce(&SelectFileDialogLinuxPortal::CancelOpenOnMainThread, - base::AsWeakPtr(this))); + this)); info_ = info; info->type = type; info->main_task_runner = base::SequencedTaskRunnerHandle::Get(); @@ -236,8 +233,7 @@ *parent_, base::BindOnce( &SelectFileDialogLinuxPortal::SelectFileImplWithParentHandle, - base::AsWeakPtr(this), title, default_path, filter_set, - default_extension))) { + this, title, default_path, filter_set, default_extension))) { // Return early to skip the fallback below. return; } else { @@ -433,7 +429,6 @@ PortalFilterSet filter_set, base::FilePath::StringType default_extension, std::string parent_handle) { - CheckCalledOnValidSequence(); bool default_path_exists = CallDirectoryExistsOnUIThread(default_path); dbus_thread_linux::GetTaskRunner()->PostTask( FROM_HERE, @@ -657,7 +652,6 @@ void SelectFileDialogLinuxPortal::CompleteOpenOnMainThread( std::vector<base::FilePath> paths, std::string current_filter) { - CheckCalledOnValidSequence(); UnparentOnMainThread(); if (listener_) {
diff --git a/ui/shell_dialogs/select_file_dialog_mac.h b/ui/shell_dialogs/select_file_dialog_mac.h index 5047380..98dc5fce 100644 --- a/ui/shell_dialogs/select_file_dialog_mac.h +++ b/ui/shell_dialogs/select_file_dialog_mac.h
@@ -39,8 +39,6 @@ bool IsRunning(gfx::NativeWindow parent_window) const override; void ListenerDestroyed() override; - ~SelectFileDialogImpl() override; - protected: // SelectFileDialog implementation. // |params| is user data we pass back via the Listener interface. @@ -76,6 +74,8 @@ mojo::Remote<remote_cocoa::mojom::SelectFileDialog> select_file_dialog; }; + ~SelectFileDialogImpl() override; + // Callback made when a panel is closed. void FileWasSelected(DialogData* dialog_data, bool is_multi, @@ -94,7 +94,6 @@ // only. base::RepeatingClosure dialog_closed_callback_for_testing_; - // TODO(lucmult): Remove this weak_factory_. base::WeakPtrFactory<SelectFileDialogImpl> weak_factory_; };
diff --git a/ui/shell_dialogs/select_file_dialog_mac.mm b/ui/shell_dialogs/select_file_dialog_mac.mm index ee81ded..3cd217d5 100644 --- a/ui/shell_dialogs/select_file_dialog_mac.mm +++ b/ui/shell_dialogs/select_file_dialog_mac.mm
@@ -39,7 +39,6 @@ } void SelectFileDialogImpl::ListenerDestroyed() { - CheckCalledOnValidSequence(); listener_ = nullptr; }
diff --git a/ui/shell_dialogs/select_file_dialog_mac_unittest.mm b/ui/shell_dialogs/select_file_dialog_mac_unittest.mm index a0a41a7a..cbe810bc0 100644 --- a/ui/shell_dialogs/select_file_dialog_mac_unittest.mm +++ b/ui/shell_dialogs/select_file_dialog_mac_unittest.mm
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <memory> #include "base/memory/raw_ptr.h" #import "ui/shell_dialogs/select_file_dialog_mac.h" @@ -137,14 +136,14 @@ } void ResetDialog() { - dialog_ = std::make_unique<SelectFileDialogImpl>(this, nullptr); + dialog_ = new SelectFileDialogImpl(this, nullptr); // Spin the run loop to get any pending Mojo IPC sent. base::RunLoop().RunUntilIdle(); } private: - std::unique_ptr<SelectFileDialogImpl> dialog_; + scoped_refptr<SelectFileDialogImpl> dialog_; std::vector<base::scoped_nsobject<NSWindow>> parent_windows_; };
diff --git a/ui/shell_dialogs/select_file_dialog_win.cc b/ui/shell_dialogs/select_file_dialog_win.cc index 8071c243..5deb21f 100644 --- a/ui/shell_dialogs/select_file_dialog_win.cc +++ b/ui/shell_dialogs/select_file_dialog_win.cc
@@ -12,7 +12,6 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/i18n/case_conversion.h" -#include "base/memory/weak_ptr.h" #include "base/notreached.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -246,7 +245,6 @@ gfx::NativeWindow owning_window, void* params, const GURL* caller) { - CheckCalledOnValidSequence(); has_multiple_file_type_choices_ = file_types ? file_types->extensions.size() > 1 : true; @@ -266,8 +264,7 @@ filter, file_type_index, default_extension, owner, base::ThreadTaskRunnerHandle::Get(), base::BindOnce(&SelectFileDialogImpl::OnSelectFileExecuted, - base::AsWeakPtr(this), type, - std::move(run_state), params))); + this, type, std::move(run_state), params))); } bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() { @@ -284,7 +281,6 @@ void SelectFileDialogImpl::ListenerDestroyed() { // Our associated listener has gone away, so we shouldn't call back to it if // our worker thread returns after the listener is dead. - CheckCalledOnValidSequence(); listener_ = nullptr; }
diff --git a/ui/shell_dialogs/select_file_dialog_win_unittest.cc b/ui/shell_dialogs/select_file_dialog_win_unittest.cc index dd79a2fe..4527e1f 100644 --- a/ui/shell_dialogs/select_file_dialog_win_unittest.cc +++ b/ui/shell_dialogs/select_file_dialog_win_unittest.cc
@@ -231,7 +231,7 @@ const auto& test_case = kTestCases[i]; - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> file_type_info; @@ -269,7 +269,7 @@ ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); base::FilePath default_path = scoped_temp_dir.GetPath(); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_UPLOAD_FOLDER, std::u16string(), default_path, nullptr, 0, L"", @@ -310,7 +310,7 @@ std::string contents = "Hello test!"; ASSERT_TRUE(base::WriteFile(default_path, contents)); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, kTitle, default_path, nullptr, 0, L"", native_window(), nullptr); @@ -338,7 +338,7 @@ std::string contents = "Hello test!"; ASSERT_TRUE(base::WriteFile(default_path, contents)); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, std::u16string(), default_path, nullptr, 0, L"", native_window(), nullptr); @@ -365,7 +365,7 @@ ui::SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back({L"html"}); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"", native_window(), @@ -389,7 +389,7 @@ ui::SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back({L"html"}); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"", native_window(), @@ -416,7 +416,7 @@ ui::SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back({L"exe"}); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"html", native_window(), @@ -443,7 +443,7 @@ ui::SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back({L"exe"}); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, std::u16string(), default_path, &file_type_info, 1, L"html", native_window(), @@ -466,7 +466,7 @@ base::FilePath default_path = scoped_temp_dir.GetPath().Append(L"does-not-exist.html"); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, std::u16string(), default_path, nullptr, 0, L"", native_window(), nullptr); @@ -502,7 +502,7 @@ ui::SelectFileDialog::FileTypeInfo file_type_info; file_type_info.extensions.push_back({L"txt"}); - std::unique_ptr<ui::SelectFileDialog> dialog = + scoped_refptr<ui::SelectFileDialog> dialog = ui::SelectFileDialog::Create(this, nullptr); dialog->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, std::u16string(), default_path, &file_type_info, 1, L"", native_window(),
diff --git a/ui/webui/resources/images/BUILD.gn b/ui/webui/resources/images/BUILD.gn index 1c69141..de5a14e 100644 --- a/ui/webui/resources/images/BUILD.gn +++ b/ui/webui/resources/images/BUILD.gn
@@ -58,6 +58,7 @@ "icon_expand_less.svg", "icon_expand_more.svg", "icon_folder_open.svg", + "icon_journeys.svg", "icon_more_vert.svg", "icon_picture_delete.svg", "icon_settings.svg",
diff --git a/chrome/browser/resources/history/images/journeys.svg b/ui/webui/resources/images/icon_journeys.svg similarity index 100% rename from chrome/browser/resources/history/images/journeys.svg rename to ui/webui/resources/images/icon_journeys.svg
diff --git a/ui/webui/resources/tools/js_modulizer.gni b/ui/webui/resources/tools/js_modulizer.gni index 4a9d8ce4..6ac60ed7 100644 --- a/ui/webui/resources/tools/js_modulizer.gni +++ b/ui/webui/resources/tools/js_modulizer.gni
@@ -64,11 +64,6 @@ if (defined(invoker.namespace_rewrites)) { args += invoker.namespace_rewrites } - - # TODO(crbug.com/1030998) Remove when File Manager uses JS modules only. - if (defined(invoker.preserve_offsets)) { - args += [ "--preserve_offsets" ] + invoker.preserve_offsets - } } # Appends the compiled outputs of |target_name| to the dependent's
diff --git a/ui/webui/resources/tools/js_modulizer.py b/ui/webui/resources/tools/js_modulizer.py index d1aaf770..642352e 100644 --- a/ui/webui/resources/tools/js_modulizer.py +++ b/ui/webui/resources/tools/js_modulizer.py
@@ -32,14 +32,6 @@ # For example "cr.foo.Bar|Bar" will replace all occurrences of "cr.foo.Bar" # with "Bar". This flag works identically with the one in # polymer_modulizer.gni. -# -# preserve_offsets: -# If present, uses regular expressions for the import and export -# replacements that contain the same number of characters in the input -# and output. This is used to support code coverage tools that map the -# original source files to evaluate coverage and need the character -# offsets to lines of code to remain constant. -# import argparse import io @@ -71,7 +63,7 @@ return string -def ProcessFile(filename, out_folder, namespace_rewrites, preserve_offsets): +def ProcessFile(filename, out_folder, namespace_rewrites): # Gather indices of lines to be removed. indices_to_remove = [] @@ -111,14 +103,8 @@ ignore_remaining_lines = True continue - # TODO(crbug.com/1030998): Remove this option when File Manager gets rid - # of its non JS-module code. - if preserve_offsets: - line = line.replace(EXPORT_LINE_REGEX, '/* */export') - line = line.replace(IMPORT_LINE_REGEX, '/**/import') - else: - line = line.replace(EXPORT_LINE_REGEX, 'export') - line = line.replace(IMPORT_LINE_REGEX, 'import') + line = line.replace(EXPORT_LINE_REGEX, 'export') + line = line.replace(IMPORT_LINE_REGEX, 'import') line = _rewrite_namespaces(line, namespace_rewrites) lines[i] = line @@ -147,7 +133,6 @@ parser.add_argument('--in_folder', required=True) parser.add_argument('--out_folder', required=True) parser.add_argument('--namespace_rewrites', required=False, nargs="*") - parser.add_argument('--preserve_offsets', required=False) args = parser.parse_args(argv) # Extract namespace rewrites from arguments. @@ -157,16 +142,11 @@ before, after = r.split('|') namespace_rewrites[before] = after - preserve_offsets = False - if args.preserve_offsets: - preserve_offsets = True - in_folder = os.path.normpath(os.path.join(_CWD, args.in_folder)) out_folder = os.path.normpath(os.path.join(_CWD, args.out_folder)) for f in args.input_files: - ProcessFile(os.path.join(in_folder, f), out_folder, namespace_rewrites, - preserve_offsets) + ProcessFile(os.path.join(in_folder, f), out_folder, namespace_rewrites) if __name__ == '__main__':
diff --git a/ui/webui/resources/tools/js_modulizer_test.py b/ui/webui/resources/tools/js_modulizer_test.py index a933892..791c73677 100755 --- a/ui/webui/resources/tools/js_modulizer_test.py +++ b/ui/webui/resources/tools/js_modulizer_test.py
@@ -25,8 +25,7 @@ with open (os.path.join(self._out_folder, file_name), 'rb') as f: return f.read() - def _run_test_(self, js_file, js_file_expected, namespace_rewrites=None, - preserve_offsets=False): + def _run_test_(self, js_file, js_file_expected, namespace_rewrites=None): assert not self._out_folder self._out_folder = tempfile.mkdtemp(dir=_HERE_DIR) args = [ @@ -37,9 +36,6 @@ if namespace_rewrites: args += ['--namespace_rewrites'] + namespace_rewrites - if preserve_offsets: - args += ['--preserve_offsets', ['True']] - js_modulizer.main(args) js_out_file = os.path.basename(js_file).replace('.js', '.m.js') @@ -64,10 +60,6 @@ def testSuccess_NonAscii(self): self._run_test_('non_ascii.js', 'non_ascii_expected.js') - def testSuccess_WithPreserveOffsets(self): - self._run_test_('with_preserve_offsets.js', - 'with_preserve_offsets_expected.js', preserve_offsets=True) - if __name__ == '__main__': unittest.main()
diff --git a/ui/webui/resources/tools/tests/with_preserve_offsets.js b/ui/webui/resources/tools/tests/with_preserve_offsets.js deleted file mode 100644 index bc66bdba..0000000 --- a/ui/webui/resources/tools/tests/with_preserve_offsets.js +++ /dev/null
@@ -1,5 +0,0 @@ -// 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. -// #import {Bar} from './module.m.js'; -/* #export */ function foo() {}
diff --git a/ui/webui/resources/tools/tests/with_preserve_offsets_expected.js b/ui/webui/resources/tools/tests/with_preserve_offsets_expected.js deleted file mode 100644 index 252c28c..0000000 --- a/ui/webui/resources/tools/tests/with_preserve_offsets_expected.js +++ /dev/null
@@ -1,5 +0,0 @@ -// 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. -/**/import {Bar} from './module.m.js'; -/* */export function foo() {}
diff --git a/weblayer/browser/file_select_helper.h b/weblayer/browser/file_select_helper.h index 3c952ae2..37d3fef 100644 --- a/weblayer/browser/file_select_helper.h +++ b/weblayer/browser/file_select_helper.h
@@ -90,7 +90,7 @@ scoped_refptr<content::FileSelectListener> listener_; // Dialog box used for choosing files to upload from file form fields. - std::unique_ptr<ui::SelectFileDialog> select_file_dialog_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; // The type of file dialog last shown. ui::SelectFileDialog::Type dialog_type_ =
diff --git a/weblayer/browser/webapps/webapk_install_scheduler.cc b/weblayer/browser/webapps/webapk_install_scheduler.cc index 67c59fd..f11bc698 100644 --- a/weblayer/browser/webapps/webapk_install_scheduler.cc +++ b/weblayer/browser/webapps/webapk_install_scheduler.cc
@@ -113,7 +113,8 @@ // triggered by the Chrome-service, is invoked on the UI thread. webapps::WebappsUtils::ShowWebApkInstallResultToast(result); - std::move(webapps_client_callback_).Run(shortcut_info_->manifest_url); + std::move(webapps_client_callback_) + .Run(shortcut_info_->manifest_url, shortcut_info_->manifest_id); delete this; }
diff --git a/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc b/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc index 7f33be08..f9e3666 100644 --- a/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc +++ b/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc
@@ -178,7 +178,7 @@ net::EmbeddedTestServer test_server_; - void OnInstallFinished(GURL manifest_url) {} + void OnInstallFinished(GURL manifest_url, GURL manifest_id) {} }; // Test building the WebAPK-proto is succeeding.
diff --git a/weblayer/browser/webapps/weblayer_webapps_client.cc b/weblayer/browser/webapps/weblayer_webapps_client.cc index a7786085..bea9f80f 100644 --- a/weblayer/browser/webapps/weblayer_webapps_client.cc +++ b/weblayer/browser/webapps/weblayer_webapps_client.cc
@@ -8,6 +8,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/feature_list.h" #include "base/guid.h" #include "base/logging.h" #include "base/no_destructor.h" @@ -16,6 +17,7 @@ #include "components/security_state/content/content_utils.h" #include "components/webapps/browser/android/add_to_homescreen_params.h" #include "components/webapps/browser/android/shortcut_info.h" +#include "components/webapps/browser/features.h" #include "components/webapps/browser/installable/installable_metrics.h" #include "content/public/browser/browser_context.h" #include "ui/android/color_utils_android.h" @@ -73,7 +75,10 @@ bool WebLayerWebappsClient::IsInstallationInProgress( content::WebContents* web_contents, - const GURL& manifest_url) { + const GURL& manifest_url, + const GURL& manifest_id) { + if (base::FeatureList::IsEnabled(webapps::features::kWebApkUniqueId)) + return current_install_ids_.count(manifest_id); return current_installs_.count(manifest_url) > 0; } @@ -90,6 +95,7 @@ const webapps::AddToHomescreenParams& params) { DCHECK(current_installs_.count(params.shortcut_info->manifest_url) == 0); current_installs_.insert(params.shortcut_info->manifest_url); + current_install_ids_.insert(params.shortcut_info->manifest_id); WebApkInstallScheduler::FetchProtoAndScheduleInstall( web_contents, *(params.shortcut_info), params.primary_icon, params.has_maskable_primary_icon, @@ -107,9 +113,11 @@ params.has_maskable_primary_icon); } -void WebLayerWebappsClient::OnInstallFinished(GURL manifest_url) { +void WebLayerWebappsClient::OnInstallFinished(GURL manifest_url, + GURL manifest_id) { DCHECK(current_installs_.count(manifest_url) == 1); current_installs_.erase(manifest_url); + current_install_ids_.erase(manifest_id); } } // namespace weblayer
diff --git a/weblayer/browser/webapps/weblayer_webapps_client.h b/weblayer/browser/webapps/weblayer_webapps_client.h index 31e96607..1034f44 100644 --- a/weblayer/browser/webapps/weblayer_webapps_client.h +++ b/weblayer/browser/webapps/weblayer_webapps_client.h
@@ -20,7 +20,7 @@ public: // Called when the scheduling of an WebAPK installation with the Chrome // service finished or failed. - using WebApkInstallFinishedCallback = base::OnceCallback<void(GURL)>; + using WebApkInstallFinishedCallback = base::OnceCallback<void(GURL, GURL)>; WebLayerWebappsClient(const WebLayerWebappsClient&) = delete; WebLayerWebappsClient& operator=(const WebLayerWebappsClient&) = delete; @@ -39,7 +39,8 @@ content::WebContents* web_contents) override; #if BUILDFLAG(IS_ANDROID) bool IsInstallationInProgress(content::WebContents* web_contents, - const GURL& manifest_url) override; + const GURL& manifest_url, + const GURL& manifest_id) override; bool CanShowAppBanners(content::WebContents* web_contents) override; void OnWebApkInstallInitiatedFromAppMenu( content::WebContents* web_contents) override; @@ -55,9 +56,10 @@ WebLayerWebappsClient(); ~WebLayerWebappsClient() override; - void OnInstallFinished(GURL manifest_url); + void OnInstallFinished(GURL manifest_url, GURL manifest_id); std::set<GURL> current_installs_; + std::set<GURL> current_install_ids_; // Used to get |weak_ptr_|. base::WeakPtrFactory<WebLayerWebappsClient> weak_ptr_factory_{this};