diff --git a/DEPS b/DEPS index a4d50cd..bde87d6 100644 --- a/DEPS +++ b/DEPS
@@ -195,7 +195,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': '530fc3bb4cbaef1f72f02cf4df64873d96c92090', + 'skia_revision': '039f681a841a5507db74458329e5be64f9edf984', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -207,7 +207,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '48ba75ac6845428971ea2a12bfb69eb85e608409', + 'angle_revision': '8956bfb9c99d9d810022b6054486ed3811f99cb5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -266,7 +266,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': '330914341bd4a018d4a9c0be0ad3e3ac2797d440', + 'devtools_frontend_revision': '12bc13e26d28eecd2846bb424beede9d7095229c', # 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. @@ -875,7 +875,7 @@ # Build tools for Chrome OS. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'fb57bbd19358a5c2f1bb50e8417bd478f83588f9', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a1d5ae72b241aea42dc26e65be8061b68981ce9d', 'condition': 'checkout_chromeos', }, @@ -1248,7 +1248,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a4cba6578f09d606d32fe32bb0a0c6283ea6d198', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '01e0ccdc9b8b4697a343b8ef49f53fd489d79a41', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1465,7 +1465,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '4c2f9c90f42591f0935b496d61ee256ebf53198f', + Var('webrtc_git') + '/src.git' + '@' + '582102c9b7f48f6ccad956fe17241668a90cb3fc', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1537,7 +1537,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0fd4513a30ec4de041c9b39003243d9640b17345', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b27f3f1980fd4f157efb8c1bb7891e6a95e654c2', 'condition': 'checkout_src_internal', }, @@ -1545,7 +1545,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'CUU63VsXItsrBlNDrRhMgCrIBW8n5Lch_BLHRTfvmNUC', + 'version': 'sQ-pH6rZbDHAmfK-kjBe53-R0rfRl9r_ObSKY2g81kUC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/aapt2.config b/android_webview/aapt2.config index c8b63db..b1398da 100644 --- a/android_webview/aapt2.config +++ b/android_webview/aapt2.config
@@ -1,2 +1 @@ -string/license_activity_title#no_obfuscate -drawable/shortcut_incognito#no_obfuscate +string/license_activity_title#no_collapse
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java index e97acb3..538c5a0 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java
@@ -60,6 +60,8 @@ private static final Pattern MAYBE_QUOTED_STRING = Pattern.compile("^(\"?)(.*)\\1$"); + private static boolean sBrowserProcessStarted; + /** * An interface to call onCreateWindow(AwContents). */ @@ -98,6 +100,9 @@ } if (needsBrowserProcessStarted()) { startBrowserProcess(); + } else { + assert !sBrowserProcessStarted + : "needsBrowserProcessStarted false and @Batch are incompatible"; } } @@ -171,7 +176,10 @@ public void startBrowserProcess() { // The Activity must be launched in order for proper webview statics to be setup. launchActivity(); - TestThreadUtils.runOnUiThreadBlocking(() -> AwBrowserProcess.start()); + if (!sBrowserProcessStarted) { + sBrowserProcessStarted = true; + TestThreadUtils.runOnUiThreadBlocking(() -> AwBrowserProcess.start()); + } if (mBrowserContext != null) { TestThreadUtils.runOnUiThreadBlocking( () -> mBrowserContext.setNativePointer(
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java index c765fdb9..e917620 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -39,10 +39,12 @@ import org.chromium.android_webview.test.util.VideoTestWebServer; import org.chromium.base.Callback; import org.chromium.base.FileUtils; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.RequiresRestart; import org.chromium.base.test.util.TestFileUtil; import org.chromium.base.test.util.UrlUtils; import org.chromium.content_public.browser.WebContents; @@ -72,6 +74,7 @@ @RunWith(AwJUnit4ClassRunner.class) @CommandLineFlags.Add({ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1", "enable-features=WebViewOriginCheckForStreamReader"}) +@Batch(Batch.PER_CLASS) public class AwSettingsTest { @Rule public AwActivityTestRule mActivityTestRule = @@ -2851,6 +2854,7 @@ } } + @RequiresRestart("Enabling appcache is global and cannot be reversed.") @Test @SmallTest @Feature({"AndroidWebView", "Preferences", "AppCache"}) @@ -2884,6 +2888,7 @@ } } + @RequiresRestart("Enabling appcache is global and cannot be reversed.") @Test @SmallTest @Feature({"AndroidWebView", "Preferences", "AppCache"})
diff --git a/ash/ambient/ambient_photo_controller.cc b/ash/ambient/ambient_photo_controller.cc index 0f0e456e..0c3b4c5 100644 --- a/ash/ambient/ambient_photo_controller.cc +++ b/ash/ambient/ambient_photo_controller.cc
@@ -323,7 +323,7 @@ } ambient_backend_model_.AppendTopics(screen_update.next_topics); - StartDownloadingWeatherConditionIcon(screen_update); + StartDownloadingWeatherConditionIcon(screen_update.weather_info); } void AmbientPhotoController::TryReadPhotoRawData() { @@ -416,41 +416,45 @@ } void AmbientPhotoController::StartDownloadingWeatherConditionIcon( - const ash::ScreenUpdate& screen_update) { - if (!screen_update.weather_info.has_value()) { + const base::Optional<WeatherInfo>& weather_info) { + if (!weather_info) { LOG(WARNING) << "No weather info included in the response."; return; } + if (!weather_info->temp_f.has_value()) { + LOG(WARNING) << "No temperature included in weather info."; + return; + } + + if (weather_info->condition_icon_url.value_or(std::string()).empty()) { + LOG(WARNING) << "No value found for condition icon url in the weather info " + "response."; + return; + } + // Ideally we should avoid downloading from the same url again to reduce the // overhead, as it's unlikely that the weather condition is changing // frequently during the day. // TODO(meilinw): avoid repeated downloading by caching the last N url hashes, // where N should depend on the icon image size. - const std::string& icon_url = - screen_update.weather_info->condition_icon_url.value_or(std::string()); - if (icon_url.empty()) { - LOG(ERROR) << "No value found for condition icon url in the weather info " - "response."; - return; - } - DownloadImageFromUrl( - icon_url, + weather_info->condition_icon_url.value(), base::BindOnce(&AmbientPhotoController::OnWeatherConditionIconDownloaded, - weak_factory_.GetWeakPtr(), - screen_update.weather_info->temp_f)); + weak_factory_.GetWeakPtr(), weather_info->temp_f.value(), + weather_info->show_celsius)); } void AmbientPhotoController::OnWeatherConditionIconDownloaded( - base::Optional<float> temp_f, + float temp_f, + bool show_celsius, const gfx::ImageSkia& icon) { // For now we only show the weather card when both fields have values. // TODO(meilinw): optimize the behavior with more specific error handling. - if (icon.isNull() || !temp_f.has_value()) + if (icon.isNull()) return; - ambient_backend_model_.UpdateWeatherInfo(icon, temp_f.value()); + ambient_backend_model_.UpdateWeatherInfo(icon, temp_f, show_celsius); } } // namespace ash
diff --git a/ash/ambient/ambient_photo_controller.h b/ash/ambient/ambient_photo_controller.h index cac890b4..2661bb5 100644 --- a/ash/ambient/ambient_photo_controller.h +++ b/ash/ambient/ambient_photo_controller.h
@@ -129,11 +129,12 @@ void OnPhotoDecoded(const gfx::ImageSkia& image); void StartDownloadingWeatherConditionIcon( - const ash::ScreenUpdate& screen_update); + const base::Optional<WeatherInfo>& weather_info); // Invoked upon completion of the weather icon download, |icon| can be a null // image if the download attempt from the url failed. - void OnWeatherConditionIconDownloaded(base::Optional<float> temp_f, + void OnWeatherConditionIconDownloaded(float temp_f, + bool show_celsius, const gfx::ImageSkia& icon); void set_url_loader_for_testing(
diff --git a/ash/ambient/backdrop/ambient_backend_controller_impl.cc b/ash/ambient/backdrop/ambient_backend_controller_impl.cc index 07681d07..9e82b308 100644 --- a/ash/ambient/backdrop/ambient_backend_controller_impl.cc +++ b/ash/ambient/backdrop/ambient_backend_controller_impl.cc
@@ -97,14 +97,20 @@ // Parse |WeatherInfo|. if (backdrop_screen_update.has_weather_info()) { - backdrop::WeatherInfo backdrop_weather_info = - backdrop_screen_update.weather_info(); + const auto& backdrop_weather_info = backdrop_screen_update.weather_info(); ash::WeatherInfo weather_info; - if (backdrop_weather_info.has_condition_icon_url()) + + if (backdrop_weather_info.has_condition_icon_url()) { weather_info.condition_icon_url = backdrop_weather_info.condition_icon_url(); + } + if (backdrop_weather_info.has_temp_f()) weather_info.temp_f = backdrop_weather_info.temp_f(); + + if (backdrop_weather_info.has_show_celsius()) + weather_info.show_celsius = backdrop_weather_info.show_celsius(); + screen_update.weather_info = weather_info; } return screen_update;
diff --git a/ash/ambient/model/ambient_backend_model.cc b/ash/ambient/model/ambient_backend_model.cc index 375d07a..505e2ac 100644 --- a/ash/ambient/model/ambient_backend_model.cc +++ b/ash/ambient/model/ambient_backend_model.cc
@@ -74,11 +74,17 @@ return current_image_; } +float AmbientBackendModel::GetTemperatureInCelsius() const { + return (temperature_fahrenheit_ - 32) * 5 / 9; +} + void AmbientBackendModel::UpdateWeatherInfo( const gfx::ImageSkia& weather_condition_icon, - float temperature) { + float temperature_fahrenheit, + bool show_celsius) { weather_condition_icon_ = weather_condition_icon; - temperature_ = temperature; + temperature_fahrenheit_ = temperature_fahrenheit; + show_celsius_ = show_celsius; if (!weather_condition_icon.isNull()) NotifyWeatherInfoUpdated();
diff --git a/ash/ambient/model/ambient_backend_model.h b/ash/ambient/model/ambient_backend_model.h index 102549d5..35dafd9 100644 --- a/ash/ambient/model/ambient_backend_model.h +++ b/ash/ambient/model/ambient_backend_model.h
@@ -53,7 +53,8 @@ // Updates the weather information and notifies observers if the icon image is // not null. void UpdateWeatherInfo(const gfx::ImageSkia& weather_condition_icon, - float temperature); + float temperature_fahrenheit, + bool show_celsius); // Returns the cached condition icon. Will return a null image if it has not // been set yet. @@ -62,7 +63,12 @@ } // Returns the cached temperature value in Fahrenheit. - float temperature() const { return temperature_; } + float temperature_fahrenheit() const { return temperature_fahrenheit_; } + + // Calculate the temperature in celsius. + float GetTemperatureInCelsius() const; + + bool show_celsius() const { return show_celsius_; } private: friend class AmbientBackendModelTest; @@ -80,10 +86,10 @@ // The index of currently shown image. int current_image_index_ = 0; - // Current weather information. The temperature is in Fahrenheit by default - // (b/154046129). + // Current weather information. gfx::ImageSkia weather_condition_icon_; - float temperature_ = 0.0f; + float temperature_fahrenheit_ = 0.0f; + bool show_celsius_ = false; // The interval to refresh photos. base::TimeDelta photo_refresh_interval_;
diff --git a/ash/ambient/ui/glanceable_info_view.cc b/ash/ambient/ui/glanceable_info_view.cc index 0b18a4f..9e80e39 100644 --- a/ash/ambient/ui/glanceable_info_view.cc +++ b/ash/ambient/ui/glanceable_info_view.cc
@@ -98,14 +98,25 @@ } void GlanceableInfoView::Show() { + AmbientBackendModel* ambient_backend_model = + delegate_->GetAmbientBackendModel(); weather_condition_icon_->SetImage( - delegate_->GetAmbientBackendModel()->weather_condition_icon()); + ambient_backend_model->weather_condition_icon()); - float temperature = delegate_->GetAmbientBackendModel()->temperature(); - // TODO(b/154046129): handle Celsius format. - temperature_->SetText(l10n_util::GetStringFUTF16Int( + temperature_->SetText(GetTemperatureText()); +} + +base::string16 GlanceableInfoView::GetTemperatureText() const { + AmbientBackendModel* ambient_backend_model = + delegate_->GetAmbientBackendModel(); + if (ambient_backend_model->show_celsius()) { + return l10n_util::GetStringFUTF16Int( + IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS, + static_cast<int>(ambient_backend_model->GetTemperatureInCelsius())); + } + return l10n_util::GetStringFUTF16Int( IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT, - static_cast<int>(temperature))); + static_cast<int>(ambient_backend_model->temperature_fahrenheit())); } void GlanceableInfoView::InitLayout() {
diff --git a/ash/ambient/ui/glanceable_info_view.h b/ash/ambient/ui/glanceable_info_view.h index 17d3917..d0d4593 100644 --- a/ash/ambient/ui/glanceable_info_view.h +++ b/ash/ambient/ui/glanceable_info_view.h
@@ -42,6 +42,8 @@ private: void InitLayout(); + base::string16 GetTemperatureText() const; + // View for the time info. Owned by the view hierarchy. ash::tray::TimeView* time_view_ = nullptr;
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 368dfffc..b0bab69 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1936,6 +1936,12 @@ <message name="IDS_ASH_LOGIN_POD_PASSWORD_PIN_PLACEHOLDER" desc="Text to display as placeholder in the password field when both password and pin are allowed."> PIN or password </message> + <message name="IDS_ASH_LOGIN_SWITCH_TO_PASSWORD" desc="Text to display on the button that is used for switching between PIN and password authentication"> + Switch to password + </message> + <message name="IDS_ASH_LOGIN_SWITCH_TO_PIN" desc="Text to display on the button that is used for switching between PIN and password authentication"> + Switch to PIN + </message> <message name="IDS_ASH_LOGIN_POD_PASSWORD_TAP_PLACEHOLDER" desc="Text to display as placeholder in the password field when the user can click/tap their profile picture to unlock."> Tap your profile image </message> @@ -2585,6 +2591,9 @@ <message name="IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT" desc="Text of the weather temperature in Fahrenheit."> <ph name="TEMPERATURE_F">$1<ex>81</ex></ph>° F </message> + <message name="IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS" desc="Text of the weather temperature in Celsius."> + <ph name="TEMPERATURE_C">$1<ex>25</ex></ph>° C + </message> </messages> </release> </grit>
diff --git a/ash/ash_strings_grd/IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS.png.sha1 b/ash/ash_strings_grd/IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS.png.sha1 new file mode 100644 index 0000000..ea2ac1f --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_CELSIUS.png.sha1
@@ -0,0 +1 @@ +36535d2bcea72bbb3cf04f90ef95817ef3da6483 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT.png.sha1 b/ash/ash_strings_grd/IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT.png.sha1 new file mode 100644 index 0000000..f6687be --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_AMBIENT_MODE_WEATHER_TEMPERATURE_IN_FAHRENHEIT.png.sha1
@@ -0,0 +1 @@ +1929c8da4ff653162e79ec0a0593ac0dd88b43da \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_LOGIN_SWITCH_TO_PASSWORD.png.sha1 b/ash/ash_strings_grd/IDS_ASH_LOGIN_SWITCH_TO_PASSWORD.png.sha1 new file mode 100644 index 0000000..b3aa70a --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_LOGIN_SWITCH_TO_PASSWORD.png.sha1
@@ -0,0 +1 @@ +11d0c44aa250b377a2c9a0aefb69c80a4d1e1db2 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_LOGIN_SWITCH_TO_PIN.png.sha1 b/ash/ash_strings_grd/IDS_ASH_LOGIN_SWITCH_TO_PIN.png.sha1 new file mode 100644 index 0000000..50f4bb8 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_LOGIN_SWITCH_TO_PIN.png.sha1
@@ -0,0 +1 @@ +a6fdc8379efd1adf0d1c4487d0b48d4ae1903e22 \ No newline at end of file
diff --git a/ash/public/cpp/ambient/ambient_backend_controller.h b/ash/public/cpp/ambient/ambient_backend_controller.h index 45761d2b3..7dbf3e9ea 100644 --- a/ash/public/cpp/ambient/ambient_backend_controller.h +++ b/ash/public/cpp/ambient/ambient_backend_controller.h
@@ -49,6 +49,10 @@ // Weather temperature in Fahrenheit. base::Optional<float> temp_f; + + // If the temperature should be displayed in celsius. Conversion must happen + // before the value in temp_f is displayed. + bool show_celsius = false; }; // Trimmed-down version of |backdrop::ScreenUpdate| proto from the backdrop
diff --git a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc index 4831b12..6c3ebca 100644 --- a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc +++ b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
@@ -17,11 +17,15 @@ constexpr AmbientModeTopicSource kTopicSource = AmbientModeTopicSource::kGooglePhotos; +constexpr AmbientModeTemperatureUnit kTemperatureUnit = + AmbientModeTemperatureUnit::kCelsius; + constexpr char kFakeUrl[] = "chrome://ambient"; AmbientSettings CreateFakeSettings() { AmbientSettings settings; settings.topic_source = kTopicSource; + settings.temperature_unit = kTemperatureUnit; ArtSetting art_setting0; art_setting0.album_id = "0"; @@ -68,6 +72,7 @@ ash::WeatherInfo weather_info; weather_info.temp_f = .0f; weather_info.condition_icon_url = kFakeUrl; + weather_info.show_celsius = true; ash::ScreenUpdate update; update.next_topics.emplace_back(topic);
diff --git a/base/BUILD.gn b/base/BUILD.gn index 448c528..3e190aef 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3775,6 +3775,7 @@ "test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java", "test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java", "test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheck.java", + "test/android/javatests/src/org/chromium/base/test/util/RequiresRestart.java", "test/android/javatests/src/org/chromium/base/test/util/Restriction.java", "test/android/javatests/src/org/chromium/base/test/util/RestrictionSkipCheck.java", "test/android/javatests/src/org/chromium/base/test/util/ScalableTimeout.java",
diff --git a/base/cpu_affinity_posix.h b/base/cpu_affinity_posix.h index db9d7049..938a64c 100644 --- a/base/cpu_affinity_posix.h +++ b/base/cpu_affinity_posix.h
@@ -10,7 +10,7 @@ namespace base { -enum class BASE_EXPORT CpuAffinityMode { +enum class CpuAffinityMode { // No restrictions on affinity. kDefault, // Restrict execution to LITTLE cores only. Only has an effect on platforms
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/RequiresRestart.java b/base/test/android/javatests/src/org/chromium/base/test/util/RequiresRestart.java new file mode 100644 index 0000000..6c9a8b8 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/util/RequiresRestart.java
@@ -0,0 +1,21 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Overrides a Batch annotation on a class and still require process restart for a particular test + * method. This should be used on individual methods only. See comments on Batch for more details. + * Optionally supply a message explaining why restart is needed as the value. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequiresRestart { + String value() default ""; +}
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index a3290e1..e9eccf26 100644 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/android/build_vars.gni") import("//build/config/android/config.gni") import("//build/config/android/rules.gni") import("//build/config/python.gni") @@ -22,6 +21,28 @@ min_sdk_version = default_min_sdk_version } } + + # Write to a file some GN vars that are useful to scripts that use the output + # directory. Format is chosen as easliy importable by both python and bash. + _lines = [ + "android_sdk_build_tools=" + + rebase_path(android_sdk_build_tools, root_build_dir), + "android_sdk_build_tools_version=$android_sdk_build_tools_version", + "android_sdk_root=" + rebase_path(android_sdk_root, root_build_dir), + "android_sdk_version=$android_sdk_version", + "android_ndk_root=" + rebase_path(android_ndk_root, root_build_dir), + "android_tool_prefix=" + rebase_path(android_tool_prefix, root_build_dir), + "android_configuration_failure_dir=" + + rebase_path(android_configuration_failure_dir, root_build_dir), + "final_android_sdk=$final_android_sdk" + ] + if (defined(android_secondary_abi_cpu)) { + _secondary_label_info = + get_label_info(":foo($android_secondary_abi_toolchain)", "root_out_dir") + _lines += [ "android_secondary_abi_toolchain=" + + rebase_path(_secondary_label_info, root_build_dir) ] + } + write_file(android_build_vars, _lines) } python_library("devil_chromium_py") { @@ -77,7 +98,7 @@ "//third_party/catapult/tracing:convert_chart_json", ] data = [ - build_vars_file, + android_build_vars, android_readelf, ] } @@ -105,19 +126,3 @@ [ "//third_party/android_platform/development/scripts:stack_py" ] } } - -# GN evaluates each .gn file once per toolchain, so restricting to default -# toolchain will ensure write_file() is called only once. -assert(current_toolchain == default_toolchain) - -# NOTE: If other platforms would benefit from exporting variables, we should -# move this to a more top-level place. -# It is currently here (instead of //BUILD.gn) to ensure that the file is -# written even for non-chromium embedders of //build. -_build_vars_json = { - # Underscore prefix so that it appears at the top. - _HEADER = "Generated during 'gn gen' by //build/android/BUILD.gn." - forward_variables_from(android_build_vars_json, "*") -} - -write_file(build_vars_file, _build_vars_json, "json")
diff --git a/build/android/docs/life_of_a_resource.md b/build/android/docs/life_of_a_resource.md index 1e542c87..4a30d27 100644 --- a/build/android/docs/life_of_a_resource.md +++ b/build/android/docs/life_of_a_resource.md
@@ -174,7 +174,7 @@ ``` The aapt2 config file is passed to the ninja target through the -`resources_config_path` variable. To add a resource to the whitelist, check +`resources_config_paths` variable. To add a resource to the whitelist, check where the config is for your target and add a new line for your resource. If none exist, create a new config file and pass its path in your target.
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py index affa6c64..603d130 100755 --- a/build/android/gradle/generate_gradle.py +++ b/build/android/gradle/generate_gradle.py
@@ -29,9 +29,6 @@ from util import build_utils from util import resource_utils -sys.path.append(os.path.dirname(_BUILD_ANDROID)) -import gn_helpers - _DEPOT_TOOLS_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'depot_tools') _DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( @@ -109,6 +106,11 @@ output_file.write(data) +def _ReadPropertiesFile(path): + with open(path) as f: + return dict(l.rstrip().split('=', 1) for l in f if '=' in l) + + def _RunGnGen(output_dir, args=None): cmd = [os.path.join(_DEPOT_TOOLS_PATH, 'gn'), 'gen', output_dir] if args: @@ -823,11 +825,10 @@ for t in targets_from_args ] # Necessary after "gn clean" - if not os.path.exists( - os.path.join(output_dir, gn_helpers.BUILD_VARS_FILENAME)): + if not os.path.exists(os.path.join(output_dir, 'build_vars.txt')): _RunGnGen(output_dir) - build_vars = gn_helpers.ReadBuildVars(output_dir) + build_vars = _ReadPropertiesFile(os.path.join(output_dir, 'build_vars.txt')) jinja_processor = jinja_template.JinjaProcessor(_FILE_DIR) if args.beta: channel = 'beta'
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py index fe64ca9..d9f6f02d 100755 --- a/build/android/gyp/compile_resources.py +++ b/build/android/gyp/compile_resources.py
@@ -197,7 +197,9 @@ '--optimized-proto-path', help='Output for `aapt2 optimize` for proto format (enables the step).') input_opts.add_argument( - '--resources-config-path', help='Path to aapt2 resources config file.') + '--resources-config-paths', + default='[]', + help='GN list of paths to aapt2 resources config files.') output_opts.add_argument( '--info-path', help='Path to output info file for the partial apk.') @@ -244,6 +246,8 @@ options.values_filter_rules) options.extra_main_r_text_files = build_utils.ParseGnList( options.extra_main_r_text_files) + options.resources_config_paths = build_utils.ParseGnList( + options.resources_config_paths) if options.optimized_proto_path and not options.proto_path: # We could write to a temp file, but it's simpler to require it. @@ -879,6 +883,14 @@ return desired_manifest_package_name +def _CombineResourceConfigs(resources_config_paths, out_config_path): + with open(out_config_path, 'w') as out_config: + for config_path in resources_config_paths: + with open(config_path) as config: + out_config.write(config.read()) + out_config.write('\n') + + def _OptimizeApk(output, options, temp_dir, unoptimized_path, r_txt_path): """Optimize intermediate .ap_ file with aapt2. @@ -900,17 +912,13 @@ # Optimize the resources.arsc file by obfuscating resource names and only # allow usage via R.java constant. if options.strip_resource_names: - # Resources of type ID are references to UI elements/views. They are used by - # UI automation testing frameworks. They are kept in so that they dont break - # tests, even though they may not actually be used during runtime. See - # https://crbug.com/900993 - id_resources = _ExtractIdResources(r_txt_path) + no_collapse_resources = _ExtractNonCollapsableResources(r_txt_path) gen_config_path = os.path.join(temp_dir, 'aapt2.config') - if options.resources_config_path: - shutil.copyfile(options.resources_config_path, gen_config_path) - with open(gen_config_path, 'a+') as config: - for resource in id_resources: - config.write('{}#no_obfuscate\n'.format(resource)) + if options.resources_config_paths: + _CombineResourceConfigs(options.resources_config_paths, gen_config_path) + with open(gen_config_path, 'a') as config: + for resource in no_collapse_resources: + config.write('{}#no_collapse\n'.format(resource)) optimize_command += [ '--collapse-resource-names', @@ -930,21 +938,30 @@ optimize_command, print_stdout=False, print_stderr=False) -def _ExtractIdResources(rtxt_path): - """Extract resources of type ID from the R.txt file +def _ExtractNonCollapsableResources(rtxt_path): + """Extract resources that should not be collapsed from the R.txt file + + Resources of type ID are references to UI elements/views. They are used by + UI automation testing frameworks. They are kept in so that they don't break + tests, even though they may not actually be used during runtime. See + https://crbug.com/900993 + App icons (aka mipmaps) are sometimes referenced by other apps by name so must + be keps as well. See https://b/161564466 Args: rtxt_path: Path to R.txt file with all the resources Returns: - List of id resources in the form of id/<resource_name> + List of resources in the form of <resource_type>/<resource_name> """ - id_resources = [] + resources = [] + _NO_COLLAPSE_TYPES = ['id', 'mipmap'] with open(rtxt_path) as rtxt: for line in rtxt: - if ' id ' in line: - resource_name = line.split()[2] - id_resources.append('id/{}'.format(resource_name)) - return id_resources + for resource_type in _NO_COLLAPSE_TYPES: + if ' {} '.format(resource_type) in line: + resource_name = line.split()[2] + resources.append('{}/{}'.format(resource_type, resource_name)) + return resources @contextlib.contextmanager @@ -1098,12 +1115,11 @@ depfile_deps = (options.dependencies_res_zips + options.extra_main_r_text_files + options.include_resources) - possible_input_paths = depfile_deps + [ + possible_input_paths = depfile_deps + options.resources_config_paths + [ options.aapt2_path, options.android_manifest, options.expected_file, options.expected_file_base, - options.resources_config_path, options.shared_resources_allowlist, options.use_resource_ids_path, options.webp_binary,
diff --git a/build/android/gyp/java_cpp_strings_tests.py b/build/android/gyp/java_cpp_strings_tests.py index 3b7d5ca..64f0f79 100755 --- a/build/android/gyp/java_cpp_strings_tests.py +++ b/build/android/gyp/java_cpp_strings_tests.py
@@ -73,7 +73,7 @@ "invalid-line-break"; """.split('\n') strings = java_cpp_strings.StringFileParser(test_data).Parse() - self.assertEqual(5, len(strings)) + self.assertEqual(6, len(strings)) self.assertEqual('A_STRING', strings[0].name) self.assertEqual('"a-value"', strings[0].value) self.assertEqual('NO_COMMENT', strings[1].name) @@ -91,6 +91,20 @@ self.assertEqual('"a-string-with-a-very-long-name-that-will-have-to-wrap2"', strings[5].value) + def testTreatWebViewLikeOneWord(self): + test_data = """ +const char kSomeWebViewSwitch[] = "some-webview-switch"; +const char kWebViewOtherSwitch[] = "webview-other-switch"; +const char kSwitchWithPluralWebViews[] = "switch-with-plural-webviews"; +""".split('\n') + strings = java_cpp_strings.StringFileParser(test_data).Parse() + self.assertEqual('SOME_WEBVIEW_SWITCH', strings[0].name) + self.assertEqual('"some-webview-switch"', strings[0].value) + self.assertEqual('WEBVIEW_OTHER_SWITCH', strings[1].name) + self.assertEqual('"webview-other-switch"', strings[1].value) + self.assertEqual('SWITCH_WITH_PLURAL_WEBVIEWS', strings[2].name) + self.assertEqual('"switch-with-plural-webviews"', strings[2].value) + def testTemplateParsing(self): test_data = """ // Copyright {YEAR} The Chromium Authors. All rights reserved.
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py index b70e00f4..a133545e 100755 --- a/build/android/gyp/lint.py +++ b/build/android/gyp/lint.py
@@ -98,10 +98,8 @@ return project -def _GenerateAndroidManifest(original_manifest_path, - min_sdk_version, - manifest_package=None): - # Set minSdkVersion and package in the manifest to the correct values. +def _GenerateAndroidManifest(original_manifest_path, min_sdk_version): + # Set minSdkVersion in the manifest to the correct value. doc, manifest, _ = manifest_utils.ParseManifest(original_manifest_path) uses_sdk = manifest.find('./uses-sdk') if uses_sdk is None: @@ -109,8 +107,6 @@ manifest.insert(0, uses_sdk) uses_sdk.set('{%s}minSdkVersion' % manifest_utils.ANDROID_NAMESPACE, min_sdk_version) - if manifest_package: - manifest.set('package', manifest_package) return doc @@ -133,7 +129,6 @@ android_sdk_version, srcjars, min_sdk_version, - manifest_package, resource_sources, resource_zips, android_sdk_root, @@ -166,8 +161,7 @@ logging.info('Generating Android manifest file') android_manifest_tree = _GenerateAndroidManifest(manifest_path, - min_sdk_version, - manifest_package) + min_sdk_version) # Include the rebased manifest_path in the lint generated path so that it is # clear in error messages where the original AndroidManifest.xml came from. lint_android_manifest_path = os.path.join(lint_gen_dir, @@ -282,8 +276,6 @@ help='If set, some checks like UnusedResources will be ' 'disabled since they are not helpful for test ' 'targets.') - parser.add_argument('--manifest-package', - help='Package name of the AndroidManifest.xml.') parser.add_argument('--warnings-as-errors', action='store_true', help='Treat all warnings as errors.') @@ -347,7 +339,6 @@ args.android_sdk_version, args.srcjars, args.min_sdk_version, - args.manifest_package, resource_sources, args.resource_zips, args.android_sdk_root,
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index 902c9de7..56ec117a 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -83,6 +83,12 @@ return files +def ReadBuildVars(path): + """Parses a build_vars.txt into a dict.""" + with open(path) as f: + return dict(l.rstrip().split('=', 1) for l in f) + + def ParseGnList(value): """Converts a "GN-list" command-line parameter into a list.
diff --git a/build/android/gyp/util/java_cpp_utils.py b/build/android/gyp/util/java_cpp_utils.py index 0b97486..855b35a 100755 --- a/build/android/gyp/util/java_cpp_utils.py +++ b/build/android/gyp/util/java_cpp_utils.py
@@ -25,6 +25,8 @@ return s # Strip the leading k. s = re.sub(r'^k', '', s) + # Treat "WebView" like one word. + s = re.sub(r'WebView', r'Webview', s) # Add _ between title words and anything else. s = re.sub(r'([^_])([A-Z][^A-Z_0-9]+)', r'\1_\2', s) # Add _ between lower -> upper transitions.
diff --git a/build/android/lint/OWNERS b/build/android/lint/OWNERS deleted file mode 100644 index b758a829..0000000 --- a/build/android/lint/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -per-file baseline.xml=*
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index e202115..95c5b86 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -201,9 +201,6 @@ <!-- We no longer supply class files to lint. --> <ignore regexp="No `.class` files were found in project"/> </issue> - <!-- We use the same baseline for all our targets. Since some targets run less - code than other targets, there will always be unused suppressions. --> - <issue id="LintBaseline" severity="ignore"/> <issue id="LogConditional" severity="ignore"/> <issue id="LongLogTag" severity="ignore"/> <issue id="MergeRootFrame" severity="Error"> @@ -370,6 +367,9 @@ <ignore regexp="The resource `R.plurals.accessibility_tab_selection_editor_group_button` appears to be unused"/> <ignore regexp="The resource `R.string.accessibility_tab_suggestion_group_tabs_message` appears to be unused"/> <ignore regexp="The resource `R.string.tab_suggestion_group_tabs_message` appears to be unused"/> + <!-- crbug.com/1114311 remove this line and the following line after the bug is resolved --> + <ignore regexp="The resource `R.string.languages_set_application_language_prompt` appears to be unused"/> + <ignore regexp="The resource `R.string.languages_set_as_application_language` appears to be unused"/> <!-- Old-style and new-style WebAPKs use same resources for simplicity. Old-style WebAPKs do not use R.style.SplashTheme but new-style WebAPKs do. TODO(crbug.com/971254): Remove suppression once old-style WebAPKs are deprecated. -->
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py index 9caf47d..5f39b3a 100644 --- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -471,7 +471,8 @@ batched_tests = dict() other_tests = [] for test in tests: - if 'Batch' in test['annotations']: + if 'Batch' in test['annotations'] and 'RequiresRestart' not in test[ + 'annotations']: batch_name = test['annotations']['Batch']['value'] if not batch_name: batch_name = test['class']
diff --git a/build/android/resource_sizes.py b/build/android/resource_sizes.py index 7f4f7ee..cd80694 100755 --- a/build/android/resource_sizes.py +++ b/build/android/resource_sizes.py
@@ -35,17 +35,14 @@ _BUILD_UTILS_PATH = os.path.join( host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gyp') -with host_paths.SysPath(os.path.join(host_paths.DIR_SOURCE_ROOT, 'build')): - import gn_helpers # pylint: disable=import-error - with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): - import perf_tests_results_helper # pylint: disable=import-error + import perf_tests_results_helper # pylint: disable=import-error with host_paths.SysPath(host_paths.TRACING_PATH): - from tracing.value import convert_chart_json # pylint: disable=import-error + from tracing.value import convert_chart_json # pylint: disable=import-error with host_paths.SysPath(_BUILD_UTILS_PATH, 0): - from util import build_utils # pylint: disable=import-error + from util import build_utils # pylint: disable=import-error from util import zipalign # pylint: disable=import-error @@ -576,7 +573,8 @@ out_dir = constants.GetOutDirectory() except Exception: # pylint: disable=broad-except return out_dir, '' - build_vars = gn_helpers.ReadBuildVars(out_dir) + build_vars = build_utils.ReadBuildVars( + os.path.join(out_dir, "build_vars.txt")) tool_prefix = os.path.join(out_dir, build_vars['android_tool_prefix']) return out_dir, tool_prefix
diff --git a/build/config/android/build_vars.gni b/build/config/android/build_vars.gni deleted file mode 100644 index a47607dc..0000000 --- a/build/config/android/build_vars.gni +++ /dev/null
@@ -1,29 +0,0 @@ -# Copyright 2020 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/android/config.gni") - -# Contains useful GN variables that may be used by scripts that take -# --output-directory as an arg. -build_vars_file = "$root_build_dir/build_vars.json" - -android_build_vars_json = { - if (enable_java_templates) { - android_ndk_root = rebase_path(android_ndk_root, root_build_dir) - android_sdk_build_tools = - rebase_path(android_sdk_build_tools, root_build_dir) - android_sdk_build_tools_version = android_sdk_build_tools_version - android_sdk_root = rebase_path(android_sdk_root, root_build_dir) - android_sdk_version = android_sdk_version - android_tool_prefix = rebase_path(android_tool_prefix, root_build_dir) - final_android_sdk = final_android_sdk - - if (defined(android_secondary_abi_cpu)) { - android_secondary_abi_toolchain = - rebase_path(get_label_info(":foo($android_secondary_abi_toolchain)", - "root_out_dir"), - root_build_dir) - } - } -}
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 9be0dc1..87afc44 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -84,7 +84,7 @@ public_android_sdk_root = "//third_party/android_sdk/public" if (android_sdk_release == "r") { default_android_sdk_root = public_android_sdk_root - default_android_sdk_version = "30" + default_android_sdk_version = 30 default_android_sdk_build_tools_version = "30.0.1" public_android_sdk = true } @@ -138,6 +138,9 @@ assert(defined(default_android_sdk_root), "SDK release " + android_sdk_release + " not recognized.") + # Where to write failed expectations for bots to read. + android_configuration_failure_dir = "$root_build_dir/failed_expectations" + declare_args() { android_ndk_root = default_android_ndk_root android_ndk_version = default_android_ndk_version @@ -247,6 +250,9 @@ enable_jdk_library_desugaring = false } + # Path to where selected build variables are written to. + android_build_vars = "$root_build_dir/build_vars.txt" + # Host stuff ----------------------------------------------------------------- # Defines the name the Android build gives to the current host CPU
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 24d239c..8b23041 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -82,9 +82,6 @@ _desugar_jdk_libs_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/desugar_jdk_libs-1.0.5.jar" _desugar_runtime_jar = "$root_build_dir/obj/third_party/bazel/desugar/Desugar_runtime.processed.jar" -# Where to write failed expectations for bots to read. -_expectations_failure_dir = "$root_build_dir/failed_expectations" - _dexdump_path = "$android_sdk_build_tools/dexdump" _dexlayout_path = "//third_party/android_build_tools/art/dexlayout" _profman_path = "//third_party/android_build_tools/art/profman" @@ -1047,14 +1044,13 @@ args += [ "--warnings-as-errors" ] } - _stamp_path = "$target_out_dir/$target_name/build.lint.stamp" if (defined(invoker.create_cache) && invoker.create_cache) { - args += [ "--silent" ] - # Putting the stamp file in the cache dir allows us to depend on ninja # to create the cache dir for us. _stamp_path = "$_cache_dir/build.lint.stamp" + args += [ "--silent" ] } else { + _stamp_path = "$target_out_dir/$target_name/build.lint.stamp" deps += [ "//build/android:prepare_android_lint_cache", invoker.build_config_dep, @@ -1063,17 +1059,6 @@ _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) - # TODO(wnwen): Remove this baseline once it is empty. - _baseline = "//build/android/lint/baseline.xml" - _rebased_baseline = rebase_path(_baseline, root_build_dir) - - if (compute_inputs_for_analyze) { - # The baseline file is included in lint.py as a depfile dep. Since - # removing it regenerates the file, it is useful to not have this as - # a gn input during local development. Add it only for bots' analyze. - inputs += [ _baseline ] - } - args += [ "--manifest-path=@FileArg($_rebased_build_config:deps_info:lint_android_manifest)", @@ -1084,14 +1069,25 @@ "--resource-sources=@FileArg($_rebased_build_config:deps_info:lint_resource_sources)", "--resource-zips=@FileArg($_rebased_build_config:deps_info:lint_resource_zips)", - # Baseline allows us to turn on lint warnings without fixing all the - # pre-existing issues. This stops the flood of new issues while the - # existing ones are being fixed. - "--baseline=$_rebased_baseline", - # The full classpath is required for annotation checks like @IntDef. "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", ] + + if (defined(invoker.lint_baseline_file)) { + if (compute_inputs_for_analyze) { + # The baseline file is included in lint.py as a depfile dep. Since + # removing it regenerates the file, it is useful to not have this as + # a gn input during local development. Add it only for bots' analyze. + inputs += [ invoker.lint_baseline_file ] + } + args += [ + # Baseline allows us to turn on lint warnings without fixing all the + # pre-existing issues. This stops the flood of new issues while the + # existing ones are being fixed. + "--baseline", + rebase_path(invoker.lint_baseline_file, root_build_dir), + ] + } } outputs = [ _stamp_path ] @@ -1265,7 +1261,7 @@ ] _actual_file = "$target_gen_dir/$target_name.proguard_configs" _failure_file = - "$_expectations_failure_dir/" + + "$android_configuration_failure_dir/" + string_replace(invoker.expected_proguard_config, "/", "_") outputs = [ _actual_file ] args = _args + [ @@ -2460,12 +2456,11 @@ rebase_path(invoker.optimized_proto_output, root_build_dir), ] } - if (defined(invoker.resources_config_path)) { - _inputs += [ invoker.resources_config_path ] - _args += [ - "--resources-config-path", - rebase_path(invoker.resources_config_path, root_build_dir), - ] + if (defined(invoker.resources_config_paths)) { + _inputs += invoker.resources_config_paths + _rebased_resource_configs = + rebase_path(invoker.resources_config_paths, root_build_dir) + _args += [ "--resources-config-paths=${_rebased_resource_configs}" ] } if (defined(invoker.short_resource_paths) && invoker.short_resource_paths) { _args += [ "--short-resource-paths" ] @@ -2644,7 +2639,7 @@ action_with_pydeps(_expectations_target) { _actual_file = "${invoker.android_manifest}.normalized" _failure_file = - "$_expectations_failure_dir/" + + "$android_configuration_failure_dir/" + string_replace(invoker.expected_android_manifest, "/", "_") inputs = [ invoker.android_manifest, @@ -2923,7 +2918,7 @@ action_with_pydeps(_expectations_target) { _actual_file = "$target_gen_dir/$target_name.libs_and_assets" _failure_file = - "$_expectations_failure_dir/" + + "$android_configuration_failure_dir/" + string_replace(invoker.expected_libs_and_assets, "/", "_") inputs = [ invoker.build_config, @@ -4143,7 +4138,7 @@ _expectations_target = "${invoker.top_target_name}_validate_libs_and_assets" action_with_pydeps(_expectations_target) { _actual_file = "$target_gen_dir/$target_name.libs_and_assets" - _failure_file = "$_expectations_failure_dir/" + + _failure_file = "$android_configuration_failure_dir/" + string_replace(invoker.expected_libs_and_assets, "/", "_") inputs = [ invoker.expected_libs_and_assets,
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index a4a7b90..dd74568 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -2088,8 +2088,8 @@ # resources.arsc file in the apk or module. # short_resource_paths: True if resource paths should be shortened in the # apk or module. - # resources_config_path: Path to the aapt2 optimize config file that tags - # resources with acceptable/non-acceptable optimizations. + # resources_config_paths: List of paths to the aapt2 optimize config files + # that tags resources with acceptable/non-acceptable optimizations. # expected_android_manifest: Enables verification of expected merged # manifest based on a golden file. # resource_ids_provider_dep: If passed, this target will use the resource @@ -2482,7 +2482,7 @@ "resource_exclusion_exceptions", "resource_exclusion_regex", "resource_values_filter_rules", - "resources_config_path", + "resources_config_paths", "shared_resources", "shared_resources_allowlist_locales", "support_zh_hk", @@ -3330,9 +3330,9 @@ android_lint("${target_name}__lint") { forward_variables_from(invoker, [ + "lint_baseline_file", "lint_suppressions_dep", "lint_suppressions_file", - "manifest_package", "min_sdk_version", ]) if (defined(invoker.lint_min_sdk_version)) { @@ -3343,10 +3343,9 @@ deps = [ ":$_java_target" ] } } else { - # TODO(wnwen): Remove manifest_package when all usages are removed. not_needed(invoker, [ - "manifest_package", + "lint_baseline_file", "lint_min_sdk_version", ]) } @@ -3456,6 +3455,7 @@ "keystore_name", "keystore_password", "keystore_path", + "lint_baseline_file", "lint_min_sdk_version", "lint_suppressions_dep", "lint_suppressions_file", @@ -3483,7 +3483,7 @@ "resource_exclusion_regex", "resource_ids_provider_dep", "resource_values_filter_rules", - "resources_config_path", + "resources_config_paths", "require_native_mocks", "secondary_abi_loadable_modules", "secondary_abi_shared_libraries", @@ -3610,7 +3610,7 @@ "resource_exclusion_regex", "resource_ids_provider_dep", "resource_values_filter_rules", - "resources_config_path", + "resources_config_paths", "secondary_abi_loadable_modules", "secondary_abi_shared_libraries", "secondary_native_lib_placeholders", @@ -4996,9 +4996,9 @@ android_lint("${target_name}__lint") { forward_variables_from(invoker, [ + "lint_baseline_file", "lint_suppressions_dep", "lint_suppressions_file", - "manifest_package", "min_sdk_version", ]) if (defined(invoker.lint_min_sdk_version)) { @@ -5009,10 +5009,9 @@ deps = _module_java_targets } } else { - # TODO(wnwen): Remove manifest_package when all usages are removed. not_needed(invoker, [ - "manifest_package", + "lint_baseline_file", "lint_min_sdk_version", ]) }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index c9dd4f31..33059c97 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200810.0.1 +0.20200810.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index c9dd4f31..33059c97 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200810.0.1 +0.20200810.1.1
diff --git a/build/gn_helpers.py b/build/gn_helpers.py index 8258658..a240d80 100644 --- a/build/gn_helpers.py +++ b/build/gn_helpers.py
@@ -20,7 +20,6 @@ file to the build directory. """ -import json import os import re import sys @@ -28,7 +27,6 @@ _CHROMIUM_ROOT = os.path.join(os.path.dirname(__file__), os.pardir) -BUILD_VARS_FILENAME = 'build_vars.json' IMPORT_RE = re.compile(r'^import\("//(\S+)"\)') @@ -498,9 +496,3 @@ self.cur = end return True return False - - -def ReadBuildVars(output_directory): - """Parses $output_directory/build_vars.json into a dict.""" - with open(os.path.join(output_directory, BUILD_VARS_FILENAME)) as f: - return json.load(f)
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index ec505ac..4e1d2392 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -8,6 +8,7 @@ #include <algorithm> #include <limits> +#include <memory> #include <set> #include <utility> @@ -6008,5 +6009,188 @@ pending_layer()->ComputeLCDTextDisallowedReasonForTesting()); } +enum { + kCanUseLCDText = 1 << 0, + kLayersAlwaysAllowedLCDText = 1 << 1, +}; + +class LCDTextTest : public PictureLayerImplTest, + public testing::WithParamInterface<unsigned> { + protected: + LayerTreeSettings CreateSettings() override { + auto settings = PictureLayerImplTest::CreateSettings(); + settings.can_use_lcd_text = GetParam() & kCanUseLCDText; + settings.layers_always_allowed_lcd_text = + GetParam() & kLayersAlwaysAllowedLCDText; + return settings; + } + + void SetUp() override { + PictureLayerImplTest::SetUp(); + + SetupDefaultTreesWithInvalidation(gfx::Size(200, 200), Region()); + tree_ = host_impl()->pending_tree(); + root_ = tree_->root_layer(); + child_ = AddLayer<PictureLayerImpl>(tree_); + grand_child_ = AddLayer<PictureLayerImpl>(tree_); + tree_->SetElementIdsForTesting(); + + root_->SetContentsOpaque(true); + child_->SetContentsOpaque(true); + grand_child_->SetContentsOpaque(true); + + root_->SetDrawsContent(true); + child_->SetDrawsContent(true); + grand_child_->SetDrawsContent(true); + + root_->SetBounds(gfx::Size(1, 1)); + child_->SetBounds(gfx::Size(1, 1)); + grand_child_->SetBounds(gfx::Size(1, 1)); + + CopyProperties(root_, child_); + CreateTransformNode(child_); + CreateEffectNode(child_).render_surface_reason = RenderSurfaceReason::kTest; + CopyProperties(child_, grand_child_); + CreateTransformNode(grand_child_); + CreateEffectNode(grand_child_); + } + + void CheckCanUseLCDText(LCDTextDisallowedReason expected_disallowed_reason, + PictureLayerImpl* layer = nullptr) { + UpdateDrawProperties(tree_); + + if (GetParam() & kLayersAlwaysAllowedLCDText) + expected_disallowed_reason = LCDTextDisallowedReason::kNone; + else if (!(GetParam() & kCanUseLCDText)) + expected_disallowed_reason = LCDTextDisallowedReason::kSetting; + + if (layer) { + EXPECT_EQ(expected_disallowed_reason, + layer->ComputeLCDTextDisallowedReasonForTesting()); + } else { + EXPECT_EQ(expected_disallowed_reason, + child_->ComputeLCDTextDisallowedReasonForTesting()); + EXPECT_EQ(expected_disallowed_reason, + grand_child_->ComputeLCDTextDisallowedReasonForTesting()); + } + } + + LayerTreeImpl* tree_ = nullptr; + LayerImpl* root_ = nullptr; + PictureLayerImpl* child_ = nullptr; + PictureLayerImpl* grand_child_ = nullptr; +}; + +INSTANTIATE_TEST_SUITE_P(All, + LCDTextTest, + testing::Values(0, + kCanUseLCDText, + kLayersAlwaysAllowedLCDText, + kCanUseLCDText | + kLayersAlwaysAllowedLCDText)); + +TEST_P(LCDTextTest, IdentityTransform) { + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, IntegralTransform) { + gfx::Transform integral_translation; + integral_translation.Translate(1.0, 2.0); + SetTransform(child_, integral_translation); + + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, NonIntegralTranslation) { + // Non-integral translation. + gfx::Transform non_integral_translation; + non_integral_translation.Translate(1.5, 2.5); + SetTransform(child_, non_integral_translation); + CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); + + SetTransform(child_, gfx::Transform()); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, NonTranslation) { + // Rotation. + gfx::Transform rotation; + rotation.Rotate(10.0); + SetTransform(child_, rotation); + CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); + + // Scale. + gfx::Transform scale; + scale.Scale(2.0, 2.0); + SetTransform(child_, scale); + CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); + + // Skew. + gfx::Transform skew; + skew.Skew(10.0, 0.0); + SetTransform(child_, skew); + CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); + + SetTransform(child_, gfx::Transform()); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, Opacity) { + // LCD-text is allowed with opacity paint property. + SetOpacity(child_, 0.5f); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); + SetOpacity(child_, 1.f); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, ContentsNotOpaque) { + // Non-opaque content and opaque background. + child_->SetContentsOpaque(false); + child_->SetBackgroundColor(SK_ColorGREEN); + CheckCanUseLCDText(LCDTextDisallowedReason::kContentsNotOpaque, child_); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); + + // Non-opaque content and non-opaque background. + child_->SetBackgroundColor(SkColorSetARGB(128, 255, 255, 255)); + CheckCanUseLCDText(LCDTextDisallowedReason::kBackgroundColorNotOpaque, + child_); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); + + child_->SetContentsOpaque(true); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, WillChangeTransform) { + child_->SetHasWillChangeTransformHint(true); + CheckCanUseLCDText(LCDTextDisallowedReason::kWillChangeTransform, child_); + // TODO(crbug.com/1114504): will-change:transform should apply to descendants. + CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); + + child_->SetHasWillChangeTransformHint(false); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, Filter) { + FilterOperations blur_filter; + blur_filter.Append(FilterOperation::CreateBlurFilter(4.0f)); + SetFilter(child_, blur_filter); + CheckCanUseLCDText(LCDTextDisallowedReason::kLayerHasFilterEffect, child_); + // TODO(crbug.com/1114504): will-change:transform should apply to descendants. + CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); + + SetFilter(child_, FilterOperations()); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone); +} + +TEST_P(LCDTextTest, ContentsOpaqueForText) { + child_->SetContentsOpaque(false); + child_->SetBackgroundColor(SK_ColorGREEN); + child_->SetContentsOpaqueForText(true); + CheckCanUseLCDText(LCDTextDisallowedReason::kNone, child_); + + child_->SetContentsOpaqueForText(false); + CheckCanUseLCDText(LCDTextDisallowedReason::kContentsNotOpaque, child_); +} + } // namespace } // namespace cc
diff --git a/cc/test/pixel_test.h b/cc/test/pixel_test.h index 9c1de03..66d31cb4 100644 --- a/cc/test/pixel_test.h +++ b/cc/test/pixel_test.h
@@ -13,6 +13,7 @@ #include "base/memory/shared_memory_mapping.h" #include "base/single_thread_task_runner.h" #include "base/test/scoped_feature_list.h" +#include "build/build_config.h" #include "cc/test/pixel_comparator.h" #include "cc/trees/layer_tree_settings.h" #include "components/viz/client/client_resource_provider.h" @@ -26,6 +27,7 @@ #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/ipc/in_process_command_buffer.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/geometry/size.h" namespace viz { @@ -170,8 +172,20 @@ bool use_gpu() const { return !!child_context_provider_; } GraphicsBackend backend() const { - if (std::is_base_of<VulkanSkiaRenderer, RendererType>::value) - return kSkiaVulkan; + if (std::is_base_of<VulkanSkiaRenderer, RendererType>::value) { +#if defined(USE_OZONE) && defined(OS_LINUX) && !defined(OS_CHROMEOS) + // TODO(https://crbug.com/1113577): Enable SkiaVulkan backend for + // PixelTests. For example, RendererPixelTest* hadn't been using + // SkiaVulkanRenderer until USE_X11 was defined for the OS_LINUX + // configuration that uses USE_OZONE. Thus, given the lack of test + // coverage, we must fix this test variant so that we do not loose + // important test coverage when USE_X11 goes away. + if (!features::IsUsingOzonePlatform()) +#endif + { + return kSkiaVulkan; + } + } if (std::is_base_of<DawnSkiaRenderer, RendererType>::value) return kSkiaDawn; return kDefault;
diff --git a/cc/trees/draw_properties_unittest.cc b/cc/trees/draw_properties_unittest.cc index 666b6a2..7e2c465 100644 --- a/cc/trees/draw_properties_unittest.cc +++ b/cc/trees/draw_properties_unittest.cc
@@ -3646,211 +3646,6 @@ front_facing, host_impl()->active_tree()->property_trees())); } -using LCDTextTestParam = std::tuple<bool, bool>; -class LCDTextTest : public DrawPropertiesTestBase, - public testing::TestWithParam<LCDTextTestParam> { - public: - LCDTextTest() : DrawPropertiesTestBase(LCDTextTestLayerTreeSettings()) {} - - protected: - LayerTreeSettings LCDTextTestLayerTreeSettings() { - LayerListSettings settings; - - can_use_lcd_text_ = std::get<0>(GetParam()); - layers_always_allowed_lcd_text_ = std::get<1>(GetParam()); - settings.can_use_lcd_text = can_use_lcd_text_; - settings.layers_always_allowed_lcd_text = layers_always_allowed_lcd_text_; - return settings; - } - - void SetUp() override { - root_ = root_layer(); - child_ = AddLayer<PictureLayerImpl>(); - grand_child_ = AddLayer<PictureLayerImpl>(); - SetElementIdsForTesting(); - - root_->SetContentsOpaque(true); - child_->SetContentsOpaque(true); - grand_child_->SetContentsOpaque(true); - - root_->SetDrawsContent(true); - child_->SetDrawsContent(true); - grand_child_->SetDrawsContent(true); - - root_->SetBounds(gfx::Size(1, 1)); - child_->SetBounds(gfx::Size(1, 1)); - grand_child_->SetBounds(gfx::Size(1, 1)); - - CopyProperties(root_, child_); - CreateTransformNode(child_); - CreateEffectNode(child_).render_surface_reason = RenderSurfaceReason::kTest; - CopyProperties(child_, grand_child_); - } - - void CheckCanUseLCDText(LCDTextDisallowedReason expected_disallowed_reason, - PictureLayerImpl* layer = nullptr) { - if (layers_always_allowed_lcd_text_) - expected_disallowed_reason = LCDTextDisallowedReason::kNone; - else if (!can_use_lcd_text_) - expected_disallowed_reason = LCDTextDisallowedReason::kSetting; - - if (layer) { - EXPECT_EQ(expected_disallowed_reason, - layer->ComputeLCDTextDisallowedReasonForTesting()); - } else { - EXPECT_EQ(expected_disallowed_reason, - child_->ComputeLCDTextDisallowedReasonForTesting()); - EXPECT_EQ(expected_disallowed_reason, - grand_child_->ComputeLCDTextDisallowedReasonForTesting()); - } - } - - bool can_use_lcd_text_; - bool layers_always_allowed_lcd_text_; - - LayerImpl* root_ = nullptr; - PictureLayerImpl* child_ = nullptr; - PictureLayerImpl* grand_child_ = nullptr; -}; - -TEST_P(LCDTextTest, CanUseLCDText) { - // Case 1: Identity transform. - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Case 2: Integral translation. - gfx::Transform integral_translation; - integral_translation.Translate(1.0, 2.0); - SetTransform(child_, integral_translation); - - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Case 3: Non-integral translation. - gfx::Transform non_integral_translation; - non_integral_translation.Translate(1.5, 2.5); - SetTransform(child_, non_integral_translation); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); - - // Case 4: Rotation. - gfx::Transform rotation; - rotation.Rotate(10.0); - SetTransform(child_, rotation); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); - - // Case 5: Scale. - gfx::Transform scale; - scale.Scale(2.0, 2.0); - SetTransform(child_, scale); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); - - // Case 6: Skew. - gfx::Transform skew; - skew.Skew(10.0, 0.0); - SetTransform(child_, skew); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); - - // Case 7: Translucent: LCD-text is allowed. - SetTransform(child_, gfx::Transform()); - SetOpacity(child_, 0.5f); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Case 8: Sanity check: restore transform and opacity. - SetTransform(child_, gfx::Transform()); - SetOpacity(child_, 1.f); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Case 9a: Non-opaque content and opaque background. - child_->SetContentsOpaque(false); - child_->SetBackgroundColor(SK_ColorGREEN); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kContentsNotOpaque, child_); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); - - // Case 9b: Non-opaque content and non-opaque background. - child_->SetBackgroundColor(SkColorSetARGB(128, 255, 255, 255)); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kBackgroundColorNotOpaque, - child_); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); - - // Case 10: Sanity check: restore content opaqueness. - child_->SetContentsOpaque(true); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Case 11: will-change: transform - child_->SetHasWillChangeTransformHint(true); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kWillChangeTransform, child_); - // TODO(wangxianzhu): Is this correct? - CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); - - // Case 12: Sanity check: restore will-change: transform. - child_->SetHasWillChangeTransformHint(false); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Case 13: Normal filter. - FilterOperations blur_filter; - blur_filter.Append(FilterOperation::CreateBlurFilter(4.0f)); - SetFilter(child_, blur_filter); - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kLayerHasFilterEffect, child_); -} - -TEST_P(LCDTextTest, CanUseLCDTextWithContentsOpaqueForText) { - child_->SetContentsOpaque(false); - child_->SetBackgroundColor(SK_ColorGREEN); - child_->SetContentsOpaqueForText(true); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone, child_); - - child_->SetContentsOpaqueForText(false); - CheckCanUseLCDText(LCDTextDisallowedReason::kContentsNotOpaque, child_); -} - -TEST_P(LCDTextTest, CanUseLCDTextWithAnimation) { - // Sanity check: Make sure can_use_lcd_text_ is set on each node. - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Add opacity animation. - gfx::Transform non_integral_translation; - non_integral_translation.Translate(1.5, 2.5); - SetTransform(child_, non_integral_translation); - AddAnimatedTransformToElementWithAnimation(child_->element_id(), timeline(), - 10.0, 12, 34); - UpdateActiveTreeDrawProperties(); - // Text LCD should be adjusted while animation is active. - CheckCanUseLCDText(LCDTextDisallowedReason::kNonIntegralTranslation); -} - -TEST_P(LCDTextTest, CanUseLCDTextWithAnimationContentsOpaque) { - // Sanity check: Make sure can_use_lcd_text_ is set on each node. - UpdateActiveTreeDrawProperties(); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone); - - // Mark contents non-opaque within the first animation frame. - child_->SetContentsOpaque(false); - child_->SetBackgroundColor(SK_ColorWHITE); - AddOpacityTransitionToElementWithAnimation(child_->element_id(), timeline(), - 10.0, 0.9f, 0.1f, false); - UpdateActiveTreeDrawProperties(); - // LCD text should be disabled for non-opaque layers even during animations. - CheckCanUseLCDText(LCDTextDisallowedReason::kContentsNotOpaque, child_); - CheckCanUseLCDText(LCDTextDisallowedReason::kNone, grand_child_); -} - -INSTANTIATE_TEST_SUITE_P(DrawPropertiesTest, - LCDTextTest, - testing::Combine(testing::Bool(), testing::Bool())); - // Needs layer tree mode: hide_layer_and_subtree. TEST_F(DrawPropertiesTestWithLayerTree, SubtreeHidden_SingleLayerImpl) { auto root = Layer::Create();
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index f569b1f..685e028 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1939,7 +1939,6 @@ "jni_registration_header", "target_type", "enable_multidex", - "lint_min_sdk_version", "lint_suppressions_dep", "lint_suppressions_file", ])
diff --git a/chrome/android/aapt2.config b/chrome/android/aapt2.config new file mode 100644 index 0000000..a1e0ee9 --- /dev/null +++ b/chrome/android/aapt2.config
@@ -0,0 +1 @@ +drawable/shortcut_incognito#no_collapse
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index ebf5013..d029559 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -609,10 +609,12 @@ } # Resources config for blocklisting resource names from obfuscation - if (defined(invoker.resources_config_path)) { - resources_config_path = invoker.resources_config_path - } else { - resources_config_path = "//android_webview/aapt2.config" + resources_config_paths = [ + "//android_webview/aapt2.config", + "//chrome/android/aapt2.config", + ] + if (defined(invoker.resources_config_paths)) { + resources_config_paths += invoker.resources_config_paths } if (defined(invoker.never_incremental)) { @@ -702,7 +704,7 @@ "no_xml_namespaces", "product_config_java_packages", "proguard_configs", - "resources_config_path", + "resources_config_paths", "secondary_abi_loadable_modules", "secondary_abi_shared_libraries", "secondary_native_lib_placeholders",
diff --git a/build/android/lint/baseline.xml b/chrome/android/expectations/lint-baseline.xml similarity index 94% rename from build/android/lint/baseline.xml rename to chrome/android/expectations/lint-baseline.xml index 5e70e32..945e044 100644 --- a/build/android/lint/baseline.xml +++ b/chrome/android/expectations/lint-baseline.xml
@@ -359,17 +359,6 @@ <issue id="WrongConstant" - message="Must be one of: Type.NO_ADJUSTMENT, Type.FRAMERATE_ADJUSTMENT" - errorLine1=" return -1;" - errorLine2=" ~~"> - <location - file="media/base/android/java/src/org/chromium/media/MediaCodecUtil.java" - line="556" - column="16"/> - </issue> - - <issue - id="WrongConstant" message="Must be one of: MediaSessionActionSource.MEDIA_NOTIFICATION, MediaSessionActionSource.MEDIA_SESSION, MediaSessionActionSource.HEADSET_UNPLUG" errorLine1=" return MediaSessionUma.MediaSessionActionSource.NUM_ENTRIES;" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -580,33 +569,11 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" setKeyboardDelegate(createKeyboardVisibilityDelegate());" - errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/base/ActivityWindowAndroid.java" - line="58" - column="9"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" setAndroidPermissionDelegate(createAndroidPermissionDelegate());" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/base/ActivityWindowAndroid.java" - line="59" - column="9"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" || !WebsitePreferenceBridgeJni.get().isContentSettingsPatternValid(" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AddExceptionPreference.java" - line="189" + line="187" column="70"/> </issue> @@ -1002,7 +969,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="237" + line="240" column="27"/> </issue> @@ -1013,7 +980,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="238" + line="241" column="31"/> </issue> @@ -1024,7 +991,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="239" + line="242" column="31"/> </issue> @@ -1035,7 +1002,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="469" + line="475" column="30"/> </issue> @@ -1046,7 +1013,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="558" + line="564" column="49"/> </issue> @@ -1057,7 +1024,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="559" + line="565" column="40"/> </issue> @@ -1068,7 +1035,7 @@ errorLine2=" ~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="574" + line="580" column="67"/> </issue> @@ -1079,7 +1046,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="612" + line="618" column="25"/> </issue> @@ -1090,7 +1057,7 @@ errorLine2=" ~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="629" + line="635" column="73"/> </issue> @@ -1101,7 +1068,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="650" + line="656" column="71"/> </issue> @@ -1112,7 +1079,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="668" + line="674" column="52"/> </issue> @@ -1123,7 +1090,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="687" + line="693" column="24"/> </issue> @@ -1134,7 +1101,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="688" + line="694" column="31"/> </issue> @@ -1145,7 +1112,7 @@ errorLine2=" ~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="689" + line="695" column="31"/> </issue> @@ -1156,7 +1123,7 @@ errorLine2=" ~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="698" + line="704" column="70"/> </issue> @@ -1167,7 +1134,7 @@ errorLine2=" ~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="703" + line="709" column="43"/> </issue> @@ -1178,7 +1145,7 @@ errorLine2=" ~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="705" + line="711" column="48"/> </issue> @@ -1189,7 +1156,7 @@ errorLine2=" ~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="728" + line="734" column="28"/> </issue> @@ -1200,7 +1167,7 @@ errorLine2=" ~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="846" + line="852" column="57"/> </issue> @@ -1211,7 +1178,7 @@ errorLine2=" ~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="933" + line="940" column="37"/> </issue> @@ -1222,7 +1189,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="934" + line="941" column="31"/> </issue> @@ -1233,7 +1200,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="955" + line="962" column="36"/> </issue> @@ -1244,7 +1211,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="970" + line="977" column="24"/> </issue> @@ -1255,7 +1222,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="972" + line="979" column="32"/> </issue> @@ -1266,7 +1233,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="972" + line="979" column="65"/> </issue> @@ -1277,7 +1244,7 @@ errorLine2=" ~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="1150" + line="1157" column="83"/> </issue> @@ -1288,7 +1255,7 @@ errorLine2=" ~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java" - line="1151" + line="1158" column="28"/> </issue> @@ -2707,7 +2674,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPromoHeader.java" - line="239" + line="237" column="40"/> </issue> @@ -3374,171 +3341,6 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.setAdapter(adapter);" - errorLine2=" ~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="46" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.setInitialSelection(initialSelection);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="50" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.show();" - errorLine2=" ~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="57" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.setOnDismissListener(listener);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="66" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.setRtl(isRtl);" - errorLine2=" ~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="74" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.disableHideOnOutsideTap();" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="82" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.setContentDescriptionForAccessibility(description);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="91" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.setOnItemClickListener(clickListener);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="100" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.postShow();" - errorLine2=" ~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="108" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.dismiss();" - errorLine2=" ~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="115" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" return mPopup.getListView();" - errorLine2=" ~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="122" - column="23"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" return mPopup.isShowing();" - errorLine2=" ~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="129" - column="23"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPopup.setFooterView(footerItem);" - errorLine2=" ~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java" - line="136" - column="16"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" implements AnchoredPopupWindow.LayoutObserver, DropdownPopupWindowInterface {" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindowImpl.java" - line="32" - column="56"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1="class DropdownPopupWindowJellyBean implements DropdownPopupWindowInterface {" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="ui/android/java/src/org/chromium/ui/DropdownPopupWindowJellyBean.java" - line="33" - column="47"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" mLastProcessedSuggestionURL = suggestion.getUrl();" errorLine2=" ~~~~~~"> <location @@ -3671,28 +3473,6 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" setKeyboardDelegate(new ActivityKeyboardVisibilityDelegate(getActivity()));" - errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - <location - file="weblayer/browser/java/org/chromium/weblayer_private/FragmentWindowAndroid.java" - line="37" - column="9"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" setAndroidPermissionDelegate(new FragmentAndroidPermissionDelegate(mFragment));" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="weblayer/browser/java/org/chromium/weblayer_private/FragmentWindowAndroid.java" - line="38" - column="9"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" ? UrlUtilities.urlsMatchIgnoringFragments(speculatedUrl, url)" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location @@ -3715,28 +3495,6 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" public static final int COMPOSITION_KEY_CODE = ImeAdapter.COMPOSITION_KEY_CODE;" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> - <location - file="content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java" - line="96" - column="63"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mCursorAnchorInfoController.setInputMethodManagerWrapper(immw);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java" - line="350" - column="41"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" IncognitoNotificationService.getRemoveAllIncognitoTabsIntent(" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location @@ -3891,83 +3649,6 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" LocationProviderAdapter.onNewLocationAvailable(location);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java" - line="62" - column="37"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" LocationProviderAdapter.newErrorAvailable(" - errorLine2=" ~~~~~~~~~~~~~~~~~"> - <location - file="services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java" - line="114" - column="37"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" LocationProviderAdapter.onNewLocationAvailable(location);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java" - line="144" - column="37"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" LocationProviderAdapter.onNewLocationAvailable(location);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java" - line="92" - column="37"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" LocationProviderAdapter.newErrorAvailable(" - errorLine2=" ~~~~~~~~~~~~~~~~~"> - <location - file="services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java" - line="104" - column="37"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" LocationProviderAdapter.newErrorAvailable(" - errorLine2=" ~~~~~~~~~~~~~~~~~"> - <location - file="services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java" - line="116" - column="33"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" LocationProviderAdapter.onNewLocationAvailable(location);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java" - line="150" - column="33"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" sController.mThrottler.queueNotification(notificationInfo);" errorLine2=" ~~~~~~~~~~"> <location @@ -4434,7 +4115,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java" - line="382" + line="381" column="46"/> </issue> @@ -4804,39 +4485,6 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" mImeAdapter.finishComposingText();" - errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - <location - file="content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnection.java" - line="583" - column="21"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mFactory.setTriggerDelayedOnCreateInputConnection(false);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java" - line="95" - column="22"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mFactory.setTriggerDelayedOnCreateInputConnection(true);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java" - line="97" - column="22"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" mTileRenderer.renderTileSection(tiles, mSectionView, mTileGroup.getTileSetupDelegate());" errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location @@ -5453,39 +5101,6 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" mVrBrowsingEnabled = mDelegate.isVrBrowsingEnabled();" - errorLine2=" ~~~~~~~~~~~~~~~~~~"> - <location - file="chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java" - line="173" - column="9"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mVrBrowsingEnabled = mDelegate.isVrBrowsingEnabled();" - errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - <location - file="chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java" - line="173" - column="40"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" setAndroidPermissionDelegate(new ActivityAndroidPermissionDelegate());" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java" - line="37" - column="9"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" mWebApkUpdateManager.get().updateIfNeeded(storage, mActivity.getIntentDataProvider());" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location @@ -5589,7 +5204,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java" - line="156" + line="155" column="18"/> </issue> @@ -5600,7 +5215,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java" - line="181" + line="180" column="30"/> </issue> @@ -5611,7 +5226,7 @@ errorLine2=" ^"> <location file="components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java" - line="236" + line="235" column="18"/> </issue>
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml index 9689c17..9185a74 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_header.xml
@@ -8,6 +8,7 @@ android:layout_height="wrap_content"> <LinearLayout + android:id="@+id/header_top_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="56dp"
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java index b246ed73..9a6819b1 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
@@ -151,6 +151,8 @@ // We don't want to animate the carousels children views as they are already animated by the // recyclers ItemAnimator, so we exclude them to avoid a clash between the animations. mLayoutTransition.excludeChildren(mActionsCoordinator.getView(), /* exclude= */ true); + mLayoutTransition.excludeChildren( + mHeaderCoordinator.getCarouselView(), /* exclude= */ true); // do not animate the contents of the payment method section inside the section choice list, // since the animation is not required and causes a rendering crash. @@ -190,7 +192,11 @@ controller.addObserver(new EmptyBottomSheetObserver() { @Override public void onSheetStateChanged(int newState) { - maybeShowHeaderChip(); + // Note: recycler view updates while the bottom sheet is SCROLLING result in a + // BottomSheet assertion. + if (newState != BottomSheetController.SheetState.SCROLLING) { + maybeShowHeaderChips(); + } } @Override @@ -256,10 +262,8 @@ } private void setupAnimations(AssistantModel model, ViewGroup rootView) { - // Animate when the chip in the header changes. model.getHeaderModel().addObserver((source, propertyKey) -> { - if (propertyKey == AssistantHeaderModel.CHIP - || propertyKey == AssistantHeaderModel.CHIP_VISIBLE) { + if (propertyKey == AssistantHeaderModel.CHIPS_VISIBLE) { animateChildren(rootView); } }); @@ -295,12 +299,12 @@ TransitionManager.beginDelayedTransition(rootView, mLayoutTransition); } - private void maybeShowHeaderChip() { - boolean showChip = + private void maybeShowHeaderChips() { + boolean showChips = mBottomSheetController.getSheetState() == BottomSheetController.SheetState.PEEK && mPeekHeightCoordinator.getPeekMode() == AssistantPeekHeightCoordinator.PeekMode.HANDLE_HEADER; - mModel.getHeaderModel().set(AssistantHeaderModel.CHIP_VISIBLE, showChip); + mModel.getHeaderModel().set(AssistantHeaderModel.CHIPS_VISIBLE, showChips); } /** @@ -350,7 +354,7 @@ /** Set the peek mode. */ void setPeekMode(@AssistantPeekHeightCoordinator.PeekMode int peekMode) { mPeekHeightCoordinator.setPeekMode(peekMode); - maybeShowHeaderChip(); + maybeShowHeaderChips(); } /** Expand the bottom sheet. */
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index 674fef83..dfc3750 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -18,7 +18,6 @@ import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantCarouselModel; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip.Type; -import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel; import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.profiles.Profile; @@ -283,55 +282,56 @@ } /** - * Adds an action button to the chip list, which executes the action {@code actionIndex}. + * Creates an action button which executes the action {@code actionIndex}. */ @CalledByNative - private void addActionButton(List<AssistantChip> chips, int icon, String text, int actionIndex, + private AssistantChip createActionButton(int icon, String text, int actionIndex, boolean disabled, boolean sticky, String identifier) { - chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, - sticky, identifier, () -> safeNativeOnUserActionSelected(actionIndex))); + return new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, sticky, + identifier, () -> safeNativeOnUserActionSelected(actionIndex)); } /** - * Adds a highlighted action button to the chip list, which executes the action {@code - * actionIndex}. + * Creates a highlighted action button which executes the action {@code actionIndex}. */ @CalledByNative - private void addHighlightedActionButton(List<AssistantChip> chips, int icon, String text, - int actionIndex, boolean disabled, boolean sticky, String identifier) { - chips.add(new AssistantChip(Type.BUTTON_FILLED_BLUE, icon, text, disabled, sticky, - identifier, () -> safeNativeOnUserActionSelected(actionIndex))); + private AssistantChip createHighlightedActionButton(int icon, String text, int actionIndex, + boolean disabled, boolean sticky, String identifier) { + return new AssistantChip(Type.BUTTON_FILLED_BLUE, icon, text, disabled, sticky, identifier, + () -> safeNativeOnUserActionSelected(actionIndex)); } /** - * Adds a cancel action button to the chip list. If the keyboard is currently shown, it - * dismisses the keyboard. Otherwise, it shows the snackbar and then executes - * {@code actionIndex}, or shuts down Autofill Assistant if {@code actionIndex} is {@code -1}. + * Creates a cancel action button. If the keyboard is currently shown, it dismisses the + * keyboard. Otherwise, it shows the snackbar and then executes {@code actionIndex}, or shuts + * down Autofill Assistant if {@code actionIndex} is {@code -1}. */ @CalledByNative - private void addCancelButton(List<AssistantChip> chips, int icon, String text, int actionIndex, + private AssistantChip createCancelButton(int icon, String text, int actionIndex, boolean disabled, boolean sticky, String identifier) { - chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, - sticky, identifier, () -> safeNativeOnCancelButtonClicked(actionIndex))); + return new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, sticky, + identifier, () -> safeNativeOnCancelButtonClicked(actionIndex)); } /** * Adds a close action button to the chip list, which shuts down Autofill Assistant. */ @CalledByNative - private void addCloseButton(List<AssistantChip> chips, int icon, String text, boolean disabled, - boolean sticky, String identifier) { - chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, - sticky, identifier, this::safeNativeOnCloseButtonClicked)); + private AssistantChip createCloseButton( + int icon, String text, boolean disabled, boolean sticky, String identifier) { + return new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, sticky, + identifier, this::safeNativeOnCloseButtonClicked); + } + + @CalledByNative + private static void appendChipToList(List<AssistantChip> chips, AssistantChip chip) { + chips.add(chip); } @CalledByNative private void setActions(List<AssistantChip> chips) { - // TODO(b/144075373): Move this to AssistantCarouselModel and AssistantHeaderModel. Move - // header chip logic to native. - AssistantCarouselModel model = getModel().getActionsModel(); - model.setChips(chips); - setHeaderChip(chips); + // TODO(b/144075373): Move this to AssistantCarouselModel. + getModel().getActionsModel().setChips(chips); } @CalledByNative @@ -358,19 +358,6 @@ model.setChips(newChips); } - private void setHeaderChip(List<AssistantChip> chips) { - // The header chip is the first sticky chip found in the actions. - AssistantChip headerChip = null; - for (AssistantChip chip : chips) { - if (chip.isSticky()) { - headerChip = chip; - break; - } - } - - getModel().getHeaderModel().set(AssistantHeaderModel.CHIP, headerChip); - } - @CalledByNative private void setViewportMode(@AssistantViewportMode int mode) { mCoordinator.getBottomBarCoordinator().setViewportMode(mode);
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipAdapter.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipAdapter.java index 4ce5656..f449346 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipAdapter.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipAdapter.java
@@ -22,7 +22,7 @@ public class AssistantChipAdapter extends RecyclerView.Adapter<AssistantChipViewHolder> { private final List<AssistantChip> mChips = new ArrayList<>(); - void setChips(List<AssistantChip> chips) { + public void setChips(List<AssistantChip> chips) { DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() { @Override public int getOldListSize() {
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java index 7653718e..7f97029f 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderCoordinator.java
@@ -5,13 +5,19 @@ package org.chromium.chrome.browser.autofill_assistant.header; import android.content.Context; +import android.graphics.Rect; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.chromium.chrome.autofill_assistant.R; import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiController; +import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipAdapter; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderViewBinder.ViewHolder; import org.chromium.chrome.browser.signin.DisplayableProfileData; import org.chromium.chrome.browser.signin.IdentityServicesProvider; @@ -32,6 +38,7 @@ private final ImageView mProfileView; private final String mSignedInAccountName; private final ViewHolder mViewHolder; + private final RecyclerView mChipsContainer; public AssistantHeaderCoordinator(Context context, AssistantHeaderModel model) { // Create the poodle and insert it before the status message. We have to create a view @@ -56,8 +63,52 @@ identityManager.getPrimaryAccountInfo(ConsentLevel.SYNC)); setupProfileImage(); + mChipsContainer = new RecyclerView(context); + final int innerChipSpacing = context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_actions_spacing); + mChipsContainer.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, + @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + outRect.top = 0; + outRect.bottom = 0; + + if (state.getItemCount() <= 1) { + return; + } + + // If old position != NO_POSITION, it means the carousel is being animated and we + // should use that position in our logic. + int position = parent.getChildAdapterPosition(view); + RecyclerView.ViewHolder viewHolder = parent.getChildViewHolder(view); + if (viewHolder != null && viewHolder.getOldPosition() != RecyclerView.NO_POSITION) { + position = viewHolder.getOldPosition(); + } + + if (position == RecyclerView.NO_POSITION) { + return; + } + + outRect.left = position == 0 ? 0 : innerChipSpacing; + outRect.right = 0; + } + }); + + AssistantChipAdapter chipAdapter = new AssistantChipAdapter(); + mChipsContainer.setAdapter(chipAdapter); + LinearLayoutManager layoutManager = new LinearLayoutManager(context); + layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + mChipsContainer.setLayoutManager(layoutManager); + mView.setPadding(mChipsContainer.getPaddingLeft(), mChipsContainer.getPaddingTop(), + context.getResources().getDimensionPixelSize( + R.dimen.autofill_assistant_profile_icon_padding), + mChipsContainer.getPaddingBottom()); + ViewGroup topContainer = mView.findViewById(R.id.header_top_container); + topContainer.addView(mChipsContainer); + // Bind view and mediator through the model. - mViewHolder = new AssistantHeaderViewBinder.ViewHolder(context, mView, poodle); + mViewHolder = + new AssistantHeaderViewBinder.ViewHolder(context, mView, poodle, mChipsContainer); AssistantHeaderViewBinder viewBinder = new AssistantHeaderViewBinder(); PropertyModelChangeProcessor.create(model, mViewHolder, viewBinder); @@ -77,6 +128,11 @@ return mView; } + /** Returns the view containing the chips. */ + public View getCarouselView() { + return mChipsContainer; + } + /** * Cleanup resources when this goes out of scope. */
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java index 1fc9fc8..7c86cc3 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderModel.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.autofill_assistant.header; +import android.support.annotation.VisibleForTesting; + import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip; @@ -18,6 +20,9 @@ */ @JNINamespace("autofill_assistant") public class AssistantHeaderModel extends PropertyModel { + public static final WritableObjectPropertyKey<List<AssistantChip>> CHIPS = + new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<String> STATUS_MESSAGE = new WritableObjectPropertyKey<>(); @@ -45,10 +50,7 @@ public static final WritableObjectPropertyKey<Runnable> FEEDBACK_BUTTON_CALLBACK = new WritableObjectPropertyKey<>(); - public static final WritableObjectPropertyKey<AssistantChip> CHIP = - new WritableObjectPropertyKey<>(); - - public static final WritableBooleanPropertyKey CHIP_VISIBLE = new WritableBooleanPropertyKey(); + public static final WritableBooleanPropertyKey CHIPS_VISIBLE = new WritableBooleanPropertyKey(); public static final WritableBooleanPropertyKey DISABLE_ANIMATIONS_FOR_TESTING = new WritableBooleanPropertyKey(); @@ -56,7 +58,8 @@ public AssistantHeaderModel() { super(STATUS_MESSAGE, BUBBLE_MESSAGE, PROGRESS, PROGRESS_ACTIVE_STEP, PROGRESS_BAR_ERROR, PROGRESS_VISIBLE, USE_STEP_PROGRESS_BAR, STEP_PROGRESS_BAR_ICONS, SPIN_POODLE, - FEEDBACK_BUTTON_CALLBACK, CHIP, CHIP_VISIBLE, DISABLE_ANIMATIONS_FOR_TESTING); + FEEDBACK_BUTTON_CALLBACK, CHIPS, CHIPS_VISIBLE, DISABLE_ANIMATIONS_FOR_TESTING); + set(CHIPS, new ArrayList<>()); } @CalledByNative @@ -127,4 +130,16 @@ private void setDisableAnimations(boolean disableAnimations) { set(DISABLE_ANIMATIONS_FOR_TESTING, disableAnimations); } + + @CalledByNative + @VisibleForTesting + public void setChips(List<AssistantChip> chips) { + // Move last chip (cancel) to first position. For legacy reasons, native builds this list + // such that the cancel chip is last, but the regular carousel will show it in the left-most + // position and the header should mirror this. + if (chips.size() > 1) { + chips.add(0, chips.remove(chips.size() - 1)); + } + set(CHIPS, chips); + } }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java index c5941419..e3cc10c 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java
@@ -11,11 +11,12 @@ import android.widget.TextView; import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; import org.chromium.chrome.autofill_assistant.R; import org.chromium.chrome.browser.autofill_assistant.AssistantTextUtils; -import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip; -import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipViewHolder; +import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipAdapter; import org.chromium.chrome.browser.settings.SettingsLauncher; import org.chromium.chrome.browser.settings.SettingsLauncherImpl; import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings; @@ -45,12 +46,12 @@ final AssistantStepProgressBar mStepProgressBar; final View mProfileIconView; final PopupMenu mProfileIconMenu; - @Nullable - AssistantChipViewHolder mChip; + final RecyclerView mChipsContainer; @Nullable TextBubble mTextBubble; - ViewHolder(Context context, ViewGroup headerView, AnimatedPoodle poodle) { + ViewHolder(Context context, ViewGroup headerView, AnimatedPoodle poodle, + RecyclerView chipsContainer) { mContext = context; mPoodle = poodle; mHeader = headerView; @@ -62,6 +63,7 @@ mProfileIconMenu = new PopupMenu(context, mProfileIconView); mProfileIconMenu.inflate(R.menu.profile_icon_menu); mProfileIconView.setOnClickListener(unusedView -> mProfileIconMenu.show()); + mChipsContainer = chipsContainer; } void disableAnimations(boolean disable) { @@ -70,6 +72,8 @@ // Hiding the animated poodle seems to be the easiest way to disable its animation since // {@link LogoView#setAnimationEnabled(boolean)} is private. mPoodle.getView().setVisibility(View.INVISIBLE); + ((DefaultItemAnimator) mChipsContainer.getItemAnimator()) + .setSupportsChangeAnimations(!disable); } void updateProgressBarVisibility(boolean visible, boolean useStepProgressBar) { @@ -110,11 +114,13 @@ view.mPoodle.setSpinEnabled(model.get(AssistantHeaderModel.SPIN_POODLE)); } else if (AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK == propertyKey) { setProfileMenuListener(view, model.get(AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK)); - } else if (AssistantHeaderModel.CHIP == propertyKey) { - bindChip(view, model.get(AssistantHeaderModel.CHIP)); - maybeShowChip(model, view); - } else if (AssistantHeaderModel.CHIP_VISIBLE == propertyKey) { - maybeShowChip(model, view); + } else if (AssistantHeaderModel.CHIPS == propertyKey) { + view.mChipsContainer.invalidateItemDecorations(); + ((AssistantChipAdapter) view.mChipsContainer.getAdapter()) + .setChips(model.get(AssistantHeaderModel.CHIPS)); + maybeShowChips(model, view); + } else if (AssistantHeaderModel.CHIPS_VISIBLE == propertyKey) { + maybeShowChips(model, view); } else if (AssistantHeaderModel.BUBBLE_MESSAGE == propertyKey) { showOrDismissBubble(model, view); } else if (AssistantHeaderModel.DISABLE_ANIMATIONS_FOR_TESTING == propertyKey) { @@ -124,45 +130,18 @@ } } - private void maybeShowChip(AssistantHeaderModel model, ViewHolder view) { - if (model.get(AssistantHeaderModel.CHIP_VISIBLE) - && model.get(AssistantHeaderModel.CHIP) != null) { - view.mChip.getView().setVisibility(View.VISIBLE); + private void maybeShowChips(AssistantHeaderModel model, ViewHolder view) { + if (model.get(AssistantHeaderModel.CHIPS_VISIBLE) + && !model.get(AssistantHeaderModel.CHIPS).isEmpty()) { + view.mChipsContainer.setVisibility(View.VISIBLE); view.mProfileIconView.setVisibility(View.GONE); } else { - if (view.mChip != null) { - view.mChip.getView().setVisibility(View.GONE); - } + view.mChipsContainer.setVisibility(View.GONE); view.mProfileIconView.setVisibility(View.VISIBLE); } } - private void bindChip(ViewHolder view, @Nullable AssistantChip chip) { - if (chip == null) { - return; - } - - int viewType = AssistantChipViewHolder.getViewType(chip); - - // If there is already a chip in the header but with incompatible type, remove it. - ViewGroup parent = (ViewGroup) view.mStatusMessage.getParent(); - if (view.mChip != null && view.mChip.getType() != viewType) { - parent.removeView(view.mChip.getView()); - view.mChip = null; - } - - // If there is no chip already in the header, create one and add it at the end of the - // header. - if (view.mChip == null) { - view.mChip = AssistantChipViewHolder.create(view.mHeader, viewType); - parent.addView(view.mChip.getView()); - } - - // Bind the chip to the view. - view.mChip.bind(chip); - } - private void setProfileMenuListener(ViewHolder view, @Nullable Runnable feedbackCallback) { view.mProfileIconMenu.setOnMenuItemClickListener(item -> { int itemId = item.getItemId();
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantHeaderUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantHeaderUiTest.java index 9a19708..cad8a5de 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantHeaderUiTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantHeaderUiTest.java
@@ -7,6 +7,7 @@ import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.assertion.PositionAssertions.isRightOf; +import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; @@ -52,6 +53,9 @@ import org.chromium.components.browser_ui.widget.MaterialProgressBar; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import java.util.ArrayList; +import java.util.List; + /** * Tests for the Autofill Assistant header. */ @@ -206,15 +210,17 @@ chipText, /* disabled= */ false, /* sticky= */ false, "", () -> {}); // Set the header chip without displaying it. - TestThreadUtils.runOnUiThreadBlocking(() -> model.set(AssistantHeaderModel.CHIP, chip)); + List<AssistantChip> chips = new ArrayList<>(); + chips.add(chip); + TestThreadUtils.runOnUiThreadBlocking(() -> model.setChips(chips)); Matcher<View> chipMatcher = allOf(isDescendantOfA(is(coordinator.getView())), withText(chipText)); - onView(chipMatcher).check(matches(not(isDisplayed()))); + onView(chipMatcher).check(doesNotExist()); // Show the chip TestThreadUtils.runOnUiThreadBlocking( - () -> model.set(AssistantHeaderModel.CHIP_VISIBLE, true)); + () -> model.set(AssistantHeaderModel.CHIPS_VISIBLE, true)); onView(chipMatcher) .check(matches(isDisplayed())) .check(isRightOf(withId(R.id.status_message)));
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 23e316f..d3f6edb 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -407,11 +407,6 @@ fail("Failed to tap 'more tabs' " + e.toString()); } onViewWaiting(withId(R.id.secondary_tasks_surface_view)); - if (isInstantReturn()) { - // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar - // omnibox. - return; - } pressBack(); onViewWaiting(withId(R.id.primary_tasks_surface_view)); @@ -474,11 +469,6 @@ fail("Failed to tap 'more tabs' " + e.toString()); } onViewWaiting(withId(R.id.secondary_tasks_surface_view)); - if (isInstantReturn()) { - // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar - // omnibox. - return; - } pressBack(); onViewWaiting(withId(R.id.primary_tasks_surface_view));
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java index 4e607a38..dafb35f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
@@ -162,7 +162,7 @@ * @return The title */ public String getTitle() { - if (mTab != null && mTab.get() != null) { + if (mTab != null && mTab.get() != null && mTab.get().isInitialized()) { return mTab.get().getTitle(); } assert mTabId != null;
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java index 79f1014..17428bf 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java
@@ -427,7 +427,7 @@ } @Test - public void testTabDestroyed() { + public void testTabDestroyedRootId() { Tab tab = new MockTab(TAB4_ID, false); PseudoTab pseudoTab = PseudoTab.fromTab(tab); tab.destroy(); @@ -436,4 +436,15 @@ // UnsupportedOperationException Assert.assertEquals(Tab.INVALID_TAB_ID, pseudoTab.getRootId()); } + + @Test + public void testTabDestroyedTitle() { + Tab tab = new MockTab(TAB4_ID, false); + PseudoTab pseudoTab = PseudoTab.fromTab(tab); + tab.destroy(); + // Title was not set. Without the isInitialized() check, + // pseudoTab.getTitle() would crash here with + // UnsupportedOperationException + Assert.assertEquals("", pseudoTab.getTitle()); + } }
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java index a26c8ae..b031505d 100644 --- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
@@ -859,7 +859,6 @@ ContextUtils.getApplicationContext(), GVR_KEYBOARD_PACKAGE_ID); } - @VisibleForTesting protected boolean isVrBrowsingEnabled() { return isVrBrowsingEnabled(mActivity, VrCoreInstallUtils.getVrSupportLevel()); }
diff --git a/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml b/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml index f0a95424..a30cc10 100644 --- a/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml +++ b/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml
@@ -27,6 +27,7 @@ app:srcCompat="@drawable/chrome_sync_logo" /> <TextView + android:id="@+id/account_picker_bottom_sheet_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="12dp"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java index ba899113..da8ab6e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java
@@ -8,6 +8,7 @@ import android.content.pm.PackageManager; import android.os.Bundle; +import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.browser.customtabs.CustomTabsSessionToken; @@ -25,8 +26,12 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.NavigationHandle; +import org.chromium.net.NetError; import org.chromium.ui.widget.Toast; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + import javax.inject.Inject; /** @@ -44,7 +49,8 @@ static final String NOTIFY = "quality_enforcement.notify"; @VisibleForTesting static final String CRASH = "quality_enforcement.crash"; - private static final String KEY_CRASH_REASON = "crash_reason"; + @VisibleForTesting + static final String KEY_CRASH_REASON = "crash_reason"; private static final String KEY_SUCCESS = "success"; private final ChromeActivity<?> mActivity; @@ -55,6 +61,17 @@ private boolean mOriginVerified; + @IntDef({ViolationType.ERROR_404, ViolationType.ERROR_5XX, ViolationType.UNAVAILABLE_OFFLINE, + ViolationType.DIGITAL_ASSERTLINKS}) + @Retention(RetentionPolicy.SOURCE) + public @interface ViolationType { + int ERROR_404 = 0; + int ERROR_5XX = 1; + int UNAVAILABLE_OFFLINE = 2; + int DIGITAL_ASSERTLINKS = 3; + int NUM_ENTRIES = 4; + } + private final CustomTabTabObserver mTabObserver = new CustomTabTabObserver() { @Override public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) { @@ -64,11 +81,15 @@ } String newUrl = tab.getOriginalUrl(); - if (isNavigationInScope(newUrl) && navigation.httpStatusCode() == 404) { - String message = ContextUtils.getApplicationContext().getString( - R.string.twa_quality_enforcement_violation_error, - navigation.httpStatusCode(), newUrl); - trigger(message); + if (isNavigationInScope(newUrl)) { + if (navigation.httpStatusCode() == 404) { + trigger(ViolationType.ERROR_404, newUrl, navigation.httpStatusCode()); + } else if (navigation.httpStatusCode() >= 500 + && navigation.httpStatusCode() <= 599) { + trigger(ViolationType.ERROR_5XX, newUrl, navigation.httpStatusCode()); + } else if (navigation.errorCode() == NetError.ERR_INTERNET_DISCONNECTED) { + trigger(ViolationType.UNAVAILABLE_OFFLINE, newUrl, navigation.httpStatusCode()); + } } } @@ -93,11 +114,12 @@ tabObserverRegistrar.registerActivityTabObserver(mTabObserver); } - private void trigger(String message) { - showErrorToast(message); + private void trigger(@ViolationType int type, String url, int httpStatusCode) { + showErrorToast(getToastMessage(type, url, httpStatusCode)); + // Notify the client app. Bundle args = new Bundle(); - args.putString(KEY_CRASH_REASON, message); + args.putString(KEY_CRASH_REASON, toTwaCrashMessage(type, url, httpStatusCode)); if (!ChromeFeatureList.isEnabled( ChromeFeatureList.TRUSTED_WEB_ACTIVITY_QUALITY_ENFORCEMENT)) { mConnection.sendExtraCallbackWithResult(mSessionToken, NOTIFY, args); @@ -129,4 +151,29 @@ mOriginVerified = !result.isFulfilled() || result.getResult(); return wasVerified && mOriginVerified; } + + /* Get the localized string for toast message. */ + private String getToastMessage(@ViolationType int type, String url, int httpStatusCode) { + if (type == ViolationType.ERROR_404 || type == ViolationType.ERROR_5XX) { + return ContextUtils.getApplicationContext().getString( + R.string.twa_quality_enforcement_violation_error, httpStatusCode, url); + } else if (type == ViolationType.UNAVAILABLE_OFFLINE) { + return ContextUtils.getApplicationContext().getString( + R.string.twa_quality_enforcement_violation_offline, url); + } + return ""; + } + + /* + * Get the string for sending message to TWA client app. We are not using the localized one as + * the toast because this is used in TWA's crash message. + */ + private String toTwaCrashMessage(@ViolationType int type, String url, int httpStatusCode) { + if (type == ViolationType.ERROR_404 || type == ViolationType.ERROR_5XX) { + return httpStatusCode + " on " + url; + } else if (type == ViolationType.UNAVAILABLE_OFFLINE) { + return "Page unavailable offline: " + url; + } + return ""; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java index 70b930e..59bc3f9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java
@@ -322,10 +322,8 @@ * Starts preparing an edge swipe gesture. */ public void startGesture() { - assert mNavigationHandler != null; - // Simulates the initial onDown event to update the internal state. - mNavigationHandler.onDown(); + if (mNavigationHandler != null) mNavigationHandler.onDown(); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java index 1b9ad62..4c0c40ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java
@@ -221,14 +221,19 @@ */ @VisibleForTesting public int getNumSignedIn() { - return PostTask.runSynchronously(UiThreadTaskTraits.DEFAULT, () -> { - // The native needs to be loaded for the usage of IdentityManager. - ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); - // We only have a single account. - IdentityManager identityManager = IdentityServicesProvider.get().getIdentityManager( - Profile.getLastUsedRegularProfile()); - return identityManager.hasPrimaryAccount() ? 1 : 0; - }); + try { + return PostTask.runSynchronously(UiThreadTaskTraits.DEFAULT, () -> { + // The native needs to be loaded for the usage of IdentityManager. + ChromeBrowserInitializer.getInstance().handleSynchronousStartup(); + // We only have a single account. + IdentityManager identityManager = IdentityServicesProvider.get().getIdentityManager( + Profile.getLastUsedRegularProfile()); + return identityManager.hasPrimaryAccount() ? 1 : 0; + }); + } catch (Exception e) { + Log.e(TAG, "Cannot get number of signed in accounts:", e); + } + return 0; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java index 26f3e925..c7e321a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java
@@ -186,6 +186,8 @@ delegate = new PaymentRequestDelegateImpl(mRenderFrameHost); } - return new ComponentPaymentRequestImpl(new PaymentRequestImpl(mRenderFrameHost, delegate)); + return new ComponentPaymentRequestImpl((componentPaymentRequest) + -> new PaymentRequestImpl(mRenderFrameHost, + componentPaymentRequest, delegate)); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index 33776b9..ba2391b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -53,9 +53,9 @@ import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.page_info.CertificateChainHelper; import org.chromium.components.payments.AbortReason; +import org.chromium.components.payments.BrowserPaymentRequest; import org.chromium.components.payments.CanMakePaymentQuery; import org.chromium.components.payments.ComponentPaymentRequestImpl; -import org.chromium.components.payments.ComponentPaymentRequestImpl.ComponentPaymentRequestDelegate; import org.chromium.components.payments.CurrencyFormatter; import org.chromium.components.payments.ErrorMessageUtil; import org.chromium.components.payments.ErrorStrings; @@ -121,10 +121,9 @@ * living in {@link ComponentPaymentRequestImpl}. */ public class PaymentRequestImpl - implements ComponentPaymentRequestDelegate, PaymentRequestUI.Client, - PaymentAppFactoryDelegate, PaymentAppFactoryParams, - PaymentRequestUpdateEventListener, PaymentApp.AbortCallback, - PaymentApp.InstrumentDetailsCallback, + implements BrowserPaymentRequest, PaymentRequestUI.Client, PaymentAppFactoryDelegate, + PaymentAppFactoryParams, PaymentRequestUpdateEventListener, + PaymentApp.AbortCallback, PaymentApp.InstrumentDetailsCallback, PaymentResponseHelper.PaymentResponseRequesterDelegate, NormalizedAddressRequestDelegate, PaymentDetailsConverter.MethodChecker, PaymentUIsManager.Delegate { @@ -231,24 +230,16 @@ } private static final String TAG = "PaymentRequest"; - - private ComponentPaymentRequestImpl mComponentPaymentRequestImpl; - - private PaymentOptions mPaymentOptions; - private boolean mRequestShipping; - private boolean mRequestPayerName; - private boolean mRequestPayerPhone; - private boolean mRequestPayerEmail; - private static PaymentRequestServiceObserverForTest sObserverForTest; private static boolean sIsLocalCanMakePaymentQueryQuotaEnforcedForTest; - /** * Hold the currently showing PaymentRequest. Used to prevent showing more than one * PaymentRequest UI per browser process. */ private static PaymentRequestImpl sShowingPaymentRequest; + private final ComponentPaymentRequestImpl mComponentPaymentRequestImpl; + /** Monitors changes in the TabModelSelector. */ private final TabModelSelectorObserver mSelectorObserver = new EmptyTabModelSelectorObserver() { @Override @@ -291,6 +282,14 @@ private final JourneyLogger mJourneyLogger; private final boolean mIsOffTheRecord; + private final PaymentUIsManager mPaymentUIsManager; + + private PaymentOptions mPaymentOptions; + private boolean mRequestShipping; + private boolean mRequestPayerName; + private boolean mRequestPayerPhone; + private boolean mRequestPayerEmail; + private boolean mIsCanMakePaymentResponsePending; private boolean mIsHasEnrolledInstrumentResponsePending; private boolean mHasEnrolledInstrumentUsesPerMethodQuota; @@ -328,7 +327,6 @@ private int mShippingType; private boolean mIsFinishedQueryingPaymentApps; private List<PaymentApp> mPendingApps = new ArrayList<>(); - private final PaymentUIsManager mPaymentUIsManager; private MinimalUICoordinator mMinimalUi; private PaymentApp mInvokedPaymentApp; private boolean mHideServerAutofillCards; @@ -413,9 +411,13 @@ * Builds the PaymentRequest service implementation. * * @param renderFrameHost The host of the frame that has invoked the PaymentRequest API. + * @param componentPaymentRequestImpl The component side of the PaymentRequest implementation. */ - public PaymentRequestImpl(RenderFrameHost renderFrameHost, Delegate delegate) { + public PaymentRequestImpl(RenderFrameHost renderFrameHost, + ComponentPaymentRequestImpl componentPaymentRequestImpl, Delegate delegate) { assert renderFrameHost != null; + assert componentPaymentRequestImpl != null; + assert delegate != null; mRenderFrameHost = renderFrameHost; mDelegate = delegate; @@ -440,18 +442,10 @@ if (sObserverForTest != null) sObserverForTest.onPaymentRequestCreated(this); mPaymentUIsManager = new PaymentUIsManager(/*delegate=*/this, /*params=*/this, mWebContents, mIsOffTheRecord, mJourneyLogger); - } - - // Implement ComponentPaymentRequestDelegate: - @Override - public void setComponentPaymentRequestImpl( - ComponentPaymentRequestImpl componentPaymentRequestImpl) { - assert mComponentPaymentRequestImpl == null; - assert componentPaymentRequestImpl != null; mComponentPaymentRequestImpl = componentPaymentRequestImpl; } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called by the merchant website to initialize the payment request data. */ @@ -712,7 +706,7 @@ return true; } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called by the merchant website to show the payment request to the user. */ @@ -1089,7 +1083,7 @@ && mInvokedPaymentApp.isValidForPaymentMethodData(methodName, null); } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called by merchant to update the shipping options and line items after the user has selected * their shipping address or shipping option. @@ -1193,7 +1187,7 @@ } } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called when the merchant received a new shipping address, shipping option, or payment method * info, but did not update the payment details in response. @@ -1545,7 +1539,7 @@ disconnectFromClientWithDebugMessage(ErrorStrings.USER_CANCELLED); } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: // This method is not supposed to be used outside this class and // ComponentPaymentRequestImpl. @Override @@ -1564,7 +1558,7 @@ } } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called by the merchant website to abort the payment. */ @@ -1597,7 +1591,7 @@ } } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called when the merchant website has processed the payment. */ @@ -1639,7 +1633,7 @@ closeUIAndDestroyNativeObjects(); } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: @Override public void retry(PaymentValidationErrors errors) { if (getClient() == null) return; @@ -1731,7 +1725,7 @@ settingsLauncher.launchSettingsActivity(context); } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** Called by the merchant website to check if the user has complete payment apps. */ @Override public void canMakePayment() { @@ -1768,7 +1762,7 @@ } } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** Called by the merchant website to check if the user has complete payment instruments. */ @Override public void hasEnrolledInstrument(boolean perMethodQuota) { @@ -1830,7 +1824,7 @@ || sIsLocalCanMakePaymentQueryQuotaEnforcedForTest; } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called when the renderer closes the Mojo connection. */ @@ -1846,7 +1840,7 @@ } } - // Implement ComponentPaymentRequestDelegate: + // Implement BrowserPaymentRequest: /** * Called when the Mojo connection encounters an error. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java index f124108..e22630d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java
@@ -8,6 +8,7 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; +import android.widget.TextView; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; @@ -28,6 +29,7 @@ class AccountPickerBottomSheetView implements BottomSheetContent { private final Context mContext; private final View mContentView; + private final TextView mAccountPickerTitle; private final RecyclerView mAccountListView; private final View mSelectedAccountView; private final ButtonCompat mContinueAsButton; @@ -36,6 +38,7 @@ mContext = context; mContentView = LayoutInflater.from(mContext).inflate( R.layout.account_picker_bottom_sheet_view, null); + mAccountPickerTitle = mContentView.findViewById(R.id.account_picker_bottom_sheet_title); mAccountListView = mContentView.findViewById(R.id.account_picker_account_list); mAccountListView.setLayoutManager(new LinearLayoutManager( mAccountListView.getContext(), LinearLayoutManager.VERTICAL, false)); @@ -113,9 +116,7 @@ * Sets up the sign-in in progress view. */ void setUpSignInInProgressView() { - // TODO(https://crbug.com/1102784): - // - Setup the sign-in string |Signing in...| - // - Add signing in progress spinner + mAccountPickerTitle.setText(R.string.signin_account_picker_bottom_sheet_signin_title); mContentView.findViewById(R.id.account_picker_bottom_sheet_subtitle) .setVisibility(View.GONE); mSelectedAccountView.setVisibility(View.GONE);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/QualityEnforcerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/QualityEnforcerTest.java index 6fad9aa..476931b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/QualityEnforcerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/QualityEnforcerTest.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.browserservices; +import static org.junit.Assert.assertEquals; + import static org.chromium.chrome.browser.browserservices.TrustedWebActivityTestUtil.createSession; import static org.chromium.chrome.browser.browserservices.TrustedWebActivityTestUtil.spoofVerification; @@ -29,11 +31,14 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils; import org.chromium.chrome.browser.document.ChromeLauncherActivity; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.net.test.EmbeddedTestServerRule; import java.util.concurrent.TimeoutException; @@ -43,6 +48,7 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@DisableFeatures(ChromeFeatureList.TRUSTED_WEB_ACTIVITY_QUALITY_ENFORCEMENT) public class QualityEnforcerTest { private static final String TEST_PAGE = "/chrome/test/data/android/google.html"; // A not exist test page to triger 404. @@ -62,6 +68,7 @@ private String mTestPage; private String mTestPage404; + private String mErrorMessage; CallbackHelper mCallbackHelper = new CallbackHelper(); CustomTabsCallback mCallback = new CustomTabsCallback() { @@ -69,6 +76,7 @@ public Bundle extraCallbackWithResult(String callbackName, Bundle args) { if (callbackName.equals(QualityEnforcer.NOTIFY)) { mCallbackHelper.notifyCalled(); + mErrorMessage = args.getString(QualityEnforcer.KEY_CRASH_REASON); } return Bundle.EMPTY; } @@ -89,6 +97,7 @@ public void notifiedWhenLaunch404() throws TimeoutException { launch(mTestPage404); mCallbackHelper.waitForFirst(); + assertEquals(mErrorMessage, "404 on " + mTestPage404); } @Test @@ -97,6 +106,17 @@ launch(mTestPage); mCustomTabActivityTestRule.loadUrl(mTestPage404); mCallbackHelper.waitForFirst(); + assertEquals(mErrorMessage, "404 on " + mTestPage404); + } + + @Test + @MediumTest + @DisabledTest(message = "This test only works when device is running offline.") + // TODO(eirage): Figure out how to make it work on local device without changing network. + public void notifiedOffline() throws TimeoutException { + launch("https://example.com/"); + mCallbackHelper.waitForFirst(); + assertEquals(mErrorMessage, "Page unavailable offline: https://example.com/"); } public void launch(String testPage) throws TimeoutException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java index 4ea57e4..db7a400f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java
@@ -28,7 +28,6 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisabledTest; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient; import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; @@ -144,7 +143,6 @@ */ @Test @MediumTest - @DisabledTest(message = "https://crbug.com/1111906") public void jsToTwaConnected() throws TimeoutException { DigitalGoodsFactory.setDigitalGoodsForTesting(createFixedDigitalGoods());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java index 02c4db65..fcc90c79a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -146,6 +146,7 @@ TestThreadUtils.runOnUiThreadBlocking( () -> { ChromeNightModeTestUtils.setUpNightModeForChromeActivity(true); }); mRenderTestRule.setNightModeEnabled(true); + mActivityTestRule.startMainActivityOnBlankPage(); buildAndShowCollapsedBottomSheet(); mRenderTestRule.render( mCoordinator.getBottomSheetViewForTesting(), "collapsed_sheet_with_account_dark"); @@ -296,6 +297,8 @@ return !bottomSheetView.findViewById(R.id.account_picker_continue_as_button).isShown(); }); verify(mAccountPickerDelegateMock).signIn(PROFILE_DATA1.getAccountName()); + onView(withText(R.string.signin_account_picker_bottom_sheet_signin_title)) + .check(matches(isDisplayed())); onView(withId(R.id.account_picker_bottom_sheet_subtitle)) .check(matches(not(isDisplayed()))); onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed()))); @@ -308,9 +311,14 @@ public void testSignInAnotherAccount() { buildAndShowExpandedBottomSheet(); onView(withText(PROFILE_DATA2.getAccountName())).perform(click()); - String continueAsText = mActivityTestRule.getActivity().getString( - R.string.signin_promo_continue_as, PROFILE_DATA2.getAccountName()); - onView(withText(continueAsText)).perform(click()); + View bottomSheetView = mCoordinator.getBottomSheetViewForTesting(); + CriteriaHelper.pollUiThread( + bottomSheetView.findViewById(R.id.account_picker_continue_as_button)::isShown); + ThreadUtils.runOnUiThread( + bottomSheetView.findViewById(R.id.account_picker_continue_as_button)::performClick); + CriteriaHelper.pollUiThread(() -> { + return !bottomSheetView.findViewById(R.id.account_picker_continue_as_button).isShown(); + }); verify(mAccountPickerDelegateMock).signIn(PROFILE_DATA2.getAccountName()); } @@ -393,7 +401,8 @@ mCoordinator = new AccountPickerBottomSheetCoordinator(mActivityTestRule.getActivity(), getBottomSheetController(), mAccountPickerDelegateMock); }); - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + CriteriaHelper.pollUiThread(mCoordinator.getBottomSheetViewForTesting().findViewById( + R.id.account_picker_continue_as_button)::isShown); } private void buildAndShowExpandedBottomSheet() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java index 7d53ad6..b3b7532 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkIntegrationTest.java
@@ -22,6 +22,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.FlakyTest; import org.chromium.chrome.browser.flags.ActivityType; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; @@ -85,6 +86,7 @@ @Test @LargeTest @Feature({"Webapps"}) + @FlakyTest(message = "https://crbug.com/1112352") public void testShare() throws TimeoutException { final String sharedSubject = "Fun tea parties"; final String sharedText = "Boston";
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java index dc28dd6..12aa5ad7 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java
@@ -44,6 +44,7 @@ import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.content_public.browser.NavigationHandle; +import org.chromium.net.NetError; /** * Tests for {@link QualityEnforcer}. @@ -96,34 +97,34 @@ @Test public void trigger_navigateTo404() { - navigateToUrl(TRUSTED_ORIGIN_PAGE, HTTP_ERROR_NOT_FOUND); + navigateToUrlNotFound(TRUSTED_ORIGIN_PAGE); verifyTriggered404(); } @Test public void notTrigger_navigationSuccess() { - navigateToUrl(TRUSTED_ORIGIN_PAGE, HTTP_STATUS_SUCCESS); + navigateToUrlNoError(TRUSTED_ORIGIN_PAGE); verifyNotTriggered(); } @Test public void notTrigger_navigateTo404NotVerifiedSite() { - navigateToUrl(UNTRUSTED_PAGE, HTTP_ERROR_NOT_FOUND); + navigateToUrlNotFound(UNTRUSTED_PAGE); verifyNotTriggered(); } @Test public void notTrigger_navigateFromNotVerifiedToVerified404() { - navigateToUrl(UNTRUSTED_PAGE, HTTP_STATUS_SUCCESS); - navigateToUrl(TRUSTED_ORIGIN_PAGE, HTTP_ERROR_NOT_FOUND); + navigateToUrlNoError(UNTRUSTED_PAGE); + navigateToUrlNotFound(TRUSTED_ORIGIN_PAGE); verifyNotTriggered(); } @Test public void trigger_notVerifiedToVerifiedThen404() { - navigateToUrl(UNTRUSTED_PAGE, HTTP_STATUS_SUCCESS); - navigateToUrl(TRUSTED_ORIGIN_PAGE, HTTP_STATUS_SUCCESS); - navigateToUrl(TRUSTED_ORIGIN_PAGE, HTTP_ERROR_NOT_FOUND); + navigateToUrlNoError(UNTRUSTED_PAGE); + navigateToUrlNoError(TRUSTED_ORIGIN_PAGE); + navigateToUrlNotFound(TRUSTED_ORIGIN_PAGE); verifyTriggered404(); } @@ -136,7 +137,7 @@ any(), eq(QualityEnforcer.CRASH), any())) .thenReturn(result); - navigateToUrl(TRUSTED_ORIGIN_PAGE, HTTP_ERROR_NOT_FOUND); + navigateToUrlNotFound(TRUSTED_ORIGIN_PAGE); verify(mActivity).finish(); } @@ -149,10 +150,16 @@ any(), eq(QualityEnforcer.CRASH), any())) .thenReturn(result); - navigateToUrl(TRUSTED_ORIGIN_PAGE, HTTP_ERROR_NOT_FOUND); + navigateToUrlNotFound(TRUSTED_ORIGIN_PAGE); verify(mActivity, never()).finish(); } + @Test + public void trigger_offline() { + navigateToUrlInternet(TRUSTED_ORIGIN_PAGE); + verifyTriggeredOffline(); + } + private void verifyTriggered404() { Assert.assertEquals(ContextUtils.getApplicationContext().getString( R.string.twa_quality_enforcement_violation_error, @@ -162,12 +169,33 @@ .sendExtraCallbackWithResult(any(), eq(QualityEnforcer.NOTIFY), any()); } + private void verifyTriggeredOffline() { + Assert.assertEquals( + ContextUtils.getApplicationContext().getString( + R.string.twa_quality_enforcement_violation_offline, TRUSTED_ORIGIN_PAGE), + ShadowToast.getTextOfLatestToast()); + verify(mCustomTabsConnection) + .sendExtraCallbackWithResult(any(), eq(QualityEnforcer.NOTIFY), any()); + } + private void verifyNotTriggered() { verify(mCustomTabsConnection, never()) .sendExtraCallbackWithResult(any(), eq(QualityEnforcer.NOTIFY), any()); } - private void navigateToUrl(String url, int httpStatusCode) { + private void navigateToUrlNoError(String url) { + navigateToUrl(url, HTTP_STATUS_SUCCESS, NetError.OK); + } + + private void navigateToUrlNotFound(String url) { + navigateToUrl(url, HTTP_ERROR_NOT_FOUND, NetError.OK); + } + + private void navigateToUrlInternet(String url) { + navigateToUrl(url, HTTP_STATUS_SUCCESS, NetError.ERR_INTERNET_DISCONNECTED); + } + + private void navigateToUrl(String url, int httpStatusCode, @NetError int errorCode) { when(mTab.getOriginalUrl()).thenReturn(url); NavigationHandle navigation = @@ -175,7 +203,7 @@ false /* isSameDocument */, false /* isRendererInitiated */); navigation.didFinish(url, false /* isErrorPage */, true /* hasCommitted */, false /* isFragmentNavigation */, false /* isDownload */, - false /* isValidSearchFormUrl */, 0 /* pageTransition */, 0 /* errorCode*/, + false /* isValidSearchFormUrl */, 0 /* pageTransition */, errorCode, httpStatusCode); for (CustomTabTabObserver tabObserver : mTabObserverCaptor.getAllValues()) { tabObserver.onDidFinishNavigation(mTab, navigation);
diff --git a/chrome/android/modules/chrome_bundle_tmpl.gni b/chrome/android/modules/chrome_bundle_tmpl.gni index 19673cb24..d9e4d08a 100644 --- a/chrome/android/modules/chrome_bundle_tmpl.gni +++ b/chrome/android/modules/chrome_bundle_tmpl.gni
@@ -88,7 +88,6 @@ "lint_min_sdk_version", "lint_suppressions_dep", "lint_suppressions_file", - "manifest_package", "min_sdk_version", "proguard_android_sdk_dep", "sign_bundle", @@ -103,6 +102,12 @@ system_image_locale_allowlist = android_apk_locales is_multi_abi = _is_multi_abi + # Use a consistent baseline so that it is easy to regenerate by deleting the + # file and re-building the "android_lint" target. + if (defined(invoker.enable_lint) && invoker.enable_lint) { + lint_baseline_file = "//chrome/android/expectations/lint-baseline.xml" + } + # List of DFMs that are installed by default by wrapper scripts, to make # testing easier. This removes the need to manually specify, e.g., # "-m dev_ui" on every install or run.
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 44028c2..a08df89 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-86.0.4208.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-86.0.4228.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index e923be4..520570c9 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -128,11 +128,12 @@ #endif #if defined(OS_ANDROID) -#include "base/android/library_loader/library_loader_hooks.h" #include "base/android/java_exception_reporter.h" +#include "base/android/library_loader/library_loader_hooks.h" #include "chrome/browser/android/crash/pure_java_exception_handler.h" #include "chrome/browser/android/metrics/uma_session_stats.h" #include "chrome/browser/flags/android/chrome_feature_list.h" +#include "chrome/common/android/cpu_affinity_experiments.h" #include "chrome/common/chrome_descriptors.h" #include "net/android/network_change_notifier_factory_android.h" #else // defined(OS_ANDROID) @@ -579,6 +580,13 @@ switches::kProcessType); bool is_browser_process = process_type.empty(); +#if defined(OS_ANDROID) + // For child processes, this requires whitelisting of the sched_setaffinity() + // syscall in the sandbox (baseline_policy_android.cc). When this call is + // removed, the sandbox whitelist should be updated too. + chrome::InitializeCpuAffinityExperiments(); +#endif + #if BUILDFLAG(ENABLE_GWP_ASAN_MALLOC) { version_info::Channel channel = chrome::GetChannel();
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 7a632dc..1263d6aa 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -516,6 +516,15 @@ <message name="IDS_OS_SETTINGS_AMBIENT_MODE_ALBUMS_SUBPAGE_PHOTOS_NUM_ONE" desc="1 photo in an album in ambient mode."> 1 photo </message> + <message name="IDS_OS_SETTINGS_AMBIENT_MODE_WEATHER_TITLE" desc="Label for the radio button group of weather."> + Weather + </message> + <message name="IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_FAHRENHEIT" desc="Label for the radio button to choose fahrenheit as the preferred temperature unit."> + Fahrenheit + </message> + <message name="IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_CELSIUS" desc="Label for the radio button to choose celsius as the preferred temperature unit."> + Celsius + </message> <!-- Search and Assistant section. --> <message name="IDS_OS_SETTINGS_SEARCH_ENGINE_LABEL" desc="Label in OS settings describing search engine behavior.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_CELSIUS.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_CELSIUS.png.sha1 new file mode 100644 index 0000000..97a98ff --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_CELSIUS.png.sha1
@@ -0,0 +1 @@ +ed42dfdad76f060f1e03cba3b5ff901838c6da1c \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_FAHRENHEIT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_FAHRENHEIT.png.sha1 new file mode 100644 index 0000000..97a98ff --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_FAHRENHEIT.png.sha1
@@ -0,0 +1 @@ +ed42dfdad76f060f1e03cba3b5ff901838c6da1c \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_WEATHER_TITLE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_WEATHER_TITLE.png.sha1 new file mode 100644 index 0000000..97a98ff --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_OS_SETTINGS_AMBIENT_MODE_WEATHER_TITLE.png.sha1
@@ -0,0 +1 @@ +ed42dfdad76f060f1e03cba3b5ff901838c6da1c \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 0771499..803ec3b 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -347,10 +347,10 @@ "content_settings/host_content_settings_map_factory.h", "content_settings/mixed_content_settings_tab_helper.cc", "content_settings/mixed_content_settings_tab_helper.h", + "content_settings/page_specific_content_settings_delegate.cc", + "content_settings/page_specific_content_settings_delegate.h", "content_settings/sound_content_setting_observer.cc", "content_settings/sound_content_setting_observer.h", - "content_settings/tab_specific_content_settings_delegate.cc", - "content_settings/tab_specific_content_settings_delegate.h", "crash_upload_list/crash_upload_list.cc", "crash_upload_list/crash_upload_list.h", "custom_handlers/protocol_handler_registry.cc",
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index a01ed3e..ed485f8 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -678,11 +678,13 @@ JNIEnv* env = AttachCurrentThread(); bool has_close_or_cancel = false; - auto chips = Java_AutofillAssistantUiController_createChipList(env); + auto jchips = Java_AutofillAssistantUiController_createChipList(env); + auto jsticky_chips = Java_AutofillAssistantUiController_createChipList(env); int user_action_count = static_cast<int>(user_actions.size()); for (int i = 0; i < user_action_count; i++) { const auto& action = user_actions[i]; const Chip& chip = action.chip(); + base::android::ScopedJavaLocalRef<jobject> jchip; switch (chip.type) { default: // Ignore actions with other chip types or with no chips. break; @@ -692,16 +694,17 @@ // can hide all the chips except for the cancel chip when the keyboard // is showing. // TODO(b/149543425): Find a better way to do this. - Java_AutofillAssistantUiController_addHighlightedActionButton( - env, java_object_, chips, chip.icon, - base::android::ConvertUTF8ToJavaString(env, chip.text), i, - !action.enabled(), chip.sticky, - base::android::ConvertUTF8ToJavaString(env, "")); + jchip = + Java_AutofillAssistantUiController_createHighlightedActionButton( + env, java_object_, chip.icon, + base::android::ConvertUTF8ToJavaString(env, chip.text), i, + !action.enabled(), chip.sticky, + base::android::ConvertUTF8ToJavaString(env, "")); break; case NORMAL_ACTION: - Java_AutofillAssistantUiController_addActionButton( - env, java_object_, chips, chip.icon, + jchip = Java_AutofillAssistantUiController_createActionButton( + env, java_object_, chip.icon, base::android::ConvertUTF8ToJavaString(env, chip.text), i, !action.enabled(), chip.sticky, base::android::ConvertUTF8ToJavaString(env, "")); @@ -710,8 +713,8 @@ case CANCEL_ACTION: // A Cancel button sneaks in an UNDO snackbar before executing the // action, while a close button behaves like a normal button. - Java_AutofillAssistantUiController_addCancelButton( - env, java_object_, chips, chip.icon, + jchip = Java_AutofillAssistantUiController_createCancelButton( + env, java_object_, chip.icon, base::android::ConvertUTF8ToJavaString(env, chip.text), i, !action.enabled(), chip.sticky, base::android::ConvertUTF8ToJavaString(env, kCancelChipIdentifier)); @@ -719,8 +722,8 @@ break; case CLOSE_ACTION: - Java_AutofillAssistantUiController_addActionButton( - env, java_object_, chips, chip.icon, + jchip = Java_AutofillAssistantUiController_createActionButton( + env, java_object_, chip.icon, base::android::ConvertUTF8ToJavaString(env, chip.text), i, !action.enabled(), chip.sticky, base::android::ConvertUTF8ToJavaString(env, "")); @@ -728,33 +731,50 @@ break; case DONE_ACTION: - Java_AutofillAssistantUiController_addHighlightedActionButton( - env, java_object_, chips, chip.icon, - base::android::ConvertUTF8ToJavaString(env, chip.text), i, - !action.enabled(), chip.sticky, - base::android::ConvertUTF8ToJavaString(env, "")); + jchip = + Java_AutofillAssistantUiController_createHighlightedActionButton( + env, java_object_, chip.icon, + base::android::ConvertUTF8ToJavaString(env, chip.text), i, + !action.enabled(), chip.sticky, + base::android::ConvertUTF8ToJavaString(env, "")); has_close_or_cancel = true; break; } + if (jchip) { + Java_AutofillAssistantUiController_appendChipToList(env, jchips, jchip); + if (chip.sticky) { + Java_AutofillAssistantUiController_appendChipToList(env, jsticky_chips, + jchip); + } + } } if (!has_close_or_cancel) { + base::android::ScopedJavaLocalRef<jobject> jcancel_chip; if (ui_delegate_->GetState() == AutofillAssistantState::STOPPED) { - Java_AutofillAssistantUiController_addCloseButton( - env, java_object_, chips, ICON_CLEAR, + jcancel_chip = Java_AutofillAssistantUiController_createCloseButton( + env, java_object_, ICON_CLEAR, base::android::ConvertUTF8ToJavaString(env, ""), /* disabled= */ false, /* sticky= */ true, base::android::ConvertUTF8ToJavaString(env, "")); } else if (ui_delegate_->GetState() != AutofillAssistantState::INACTIVE) { - Java_AutofillAssistantUiController_addCancelButton( - env, java_object_, chips, ICON_CLEAR, + jcancel_chip = Java_AutofillAssistantUiController_createCancelButton( + env, java_object_, ICON_CLEAR, base::android::ConvertUTF8ToJavaString(env, ""), -1, /* disabled= */ false, /* sticky= */ true, base::android::ConvertUTF8ToJavaString(env, kCancelChipIdentifier)); } + if (jcancel_chip) { + Java_AutofillAssistantUiController_appendChipToList(env, jchips, + jcancel_chip); + Java_AutofillAssistantUiController_appendChipToList(env, jsticky_chips, + jcancel_chip); + } } - Java_AutofillAssistantUiController_setActions(env, java_object_, chips); + Java_AutofillAssistantUiController_setActions(env, java_object_, jchips); + Java_AssistantHeaderModel_setChips(AttachCurrentThread(), GetHeaderModel(), + jsticky_chips); } void UiControllerAndroid::OnUserActionsChanged(
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc index 1c3c55bb..354c959c 100644 --- a/chrome/browser/apps/app_service/app_icon_factory.cc +++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -391,6 +391,9 @@ // The scale factor the icon is intended for. See gfx::ImageSkiaRep::scale // comments. float icon_scale_ = 0.0f; + // A scale factor to take as input for the IconType::kCompressed response. See + // gfx::ImageSkia::GetRepresentation() comments. + float icon_scale_for_compressed_response_ = 1.0f; bool is_placeholder_icon_; apps::IconEffects icon_effects_; @@ -441,6 +444,16 @@ fallback_favicon_url_ = launch_url; profile_ = profile; + + // In all other callpaths MaybeApplyEffectsAndComplete() uses + // |icon_scale_for_compressed_response_| to apps::EncodeImageToPngBytes(). In + // most cases IconLoadingPipeline always uses the 1.0 intended icon scale + // factor as an intermediate representation to be compressed and returned. + // TODO(crbug.com/1112737): Investigate how to unify it and set + // |icon_scale_for_compressed_response_| value in IconLoadingPipeline() + // constructor. + icon_scale_for_compressed_response_ = icon_scale_; + if (icon_manager.HasSmallestIcon(web_app_id, icon_size_in_px_)) { switch (icon_type_) { case apps::mojom::IconType::kCompressed: @@ -509,11 +522,8 @@ // LoadImageAtEveryScaleFactorAsync here, because the caller has asked // for compressed icons (i.e. PNG-formatted data), not uncompressed // (i.e. a gfx::ImageSkia). - constexpr bool quantize_to_supported_scale_factor = true; - int size_hint_in_px = apps_util::ConvertDipToPx( - size_hint_in_dip_, quantize_to_supported_scale_factor); LoadCompressedDataFromExtension( - extension, size_hint_in_px, + extension, icon_size_in_px_, base::BindOnce(&IconLoadingPipeline::CompleteWithCompressed, base::WrapRefCounted(this))); return; @@ -774,7 +784,8 @@ processed_image.MakeThreadSafe(); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&apps::EncodeImageToPngBytes, processed_image), + base::BindOnce(&apps::EncodeImageToPngBytes, processed_image, + icon_scale_for_compressed_response_), base::BindOnce(&IconLoadingPipeline::CompleteWithCompressed, base::WrapRefCounted(this))); } @@ -807,10 +818,8 @@ } void IconLoadingPipeline::MaybeLoadFallbackOrCompleteEmpty() { - const int icon_size_in_px = apps_util::ConvertDipToPx( - size_hint_in_dip_, /*quantize_to_supported_scale_factor=*/true); if (fallback_favicon_url_.is_valid() && - icon_size_in_px == kFaviconFallbackImagePx) { + icon_size_in_px_ == kFaviconFallbackImagePx) { GURL favicon_url = fallback_favicon_url_; // Reset to avoid infinite loops. fallback_favicon_url_ = GURL(); @@ -899,14 +908,16 @@ std::move(callback), icon_scale); } -std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image) { +std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image, + float rep_icon_scale) { base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, base::BlockingType::MAY_BLOCK); std::vector<uint8_t> image_data; - const gfx::ImageSkiaRep& image_skia_rep = image.GetRepresentation(1.0f); - if (image_skia_rep.scale() != 1.0f) { + const gfx::ImageSkiaRep& image_skia_rep = + image.GetRepresentation(rep_icon_scale); + if (image_skia_rep.scale() != rep_icon_scale) { return image_data; }
diff --git a/chrome/browser/apps/app_service/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon_factory.h index 1238d4ce..475d38a 100644 --- a/chrome/browser/apps/app_service/app_icon_factory.h +++ b/chrome/browser/apps/app_service/app_icon_factory.h
@@ -60,10 +60,12 @@ base::OnceCallback<void(gfx::ImageSkia)> callback, float icon_scale); -// Encode the ImageSkia to the compressed PNG data with the image's 1.0f scale -// factor representation. Return the encoded PNG data. -// This function should not be called on the UI thread. -std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image); +// Encodes a single SkBitmap representation from the given ImageSkia to the +// compressed PNG data. |rep_icon_scale| argument denotes, which ImageSkiaRep to +// take as input. See ImageSkia::GetRepresentation() comments. Returns the +// encoded PNG data. This function should not be called on the UI thread. +std::vector<uint8_t> EncodeImageToPngBytes(const gfx::ImageSkia image, + float rep_icon_scale); #if defined(OS_CHROMEOS) void ArcRawIconPngDataToImageSkia(
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index 55cc8d9..c4607a1de 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -130,7 +130,8 @@ iv->uncompressed.MakeThreadSafe(); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&apps::EncodeImageToPngBytes, iv->uncompressed), + base::BindOnce(&apps::EncodeImageToPngBytes, iv->uncompressed, + /*rep_icon_scale=*/1.0f), base::BindOnce(&CompleteWithCompressed, std::move(callback))); return; }
diff --git a/chrome/browser/browsing_data/README.md b/chrome/browser/browsing_data/README.md index b48040e..3493a2a 100644 --- a/chrome/browser/browsing_data/README.md +++ b/chrome/browser/browsing_data/README.md
@@ -27,7 +27,7 @@ some details (e.g. full details for cookies, but only the usage of other storage typess). -* TabSpecificContentSettings is notified on storage access/blocked. +* PageSpecificContentSettings is notified on storage access/blocked. * It calls into the "canned" helper instance for the storage type. * The "canned" instance records necessary "pending" info about the access. * On demand, the "pending" info is used to populate a CookiesTreeModel.
diff --git a/chrome/browser/browsing_data/access_context_audit_database.cc b/chrome/browser/browsing_data/access_context_audit_database.cc index a15cd87f..e7997bc 100644 --- a/chrome/browser/browsing_data/access_context_audit_database.cc +++ b/chrome/browser/browsing_data/access_context_audit_database.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/browsing_data/access_context_audit_database.h" #include "base/logging.h" +#include "net/cookies/cookie_util.h" #include "sql/database.h" #include "sql/meta_table.h" #include "sql/recovery.h" @@ -72,6 +73,25 @@ return db->Execute(remove.c_str()); } +bool IsContentSettingSessionOnly( + const GURL& url, + const ContentSettingsForOneType& content_settings) { + // ContentSettingsForOneType are in order of decreasing specificity, such + // that the first matching entry defines the effective content setting. + for (const auto& setting : content_settings) { + // A match is performed against both primary and secondary patterns. This + // aligns with the behavior in CookieSettingsBase::ShouldDeleteCookieOnExit, + // which is used by the cookie store. + if (setting.primary_pattern.Matches(url) && + setting.secondary_pattern.Matches(url)) { + return setting.GetContentSetting() == + ContentSetting::CONTENT_SETTING_SESSION_ONLY; + } + } + NOTREACHED(); + return false; +} + } // namespace AccessContextAuditDatabase::AccessRecord::AccessRecord( @@ -339,51 +359,70 @@ } void AccessContextAuditDatabase::RemoveSessionOnlyRecords( - scoped_refptr<content_settings::CookieSettings> cookie_settings, const ContentSettingsForOneType& content_settings) { + // ContentSettingsForOneType is a list of settings in decreasing specificity + // for origins, ending with a setting that matches all and is the default. + DCHECK(content_settings.size()); + if (content_settings.size() == 1) { + DCHECK_EQ(content_settings[0].primary_pattern, + ContentSettingsPattern::Wildcard()); + DCHECK_EQ(content_settings[0].secondary_pattern, + ContentSettingsPattern::Wildcard()); + if (content_settings[0].GetContentSetting() == + ContentSetting::CONTENT_SETTING_SESSION_ONLY) { + RemoveAllRecords(); + } + // As only the default content setting is set, there is no need to inspect + // any individual records. + return; + } + sql::Transaction transaction(&db_); if (!transaction.Begin()) return; - // Extract the set of all domains from the cookies table. + // Extract the set of all domains from the cookies table, determine the + // effective content setting, and store for removal if appropriate. std::string select = "SELECT DISTINCT domain FROM "; select.append(kCookieTableName); sql::Statement select_cookie_domains( db_.GetCachedStatement(SQL_FROM_HERE, select.c_str())); - std::vector<std::string> cookie_domains; + std::vector<std::string> cookie_domains_for_removal; while (select_cookie_domains.Step()) { - cookie_domains.emplace_back(select_cookie_domains.ColumnString(0)); + auto domain = select_cookie_domains.ColumnString(0); + GURL url = net::cookie_util::CookieOriginToURL(domain, + /* is_https */ false); + GURL secure_url = net::cookie_util::CookieOriginToURL(domain, + /* is_https */ true); + if (IsContentSettingSessionOnly(url, content_settings) || + IsContentSettingSessionOnly(secure_url, content_settings)) { + cookie_domains_for_removal.emplace_back(std::move(domain)); + } } - // Extract the set of all origins from the storage API table. + // Repeat the above, but for the origin keyed storage API table. select = "SELECT DISTINCT origin FROM "; select.append(kStorageAPITableName); sql::Statement select_storage_origins( db_.GetCachedStatement(SQL_FROM_HERE, select.c_str())); - std::vector<url::Origin> storage_origins; + std::vector<std::string> storage_origins_for_removal; while (select_storage_origins.Step()) { - storage_origins.emplace_back( - url::Origin::Create(GURL(select_storage_origins.ColumnString(0)))); + auto origin = select_storage_origins.ColumnString(0); + if (IsContentSettingSessionOnly(GURL(origin), content_settings)) + storage_origins_for_removal.emplace_back(origin); } - // Remove records for all cookie domains and storage origins for which the - // provided settings indicate should be cleared on exit. + // Remove entries belonging to cookie domains and origins identified as having + // a SESSION_ONLY content setting. std::string remove = "DELETE FROM "; remove.append(kCookieTableName); remove.append(" WHERE domain = ?"); sql::Statement remove_cookies( db_.GetCachedStatement(SQL_FROM_HERE, remove.c_str())); - for (const auto& domain : cookie_domains) { - if (!cookie_settings->ShouldDeleteCookieOnExit(content_settings, domain, - true) && - !cookie_settings->ShouldDeleteCookieOnExit(content_settings, domain, - false)) { - continue; - } - + for (const auto& domain : cookie_domains_for_removal) { remove_cookies.BindString(0, domain); if (!remove_cookies.Run()) return; @@ -396,13 +435,8 @@ sql::Statement remove_storage_apis( db_.GetCachedStatement(SQL_FROM_HERE, remove.c_str())); - for (const auto& origin : storage_origins) { - // TODO(crbug.com/1099164): Rename IsCookieSessionOnly to better convey - // its actual functionality. - if (!cookie_settings->IsCookieSessionOnly(origin.GetURL())) - continue; - - remove_storage_apis.BindString(0, origin.Serialize()); + for (const auto& origin : storage_origins_for_removal) { + remove_storage_apis.BindString(0, origin); if (!remove_storage_apis.Run()) return; remove_storage_apis.Reset(true);
diff --git a/chrome/browser/browsing_data/access_context_audit_database.h b/chrome/browser/browsing_data/access_context_audit_database.h index b80b796..e4e631d 100644 --- a/chrome/browser/browsing_data/access_context_audit_database.h +++ b/chrome/browser/browsing_data/access_context_audit_database.h
@@ -104,10 +104,10 @@ void RemoveAllRecordsForTopFrameOrigins( const std::vector<url::Origin>& origins); - // Removes all records for cookie domains and API origins that match session - // only entries in |settings| + // Removes all records for which the result of inspecting |content_settings| + // for the storage origin or cookie domain is a content setting of + // CLEAR_ON_EXIT. void RemoveSessionOnlyRecords( - scoped_refptr<content_settings::CookieSettings> cookie_settings, const ContentSettingsForOneType& content_settings); protected:
diff --git a/chrome/browser/browsing_data/access_context_audit_database_unittest.cc b/chrome/browser/browsing_data/access_context_audit_database_unittest.cc index 8eca3b50..98c06c94 100644 --- a/chrome/browser/browsing_data/access_context_audit_database_unittest.cc +++ b/chrome/browser/browsing_data/access_context_audit_database_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/browsing_data/access_context_audit_database.h" #include "base/files/scoped_temp_dir.h" +#include "components/content_settings/core/common/content_settings_utils.h" #include "sql/database.h" #include "sql/test/scoped_error_expecter.h" #include "testing/gtest/include/gtest/gtest.h" @@ -459,3 +460,63 @@ EXPECT_EQ(num_test_cookie_entries, cookie_rows); EXPECT_EQ(num_test_storage_entries, storage_api_rows); } + +TEST_F(AccessContextAuditDatabaseTest, RemoveSessionOnlyRecords) { + // Check that records are cleared appropriately by RemoveSessionOnlyRecords + // when the provided content settings indicate they should. + auto test_records = GetTestRecords(); + OpenDatabase(); + database()->AddRecords(test_records); + ValidateDatabaseRecords(database(), test_records); + + // Test that default content setting of SESSION_ONLY results in all records + // being removed. + ContentSettingsForOneType content_settings; + content_settings.emplace_back( + ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), + base::Value::FromUniquePtrValue(content_settings::ContentSettingToValue( + CONTENT_SETTING_SESSION_ONLY)), + std::string(), /* incognito */ false); + + database()->RemoveSessionOnlyRecords(content_settings); + ValidateDatabaseRecords(database(), {}); + + // Check that a more targeted content setting also removes the appropriate + // records. + content_settings.clear(); + database()->AddRecords(test_records); + ValidateDatabaseRecords(database(), test_records); + + content_settings.emplace_back( + ContentSettingsPattern::FromString(kManyContextsCookieDomain), + ContentSettingsPattern::Wildcard(), + base::Value::FromUniquePtrValue(content_settings::ContentSettingToValue( + CONTENT_SETTING_SESSION_ONLY)), + std::string(), /* incognito */ false); + content_settings.emplace_back( + ContentSettingsPattern::FromString(kManyContextsStorageAPIOrigin), + ContentSettingsPattern::Wildcard(), + base::Value::FromUniquePtrValue(content_settings::ContentSettingToValue( + CONTENT_SETTING_SESSION_ONLY)), + std::string(), /* incognito */ false); + content_settings.emplace_back( + ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), + base::Value::FromUniquePtrValue( + content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW)), + std::string(), /* incognito */ false); + database()->RemoveSessionOnlyRecords(content_settings); + + test_records.erase( + std::remove_if( + test_records.begin(), test_records.end(), + [=](const AccessContextAuditDatabase::AccessRecord& record) { + if (record.type == + AccessContextAuditDatabase::StorageAPIType::kCookie) { + return record.domain == kManyContextsCookieDomain; + } + return record.origin == + url::Origin::Create(GURL(kManyContextsStorageAPIOrigin)); + }), + test_records.end()); + ValidateDatabaseRecords(database(), test_records); +}
diff --git a/chrome/browser/browsing_data/access_context_audit_service.cc b/chrome/browser/browsing_data/access_context_audit_service.cc index ced41ab..4a55922 100644 --- a/chrome/browser/browsing_data/access_context_audit_service.cc +++ b/chrome/browser/browsing_data/access_context_audit_service.cc
@@ -192,6 +192,5 @@ database_task_runner_->PostTask( FROM_HERE, base::BindOnce(&AccessContextAuditDatabase::RemoveSessionOnlyRecords, - database_, CookieSettingsFactory::GetForProfile(profile_), - std::move(settings))); + database_, std::move(settings))); }
diff --git a/chrome/browser/browsing_data/access_context_audit_service_unittest.cc b/chrome/browser/browsing_data/access_context_audit_service_unittest.cc index eae050481..d5a6799 100644 --- a/chrome/browser/browsing_data/access_context_audit_service_unittest.cc +++ b/chrome/browser/browsing_data/access_context_audit_service_unittest.cc
@@ -448,12 +448,7 @@ CheckContainsStorageAPIRecord(kOrigin1, kTestStorageType2, kOrigin1, records); } -#if defined(THREAD_SANITIZER) -#define MAYBE_SessionOnlyRecords DISABLED_SessionOnlyRecords -#else -#define MAYBE_SessionOnlyRecords SessionOnlyRecords -#endif -TEST_F(AccessContextAuditServiceTest, MAYBE_SessionOnlyRecords) { +TEST_F(AccessContextAuditServiceTest, SessionOnlyRecords) { // Check that data for cookie domains and storage origins are cleared on // service shutdown when the associated content settings indicate they should. const GURL kTestPersistentURL("https://persistent.com"); @@ -516,4 +511,13 @@ kTopFrameOrigin, records); CheckContainsStorageAPIRecord(url::Origin::Create(GURL(kTestPersistentURL)), kTestStorageType, kTopFrameOrigin, records); + + // Update the default content setting to SESSION_ONLY and ensure that all + // records are cleared. + HostContentSettingsMapFactory::GetForProfile(profile()) + ->SetDefaultContentSetting(ContentSettingsType::COOKIES, + ContentSetting::CONTENT_SETTING_SESSION_ONLY); + service()->ClearSessionOnlyRecords(); + records = GetAllAccessRecords(); + ASSERT_EQ(0u, records.size()); }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 68b973e..91b9459 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -192,7 +192,7 @@ #include "components/cdm/browser/cdm_message_filter_android.h" #include "components/certificate_matching/certificate_principal_pattern.h" #include "components/cloud_devices/common/cloud_devices_switches.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -2515,7 +2515,7 @@ // Check if this is an extension-related service worker, and, if so, if it's // allowed (this can return false if, e.g., the extension is disabled). // If it's not allowed, return immediately. We deliberately do *not* report - // to the TabSpecificContentSettings, since the service worker is blocked + // to the PageSpecificContentSettings, since the service worker is blocked // because of the extension, rather than because of the user's content // settings. if (!ChromeContentBrowserClientExtensionsPart::AllowServiceWorkerOnIO( @@ -2557,7 +2557,7 @@ // Check if this is an extension-related service worker, and, if so, if it's // allowed (this can return false if, e.g., the extension is disabled). // If it's not allowed, return immediately. We deliberately do *not* report - // to the TabSpecificContentSettings, since the service worker is blocked + // to the PageSpecificContentSettings, since the service worker is blocked // because of the extension, rather than because of the user's content // settings. if (!ChromeContentBrowserClientExtensionsPart::AllowServiceWorkerOnUI( @@ -2603,7 +2603,7 @@ ->IsCookieAccessAllowed(worker_url, site_for_cookies, top_frame_origin); - content_settings::TabSpecificContentSettings::SharedWorkerAccessed( + content_settings::PageSpecificContentSettings::SharedWorkerAccessed( render_process_id, render_frame_id, worker_url, name, constructor_origin, !allow); return allow; @@ -2687,7 +2687,7 @@ bool allow) { // Record access to file system for potential display in UI. for (const auto& it : render_frames) { - content_settings::TabSpecificContentSettings::FileSystemAccessed( + content_settings::PageSpecificContentSettings::FileSystemAccessed( it.child_id, it.frame_routing_id, url, !allow); } std::move(callback).Run(allow); @@ -2704,7 +2704,7 @@ // Record access to IndexedDB for potential display in UI. for (const auto& it : render_frames) { - content_settings::TabSpecificContentSettings::IndexedDBAccessed( + content_settings::PageSpecificContentSettings::IndexedDBAccessed( it.child_id, it.frame_routing_id, url, !allow); } @@ -2721,7 +2721,7 @@ // Record access to CacheStorage for potential display in UI. for (const auto& it : render_frames) { - content_settings::TabSpecificContentSettings::CacheStorageAccessed( + content_settings::PageSpecificContentSettings::CacheStorageAccessed( it.child_id, it.frame_routing_id, url, !allow); }
diff --git a/chrome/browser/chrome_service_worker_browsertest.cc b/chrome/browser/chrome_service_worker_browsertest.cc index 2af369c..2399b571 100644 --- a/chrome/browser/chrome_service_worker_browsertest.cc +++ b/chrome/browser/chrome_service_worker_browsertest.cc
@@ -27,7 +27,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/test_chrome_web_ui_controller_factory.h" #include "chrome/test/base/ui_test_utils.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/pref_names.h" #include "components/favicon/content/content_favicon_driver.h" @@ -222,7 +222,7 @@ content::RenderFrameHost* main_frame = browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(); EXPECT_TRUE( - content_settings::TabSpecificContentSettings::GetForFrame(main_frame) + content_settings::PageSpecificContentSettings::GetForFrame(main_frame) ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); }
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 157dcac..ea61dc36 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -989,6 +989,8 @@ "crostini/crosvm_process_list.h", "crostini/fake_crostini_installer_ui_delegate.cc", "crostini/fake_crostini_installer_ui_delegate.h", + "crostini/termina_installer.cc", + "crostini/termina_installer.h", "crostini/throttle/crostini_active_window_throttle_observer.cc", "crostini/throttle/crostini_active_window_throttle_observer.h", "crostini/throttle/crostini_throttle.cc", @@ -1873,10 +1875,10 @@ "platform_keys/extension_platform_keys_service.h", "platform_keys/extension_platform_keys_service_factory.cc", "platform_keys/extension_platform_keys_service_factory.h", - "platform_keys/key_permissions.cc", - "platform_keys/key_permissions.h", - "platform_keys/key_permissions_policy_handler.cc", - "platform_keys/key_permissions_policy_handler.h", + "platform_keys/key_permissions/key_permissions.cc", + "platform_keys/key_permissions/key_permissions.h", + "platform_keys/key_permissions/key_permissions_policy_handler.cc", + "platform_keys/key_permissions/key_permissions_policy_handler.h", "platform_keys/platform_keys_service.cc", "platform_keys/platform_keys_service.h", "platform_keys/platform_keys_service_factory.cc", @@ -3085,6 +3087,7 @@ "crostini/crostini_util_unittest.cc", "crostini/crosvm_metrics_unittest.cc", "crostini/crosvm_process_list_unittest.cc", + "crostini/termina_installer_unittest.cc", "crostini/throttle/crostini_active_window_throttle_observer_unittest.cc", "crostini/throttle/crostini_throttle_unittest.cc", "cryptauth/client_app_metadata_provider_service_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc index 725f0b0..4ff9ffc 100644 --- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc +++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.cc
@@ -13,7 +13,7 @@ #include "base/callback.h" #include "base/logging.h" #include "base/memory/singleton.h" -#include "chrome/browser/chromeos/platform_keys/key_permissions.h" +#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/net/nss_context.h" #include "chrome/browser/policy/profile_policy_connector.h" @@ -82,7 +82,7 @@ std::string spki_der = chromeos::platform_keys::GetSubjectPublicKeyInfo(cert); std::string public_key_spki_der_b64; base::Base64Encode(spki_der, &public_key_spki_der_b64); - if (!chromeos::KeyPermissions::IsCorporateKeyForProfile( + if (!chromeos::platform_keys::KeyPermissions::IsCorporateKeyForProfile( public_key_spki_der_b64, prefs)) { DVLOG(1) << "Certificate is not allowed to be used by ARC."; return false; @@ -303,9 +303,8 @@ void ArcCertStoreBridge::UpdateFromKeyPermissionsPolicy() { DVLOG(1) << "ArcCertStoreBridge::UpdateFromKeyPermissionsPolicy"; - std::vector<std::string> app_ids = - chromeos::KeyPermissions::GetCorporateKeyUsageAllowedAppIds( - policy_service_); + std::vector<std::string> app_ids = chromeos::platform_keys::KeyPermissions:: + GetCorporateKeyUsageAllowedAppIds(policy_service_); std::vector<std::string> permissions; for (const auto& app_id : app_ids) { if (LooksLikeAndroidPackageName(app_id))
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc index b54cef5..2f7742c7 100644 --- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc +++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc
@@ -15,7 +15,7 @@ #include "chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge.h" #include "chrome/browser/chromeos/arc/session/arc_service_launcher.h" #include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h" -#include "chrome/browser/chromeos/platform_keys/key_permissions.h" +#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/policy/user_policy_test_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -210,7 +210,7 @@ extensions::StateStore* const state_store = extensions::ExtensionSystem::Get(browser()->profile())->state_store(); - chromeos::KeyPermissions permissions( + chromeos::platform_keys::KeyPermissions permissions( policy_connector->IsManaged(), browser()->profile()->GetPrefs(), policy_connector->policy_service(), state_store); @@ -262,13 +262,15 @@ // client_cert2_ is not allowed. void GotPermissionsForExtension( const base::Closure& done_callback, - std::unique_ptr<chromeos::KeyPermissions::PermissionsForExtension> + std::unique_ptr< + chromeos::platform_keys::KeyPermissions::PermissionsForExtension> permissions_for_ext) { std::string client_cert1_spki( client_cert1_->derPublicKey.data, client_cert1_->derPublicKey.data + client_cert1_->derPublicKey.len); permissions_for_ext->RegisterKeyForCorporateUsage( - client_cert1_spki, {chromeos::KeyPermissions::KeyLocation::kUserSlot}); + client_cert1_spki, + {chromeos::platform_keys::KeyPermissions::KeyLocation::kUserSlot}); done_callback.Run(); }
diff --git a/chrome/browser/chromeos/crostini/crostini_installer_unittest.cc b/chrome/browser/chromeos/crostini/crostini_installer_unittest.cc index c5bef593..47d66350 100644 --- a/chrome/browser/chromeos/crostini/crostini_installer_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_installer_unittest.cc
@@ -16,11 +16,14 @@ #include "chrome/browser/chromeos/crostini/crostini_installer_ui_delegate.h" #include "chrome/browser/chromeos/crostini/crostini_test_helper.h" #include "chrome/browser/chromeos/crostini/crostini_types.mojom.h" +#include "chrome/browser/component_updater/fake_cros_component_manager.h" +#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/concierge/concierge_service.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" #include "chromeos/dbus/fake_concierge_client.h" #include "chromeos/disks/disk_mount_manager.h" #include "chromeos/disks/mock_disk_mount_manager.h" @@ -114,9 +117,21 @@ CrostiniInstallerTest() : local_state_(std::make_unique<ScopedTestingLocalState>( - TestingBrowserProcess::GetGlobal())) {} + TestingBrowserProcess::GetGlobal())), + browser_part_(g_browser_process->platform_part()) {} void SetUp() override { + component_manager_ = + base::MakeRefCounted<component_updater::FakeCrOSComponentManager>(); + component_manager_->set_supported_components({"cros-termina"}); + component_manager_->ResetComponentState( + "cros-termina", + component_updater::FakeCrOSComponentManager::ComponentInfo( + component_updater::CrOSComponentManager::Error::NONE, + base::FilePath("/install/path"), base::FilePath("/mount/path"))); + browser_part_.InitializeCrosComponentManager(component_manager_); + + chromeos::DlcserviceClient::InitializeFake(); waiting_fake_concierge_client_ = new WaitingFakeConciergeClient; chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient( base::WrapUnique(waiting_fake_concierge_client_)); @@ -147,6 +162,10 @@ chromeos::disks::MockDiskMountManager::Shutdown(); chromeos::DBusThreadManager::Shutdown(); + chromeos::DlcserviceClient::Shutdown(); + + browser_part_.ShutdownCrosComponentManager(); + component_manager_.reset(); } void Install() { @@ -182,6 +201,8 @@ private: std::unique_ptr<ScopedTestingLocalState> local_state_; + scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_; + BrowserProcessPlatformPartTestApi browser_part_; DISALLOW_COPY_AND_ASSIGN(CrostiniInstallerTest); };
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index dc3d23f..dfd2e1a 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -311,7 +311,7 @@ } StartStage(mojom::InstallerState::kInstallImageLoader); - crostini_manager_->InstallTerminaComponent( + crostini_manager_->InstallTermina( base::BindOnce(&CrostiniRestarter::LoadComponentFinished, weak_ptr_factory_.GetWeakPtr())); } @@ -675,7 +675,6 @@ CrostiniManager::RestartId CrostiniManager::CrostiniRestarter::next_restart_id_ = 0; -bool CrostiniManager::is_cros_termina_registered_ = false; // Unit tests need this initialized to true. In Browser tests and real life, // it is updated via MaybeUpdateCrostini. bool CrostiniManager::is_dev_kvm_present_ = true; @@ -977,29 +976,16 @@ } // static -bool CrostiniManager::IsCrosTerminaInstalled() { - return is_cros_termina_registered_; -} - -// static bool CrostiniManager::IsDevKvmPresent() { return is_dev_kvm_present_; } void CrostiniManager::MaybeUpdateCrostini() { - scoped_refptr<component_updater::CrOSComponentManager> component_manager = - g_browser_process->platform_part()->cros_component_manager(); - if (!component_manager) { - // |component_manager| may be nullptr in unit tests. - return; - } // This is a new user session, perhaps using an old CrostiniManager. container_upgrade_prompt_shown_.clear(); base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock()}, - base::BindOnce( - CrostiniManager::CheckPathsAndComponents, - g_browser_process->platform_part()->cros_component_manager()), + base::BindOnce(&CrostiniManager::CheckPaths), base::BindOnce(&CrostiniManager::MaybeUpdateCrostiniAfterChecks, weak_ptr_factory_.GetWeakPtr())); // Probe Concierge - if it's still running after an unclean shutdown, a @@ -1030,167 +1016,51 @@ } // static -void CrostiniManager::CheckPathsAndComponents( - scoped_refptr<component_updater::CrOSComponentManager> component_manager) { - DCHECK(component_manager); +void CrostiniManager::CheckPaths() { is_dev_kvm_present_ = base::PathExists(base::FilePath("/dev/kvm")); - is_cros_termina_registered_ = component_manager->IsRegisteredMayBlock( - imageloader::kTerminaComponentName); } void CrostiniManager::MaybeUpdateCrostiniAfterChecks() { if (!is_dev_kvm_present_) { return; } - if (!is_cros_termina_registered_) { + if (!CrostiniFeatures::Get()->IsEnabled(profile_)) { return; } if (!CrostiniFeatures::Get()->IsAllowed(profile_)) { return; } - termina_update_check_needed_ = true; - if (content::GetNetworkConnectionTracker()->IsOffline()) { - // Can't do a component Load with kForce when offline. - VLOG(1) << "Not online, so can't check now for cros-termina upgrade."; - return; - } if (ShouldPromptContainerUpgrade(DefaultContainerId())) { upgrade_available_notification_ = CrostiniUpgradeAvailableNotification::Show(profile_, base::DoNothing()); } - InstallTerminaComponent(base::DoNothing()); + // TODO(crbug/953544) Remove this once we have transitioned completely to DLC + InstallTermina(base::DoNothing()); } -using UpdatePolicy = component_updater::CrOSComponentManager::UpdatePolicy; - -void CrostiniManager::InstallTerminaComponent(CrostiniResultCallback callback) { - scoped_refptr<component_updater::CrOSComponentManager> component_manager = - g_browser_process->platform_part()->cros_component_manager(); - if (!component_manager) { - // Running in a unit test. We still PostTask to prevent races. - content::GetUIThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&CrostiniManager::OnInstallTerminaComponent, - weak_ptr_factory_.GetWeakPtr(), std::move(callback), - true, component_manager_load_error_for_testing_, - base::FilePath())); - return; - } - - DCHECK(component_manager); - - bool major_update_required = - is_cros_termina_registered_ && - component_manager->GetCompatiblePath(imageloader::kTerminaComponentName) - .empty(); - bool is_offline = content::GetNetworkConnectionTracker()->IsOffline(); - - if (major_update_required) { - termina_update_check_needed_ = false; - if (is_offline) { - LOG(ERROR) << "Need to load a major component update, but we're offline."; - // TODO(nverne): Show a dialog/notification here for online upgrade - // required. - std::move(callback).Run(CrostiniResult::OFFLINE_WHEN_UPGRADE_REQUIRED); - return; - } - } - - UpdatePolicy update_policy; - if (termina_update_check_needed_ && !is_offline) { - // Don't use kForce all the time because it generates traffic to - // ComponentUpdaterService. Also, it's only appropriate for minor version - // updates. Not major version incompatiblility. - update_policy = UpdatePolicy::kForce; - } else { - update_policy = UpdatePolicy::kDontForce; - } - - component_manager->Load( - imageloader::kTerminaComponentName, - component_updater::CrOSComponentManager::MountPolicy::kMount, - update_policy, - base::BindOnce(&CrostiniManager::OnInstallTerminaComponent, - weak_ptr_factory_.GetWeakPtr(), std::move(callback), - update_policy == UpdatePolicy::kForce)); +void CrostiniManager::InstallTermina(CrostiniResultCallback callback) { + termina_installer_.Install(base::BindOnce( + [](CrostiniResultCallback callback, + TerminaInstaller::InstallResult result) { + CrostiniResult res; + if (result == TerminaInstaller::InstallResult::Success) { + res = CrostiniResult::SUCCESS; + } else if (result == TerminaInstaller::InstallResult::Offline) { + res = CrostiniResult::OFFLINE_WHEN_UPGRADE_REQUIRED; + } else if (result == TerminaInstaller::InstallResult::Failure) { + res = CrostiniResult::LOAD_COMPONENT_FAILED; + } else { + CHECK(false) + << "Got unexpected value of TerminaInstaller::InstallResult"; + res = CrostiniResult::LOAD_COMPONENT_FAILED; + } + std::move(callback).Run(res); + }, + std::move(callback))); } -void CrostiniManager::OnInstallTerminaComponent( - CrostiniResultCallback callback, - bool is_update_checked, - component_updater::CrOSComponentManager::Error error, - const base::FilePath& path) { - bool is_successful = - error == component_updater::CrOSComponentManager::Error::NONE; - - if (is_successful) { - is_cros_termina_registered_ = true; - } else { - LOG(ERROR) - << "Failed to install the cros-termina component with error code: " - << static_cast<int>(error); - if (is_cros_termina_registered_ && is_update_checked) { - scoped_refptr<component_updater::CrOSComponentManager> component_manager = - g_browser_process->platform_part()->cros_component_manager(); - if (component_manager) { - // Try again, this time with no update checking. The reason we do this - // is that we may still be offline even when is_offline above was - // false. It's notoriously difficult to know when you're really - // connected to the Internet, and it's also possible to be unable to - // connect to a service like ComponentUpdaterService even when you are - // connected to the rest of the Internet. - UpdatePolicy update_policy = UpdatePolicy::kDontForce; - - LOG(ERROR) << "Retrying cros-termina component load, no update check"; - // Load the existing component on disk. - component_manager->Load( - imageloader::kTerminaComponentName, - component_updater::CrOSComponentManager::MountPolicy::kMount, - update_policy, - base::BindOnce(&CrostiniManager::OnInstallTerminaComponent, - weak_ptr_factory_.GetWeakPtr(), std::move(callback), - false)); - return; - } - } - } - - if (is_successful && is_update_checked) { - VLOG(1) << "cros-termina update check successful."; - termina_update_check_needed_ = false; - } - CrostiniResult result = CrostiniResult::SUCCESS; - if (!is_successful) { - if (error == - component_updater::CrOSComponentManager::Error::UPDATE_IN_PROGRESS) { - // Something else triggered an update that we have to wait on. We don't - // know what, or when they will be finished, so just retry every 5 seconds - // until we get a different result. - content::GetUIThreadTaskRunner({})->PostDelayedTask( - FROM_HERE, - base::BindOnce(&CrostiniManager::InstallTerminaComponent, - weak_ptr_factory_.GetWeakPtr(), std::move(callback)), - base::TimeDelta::FromSeconds(5)); - return; - } else { - result = CrostiniResult::LOAD_COMPONENT_FAILED; - } - } - - std::move(callback).Run(result); -} - -bool CrostiniManager::UninstallTerminaComponent() { - bool success = true; - scoped_refptr<component_updater::CrOSComponentManager> component_manager = - g_browser_process->platform_part()->cros_component_manager(); - if (component_manager) { - success = component_manager->Unload(imageloader::kTerminaComponentName); - } - if (success) { - is_cros_termina_registered_ = false; - } - return success; +void CrostiniManager::UninstallTermina(BoolCallback callback) { + termina_installer_.Uninstall(std::move(callback)); } void CrostiniManager::StartConcierge(BoolCallback callback) { @@ -1330,6 +1200,11 @@ } vm_tools::concierge::StartVmRequest request; + base::FilePath base_path = termina_installer_.GetInstallLocation(); + request.mutable_vm()->set_kernel( + base_path.Append(kCrostiniKernel).AsUTF8Unsafe()); + request.mutable_vm()->set_rootfs( + base_path.Append(kCrostiniRootfs).AsUTF8Unsafe()); request.set_name(std::move(name)); request.set_start_termina(true); request.set_owner_id(owner_id_); @@ -1344,11 +1219,24 @@ DCHECK_LT(0, cpus); request.set_cpus(cpus); - vm_tools::concierge::DiskImage* disk_image = request.add_disks(); - disk_image->set_path(std::move(disk_path_string)); - disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO); - disk_image->set_writable(true); - disk_image->set_do_mount(false); + // The stateful disk must be added first because concierge treats it + // specially. + { + vm_tools::concierge::DiskImage* disk_image = request.add_disks(); + disk_image->set_path(std::move(disk_path_string)); + disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO); + disk_image->set_writable(true); + disk_image->set_do_mount(false); + } + + { + vm_tools::concierge::DiskImage* disk_image = request.add_disks(); + disk_image->set_path(base_path.Append(kCrostiniToolfs).AsUTF8Unsafe()); + disk_image->set_mount_point(kCrostiniToolfsMountPath); + disk_image->set_fstype(kCrostiniToolfsType); + disk_image->set_writable(false); + disk_image->set_do_mount(true); + } GetConciergeClient()->StartTerminaVm( request, base::BindOnce(&CrostiniManager::OnStartTerminaVm,
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h index 007ed735..e866d3e 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.h +++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -19,6 +19,7 @@ #include "chrome/browser/chromeos/crostini/crostini_simple_types.h" #include "chrome/browser/chromeos/crostini/crostini_types.mojom-forward.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" +#include "chrome/browser/chromeos/crostini/termina_installer.h" #include "chrome/browser/chromeos/vm_starting_observer.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" #include "chrome/browser/ui/browser.h" @@ -227,21 +228,20 @@ base::WeakPtr<CrostiniManager> GetWeakPtr(); - // Returns true if the cros-termina component is installed. - static bool IsCrosTerminaInstalled(); - // Returns true if the /dev/kvm directory is present. static bool IsDevKvmPresent(); - // Upgrades cros-termina component if the current version is not compatible. + // Upgrades cros-termina component if the current version is not + // compatible. This is a no-op if chromeos::features::kCrostiniUseDlc is + // enabled. void MaybeUpdateCrostini(); - // Installs the current version of cros-termina component. Attempts to apply - // pending upgrades if a MaybeUpdateCrostini failed. - void InstallTerminaComponent(CrostiniResultCallback callback); + // Installs termina using either component updater or the DLC service + // depending on the value of chromeos::features::kCrostiniUseDlc + void InstallTermina(CrostiniResultCallback callback); - // Unloads and removes the cros-termina component. Returns success/failure. - bool UninstallTerminaComponent(); + // Unloads and removes termina. + void UninstallTermina(BoolCallback callback); // Starts the Concierge service. |callback| is called after the method call // finishes. @@ -710,14 +710,6 @@ base::Optional<vm_tools::concierge::GetVmEnterpriseReportingInfoResponse> response); - // Callback for CrostiniManager::InstallCrostiniComponent. Must be called on - // the UI thread. - void OnInstallTerminaComponent( - CrostiniResultCallback callback, - bool is_update_checked, - component_updater::CrOSComponentManager::Error error, - const base::FilePath& path); - // Callback for CrostiniClient::StartConcierge. Called after the // DebugDaemon service method finishes. void OnStartConcierge(BoolCallback callback, bool success); @@ -846,9 +838,8 @@ void OnDefaultContainerConfigured(bool success); // Helper for CrostiniManager::MaybeUpdateCrostini. Makes blocking calls to - // check for file paths and registered components. - static void CheckPathsAndComponents( - scoped_refptr<component_updater::CrOSComponentManager> component_manager); + // check for /dev/kvm. + static void CheckPaths(); // Helper for CrostiniManager::MaybeUpdateCrostini. Separated because the // checking component registration code may block. @@ -879,8 +870,6 @@ component_manager_load_error_for_testing_ = component_updater::CrOSComponentManager::Error::NONE; - static bool is_cros_termina_registered_; - bool termina_update_check_needed_ = false; static bool is_dev_kvm_present_; // |is_unclean_startup_| is true when we detect Concierge still running at @@ -974,6 +963,8 @@ std::unique_ptr<CrostiniUpgradeAvailableNotification> upgrade_available_notification_; + TerminaInstaller termina_installer_{}; + // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed. base::WeakPtrFactory<CrostiniManager> weak_ptr_factory_{this};
diff --git a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc index 4ea6fe4f..ecdf41d8 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
@@ -25,8 +25,10 @@ #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/policy/powerwash_requirements_checker.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" +#include "chrome/browser/component_updater/fake_cros_component_manager.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/common/chrome_features.h" +#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -34,6 +36,7 @@ #include "chromeos/dbus/concierge/concierge_service.pb.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" #include "chromeos/dbus/fake_anomaly_detector_client.h" #include "chromeos/dbus/fake_cicerone_client.h" #include "chromeos/dbus/fake_concierge_client.h" @@ -158,10 +161,20 @@ std::move(closure).Run(); } + void EnsureTerminaInstalled() { + base::RunLoop run_loop; + crostini_manager()->InstallTermina( + base::BindOnce([](base::OnceClosure callback, + CrostiniResult) { std::move(callback).Run(); }, + run_loop.QuitClosure())); + run_loop.Run(); + } + CrostiniManagerTest() : task_environment_(content::BrowserTaskEnvironment::REAL_IO_THREAD), local_state_(std::make_unique<ScopedTestingLocalState>( - TestingBrowserProcess::GetGlobal())) { + TestingBrowserProcess::GetGlobal())), + browser_part_(g_browser_process->platform_part()) { chromeos::DBusThreadManager::Initialize(); fake_cicerone_client_ = static_cast<chromeos::FakeCiceroneClient*>( chromeos::DBusThreadManager::Get()->GetCiceroneClient()); @@ -175,6 +188,17 @@ ~CrostiniManagerTest() override { chromeos::DBusThreadManager::Shutdown(); } void SetUp() override { + component_manager_ = + base::MakeRefCounted<component_updater::FakeCrOSComponentManager>(); + component_manager_->set_supported_components({"cros-termina"}); + component_manager_->ResetComponentState( + "cros-termina", + component_updater::FakeCrOSComponentManager::ComponentInfo( + component_updater::CrOSComponentManager::Error::NONE, + base::FilePath("/install/path"), base::FilePath("/mount/path"))); + browser_part_.InitializeCrosComponentManager(component_manager_); + chromeos::DlcserviceClient::InitializeFake(); + scoped_feature_list_.InitWithFeatures( {features::kCrostini, features::kCrostiniArcSideload}, {}); run_loop_ = std::make_unique<base::RunLoop>(); @@ -209,6 +233,9 @@ crostini_manager_->Shutdown(); profile_.reset(); run_loop_.reset(); + chromeos::DlcserviceClient::Shutdown(); + browser_part_.ShutdownCrosComponentManager(); + component_manager_.reset(); } protected: @@ -239,6 +266,8 @@ content::BrowserTaskEnvironment task_environment_; std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; std::unique_ptr<ScopedTestingLocalState> local_state_; + scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_; + BrowserProcessPlatformPartTestApi browser_part_; DISALLOW_COPY_AND_ASSIGN(CrostiniManagerTest); }; @@ -413,6 +442,7 @@ response.set_mount_result(vm_tools::concierge::StartVmResponse::FAILURE); fake_concierge_client_->set_start_vm_response(response); + EnsureTerminaInstalled(); crostini_manager()->StartTerminaVm( kVmName, disk_path, 0, base::BindOnce(&ExpectFailure, run_loop()->QuitClosure())); @@ -432,6 +462,7 @@ vm_tools::concierge::StartVmResponse::PARTIAL_DATA_LOSS); fake_concierge_client_->set_start_vm_response(response); + EnsureTerminaInstalled(); crostini_manager()->StartTerminaVm( kVmName, disk_path, 0, base::BindOnce(&ExpectSuccess, run_loop()->QuitClosure())); @@ -445,6 +476,7 @@ base::HistogramTester histogram_tester{}; const base::FilePath& disk_path = base::FilePath(kVmName); + EnsureTerminaInstalled(); crostini_manager()->StartTerminaVm( kVmName, disk_path, 0, base::BindOnce(&ExpectSuccess, run_loop()->QuitClosure())); @@ -458,6 +490,7 @@ const std::string owner_id = CryptohomeIdForProfile(profile()); // Start the Vm. + EnsureTerminaInstalled(); crostini_manager()->StartTerminaVm( kVmName, disk_path, 0, base::BindOnce(&ExpectSuccess, run_loop()->QuitClosure()));
diff --git a/chrome/browser/chromeos/crostini/crostini_remover.cc b/chrome/browser/chromeos/crostini/crostini_remover.cc index b0d7563..e3133ab 100644 --- a/chrome/browser/chromeos/crostini/crostini_remover.cc +++ b/chrome/browser/chromeos/crostini/crostini_remover.cc
@@ -34,21 +34,6 @@ void CrostiniRemover::RemoveCrostini() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (CrostiniManager::GetForProfile(profile_)->IsCrosTerminaInstalled()) { - CrostiniManager::GetForProfile(profile_)->InstallTerminaComponent( - base::BindOnce(&CrostiniRemover::OnComponentLoaded, this)); - } else { - // Crostini installation didn't install the component. Concierge should not - // be running, nor should there be any VMs. - CrostiniRemover::DestroyDiskImageFinished(true); - } -} - -void CrostiniRemover::OnComponentLoaded(CrostiniResult result) { - if (result != CrostiniResult::SUCCESS) { - std::move(callback_).Run(result); - return; - } CrostiniManager::GetForProfile(profile_)->StartConcierge( base::BindOnce(&CrostiniRemover::OnConciergeStarted, this)); } @@ -87,17 +72,21 @@ return; } - // UninstallTerminaComponent returns false both if Termina wasn't installed - // and if the uninstall failed, so we explicitly reset the relevant - // preferences even if it's already uninstalled - if (!CrostiniManager::GetForProfile(profile_)->IsCrosTerminaInstalled() || - CrostiniManager::GetForProfile(profile_)->UninstallTerminaComponent()) { - profile_->GetPrefs()->SetBoolean(prefs::kCrostiniEnabled, false); - profile_->GetPrefs()->ClearPref(prefs::kCrostiniLastDiskSize); - profile_->GetPrefs()->Set(prefs::kCrostiniContainers, - base::Value(base::Value::Type::LIST)); - profile_->GetPrefs()->ClearPref(prefs::kCrostiniDefaultContainerConfigured); + CrostiniManager::GetForProfile(profile_)->UninstallTermina( + base::BindOnce(&CrostiniRemover::UninstallTerminaFinished, this)); +} + +void CrostiniRemover::UninstallTerminaFinished(bool success) { + if (!success) { + std::move(callback_).Run(CrostiniResult::UNKNOWN_ERROR); + return; } + + profile_->GetPrefs()->SetBoolean(prefs::kCrostiniEnabled, false); + profile_->GetPrefs()->ClearPref(prefs::kCrostiniLastDiskSize); + profile_->GetPrefs()->Set(prefs::kCrostiniContainers, + base::Value(base::Value::Type::LIST)); + profile_->GetPrefs()->ClearPref(prefs::kCrostiniDefaultContainerConfigured); std::move(callback_).Run(CrostiniResult::SUCCESS); }
diff --git a/chrome/browser/chromeos/crostini/crostini_remover.h b/chrome/browser/chromeos/crostini/crostini_remover.h index 9e4b6181..afc43327 100644 --- a/chrome/browser/chromeos/crostini/crostini_remover.h +++ b/chrome/browser/chromeos/crostini/crostini_remover.h
@@ -22,10 +22,10 @@ ~CrostiniRemover(); - void OnComponentLoaded(crostini::CrostiniResult result); void OnConciergeStarted(bool is_successful); void StopVmFinished(crostini::CrostiniResult result); void DestroyDiskImageFinished(bool success); + void UninstallTerminaFinished(bool success); Profile* profile_; std::string vm_name_;
diff --git a/chrome/browser/chromeos/crostini/crostini_util.cc b/chrome/browser/chromeos/crostini/crostini_util.cc index c12521e2..f48067b0 100644 --- a/chrome/browser/chromeos/crostini/crostini_util.cc +++ b/chrome/browser/chromeos/crostini/crostini_util.cc
@@ -66,6 +66,13 @@ "https://storage.googleapis.com/cros-containers/%d"; const char kCrostiniStretchImageAlias[] = "debian/stretch"; const char kCrostiniBusterImageAlias[] = "debian/buster"; +const char kCrostiniDlcName[] = "termina-dlc"; + +const char kCrostiniKernel[] = "vm_kernel"; +const char kCrostiniRootfs[] = "vm_rootfs.img"; +const char kCrostiniToolfs[] = "vm_tools.img"; +const char kCrostiniToolfsMountPath[] = "/opt/google/cros-containers"; +const char kCrostiniToolfsType[] = "ext4"; const base::FilePath::CharType kHomeDirectory[] = FILE_PATH_LITERAL("/home"); @@ -383,8 +390,7 @@ // At this point, we know that Crostini UI is allowed. if (app_id == kCrostiniTerminalSystemAppId && - (!crostini_manager->IsCrosTerminaInstalled() || - !CrostiniFeatures::Get()->IsEnabled(profile))) { + !CrostiniFeatures::Get()->IsEnabled(profile)) { crostini::CrostiniInstaller::GetForProfile(profile)->ShowDialog( CrostiniUISurface::kAppList); return std::move(callback).Run(false, "Crostini not installed");
diff --git a/chrome/browser/chromeos/crostini/crostini_util.h b/chrome/browser/chromeos/crostini/crostini_util.h index 0694878c..eb5a679 100644 --- a/chrome/browser/chromeos/crostini/crostini_util.h +++ b/chrome/browser/chromeos/crostini/crostini_util.h
@@ -46,6 +46,13 @@ extern const char kCrostiniDefaultImageServerUrl[]; extern const char kCrostiniStretchImageAlias[]; extern const char kCrostiniBusterImageAlias[]; +extern const char kCrostiniDlcName[]; + +extern const char kCrostiniKernel[]; +extern const char kCrostiniRootfs[]; +extern const char kCrostiniToolfs[]; +extern const char kCrostiniToolfsMountPath[]; +extern const char kCrostiniToolfsType[]; extern const base::FilePath::CharType kHomeDirectory[];
diff --git a/chrome/browser/chromeos/crostini/crostini_util_unittest.cc b/chrome/browser/chromeos/crostini/crostini_util_unittest.cc index b4236fa..640d69ad 100644 --- a/chrome/browser/chromeos/crostini/crostini_util_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_util_unittest.cc
@@ -8,10 +8,13 @@ #include "base/run_loop.h" #include "chrome/browser/browser_process_platform_part_base.h" #include "chrome/browser/chromeos/crostini/crostini_test_helper.h" +#include "chrome/browser/component_updater/fake_cros_component_manager.h" +#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" #include "chromeos/dbus/fake_concierge_client.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -36,7 +39,8 @@ : app_id_(crostini::CrostiniTestHelper::GenerateAppId(kDesktopFileId)), task_environment_(content::BrowserTaskEnvironment::REAL_IO_THREAD), local_state_(std::make_unique<ScopedTestingLocalState>( - TestingBrowserProcess::GetGlobal())) { + TestingBrowserProcess::GetGlobal())), + browser_part_(g_browser_process->platform_part()) { chromeos::DBusThreadManager::Initialize(); fake_concierge_client_ = static_cast<chromeos::FakeConciergeClient*>( @@ -47,6 +51,18 @@ CrostiniUtilTest& operator=(const CrostiniUtilTest&) = delete; void SetUp() override { + chromeos::DlcserviceClient::InitializeFake(); + + component_manager_ = + base::MakeRefCounted<component_updater::FakeCrOSComponentManager>(); + component_manager_->set_supported_components({"cros-termina"}); + component_manager_->ResetComponentState( + "cros-termina", + component_updater::FakeCrOSComponentManager::ComponentInfo( + component_updater::CrOSComponentManager::Error::NONE, + base::FilePath("/install/path"), base::FilePath("/mount/path"))); + browser_part_.InitializeCrosComponentManager(component_manager_); + run_loop_ = std::make_unique<base::RunLoop>(); profile_ = std::make_unique<TestingProfile>(); test_helper_ = std::make_unique<CrostiniTestHelper>(profile_.get()); @@ -60,6 +76,9 @@ test_helper_.reset(); run_loop_.reset(); profile_.reset(); + browser_part_.ShutdownCrosComponentManager(); + component_manager_.reset(); + chromeos::DlcserviceClient::Shutdown(); } protected: @@ -73,6 +92,8 @@ private: content::BrowserTaskEnvironment task_environment_; std::unique_ptr<ScopedTestingLocalState> local_state_; + scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_; + BrowserProcessPlatformPartTestApi browser_part_; }; TEST_F(CrostiniUtilTest, ContainerIdEquality) {
diff --git a/chrome/browser/chromeos/crostini/termina_installer.cc b/chrome/browser/chromeos/crostini/termina_installer.cc new file mode 100644 index 0000000..8935d6a --- /dev/null +++ b/chrome/browser/chromeos/crostini/termina_installer.cc
@@ -0,0 +1,311 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/crostini/termina_installer.h" + +#include <memory> + +#include "base/barrier_closure.h" +#include "base/bind.h" +#include "base/callback.h" +#include "base/feature_list.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part_chromeos.h" +#include "chrome/browser/chromeos/crostini/crostini_util.h" +#include "chromeos/constants/chromeos_features.h" +#include "content/public/browser/network_service_instance.h" +#include "services/network/public/cpp/network_connection_tracker.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace crostini { + +TerminaInstaller::TerminaInstaller() {} +TerminaInstaller::~TerminaInstaller() {} + +void TerminaInstaller::Install( + base::OnceCallback<void(InstallResult)> callback) { + // The Remove*IfPresent methods require an unowned UninstallResult pointer to + // record their success/failure state. This has to be unowned so that in + // Uninstall it can be accessed further down the callback chain, but here we + // don't care about it, so we assign ownership of the pointer to a + // base::DoNothing that will delete it once called. + auto ptr = std::make_unique<UninstallResult>(); + auto* uninstall_result_ptr = ptr.get(); + auto remove_callback = base::BindOnce( + [](std::unique_ptr<UninstallResult> ptr) {}, std::move(ptr)); + + // Remove whichever version of termina we're *not* using and install the right + // one. + if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniUseDlc)) { + RemoveComponentIfPresent(std::move(remove_callback), uninstall_result_ptr); + InstallDlc(std::move(callback)); + } else { + RemoveDlcIfPresent(std::move(remove_callback), uninstall_result_ptr); + InstallComponent(std::move(callback)); + } +} + +void TerminaInstaller::InstallDlc( + base::OnceCallback<void(InstallResult)> callback) { + chromeos::DlcserviceClient::Get()->Install( + kCrostiniDlcName, + base::BindOnce(&TerminaInstaller::OnInstallDlc, + weak_ptr_factory_.GetWeakPtr(), std::move(callback)), + base::DoNothing()); +} + +void TerminaInstaller::OnInstallDlc( + base::OnceCallback<void(InstallResult)> callback, + const chromeos::DlcserviceClient::InstallResult& result) { + CHECK(result.dlc_id == kCrostiniDlcName); + InstallResult response; + if (result.error == dlcservice::kErrorNone) { + response = InstallResult::Success; + termina_location_ = base::FilePath(result.root_path); + } else { + if (content::GetNetworkConnectionTracker()->IsOffline()) { + LOG(ERROR) << "Failed to install termina-dlc while offline, assuming " + "network issue: " + << result.error; + response = InstallResult::Offline; + } else { + LOG(ERROR) << "Failed to install termina-dlc: " << result.error; + response = InstallResult::Failure; + } + } + std::move(callback).Run(response); +} + +using UpdatePolicy = component_updater::CrOSComponentManager::UpdatePolicy; + +void TerminaInstaller::InstallComponent( + base::OnceCallback<void(InstallResult)> callback) { + scoped_refptr<component_updater::CrOSComponentManager> component_manager = + g_browser_process->platform_part()->cros_component_manager(); + + bool major_update_required = + component_manager->GetCompatiblePath(imageloader::kTerminaComponentName) + .empty(); + bool is_offline = content::GetNetworkConnectionTracker()->IsOffline(); + + if (major_update_required) { + component_update_check_needed_ = false; + if (is_offline) { + LOG(ERROR) << "Need to load a major component update, but we're offline."; + std::move(callback).Run(InstallResult::Offline); + return; + } + } + + UpdatePolicy update_policy; + if (component_update_check_needed_ && !is_offline) { + // Don't use kForce all the time because it generates traffic to + // ComponentUpdaterService. Also, it's only appropriate for minor version + // updates. Not major version incompatiblility. + update_policy = UpdatePolicy::kForce; + } else { + update_policy = UpdatePolicy::kDontForce; + } + + component_manager->Load( + imageloader::kTerminaComponentName, + component_updater::CrOSComponentManager::MountPolicy::kMount, + update_policy, + base::BindOnce(&TerminaInstaller::OnInstallComponent, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + update_policy == UpdatePolicy::kForce)); +} + +void TerminaInstaller::OnInstallComponent( + base::OnceCallback<void(InstallResult)> callback, + bool is_update_checked, + component_updater::CrOSComponentManager::Error error, + const base::FilePath& path) { + bool is_successful = + error == component_updater::CrOSComponentManager::Error::NONE; + + if (is_successful) { + termina_location_ = path; + } else { + LOG(ERROR) + << "Failed to install the cros-termina component with error code: " + << static_cast<int>(error); + if (is_update_checked) { + scoped_refptr<component_updater::CrOSComponentManager> component_manager = + g_browser_process->platform_part()->cros_component_manager(); + if (component_manager) { + // Try again, this time with no update checking. The reason we do this + // is that we may still be offline even when is_offline above was + // false. It's notoriously difficult to know when you're really + // connected to the Internet, and it's also possible to be unable to + // connect to a service like ComponentUpdaterService even when you are + // connected to the rest of the Internet. + UpdatePolicy update_policy = UpdatePolicy::kDontForce; + + LOG(ERROR) << "Retrying cros-termina component load, no update check"; + // Load the existing component on disk. + component_manager->Load( + imageloader::kTerminaComponentName, + component_updater::CrOSComponentManager::MountPolicy::kMount, + update_policy, + base::BindOnce(&TerminaInstaller::OnInstallComponent, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + false)); + return; + } + } + } + + if (is_successful && is_update_checked) { + VLOG(1) << "cros-termina update check successful."; + component_update_check_needed_ = false; + } + InstallResult result = InstallResult::Success; + if (!is_successful) { + if (error == + component_updater::CrOSComponentManager::Error::UPDATE_IN_PROGRESS) { + // Something else triggered an update that we have to wait on. We don't + // know what, or when they will be finished, so just retry every 5 seconds + // until we get a different result. + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&TerminaInstaller::InstallComponent, + weak_ptr_factory_.GetWeakPtr(), std::move(callback)), + base::TimeDelta::FromSeconds(5)); + return; + } else { + result = InstallResult::Failure; + } + } + + std::move(callback).Run(result); +} + +void TerminaInstaller::Uninstall(base::OnceCallback<void(bool)> callback) { + // Unset |termina_location_| now since it will become invalid at some point + // soon. + termina_location_ = base::nullopt; + + // This is really a vector of bool, but std::vector<bool> has weird properties + // that stop us from using it in this way. + std::vector<UninstallResult> partial_results{0, 0}; + UninstallResult* component_result = &partial_results[0]; + UninstallResult* dlc_result = &partial_results[1]; + + // We want to get the results from both uninstall calls and combine them, and + // the asynchronous nature of this process means we can't use return values, + // so we need to pass a pointer into those calls to store their results and + // pass ownership of that memory into the result callback. + auto b_closure = BarrierClosure( + 2, base::BindOnce(&TerminaInstaller::OnUninstallFinished, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + std::move(partial_results))); + + RemoveComponentIfPresent(b_closure, component_result); + RemoveDlcIfPresent(b_closure, dlc_result); +} + +void TerminaInstaller::RemoveComponentIfPresent( + base::OnceCallback<void()> callback, + UninstallResult* result) { + scoped_refptr<component_updater::CrOSComponentManager> component_manager = + g_browser_process->platform_part()->cros_component_manager(); + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, + base::BindOnce( + [](scoped_refptr<component_updater::CrOSComponentManager> + component_manager) { + return component_manager->IsRegisteredMayBlock( + imageloader::kTerminaComponentName); + }, + std::move(component_manager)), + base::BindOnce( + [](base::OnceCallback<void()> callback, UninstallResult* result, + bool is_present) { + scoped_refptr<component_updater::CrOSComponentManager> + component_manager = g_browser_process->platform_part() + ->cros_component_manager(); + if (is_present) { + *result = + component_manager->Unload(imageloader::kTerminaComponentName); + if (!*result) { + LOG(ERROR) << "Failed to remove cros-termina component"; + } + } else { + *result = true; + } + std::move(callback).Run(); + }, + std::move(callback), result)); +} + +void TerminaInstaller::RemoveDlcIfPresent(base::OnceCallback<void()> callback, + UninstallResult* result) { + chromeos::DlcserviceClient::Get()->GetExistingDlcs(base::BindOnce( + [](base::WeakPtr<TerminaInstaller> weak_this, + base::OnceCallback<void()> callback, UninstallResult* result, + const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content) { + if (!weak_this) + return; + + if (err != dlcservice::kErrorNone) { + LOG(ERROR) << "Failed to list installed DLCs: " << err; + *result = false; + std::move(callback).Run(); + return; + } + for (const auto& dlc : dlcs_with_content.dlc_infos()) { + if (dlc.id() == kCrostiniDlcName) { + weak_this->RemoveDlc(std::move(callback), result); + return; + } + } + *result = true; + std::move(callback).Run(); + }, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), result)); +} + +void TerminaInstaller::RemoveDlc(base::OnceCallback<void()> callback, + UninstallResult* result) { + chromeos::DlcserviceClient::Get()->Uninstall( + kCrostiniDlcName, + base::BindOnce( + [](base::OnceCallback<void()> callback, UninstallResult* result, + const std::string& err) { + if (err == dlcservice::kErrorNone) { + *result = true; + } else { + LOG(ERROR) << "Failed to remove termina-dlc: " << err; + *result = false; + } + std::move(callback).Run(); + }, + std::move(callback), result)); +} + +void TerminaInstaller::OnUninstallFinished( + base::OnceCallback<void(bool)> callback, + std::vector<UninstallResult> partial_results) { + for (auto i : partial_results) { + if (!i) { + std::move(callback).Run(false); + return; + } + } + std::move(callback).Run(true); +} + +base::FilePath TerminaInstaller::GetInstallLocation() { + CHECK(termina_location_) + << "GetInstallLocation() called while termina not installed"; + return *termina_location_; +} + +} // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/termina_installer.h b/chrome/browser/chromeos/crostini/termina_installer.h new file mode 100644 index 0000000..9696bb46 --- /dev/null +++ b/chrome/browser/chromeos/crostini/termina_installer.h
@@ -0,0 +1,88 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_TERMINA_INSTALLER_H_ +#define CHROME_BROWSER_CHROMEOS_CROSTINI_TERMINA_INSTALLER_H_ + +#include <vector> + +#include "base/callback_forward.h" +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "chrome/browser/component_updater/cros_component_manager.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" + +namespace crostini { + +// This class is responsible for tracking which source the termina VM is +// installed from (component updater, dlc service etc.) and ensuring that any +// unneeded versions are cleaned up. +class TerminaInstaller { + public: + TerminaInstaller(); + ~TerminaInstaller(); + + TerminaInstaller(const TerminaInstaller&) = delete; + TerminaInstaller& operator=(const TerminaInstaller&) = delete; + + enum class InstallResult { + // The install succeeded. + Success, + // The install failed for an unspecified reason. + Failure, + // The install failed because it needed to download an image and the device + // is offline. + Offline, + }; + + // This is really a bool, but std::vector<bool> has weird properties that stop + // us from using bool here. + using UninstallResult = int; + + // Ensure that termina is installed. This will also attempt to remove any + // other instances of termina that may be installed, but will not block on or + // check the result of this. + void Install(base::OnceCallback<void(InstallResult)> callback); + + // Remove termina entirely. This will also attempt to remove any + // other instances of termina that may be installed. + void Uninstall(base::OnceCallback<void(bool)> callback); + + // Get a path to the install location of termina. You must call Install and + // get a Success response back before calling this method. + base::FilePath GetInstallLocation(); + + private: + void InstallDlc(base::OnceCallback<void(InstallResult)> callback); + void OnInstallDlc(base::OnceCallback<void(InstallResult)> callback, + const chromeos::DlcserviceClient::InstallResult& result); + + void InstallComponent(base::OnceCallback<void(InstallResult)> callback); + void OnInstallComponent(base::OnceCallback<void(InstallResult)> callback, + bool is_update_checked, + component_updater::CrOSComponentManager::Error error, + const base::FilePath& path); + + void RemoveComponentIfPresent(base::OnceCallback<void()> callback, + UninstallResult* result); + void RemoveDlcIfPresent(base::OnceCallback<void()> callback, + UninstallResult* result); + void RemoveDlc(base::OnceCallback<void()> callback, UninstallResult* result); + + void OnUninstallFinished(base::OnceCallback<void(bool)> callback, + std::vector<UninstallResult> partial_results); + + // Do we need to try to force a component update? We want to do this at most + // once per session, so this is initialized to true and unset whenever we + // successfully check for an update or we need to install a new major version. + bool component_update_check_needed_{true}; + + base::Optional<base::FilePath> termina_location_{base::nullopt}; + base::WeakPtrFactory<TerminaInstaller> weak_ptr_factory_{this}; +}; + +} // namespace crostini + +#endif // CHROME_BROWSER_CHROMEOS_CROSTINI_TERMINA_INSTALLER_H_
diff --git a/chrome/browser/chromeos/crostini/termina_installer_unittest.cc b/chrome/browser/chromeos/crostini/termina_installer_unittest.cc new file mode 100644 index 0000000..ab9a8c3 --- /dev/null +++ b/chrome/browser/chromeos/crostini/termina_installer_unittest.cc
@@ -0,0 +1,538 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/crostini/termina_installer.h" + +#include "base/bind.h" +#include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/crostini/crostini_util.h" +#include "chrome/browser/component_updater/fake_cros_component_manager.h" +#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" +#include "chromeos/constants/chromeos_features.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" +#include "chromeos/dbus/dlcservice/fake_dlcservice_client.h" +#include "services/network/test/test_network_connection_tracker.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace crostini { + +class TerminaInstallTest : public testing::Test { + public: + TerminaInstallTest() : browser_part_(g_browser_process->platform_part()) {} + + void SetUp() override { + component_manager_ = + base::MakeRefCounted<component_updater::FakeCrOSComponentManager>(); + browser_part_.InitializeCrosComponentManager(component_manager_); + chromeos::DlcserviceClient::InitializeFake(); + fake_dlc_client_ = static_cast<chromeos::FakeDlcserviceClient*>( + chromeos::DlcserviceClient::Get()); + fake_dlc_client_->set_install_root_path(dlc_root_path_); + } + + void TearDown() override { + chromeos::DlcserviceClient::Shutdown(); + browser_part_.ShutdownCrosComponentManager(); + component_manager_.reset(); + } + + void ExpectTrue(bool result) { + EXPECT_TRUE(result); + run_loop_.Quit(); + } + + void ExpectFalse(bool result) { + EXPECT_FALSE(result); + run_loop_.Quit(); + } + + void ExpectSuccess(TerminaInstaller::InstallResult result) { + EXPECT_EQ(result, TerminaInstaller::InstallResult::Success); + run_loop_.Quit(); + } + + void ExpectSuccess2(TerminaInstaller::InstallResult result) { + EXPECT_EQ(result, TerminaInstaller::InstallResult::Success); + run_loop_2_.Quit(); + } + + void ExpectFailure(TerminaInstaller::InstallResult result) { + EXPECT_EQ(result, TerminaInstaller::InstallResult::Failure); + run_loop_.Quit(); + } + + void ExpectOffline(TerminaInstaller::InstallResult result) { + EXPECT_EQ(result, TerminaInstaller::InstallResult::Offline); + run_loop_.Quit(); + } + + void InjectDlc() { + dlcservice::DlcsWithContent dlcs; + auto* dlc_info = dlcs.add_dlc_infos(); + dlc_info->set_id(kCrostiniDlcName); + fake_dlc_client_->set_dlcs_with_content(dlcs); + } + + const base::FilePath component_install_path_ = + base::FilePath("/install/path"); + const base::FilePath component_mount_path_ = base::FilePath("/mount/path"); + using ComponentError = component_updater::CrOSComponentManager::Error; + using ComponentInfo = + component_updater::FakeCrOSComponentManager::ComponentInfo; + + void PrepareComponentForLoad() { + component_manager_->set_supported_components( + {imageloader::kTerminaComponentName}); + component_manager_->ResetComponentState( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + } + + const std::string dlc_root_path_ = "/dlc/root/path"; + + void CheckDlcInstalled() { + base::RunLoop run_loop; + + fake_dlc_client_->GetExistingDlcs(base::BindOnce( + [](base::OnceClosure quit, const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content) { + std::move(quit).Run(); + ASSERT_EQ(dlcs_with_content.dlc_infos_size(), 1); + EXPECT_EQ(dlcs_with_content.dlc_infos(0).id(), kCrostiniDlcName); + }, + run_loop.QuitClosure())); + + EXPECT_EQ(termina_installer_.GetInstallLocation(), + base::FilePath(dlc_root_path_)); + + run_loop.Run(); + } + + void CheckDlcNotInstalled() { + base::RunLoop run_loop; + + fake_dlc_client_->GetExistingDlcs(base::BindOnce( + [](base::OnceClosure quit, const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content) { + std::move(quit).Run(); + EXPECT_EQ(dlcs_with_content.dlc_infos_size(), 0); + }, + run_loop.QuitClosure())); + + run_loop.Run(); + } + + protected: + scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_; + BrowserProcessPlatformPartTestApi browser_part_; + chromeos::FakeDlcserviceClient* fake_dlc_client_; + TerminaInstaller termina_installer_; + base::test::TaskEnvironment task_env_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + base::RunLoop run_loop_; + base::RunLoop run_loop_2_; +}; + +// Specialization of TerminaInstallTest that force-enables installing via DLC +class TerminaDlcInstallTest : public TerminaInstallTest { + public: + TerminaDlcInstallTest() { + feature_list_.InitWithFeatures( + /*enabled_features=*/{chromeos::features::kCrostiniUseDlc}, + /*disabled_features=*/{}); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// Specialization of TerminaInstallTest that force-disables installing via DLC +class TerminaComponentInstallTest : public TerminaInstallTest { + public: + TerminaComponentInstallTest() { + feature_list_.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{chromeos::features::kCrostiniUseDlc}); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(TerminaInstallTest, UninstallWithNothingInstalled) { + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectTrue, base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaInstallTest, UninstallWithNothingInstalledListError) { + fake_dlc_client_->set_get_existing_dlcs_error("An error"); + + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectFalse, base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaInstallTest, UninstallWithNothingInstalledUninstallError) { + // These should be ignored because nothing needs to be uninstalled + component_manager_->set_unload_component_result(false); + fake_dlc_client_->set_uninstall_error("An error"); + + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectTrue, base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaInstallTest, UninstallWithComponentInstalled) { + component_manager_->SetRegisteredComponents( + {imageloader::kTerminaComponentName}); + + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectTrue, base::Unretained(this))); + run_loop_.Run(); + + EXPECT_FALSE(component_manager_->IsRegisteredMayBlock( + imageloader::kTerminaComponentName)); +} + +TEST_F(TerminaInstallTest, UninstallWithComponentInstalledError) { + component_manager_->SetRegisteredComponents( + {imageloader::kTerminaComponentName}); + component_manager_->set_unload_component_result(false); + + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectFalse, base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaInstallTest, UninstallWithDlcInstalled) { + InjectDlc(); + + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectTrue, base::Unretained(this))); + run_loop_.Run(); + + CheckDlcNotInstalled(); +} + +TEST_F(TerminaInstallTest, UninstallWithDlcInstalledUninstallError) { + InjectDlc(); + fake_dlc_client_->set_uninstall_error("An error"); + + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectFalse, base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaInstallTest, UninstallWithBothInstalled) { + component_manager_->SetRegisteredComponents( + {imageloader::kTerminaComponentName}); + InjectDlc(); + + termina_installer_.Uninstall( + base::BindOnce(&TerminaInstallTest::ExpectTrue, base::Unretained(this))); + run_loop_.Run(); + + EXPECT_FALSE(component_manager_->IsRegisteredMayBlock( + imageloader::kTerminaComponentName)); + CheckDlcNotInstalled(); +} + +TEST_F(TerminaDlcInstallTest, InstallDlc) { + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + run_loop_.Run(); + + CheckDlcInstalled(); +} + +TEST_F(TerminaDlcInstallTest, InstallDlcError) { + fake_dlc_client_->set_install_error("An error"); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectFailure, + base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaDlcInstallTest, InstallDlcOffline) { + fake_dlc_client_->set_install_error("An error"); + + auto* network_connection_tracker = + network::TestNetworkConnectionTracker::GetInstance(); + network_connection_tracker->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectOffline, + base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaDlcInstallTest, InstallDlcWithComponentInstalled) { + component_manager_->SetRegisteredComponents( + {imageloader::kTerminaComponentName}); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + run_loop_.Run(); + + CheckDlcInstalled(); + + task_env_.RunUntilIdle(); + EXPECT_FALSE(component_manager_->IsRegisteredMayBlock( + imageloader::kTerminaComponentName)); +} + +TEST_F(TerminaDlcInstallTest, InstallDlcWithComponentInstalledUninstallError) { + component_manager_->SetRegisteredComponents( + {imageloader::kTerminaComponentName}); + component_manager_->set_unload_component_result(false); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + run_loop_.Run(); + + CheckDlcInstalled(); +} + +TEST_F(TerminaComponentInstallTest, InstallComponent) { + PrepareComponentForLoad(); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + run_loop_.Run(); + + EXPECT_TRUE(component_manager_->IsRegisteredMayBlock( + imageloader::kTerminaComponentName)); + EXPECT_EQ(termina_installer_.GetInstallLocation(), component_mount_path_); +} + +TEST_F(TerminaComponentInstallTest, InstallComponentOffline) { + PrepareComponentForLoad(); + auto* network_connection_tracker = + network::TestNetworkConnectionTracker::GetInstance(); + network_connection_tracker->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectOffline, + base::Unretained(this))); + run_loop_.Run(); +} + +TEST_F(TerminaComponentInstallTest, InstallComponentWithDlcInstalled) { + PrepareComponentForLoad(); + InjectDlc(); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + run_loop_.Run(); + + EXPECT_TRUE(component_manager_->IsRegisteredMayBlock( + imageloader::kTerminaComponentName)); + CheckDlcNotInstalled(); + EXPECT_EQ(termina_installer_.GetInstallLocation(), component_mount_path_); +} + +TEST_F(TerminaComponentInstallTest, InstallComponentWithDlcInstalledError) { + PrepareComponentForLoad(); + InjectDlc(); + fake_dlc_client_->set_uninstall_error("An error"); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + run_loop_.Run(); + + EXPECT_TRUE(component_manager_->IsRegisteredMayBlock( + imageloader::kTerminaComponentName)); + EXPECT_EQ(termina_installer_.GetInstallLocation(), component_mount_path_); +} + +TEST_F(TerminaComponentInstallTest, LoadComponentAlreadyInstalled) { + component_manager_->set_supported_components( + {imageloader::kTerminaComponentName}); + component_manager_->set_queue_load_requests(true); + component_manager_->RegisterCompatiblePath(imageloader::kTerminaComponentName, + component_install_path_); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + run_loop_.Run(); +} + +TEST_F(TerminaComponentInstallTest, LoadComponentInitiallyOffline) { + component_manager_->set_supported_components( + {imageloader::kTerminaComponentName}); + component_manager_->set_queue_load_requests(true); + component_manager_->RegisterCompatiblePath(imageloader::kTerminaComponentName, + component_install_path_); + auto* network_connection_tracker = + network::TestNetworkConnectionTracker::GetInstance(); + network_connection_tracker->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_FALSE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + + network_connection_tracker->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_ETHERNET); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess2, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + run_loop_.Run(); + run_loop_2_.Run(); +} + +TEST_F(TerminaComponentInstallTest, ComponentUpdatesOnlyOnce) { + component_manager_->set_supported_components( + {imageloader::kTerminaComponentName}); + component_manager_->set_queue_load_requests(true); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + run_loop_.Run(); + + termina_installer_.Install(base::DoNothing()); + EXPECT_FALSE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); +} + +TEST_F(TerminaComponentInstallTest, UpdateComponentErrorRetry) { + component_manager_->set_supported_components( + {imageloader::kTerminaComponentName}); + component_manager_->set_queue_load_requests(true); + component_manager_->RegisterCompatiblePath(imageloader::kTerminaComponentName, + component_install_path_); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::INSTALL_FAILURE, base::FilePath(), + base::FilePath())); + + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_FALSE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess2, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + + run_loop_.Run(); + run_loop_2_.Run(); +} + +TEST_F(TerminaComponentInstallTest, InstallComponentErrorNoRetry) { + component_manager_->set_supported_components( + {imageloader::kTerminaComponentName}); + component_manager_->set_queue_load_requests(true); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectFailure, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::INSTALL_FAILURE, base::FilePath(), + base::FilePath())); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess2, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + + run_loop_.Run(); + run_loop_2_.Run(); +} + +TEST_F(TerminaComponentInstallTest, UpdateInProgressTriggersRetry) { + component_manager_->set_supported_components( + {imageloader::kTerminaComponentName}); + component_manager_->set_queue_load_requests(true); + + termina_installer_.Install(base::BindOnce(&TerminaInstallTest::ExpectSuccess, + base::Unretained(this))); + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::UPDATE_IN_PROGRESS, base::FilePath(), + base::FilePath())); + + task_env_.FastForwardBy(base::TimeDelta::FromSeconds(6)); + + EXPECT_TRUE(component_manager_->HasPendingInstall( + imageloader::kTerminaComponentName)); + EXPECT_TRUE( + component_manager_->UpdateRequested(imageloader::kTerminaComponentName)); + component_manager_->FinishLoadRequest( + imageloader::kTerminaComponentName, + ComponentInfo(ComponentError::NONE, component_install_path_, + component_mount_path_)); + run_loop_.Run(); +} + +} // namespace crostini
diff --git a/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc b/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc index 0e15c174..08c9d30 100644 --- a/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc +++ b/chrome/browser/chromeos/guest_os/guest_os_share_path_unittest.cc
@@ -21,12 +21,15 @@ #include "chrome/browser/chromeos/file_system_provider/service_factory.h" #include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/component_updater/fake_cros_component_manager.h" #include "chrome/common/chrome_features.h" +#include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" #include "chromeos/dbus/fake_cicerone_client.h" #include "chromeos/dbus/fake_concierge_client.h" #include "chromeos/dbus/fake_seneschal_client.h" @@ -209,7 +212,8 @@ GuestOsSharePathTest() : local_state_(std::make_unique<ScopedTestingLocalState>( - TestingBrowserProcess::GetGlobal())) { + TestingBrowserProcess::GetGlobal())), + browser_part_(g_browser_process->platform_part()) { chromeos::DBusThreadManager::Initialize(); fake_concierge_client_ = static_cast<chromeos::FakeConciergeClient*>( chromeos::DBusThreadManager::Get()->GetConciergeClient()); @@ -246,6 +250,17 @@ } void SetUp() override { + component_manager_ = + base::MakeRefCounted<component_updater::FakeCrOSComponentManager>(); + component_manager_->set_supported_components({"cros-termina"}); + component_manager_->ResetComponentState( + "cros-termina", + component_updater::FakeCrOSComponentManager::ComponentInfo( + component_updater::CrOSComponentManager::Error::NONE, + base::FilePath("/install/path"), base::FilePath("/mount/path"))); + browser_part_.InitializeCrosComponentManager(component_manager_); + chromeos::DlcserviceClient::InitializeFake(); + run_loop_ = std::make_unique<base::RunLoop>(); profile_ = std::make_unique<TestingProfile>(); guest_os_share_path_ = GuestOsSharePath::GetForProfile(profile()); @@ -283,6 +298,9 @@ run_loop_.reset(); scoped_user_manager_.reset(); profile_.reset(); + chromeos::DlcserviceClient::Shutdown(); + browser_part_.ShutdownCrosComponentManager(); + component_manager_.reset(); } chromeos::FakeChromeUserManager* GetFakeUserManager() const { @@ -314,6 +332,8 @@ private: std::unique_ptr<ScopedTestingLocalState> local_state_; + scoped_refptr<component_updater::FakeCrOSComponentManager> component_manager_; + BrowserProcessPlatformPartTestApi browser_part_; DISALLOW_COPY_AND_ASSIGN(GuestOsSharePathTest); };
diff --git a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc index 8cba1a0c..ee9037d 100644 --- a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc +++ b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc
@@ -55,16 +55,18 @@ // Converts |token_ids| (string-based token identifiers used in the // platformKeys API) to a vector of KeyPermissions::KeyLocation. -std::vector<KeyPermissions::KeyLocation> TokenIdsToKeyLocations( +std::vector<platform_keys::KeyPermissions::KeyLocation> TokenIdsToKeyLocations( const std::vector<platform_keys::TokenId>& token_ids) { - std::vector<KeyPermissions::KeyLocation> key_locations; + std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations; for (const auto& token_id : token_ids) { switch (token_id) { case platform_keys::TokenId::kUser: - key_locations.push_back(KeyPermissions::KeyLocation::kUserSlot); + key_locations.push_back( + platform_keys::KeyPermissions::KeyLocation::kUserSlot); break; case platform_keys::TokenId::kSystem: - key_locations.push_back(KeyPermissions::KeyLocation::kSystemSlot); + key_locations.push_back( + platform_keys::KeyPermissions::KeyLocation::kSystemSlot); break; } } @@ -96,7 +98,7 @@ GenerateKeyTask(platform_keys::TokenId token_id, const std::string& extension_id, const GenerateKeyCallback& callback, - KeyPermissions* key_permissions, + platform_keys::KeyPermissions* key_permissions, ExtensionPlatformKeysService* service) : token_id_(token_id), extension_id_(extension_id), @@ -120,9 +122,9 @@ std::string public_key_spki_der_; const std::string extension_id_; GenerateKeyCallback callback_; - std::unique_ptr<KeyPermissions::PermissionsForExtension> + std::unique_ptr<platform_keys::KeyPermissions::PermissionsForExtension> extension_permissions_; - KeyPermissions* const key_permissions_; + platform_keys::KeyPermissions* const key_permissions_; ExtensionPlatformKeysService* const service_; private: @@ -170,7 +172,7 @@ } void UpdatePermissionsAndCallBack() { - std::vector<KeyPermissions::KeyLocation> key_locations = + std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations = TokenIdsToKeyLocations({token_id_}); extension_permissions_->RegisterKeyForCorporateUsage(public_key_spki_der_, key_locations); @@ -179,8 +181,9 @@ return; } - void GotPermissions(std::unique_ptr<KeyPermissions::PermissionsForExtension> - extension_permissions) { + void GotPermissions( + std::unique_ptr<platform_keys::KeyPermissions::PermissionsForExtension> + extension_permissions) { extension_permissions_ = std::move(extension_permissions); DoStep(); } @@ -202,7 +205,7 @@ unsigned int modulus_length, const std::string& extension_id, const GenerateKeyCallback& callback, - KeyPermissions* key_permissions, + platform_keys::KeyPermissions* key_permissions, ExtensionPlatformKeysService* service) : GenerateKeyTask(token_id, extension_id, @@ -232,7 +235,7 @@ const std::string& named_curve, const std::string& extension_id, const GenerateKeyCallback& callback, - KeyPermissions* key_permissions, + platform_keys::KeyPermissions* key_permissions, ExtensionPlatformKeysService* service) : GenerateKeyTask(token_id, extension_id, @@ -277,7 +280,7 @@ platform_keys::HashAlgorithm hash_algorithm, const std::string& extension_id, const SignCallback& callback, - KeyPermissions* key_permissions, + platform_keys::KeyPermissions* key_permissions, ExtensionPlatformKeysService* service) : token_id_(token_id), data_(data), @@ -343,8 +346,9 @@ base::Bind(&SignTask::GotPermissions, base::Unretained(this))); } - void GotPermissions(std::unique_ptr<KeyPermissions::PermissionsForExtension> - extension_permissions) { + void GotPermissions( + std::unique_ptr<platform_keys::KeyPermissions::PermissionsForExtension> + extension_permissions) { extension_permissions_ = std::move(extension_permissions); DoStep(); } @@ -417,10 +421,10 @@ const platform_keys::HashAlgorithm hash_algorithm_; const std::string extension_id_; const SignCallback callback_; - std::unique_ptr<KeyPermissions::PermissionsForExtension> + std::unique_ptr<platform_keys::KeyPermissions::PermissionsForExtension> extension_permissions_; - KeyPermissions* const key_permissions_; - std::vector<KeyPermissions::KeyLocation> key_locations_; + platform_keys::KeyPermissions* const key_permissions_; + std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations_; ExtensionPlatformKeysService* const service_; base::WeakPtrFactory<SignTask> weak_factory_{this}; @@ -453,7 +457,7 @@ const std::string& extension_id, const SelectCertificatesCallback& callback, content::WebContents* web_contents, - KeyPermissions* key_permissions, + platform_keys::KeyPermissions* key_permissions, ExtensionPlatformKeysService* service) : request_(request), input_client_certificates_(std::move(input_client_certificates)), @@ -521,8 +525,9 @@ base::Bind(&SelectTask::GotPermissions, base::Unretained(this))); } - void GotPermissions(std::unique_ptr<KeyPermissions::PermissionsForExtension> - extension_permissions) { + void GotPermissions( + std::unique_ptr<platform_keys::KeyPermissions::PermissionsForExtension> + extension_permissions) { extension_permissions_ = std::move(extension_permissions); DoStep(); } @@ -610,7 +615,7 @@ const std::string public_key_spki_der( platform_keys::GetSubjectPublicKeyInfo(certificate)); - std::vector<KeyPermissions::KeyLocation> key_locations = + std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations = TokenIdsToKeyLocations(token_ids); // Use this key if the user can use it for signing or can grant permission @@ -726,7 +731,8 @@ net::CertificateList matches_; // Mapping of DER-encoded Subject Public Key Info to the KeyLocations // determined for the corresponding private key. - base::flat_map<std::string, std::vector<KeyPermissions::KeyLocation>> + base::flat_map<std::string, + std::vector<platform_keys::KeyPermissions::KeyLocation>> key_locations_for_matches_; scoped_refptr<net::X509Certificate> selected_cert_; platform_keys::ClientCertificateRequest request_; @@ -735,9 +741,9 @@ const std::string extension_id_; const SelectCertificatesCallback callback_; content::WebContents* const web_contents_; - std::unique_ptr<KeyPermissions::PermissionsForExtension> + std::unique_ptr<platform_keys::KeyPermissions::PermissionsForExtension> extension_permissions_; - KeyPermissions* const key_permissions_; + platform_keys::KeyPermissions* const key_permissions_; ExtensionPlatformKeysService* const service_; base::WeakPtrFactory<SelectTask> weak_factory_{this};
diff --git a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h index ddb3f58..47f7be1 100644 --- a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h +++ b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h
@@ -13,7 +13,7 @@ #include "base/containers/queue.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/chromeos/platform_keys/key_permissions.h" +#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "components/keyed_service/core/keyed_service.h" @@ -225,7 +225,7 @@ content::BrowserContext* const browser_context_ = nullptr; platform_keys::PlatformKeysService* const platform_keys_service_ = nullptr; - KeyPermissions key_permissions_; + platform_keys::KeyPermissions key_permissions_; std::unique_ptr<SelectDelegate> select_delegate_; base::queue<std::unique_ptr<Task>> tasks_; base::WeakPtrFactory<ExtensionPlatformKeysService> weak_factory_{this};
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions/README.md b/chrome/browser/chromeos/platform_keys/key_permissions/README.md new file mode 100644 index 0000000..b6e905c --- /dev/null +++ b/chrome/browser/chromeos/platform_keys/key_permissions/README.md
@@ -0,0 +1,37 @@ +# Key Permissions + +This directory contains code managing platform key permissions. + +## Key Usages + +This can only be “corporate” or undefined. If a key is marked for “corporate” +usage, only extensions listed in +[KeyPermissions](https://cloud.google.com/docs/chrome-enterprise/policies/?policy=KeyPermissions) +policy will be allowed to access this key via chrome.platformKeys and +chrome.enterprise.platformKeys APIs. Key Usages are considered to be +properties / metadata attached to keys themselves. This metadata was +historically persisted in a chromium Preference, but is now being migrated to +the backing key store (which is implemented by the chaps daemon on Chrome OS). + +Usage of keys/certificates for network authentication and TLS client +authentication is currently not restricted by key usages, but this may change in +the future. + +## Signing Permissions for Extensions + +A (key, extension id) pair can have one of the following signing permissions: + +* The key can be used once for signing. This permission is granted if an +extension generated the key using the enterprise.platformKeys API, so that it +can build a certification request. + +* The key can not be used for signing. That will happen after an extension +generates a key using the enterprise.platformKeys API, and signs using it for +the first time to build a certification request. + +* The key can be used for signing unlimited number of times. This permission is +granted by the user (only when the key is non-corporate and the profile is +non-managed) or the KeyPermissions policy to allow the extension to use the +key for signing through the +[enterprise.platformKeys](https://developer.chrome.com/extensions/enterprise_platformKeys) +or [platformKeys](https://developer.chrome.com/extensions/platformKeys) API.
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions.cc b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.cc similarity index 98% rename from chrome/browser/chromeos/platform_keys/key_permissions.cc rename to chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.cc index ff9b4c1c..705b6a4 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions.cc +++ b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/platform_keys/key_permissions.h" +#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h" #include <utility> @@ -23,9 +23,9 @@ #include "extensions/browser/state_store.h" namespace chromeos { +namespace platform_keys { namespace { - // The key at which platform key specific data is stored in each extension's // state store. // @@ -190,8 +190,7 @@ KeyEntriesFromState(*state_store_value); } -KeyPermissions::PermissionsForExtension::~PermissionsForExtension() { -} +KeyPermissions::PermissionsForExtension::~PermissionsForExtension() {} bool KeyPermissions::PermissionsForExtension::CanUseKeyForSigning( const std::string& public_key_spki_der, @@ -410,8 +409,7 @@ DCHECK(!profile_is_managed_ || profile_policies_); } -KeyPermissions::~KeyPermissions() { -} +KeyPermissions::~KeyPermissions() {} void KeyPermissions::GetPermissionsForExtension( const std::string& extension_id, @@ -519,4 +517,5 @@ extension_id, kStateStorePlatformKeys, std::move(value)); } +} // namespace platform_keys } // namespace chromeos
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions.h b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h similarity index 97% rename from chrome/browser/chromeos/platform_keys/key_permissions.h rename to chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h index dbc40f5..e2c3874f 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions.h +++ b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_H_ -#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_H_ +#ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_H_ +#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_H_ #include <memory> #include <string> @@ -32,6 +32,7 @@ } namespace chromeos { +namespace platform_keys { // This class manages permissions for extensions to use private keys through // chrome.platformKeys or chrome.enterprise.platformKeys . @@ -234,6 +235,7 @@ DISALLOW_COPY_AND_ASSIGN(KeyPermissions); }; +} // namespace platform_keys } // namespace chromeos -#endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_H_ +#endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_H_
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.cc b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.cc similarity index 74% rename from chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.cc rename to chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.cc index 79db821a..e24bfea 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.cc +++ b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.cc
@@ -2,24 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.h" +#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.h" #include "components/policy/core/common/schema.h" #include "components/policy/policy_constants.h" namespace chromeos { +namespace platform_keys { KeyPermissionsPolicyHandler::KeyPermissionsPolicyHandler( const policy::Schema& chrome_schema) : policy::SchemaValidatingPolicyHandler( policy::key::kKeyPermissions, chrome_schema.GetKnownProperty(policy::key::kKeyPermissions), - policy::SCHEMA_ALLOW_UNKNOWN) { -} + policy::SCHEMA_ALLOW_UNKNOWN) {} void KeyPermissionsPolicyHandler::ApplyPolicySettings( const policy::PolicyMap& /* policies */, - PrefValueMap* /* prefs */) { -} + PrefValueMap* /* prefs */) {} +} // namespace platform_keys } // namespace chromeos
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.h b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.h similarity index 74% rename from chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.h rename to chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.h index 67d6aac..27c8389 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.h +++ b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_POLICY_HANDLER_H_ -#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_POLICY_HANDLER_H_ +#ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_POLICY_HANDLER_H_ +#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_POLICY_HANDLER_H_ #include "base/macros.h" #include "components/policy/core/browser/configuration_policy_handler.h" @@ -13,6 +13,7 @@ } namespace chromeos { +namespace platform_keys { class KeyPermissionsPolicyHandler : public policy::SchemaValidatingPolicyHandler { @@ -27,6 +28,7 @@ DISALLOW_COPY_AND_ASSIGN(KeyPermissionsPolicyHandler); }; +} // namespace platform_keys } // namespace chromeos -#endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_POLICY_HANDLER_H_ +#endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_POLICY_HANDLER_H_
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc index 85cacbd5..ef29685 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
@@ -697,7 +697,7 @@ TEST_F(PluginVmInstallerDriveTest, SuccessfulDriveDownloadTest) { SetPluginVmImagePref(kDriveUrl, kHash); - fake_dlcservice_client_->SetInstallError(dlcservice::kErrorNone); + fake_dlcservice_client_->set_install_error(dlcservice::kErrorNone); ExpectObserverEventsUntil(InstallingState::kImporting); EXPECT_CALL(*observer_, OnDownloadProgressUpdated(_, std::strlen(kContent))) @@ -711,7 +711,7 @@ TEST_F(PluginVmInstallerDriveTest, InstallingPluingVmDlcInternal) { SetPluginVmImagePref(kDriveUrl, kHash); - fake_dlcservice_client_->SetInstallError(dlcservice::kErrorInternal); + fake_dlcservice_client_->set_install_error(dlcservice::kErrorInternal); ExpectObserverEventsUntil(InstallingState::kDownloadingDlc); EXPECT_CALL(*observer_, OnError(FailureReason::DLC_INTERNAL)); @@ -724,7 +724,7 @@ TEST_F(PluginVmInstallerDriveTest, InstallingPluingVmDlcBusy) { SetPluginVmImagePref(kDriveUrl, kHash); - fake_dlcservice_client_->SetInstallError(dlcservice::kErrorBusy); + fake_dlcservice_client_->set_install_error(dlcservice::kErrorBusy); ExpectObserverEventsUntil(InstallingState::kDownloadingDlc); EXPECT_CALL(*observer_, OnError(FailureReason::DLC_BUSY)); @@ -736,7 +736,7 @@ TEST_F(PluginVmInstallerDriveTest, InstallingPluginVmDlcNeedReboot) { SetPluginVmImagePref(kDriveUrl, kHash); - fake_dlcservice_client_->SetInstallError(dlcservice::kErrorNeedReboot); + fake_dlcservice_client_->set_install_error(dlcservice::kErrorNeedReboot); ExpectObserverEventsUntil(InstallingState::kDownloadingDlc); EXPECT_CALL(*observer_, OnError(FailureReason::DLC_NEED_REBOOT)); @@ -749,7 +749,7 @@ TEST_F(PluginVmInstallerDriveTest, InstallingPluginVmDlcNeedSpace) { SetPluginVmImagePref(kDriveUrl, kHash); - fake_dlcservice_client_->SetInstallError(dlcservice::kErrorAllocation); + fake_dlcservice_client_->set_install_error(dlcservice::kErrorAllocation); ExpectObserverEventsUntil(InstallingState::kDownloadingDlc); EXPECT_CALL(*observer_, OnError(FailureReason::DLC_NEED_SPACE)); @@ -762,7 +762,7 @@ TEST_F(PluginVmInstallerDriveTest, InstallingPluginVmDlcWhenUnsupported) { SetPluginVmImagePref(kDriveUrl, kHash); - fake_dlcservice_client_->SetInstallError(dlcservice::kErrorInvalidDlc); + fake_dlcservice_client_->set_install_error(dlcservice::kErrorInvalidDlc); ExpectObserverEventsUntil(InstallingState::kDownloadingDlc); EXPECT_CALL(*observer_, OnError(FailureReason::DLC_UNSUPPORTED));
diff --git a/chrome/browser/chromeos/web_applications/telemetry_extension_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/telemetry_extension_integration_browsertest.cc index c717ad5..4552c3d 100644 --- a/chrome/browser/chromeos/web_applications/telemetry_extension_integration_browsertest.cc +++ b/chrome/browser/chromeos/web_applications/telemetry_extension_integration_browsertest.cc
@@ -23,7 +23,7 @@ namespace { constexpr char kNonExistentUrlPath[] = "non-existent-url.html"; constexpr char kLoadFromDiskUrlPath[] = "telemetry_extension_test.html"; -constexpr char kRegisteredUrlPath[] = "untrusted.html"; +constexpr char kRegisteredUrlPath[] = "dpsl.js"; } // namespace class TelemetryExtensionIntegrationTest : public SystemWebAppIntegrationTest { @@ -73,10 +73,6 @@ // The |registered_resource_gurl| is a file that is included in the // TelemteryExtensionUntrustedSource's list of registered resources. EXPECT_TRUE(content::NavigateToURL(web_contents, registered_resource_gurl)); - - // Verify that the file loaded from disk has the expected title. - EXPECT_EQ(base::UTF8ToUTF16("Untrusted Telemetry Extension"), - web_contents->GetTitle()); } INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc index 74673a05..3ea2395 100644 --- a/chrome/browser/client_hints/client_hints_browsertest.cc +++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -23,7 +23,7 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/pref_names.h" @@ -300,10 +300,10 @@ // Verify that the user is not notified that cookies or JavaScript were // blocked on the webpage due to the checks done by client hints. void VerifyContentSettingsNotNotified() const { - auto* tscs = content_settings::TabSpecificContentSettings::GetForFrame( + auto* pscs = content_settings::PageSpecificContentSettings::GetForFrame( browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); - EXPECT_FALSE(tscs->IsContentBlocked(ContentSettingsType::COOKIES)); - EXPECT_FALSE(tscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); + EXPECT_FALSE(pscs->IsContentBlocked(ContentSettingsType::COOKIES)); + EXPECT_FALSE(pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); } void SetExpectedEffectiveConnectionType(
diff --git a/chrome/browser/clipboard/clipboard_read_write_permission_context.cc b/chrome/browser/clipboard/clipboard_read_write_permission_context.cc index 8cdd8dc..b659241 100644 --- a/chrome/browser/clipboard/clipboard_read_write_permission_context.cc +++ b/chrome/browser/clipboard/clipboard_read_write_permission_context.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/clipboard/clipboard_read_write_permission_context.h" #include "chrome/common/chrome_features.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/permissions/permission_request_id.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h" @@ -23,8 +23,8 @@ const permissions::PermissionRequestID& id, const GURL& requesting_frame, bool allowed) { - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( id.render_process_id(), id.render_frame_id()); if (!content_settings) return;
diff --git a/chrome/browser/component_updater/fake_cros_component_manager.cc b/chrome/browser/component_updater/fake_cros_component_manager.cc index 2578e13..f4659ca 100644 --- a/chrome/browser/component_updater/fake_cros_component_manager.cc +++ b/chrome/browser/component_updater/fake_cros_component_manager.cc
@@ -137,7 +137,7 @@ } mounted_components_.erase(name); installed_components_.erase(name); - return true; + return unload_component_result_; } void FakeCrOSComponentManager::RegisterCompatiblePath(
diff --git a/chrome/browser/component_updater/fake_cros_component_manager.h b/chrome/browser/component_updater/fake_cros_component_manager.h index 04956b8..6465aa23 100644 --- a/chrome/browser/component_updater/fake_cros_component_manager.h +++ b/chrome/browser/component_updater/fake_cros_component_manager.h
@@ -51,6 +51,9 @@ void set_supported_components(const std::set<std::string>& components) { supported_components_ = components; } + void set_unload_component_result(bool result) { + unload_component_result_ = result; + } void SetRegisteredComponents(const std::set<std::string>& components); // Finishes a queued component load request. Should be used only if @@ -130,6 +133,8 @@ // FinishLoadRequest(). bool queue_load_requests_ = false; + bool unload_component_result_ = true; + // Set of components that can be handled by this component manager. std::set<std::string> supported_components_;
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc index 47b4ecb..56b3468 100644 --- a/chrome/browser/content_settings/content_settings_browsertest.cc +++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -27,7 +27,7 @@ #include "chrome/test/base/test_launcher_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/browsing_data/content/cookie_helper.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" @@ -67,23 +67,23 @@ #endif using content::BrowserThread; -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; using net::URLRequestMockHTTPJob; namespace { browsing_data::CannedCookieHelper* GetSiteSettingsCookieContainer( Browser* browser) { - TabSpecificContentSettings* settings = - TabSpecificContentSettings::GetForFrame( + PageSpecificContentSettings* settings = + PageSpecificContentSettings::GetForFrame( browser->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); return settings->allowed_local_shared_objects().cookies(); } browsing_data::CannedCookieHelper* GetSiteSettingsBlockedCookieContainer( Browser* browser) { - TabSpecificContentSettings* settings = - TabSpecificContentSettings::GetForFrame( + PageSpecificContentSettings* settings = + PageSpecificContentSettings::GetForFrame( browser->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); return settings->blocked_local_shared_objects().cookies(); } @@ -731,13 +731,13 @@ ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(&observer)); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); } // Any cookie access during a navigation does not end up in a new document (e.g. // due to the request returning HTTP 204) should not be tracked by the -// TabSpecificContentSettings. +// PageSpecificContentSettings. IN_PROC_BROWSER_TEST_F(ContentSettingsTest, CookiesIgnoredFor204) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -753,7 +753,7 @@ ui_test_utils::NavigateToURL(browser(), test_url); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); } @@ -792,20 +792,20 @@ content::RenderFrameHost* main_frame = web_contents->GetMainFrame(); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); ui_test_utils::NavigateToURL(browser(), other_url); EXPECT_TRUE(main_frame->IsInBackForwardCache()); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); web_contents->GetController().GoBack(); EXPECT_TRUE(WaitForLoadStop(web_contents)); EXPECT_EQ(main_frame, web_contents->GetMainFrame()); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); } @@ -823,12 +823,12 @@ ui_test_utils::NavigateToURL(browser(), test_url); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); ui_test_utils::NavigateToURL(browser(), other_url); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); // This triggers a OnContentSettingChanged notification that should be @@ -839,7 +839,7 @@ web_contents->GetController().GoBack(); EXPECT_TRUE(WaitForLoadStop(web_contents)); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); } @@ -896,7 +896,7 @@ ASSERT_EQ(base::UTF8ToUTF16("Data URL"), web_contents->GetTitle()); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); } @@ -922,7 +922,7 @@ browser()->tab_strip_model()->GetActiveWebContents(); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::COOKIES)); } @@ -1062,7 +1062,7 @@ ui_test_utils::WaitForViewVisibility( browser(), VIEW_ID_CONTENT_SETTING_JAVASCRIPT, true); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); } @@ -1211,10 +1211,10 @@ ui_test_utils::NavigateToURL(browser(), url); EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); - auto* tscs = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + auto* pscs = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); EXPECT_EQ(!expect_loaded, - tscs && tscs->IsContentBlocked(ContentSettingsType::PLUGINS)); + pscs && pscs->IsContentBlocked(ContentSettingsType::PLUGINS)); } void RunJavaScriptBlockedTest(const char* path, @@ -1253,11 +1253,11 @@ // the TitleWatcher adding sufficient delay most of the time. } - TabSpecificContentSettings* tab_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); EXPECT_EQ(expect_is_javascript_content_blocked, - tab_settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); - EXPECT_FALSE(tab_settings->IsContentBlocked(ContentSettingsType::PLUGINS)); + settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); + EXPECT_FALSE(settings->IsContentBlocked(ContentSettingsType::PLUGINS)); } private:
diff --git a/chrome/browser/content_settings/content_settings_manager_delegate.cc b/chrome/browser/content_settings/content_settings_manager_delegate.cc index cb0287a..7fd77de 100644 --- a/chrome/browser/content_settings/content_settings_manager_delegate.cc +++ b/chrome/browser/content_settings/content_settings_manager_delegate.cc
@@ -6,7 +6,7 @@ #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/profiles/profile.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "extensions/buildflags/buildflags.h" @@ -25,7 +25,7 @@ const GURL& url, base::OnceCallback<void(bool)> callback, bool allowed) { - content_settings::TabSpecificContentSettings::FileSystemAccessed( + content_settings::PageSpecificContentSettings::FileSystemAccessed( render_process_id, render_frame_id, url, !allowed); std::move(callback).Run(allowed); }
diff --git a/chrome/browser/content_settings/content_settings_usages_state_unittest.cc b/chrome/browser/content_settings/content_settings_usages_state_unittest.cc index f35b3ac7..f7f1d08 100644 --- a/chrome/browser/content_settings/content_settings_usages_state_unittest.cc +++ b/chrome/browser/content_settings/content_settings_usages_state_unittest.cc
@@ -7,7 +7,7 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" #include "chrome/test/base/testing_profile.h" -#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h" +#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permission_result.h" @@ -17,16 +17,16 @@ namespace { class TestDelegate - : public content_settings::TestTabSpecificContentSettingsDelegate { + : public content_settings::TestPageSpecificContentSettingsDelegate { public: explicit TestDelegate( HostContentSettingsMap* map, permissions::PermissionDecisionAutoBlocker* auto_blocker) - : TestTabSpecificContentSettingsDelegate(/*prefs=*/nullptr, map), + : TestPageSpecificContentSettingsDelegate(/*prefs=*/nullptr, map), auto_blocker_(auto_blocker) {} private: - // content_settings::TabSpecificContentSettings::Delegate: + // content_settings::PageSpecificContentSettings::Delegate: ContentSetting GetEmbargoSetting(const GURL& request_origin, ContentSettingsType permission) override { return auto_blocker_->GetEmbargoResult(request_origin, permission)
diff --git a/chrome/browser/content_settings/generated_cookie_prefs.cc b/chrome/browser/content_settings/generated_cookie_prefs.cc index 1a5ee96c..4ad82c8f 100644 --- a/chrome/browser/content_settings/generated_cookie_prefs.cc +++ b/chrome/browser/content_settings/generated_cookie_prefs.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/content_settings/generated_cookie_prefs.h" +#include "base/notreached.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/settings_private.h" @@ -93,6 +94,19 @@ : extensions::settings_private::SetPrefResult::PREF_NOT_MODIFIABLE; } +CookiePrimarySetting ToCookiePrimarySetting( + CookieControlsMode cookie_controls_mode) { + switch (cookie_controls_mode) { + case CookieControlsMode::kBlockThirdParty: + return CookiePrimarySetting::BLOCK_THIRD_PARTY; + case CookieControlsMode::kIncognitoOnly: + return CookiePrimarySetting::BLOCK_THIRD_PARTY_INCOGNITO; + case CookieControlsMode::kOff: + return CookiePrimarySetting::ALLOW_ALL; + } + NOTREACHED(); +} + } // namespace const char kCookiePrimarySetting[] = "generated.cookie_primary_setting"; @@ -107,10 +121,6 @@ user_prefs_registrar_.Init(profile->GetPrefs()); user_prefs_registrar_.Add( - prefs::kBlockThirdPartyCookies, - base::BindRepeating(&GeneratedCookiePrefBase::OnCookiePreferencesChanged, - base::Unretained(this))); - user_prefs_registrar_.Add( prefs::kCookieControlsMode, base::BindRepeating(&GeneratedCookiePrefBase::OnCookiePreferencesChanged, base::Unretained(this))); @@ -180,23 +190,15 @@ auto content_setting = host_content_settings_map_->GetDefaultContentSetting( ContentSettingsType::COOKIES, nullptr); - auto block_third_party_pref_enabled = - profile_->GetPrefs()->GetBoolean(prefs::kBlockThirdPartyCookies); - auto cookie_controls_pref_value = static_cast<CookieControlsMode>( + auto cookie_controls_mode = static_cast<CookieControlsMode>( profile_->GetPrefs()->GetInteger(prefs::kCookieControlsMode)); if (content_setting == ContentSetting::CONTENT_SETTING_BLOCK) { pref_object->value = std::make_unique<base::Value>( static_cast<int>(CookiePrimarySetting::BLOCK_ALL)); - } else if (block_third_party_pref_enabled) { - pref_object->value = std::make_unique<base::Value>( - static_cast<int>(CookiePrimarySetting::BLOCK_THIRD_PARTY)); - } else if (cookie_controls_pref_value == CookieControlsMode::kIncognitoOnly) { - pref_object->value = std::make_unique<base::Value>( - static_cast<int>(CookiePrimarySetting::BLOCK_THIRD_PARTY_INCOGNITO)); } else { pref_object->value = std::make_unique<base::Value>( - static_cast<int>(CookiePrimarySetting::ALLOW_ALL)); + static_cast<int>(ToCookiePrimarySetting(cookie_controls_mode))); } ApplyPrimaryCookieSettingManagedState(pref_object.get(), profile_); @@ -238,20 +240,17 @@ // Both the content setting and the block_third_party preference can // be controlled via policy. - const PrefService::Preference* block_third_party_pref = - profile->GetPrefs()->FindPreference(prefs::kBlockThirdPartyCookies); - bool block_third_party_on = block_third_party_pref->GetValue()->GetBool(); - bool block_third_party_enforced = !block_third_party_pref->IsUserModifiable(); + const PrefService::Preference* cookie_controls_mode_pref = + profile->GetPrefs()->FindPreference(prefs::kCookieControlsMode); + bool cookie_controls_mode_enforced = + !cookie_controls_mode_pref->IsUserModifiable(); // IsRecommended() cannot be used as we care if a recommended value exists at // all, even if a user has overwritten it. - bool block_third_party_recommended = - (block_third_party_pref && block_third_party_pref->GetRecommendedValue()); - bool block_third_party_recommended_on = - block_third_party_recommended && - block_third_party_pref->GetRecommendedValue()->GetBool(); + bool cookie_controls_mode_recommended = + cookie_controls_mode_pref->GetRecommendedValue(); - if (!content_setting_enforced && !block_third_party_enforced && - !block_third_party_recommended) { + if (!content_setting_enforced && !cookie_controls_mode_enforced && + !cookie_controls_mode_recommended) { // No cookie controls are managed or recommended. return; } @@ -264,70 +263,58 @@ return; } - if (content_setting_enforced && block_third_party_enforced) { + if (content_setting_enforced && cookie_controls_mode_enforced) { // Preference is considered fully managed by the third party preference. pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_ENFORCED; extensions::settings_private::GeneratedPref::ApplyControlledByFromPref( - pref_object, block_third_party_pref); + pref_object, cookie_controls_mode_pref); return; } - DCHECK(!content_setting_enforced || - content_setting == CONTENT_SETTING_ALLOW || - content_setting == CONTENT_SETTING_SESSION_ONLY); - DCHECK(!content_setting_enforced || !block_third_party_enforced); - // At this stage the content setting is not enforcing a BLOCK state. Given // this, allow and block_third_party are still valid choices that do not // contradict the content setting. They can thus be controlled or recommended // by the block_third_party preference. - if (block_third_party_recommended) { + DCHECK(!content_setting_enforced || !cookie_controls_mode_enforced); + + if (cookie_controls_mode_recommended) { + auto recommended_value = static_cast<CookieControlsMode>( + cookie_controls_mode_pref->GetRecommendedValue()->GetInt()); pref_object->recommended_value = std::make_unique<base::Value>( - static_cast<int>(block_third_party_recommended_on - ? CookiePrimarySetting::BLOCK_THIRD_PARTY - : CookiePrimarySetting::ALLOW_ALL)); + static_cast<int>(ToCookiePrimarySetting(recommended_value))); // Based on state assessed so far the enforcement is only recommended. This // may be changed to ENFORCED later in this function. pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_RECOMMENDED; - if (!content_setting_enforced) - return; } - if (!content_setting_enforced) { - AddUserSelectableValue(pref_object, CookiePrimarySetting::BLOCK_ALL); - } else { - pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_ENFORCED; - // This may overwritten later in the function by the third party preference, - // if it too is enforced. - pref_object->controlled_by = - GetControlledByForContentSettingSource(content_setting_source); - } - - if (block_third_party_enforced) { - DCHECK(!content_setting_enforced); + // If cookie controls are enforced and the content settings is not enforced, + // you can choose between the selected cookie controls setting and "BLOCK" + if (cookie_controls_mode_enforced) { pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_ENFORCED; extensions::settings_private::GeneratedPref::ApplyControlledByFromPref( - pref_object, block_third_party_pref); - if (block_third_party_on && !content_setting_enforced) { - AddUserSelectableValue(pref_object, - CookiePrimarySetting::BLOCK_THIRD_PARTY); - } else { - AddUserSelectableValue(pref_object, CookiePrimarySetting::ALLOW_ALL); - } + pref_object, cookie_controls_mode_pref); + auto value = static_cast<CookieControlsMode>( + cookie_controls_mode_pref->GetValue()->GetInt()); + AddUserSelectableValue(pref_object, ToCookiePrimarySetting(value)); + AddUserSelectableValue(pref_object, CookiePrimarySetting::BLOCK_ALL); return; } - AddUserSelectableValue(pref_object, CookiePrimarySetting::ALLOW_ALL); - AddUserSelectableValue(pref_object, CookiePrimarySetting::BLOCK_THIRD_PARTY); - AddUserSelectableValue(pref_object, - CookiePrimarySetting::BLOCK_THIRD_PARTY_INCOGNITO); - if (block_third_party_recommended) { - pref_object->recommended_value = std::make_unique<base::Value>( - static_cast<int>(block_third_party_recommended_on - ? CookiePrimarySetting::BLOCK_THIRD_PARTY - : CookiePrimarySetting::ALLOW_ALL)); + // The content setting is enforced to either ALLOW OR SESSION_ONLY + if (content_setting_enforced) { + DCHECK(content_setting == CONTENT_SETTING_ALLOW || + content_setting == CONTENT_SETTING_SESSION_ONLY); + pref_object->enforcement = settings_api::Enforcement::ENFORCEMENT_ENFORCED; + pref_object->controlled_by = + GetControlledByForContentSettingSource(content_setting_source); + + AddUserSelectableValue(pref_object, CookiePrimarySetting::ALLOW_ALL); + AddUserSelectableValue(pref_object, + CookiePrimarySetting::BLOCK_THIRD_PARTY); + AddUserSelectableValue(pref_object, + CookiePrimarySetting::BLOCK_THIRD_PARTY_INCOGNITO); } }
diff --git a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc index 0d2411f4..feaff0a3 100644 --- a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc +++ b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
@@ -35,9 +35,7 @@ GeneratedCookiePrimarySettingPref* generated_pref, CookiePrimarySetting pref_value, ContentSetting expected_content_setting, - bool expected_block_third_party, - CookieControlsMode expected_cookie_controls_mode, - CookiePrimarySetting expected_pref_value) { + CookieControlsMode expected_cookie_controls_mode) { EXPECT_EQ( generated_pref->SetPref( std::make_unique<base::Value>(static_cast<int>(pref_value)).get()), @@ -45,14 +43,12 @@ EXPECT_EQ( map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr), expected_content_setting); - EXPECT_EQ(prefs->GetUserPref(prefs::kBlockThirdPartyCookies)->GetBool(), - expected_block_third_party); EXPECT_EQ(static_cast<CookieControlsMode>( prefs->GetUserPref(prefs::kCookieControlsMode)->GetInt()), expected_cookie_controls_mode); EXPECT_EQ(static_cast<CookiePrimarySetting>( generated_pref->GetPrefObject()->value->GetInt()), - expected_pref_value); + pref_value); } // Define additional unused values of Enforcement, ControlledBy and @@ -288,24 +284,28 @@ provider_type); } if (test_case.block_third_party != settings_private::PrefSetting::kNotSet) { - bool third_party_value = - test_case.block_third_party == + CookieControlsMode cookie_controls_mode = CookieControlsMode::kOff; + if (test_case.block_third_party == settings_private::PrefSetting::kRecommendedOn || test_case.block_third_party == - settings_private::PrefSetting::kEnforcedOn; + settings_private::PrefSetting::kEnforcedOn) { + cookie_controls_mode = CookieControlsMode::kBlockThirdParty; + } + auto cookie_controls_mode_value = + std::make_unique<base::Value>(static_cast<int>(cookie_controls_mode)); + if (test_case.block_third_party_source == settings_private::PrefSource::kExtension) { - prefs->SetExtensionPref(prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(third_party_value)); + prefs->SetExtensionPref(prefs::kCookieControlsMode, + std::move(cookie_controls_mode_value)); } else if (test_case.block_third_party_source == settings_private::PrefSource::kDevicePolicy) { - prefs->SetManagedPref(prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(third_party_value)); + prefs->SetManagedPref(prefs::kCookieControlsMode, + std::move(cookie_controls_mode_value)); } else if (test_case.block_third_party_source == settings_private::PrefSource::kRecommended) { - prefs->SetRecommendedPref( - prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(third_party_value)); + prefs->SetRecommendedPref(prefs::kCookieControlsMode, + std::move(cookie_controls_mode_value)); } } } @@ -361,8 +361,6 @@ // Setup a baseline content setting and preference state. map->SetDefaultContentSetting(ContentSettingsType::COOKIES, ContentSetting::CONTENT_SETTING_ALLOW); - prefs()->SetDefaultPrefValue(prefs::kBlockThirdPartyCookies, - base::Value(false)); prefs()->SetDefaultPrefValue( prefs::kCookieControlsMode, base::Value(static_cast<int>(CookieControlsMode::kOff))); @@ -370,25 +368,22 @@ // Check that each of the four possible preference values sets the correct // state and is correctly reflected in a newly returned PrefObject. // First test this without the improved cookie controls enabled. - ValidatePrimarySettingPrefValue( - map, prefs(), pref.get(), CookiePrimarySetting::BLOCK_ALL, - ContentSetting::CONTENT_SETTING_BLOCK, /* block 3P */ true, - CookieControlsMode::kBlockThirdParty, CookiePrimarySetting::BLOCK_ALL); - ValidatePrimarySettingPrefValue( - map, prefs(), pref.get(), CookiePrimarySetting::BLOCK_THIRD_PARTY, - ContentSetting::CONTENT_SETTING_ALLOW, /* block 3P */ true, - CookieControlsMode::kBlockThirdParty, - CookiePrimarySetting::BLOCK_THIRD_PARTY); + ValidatePrimarySettingPrefValue(map, prefs(), pref.get(), + CookiePrimarySetting::BLOCK_ALL, + ContentSetting::CONTENT_SETTING_BLOCK, + CookieControlsMode::kBlockThirdParty); + ValidatePrimarySettingPrefValue(map, prefs(), pref.get(), + CookiePrimarySetting::BLOCK_THIRD_PARTY, + ContentSetting::CONTENT_SETTING_ALLOW, + CookieControlsMode::kBlockThirdParty); ValidatePrimarySettingPrefValue( map, prefs(), pref.get(), CookiePrimarySetting::ALLOW_ALL, - ContentSetting::CONTENT_SETTING_ALLOW, /* block 3P */ false, - CookieControlsMode::kOff, CookiePrimarySetting::ALLOW_ALL); + ContentSetting::CONTENT_SETTING_ALLOW, CookieControlsMode::kOff); ValidatePrimarySettingPrefValue( map, prefs(), pref.get(), CookiePrimarySetting::BLOCK_THIRD_PARTY_INCOGNITO, - ContentSetting::CONTENT_SETTING_ALLOW, /* block 3P */ false, - CookieControlsMode::kIncognitoOnly, - CookiePrimarySetting::BLOCK_THIRD_PARTY_INCOGNITO); + ContentSetting::CONTENT_SETTING_ALLOW, + CookieControlsMode::kIncognitoOnly); // Confirm that a type mismatch is reported as such. EXPECT_EQ(pref->SetPref(std::make_unique<base::Value>(true).get()), @@ -409,17 +404,17 @@ std::make_unique<base::Value>(ContentSetting::CONTENT_SETTING_ALLOW)); content_settings::TestUtils::OverrideProvider( map, std::move(provider), HostContentSettingsMap::POLICY_PROVIDER); - ValidatePrimarySettingPrefValue( - map, prefs(), pref.get(), CookiePrimarySetting::BLOCK_THIRD_PARTY, - ContentSetting::CONTENT_SETTING_ALLOW, /* block 3P */ true, - CookieControlsMode::kBlockThirdParty, - CookiePrimarySetting::BLOCK_THIRD_PARTY); + ValidatePrimarySettingPrefValue(map, prefs(), pref.get(), + CookiePrimarySetting::BLOCK_THIRD_PARTY, + ContentSetting::CONTENT_SETTING_ALLOW, + CookieControlsMode::kBlockThirdParty); // Update source preferences and ensure that an observer is fired. settings_private::TestGeneratedPrefObserver test_observer; pref->AddObserver(&test_observer); - prefs()->SetUserPref(prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(false)); + prefs()->SetUserPref(prefs::kCookieControlsMode, + std::make_unique<base::Value>(static_cast<int>( + CookieControlsMode::kIncognitoOnly))); EXPECT_EQ(test_observer.GetUpdatedPrefName(), kCookiePrimarySetting); test_observer.Reset();
diff --git a/chrome/browser/content_settings/tab_specific_content_settings_delegate.cc b/chrome/browser/content_settings/page_specific_content_settings_delegate.cc similarity index 73% rename from chrome/browser/content_settings/tab_specific_content_settings_delegate.cc rename to chrome/browser/content_settings/page_specific_content_settings_delegate.cc index b4afc9c..bc2f9e37 100644 --- a/chrome/browser/content_settings/tab_specific_content_settings_delegate.cc +++ b/chrome/browser/content_settings/page_specific_content_settings_delegate.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "build/build_config.h" #include "chrome/browser/browsing_data/browsing_data_file_system_util.h" @@ -17,7 +17,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" #include "chrome/common/renderer_configuration.mojom.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/prefs/pref_service.h" #include "content/public/browser/navigation_handle.h" @@ -28,30 +28,30 @@ #include "chrome/browser/browsing_data/access_context_audit_service_factory.h" #endif // !defined(OS_ANDROID) -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; namespace chrome { -TabSpecificContentSettingsDelegate::TabSpecificContentSettingsDelegate( +PageSpecificContentSettingsDelegate::PageSpecificContentSettingsDelegate( content::WebContents* web_contents) : WebContentsObserver(web_contents) {} -TabSpecificContentSettingsDelegate::~TabSpecificContentSettingsDelegate() = +PageSpecificContentSettingsDelegate::~PageSpecificContentSettingsDelegate() = default; // static -TabSpecificContentSettingsDelegate* -TabSpecificContentSettingsDelegate::FromWebContents( +PageSpecificContentSettingsDelegate* +PageSpecificContentSettingsDelegate::FromWebContents( content::WebContents* web_contents) { - return static_cast<TabSpecificContentSettingsDelegate*>( - TabSpecificContentSettings::GetDelegateForWebContents(web_contents)); + return static_cast<PageSpecificContentSettingsDelegate*>( + PageSpecificContentSettings::GetDelegateForWebContents(web_contents)); } -void TabSpecificContentSettingsDelegate::UpdateLocationBar() { +void PageSpecificContentSettingsDelegate::UpdateLocationBar() { content_settings::UpdateLocationBarUiForWebContents(web_contents()); } -void TabSpecificContentSettingsDelegate::SetContentSettingRules( +void PageSpecificContentSettingsDelegate::SetContentSettingRules( content::RenderProcessHost* process, const RendererContentSettingRules& rules) { // |channel| may be null in tests. @@ -64,7 +64,7 @@ rc_interface->SetContentSettingRules(rules); } -PrefService* TabSpecificContentSettingsDelegate::GetPrefs() { +PrefService* PageSpecificContentSettingsDelegate::GetPrefs() { Profile* profile = Profile::FromBrowserContext(web_contents()->GetBrowserContext()); if (!profile) @@ -73,12 +73,12 @@ return profile->GetPrefs(); } -HostContentSettingsMap* TabSpecificContentSettingsDelegate::GetSettingsMap() { +HostContentSettingsMap* PageSpecificContentSettingsDelegate::GetSettingsMap() { return HostContentSettingsMapFactory::GetForProfile( Profile::FromBrowserContext(web_contents()->GetBrowserContext())); } -ContentSetting TabSpecificContentSettingsDelegate::GetEmbargoSetting( +ContentSetting PageSpecificContentSettingsDelegate::GetEmbargoSetting( const GURL& request_origin, ContentSettingsType permission) { return PermissionDecisionAutoBlockerFactory::GetForProfile( @@ -88,18 +88,18 @@ } std::vector<storage::FileSystemType> -TabSpecificContentSettingsDelegate::GetAdditionalFileSystemTypes() { +PageSpecificContentSettingsDelegate::GetAdditionalFileSystemTypes() { return browsing_data_file_system_util::GetAdditionalFileSystemTypes(); } browsing_data::CookieHelper::IsDeletionDisabledCallback -TabSpecificContentSettingsDelegate::GetIsDeletionDisabledCallback() { +PageSpecificContentSettingsDelegate::GetIsDeletionDisabledCallback() { return CookiesTreeModel::GetCookieDeletionDisabledCallback( Profile::FromBrowserContext(web_contents()->GetBrowserContext())); } -bool TabSpecificContentSettingsDelegate::IsMicrophoneCameraStateChanged( - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state, +bool PageSpecificContentSettingsDelegate::IsMicrophoneCameraStateChanged( + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state, const std::string& media_stream_selected_audio_device, const std::string& media_stream_selected_video_device) { PrefService* prefs = GetPrefs(); @@ -108,13 +108,14 @@ ->GetMediaStreamCaptureIndicator(); if ((microphone_camera_state & - TabSpecificContentSettings::MICROPHONE_ACCESSED) && + PageSpecificContentSettings::MICROPHONE_ACCESSED) && prefs->GetString(prefs::kDefaultAudioCaptureDevice) != media_stream_selected_audio_device && media_indicator->IsCapturingAudio(web_contents())) return true; - if ((microphone_camera_state & TabSpecificContentSettings::CAMERA_ACCESSED) && + if ((microphone_camera_state & + PageSpecificContentSettings::CAMERA_ACCESSED) && prefs->GetString(prefs::kDefaultVideoCaptureDevice) != media_stream_selected_video_device && media_indicator->IsCapturingVideo(web_contents())) @@ -123,10 +124,10 @@ return false; } -TabSpecificContentSettings::MicrophoneCameraState -TabSpecificContentSettingsDelegate::GetMicrophoneCameraState() { - TabSpecificContentSettings::MicrophoneCameraState state = - TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED; +PageSpecificContentSettings::MicrophoneCameraState +PageSpecificContentSettingsDelegate::GetMicrophoneCameraState() { + PageSpecificContentSettings::MicrophoneCameraState state = + PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED; // Include capture devices in the state if there are still consumers of the // approved media stream. @@ -134,14 +135,14 @@ MediaCaptureDevicesDispatcher::GetInstance() ->GetMediaStreamCaptureIndicator(); if (media_indicator->IsCapturingAudio(web_contents())) - state |= TabSpecificContentSettings::MICROPHONE_ACCESSED; + state |= PageSpecificContentSettings::MICROPHONE_ACCESSED; if (media_indicator->IsCapturingVideo(web_contents())) - state |= TabSpecificContentSettings::CAMERA_ACCESSED; + state |= PageSpecificContentSettings::CAMERA_ACCESSED; return state; } -void TabSpecificContentSettingsDelegate::OnContentBlocked( +void PageSpecificContentSettingsDelegate::OnContentBlocked( ContentSettingsType type) { if (type == ContentSettingsType::PLUGINS) { content_settings::RecordPluginsAction( @@ -152,7 +153,7 @@ } } -void TabSpecificContentSettingsDelegate::OnCookieAccessAllowed( +void PageSpecificContentSettingsDelegate::OnCookieAccessAllowed( const net::CookieList& accessed_cookies) { #if !defined(OS_ANDROID) auto* access_context_audit_service = @@ -165,7 +166,7 @@ #endif // !defined(OS_ANDROID) } -void TabSpecificContentSettingsDelegate::DidFinishNavigation( +void PageSpecificContentSettingsDelegate::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted() ||
diff --git a/chrome/browser/content_settings/tab_specific_content_settings_delegate.h b/chrome/browser/content_settings/page_specific_content_settings_delegate.h similarity index 77% rename from chrome/browser/content_settings/tab_specific_content_settings_delegate.h rename to chrome/browser/content_settings/page_specific_content_settings_delegate.h index 6eab8dbd..93998a0 100644 --- a/chrome/browser/content_settings/tab_specific_content_settings_delegate.h +++ b/chrome/browser/content_settings/page_specific_content_settings_delegate.h
@@ -2,27 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CONTENT_SETTINGS_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ -#define CHROME_BROWSER_CONTENT_SETTINGS_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ +#ifndef CHROME_BROWSER_CONTENT_SETTINGS_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ +#define CHROME_BROWSER_CONTENT_SETTINGS_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ #include "chrome/common/custom_handlers/protocol_handler.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" namespace chrome { -class TabSpecificContentSettingsDelegate - : public content_settings::TabSpecificContentSettings::Delegate, +class PageSpecificContentSettingsDelegate + : public content_settings::PageSpecificContentSettings::Delegate, public content::WebContentsObserver { public: - explicit TabSpecificContentSettingsDelegate( + explicit PageSpecificContentSettingsDelegate( content::WebContents* web_contents); - ~TabSpecificContentSettingsDelegate() override; - TabSpecificContentSettingsDelegate( - const TabSpecificContentSettingsDelegate&) = delete; - TabSpecificContentSettingsDelegate& operator=( - const TabSpecificContentSettingsDelegate&) = delete; + ~PageSpecificContentSettingsDelegate() override; + PageSpecificContentSettingsDelegate( + const PageSpecificContentSettingsDelegate&) = delete; + PageSpecificContentSettingsDelegate& operator=( + const PageSpecificContentSettingsDelegate&) = delete; - static TabSpecificContentSettingsDelegate* FromWebContents( + static PageSpecificContentSettingsDelegate* FromWebContents( content::WebContents* web_contents); // Call to indicate that there is a protocol handler pending user approval. @@ -59,7 +59,7 @@ } private: - // TabSpecificContentSettings::Delegate: + // PageSpecificContentSettings::Delegate: void UpdateLocationBar() override; void SetContentSettingRules( content::RenderProcessHost* process, @@ -72,11 +72,11 @@ browsing_data::CookieHelper::IsDeletionDisabledCallback GetIsDeletionDisabledCallback() override; bool IsMicrophoneCameraStateChanged( - content_settings::TabSpecificContentSettings::MicrophoneCameraState + content_settings::PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state, const std::string& media_stream_selected_audio_device, const std::string& media_stream_selected_video_device) override; - content_settings::TabSpecificContentSettings::MicrophoneCameraState + content_settings::PageSpecificContentSettings::MicrophoneCameraState GetMicrophoneCameraState() override; void OnContentBlocked(ContentSettingsType type) override; void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override; @@ -105,4 +105,4 @@ } // namespace chrome -#endif // CHROME_BROWSER_CONTENT_SETTINGS_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ +#endif // CHROME_BROWSER_CONTENT_SETTINGS_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
diff --git a/chrome/browser/content_settings/sound_content_setting_observer.cc b/chrome/browser/content_settings/sound_content_setting_observer.cc index a8e905b..13ad04c 100644 --- a/chrome/browser/content_settings/sound_content_setting_observer.cc +++ b/chrome/browser/content_settings/sound_content_setting_observer.cc
@@ -9,7 +9,7 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" @@ -161,8 +161,8 @@ // This is a page level event so it is OK to get the main frame here. // TODO(https://crbug.com/1103176): We should figure a way of not having to // use GetMainFrame here. (pass the source frame somehow) - content_settings::TabSpecificContentSettings* settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); if (settings) settings->OnAudioBlocked();
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 91e9867..ddd8f65 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -114,6 +114,12 @@ "DevTools.GridSettingChanged"; static const char kDevtoolsCSSGridSettingsHistogram[] = "DevTools.CSSGridSettings"; +static const char kDevtoolsExperimentEnabledHistogram[] = + "DevTools.ExperimentEnabled"; +static const char kDevtoolsExperimentDisabledHistogram[] = + "DevTools.ExperimentDisabled"; +static const char kDevtoolsExperimentEnabledAtLaunchHistogram[] = + "DevTools.ExperimentEnabledAtLaunch"; static const char kRemotePageActionInspect[] = "inspect"; static const char kRemotePageActionReload[] = "reload"; @@ -1275,6 +1281,12 @@ base::UmaHistogramExactLinear(name, sample, boundary_value); else if (name == kDevtoolsCSSGridSettingsHistogram) base::UmaHistogramExactLinear(name, sample, boundary_value); + else if (name == kDevtoolsExperimentEnabledHistogram) + base::UmaHistogramExactLinear(name, sample, boundary_value); + else if (name == kDevtoolsExperimentDisabledHistogram) + base::UmaHistogramExactLinear(name, sample, boundary_value); + else if (name == kDevtoolsExperimentEnabledAtLaunchHistogram) + base::UmaHistogramExactLinear(name, sample, boundary_value); else frontend_host_->BadMessageRecieved(); }
diff --git a/chrome/browser/download/download_request_limiter.cc b/chrome/browser/download/download_request_limiter.cc index d76244e..e0e1323 100644 --- a/chrome/browser/download/download_request_limiter.cc +++ b/chrome/browser/download/download_request_limiter.cc
@@ -346,7 +346,7 @@ return; GURL origin = origin_.GetURL(); - // Analogous to TabSpecificContentSettings::OnContentSettingChanged: + // Analogous to PageSpecificContentSettings::OnContentSettingChanged: const ContentSettingsDetails details(primary_pattern, secondary_pattern, content_type, resource_identifier);
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc index 0f82a4d..3c46570 100644 --- a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
@@ -137,7 +137,7 @@ extensions::StateStore* const state_store = extensions::ExtensionSystem::Get(profile())->state_store(); - chromeos::KeyPermissions permissions( + chromeos::platform_keys::KeyPermissions permissions( policy_connector->IsManaged(), profile()->GetPrefs(), policy_connector->policy_service(), state_store); @@ -168,12 +168,14 @@ void GotPermissionsForExtension( const base::Closure& done_callback, - std::unique_ptr<chromeos::KeyPermissions::PermissionsForExtension> + std::unique_ptr< + chromeos::platform_keys::KeyPermissions::PermissionsForExtension> permissions_for_ext) { std::string client_cert1_spki = chromeos::platform_keys::GetSubjectPublicKeyInfo(client_cert1_); permissions_for_ext->RegisterKeyForCorporateUsage( - client_cert1_spki, {chromeos::KeyPermissions::KeyLocation::kUserSlot}); + client_cert1_spki, + {chromeos::platform_keys::KeyPermissions::KeyLocation::kUserSlot}); done_callback.Run(); }
diff --git a/chrome/browser/generic_sensor/sensor_permission_context.cc b/chrome/browser/generic_sensor/sensor_permission_context.cc index a68a5c8..810d8bb 100644 --- a/chrome/browser/generic_sensor/sensor_permission_context.cc +++ b/chrome/browser/generic_sensor/sensor_permission_context.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/generic_sensor/sensor_permission_context.h" #include "base/feature_list.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/permissions/permission_request_id.h" @@ -26,7 +26,7 @@ const GURL& requesting_frame, bool allowed) { auto* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings::GetForFrame( id.render_process_id(), id.render_frame_id()); if (!content_settings) return;
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc index 8ba14cc..612dc1a 100644 --- a/chrome/browser/geolocation/geolocation_browsertest.cc +++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -27,7 +27,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/browser/content_settings_usages_state.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/permissions/features.h" #include "components/permissions/permission_request_manager.h"
diff --git a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc index d09a3a6..3bce946 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc
@@ -3,12 +3,12 @@ // found in the LICENSE file. #include "build/build_config.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "components/content_settings/browser/content_settings_usages_state.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/permissions/permission_manager.h" #include "components/permissions/permission_request_manager.h" @@ -56,9 +56,9 @@ ChromeRenderViewHostTestHarness::SetUp(); permissions::PermissionRequestManager::CreateForWebContents(web_contents()); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); #if defined(OS_ANDROID) static_cast<permissions::GeolocationPermissionContextAndroid*>( @@ -76,8 +76,8 @@ void CheckTabContentsState(const GURL& requesting_frame, ContentSetting expected_content_setting) { - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); const ContentSettingsUsagesState::StateMap& state_map = content_settings->geolocation_usages_state().state_map();
diff --git a/chrome/browser/idle/idle_detection_permission_context.cc b/chrome/browser/idle/idle_detection_permission_context.cc index 6c78d5b..cc3039b7 100644 --- a/chrome/browser/idle/idle_detection_permission_context.cc +++ b/chrome/browser/idle/idle_detection_permission_context.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/idle/idle_detection_permission_context.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_request_id.h" #include "url/gurl.h" @@ -20,8 +20,8 @@ const permissions::PermissionRequestID& id, const GURL& requesting_frame, bool allowed) { - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( id.render_process_id(), id.render_frame_id()); if (!content_settings) return;
diff --git a/chrome/browser/media/midi_sysex_permission_context.cc b/chrome/browser/media/midi_sysex_permission_context.cc index c14e8677..020d5ea 100644 --- a/chrome/browser/media/midi_sysex_permission_context.cc +++ b/chrome/browser/media/midi_sysex_permission_context.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/media/midi_sysex_permission_context.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_request_id.h" #include "content/public/browser/child_process_security_policy.h" #include "url/gurl.h" @@ -21,8 +21,8 @@ const permissions::PermissionRequestID& id, const GURL& requesting_frame, bool allowed) { - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( id.render_process_id(), id.render_frame_id()); if (!content_settings) return;
diff --git a/chrome/browser/media/protected_media_identifier_permission_context.cc b/chrome/browser/media/protected_media_identifier_permission_context.cc index 45d98b90..da41e0a 100644 --- a/chrome/browser/media/protected_media_identifier_permission_context.cc +++ b/chrome/browser/media/protected_media_identifier_permission_context.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_util.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" @@ -157,8 +157,8 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // WebContents may have gone away. - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( id.render_process_id(), id.render_frame_id()); if (content_settings) { content_settings->OnProtectedMediaIdentifierPermissionSet(
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc index 3914c71..29560e1 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -23,7 +23,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/ui_test_utils.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/permissions/permission_context_base.h" #include "components/permissions/permission_manager.h" @@ -41,7 +41,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/mediastream/media_stream_request.h" -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; class MediaStreamDevicesControllerTest : public WebRtcTestBase { public: @@ -67,8 +67,8 @@ const GURL& example_url() const { return example_url_; } - TabSpecificContentSettings* GetContentSettings() { - return TabSpecificContentSettings::GetForFrame( + PageSpecificContentSettings* GetContentSettings() { + return PageSpecificContentSettings::GetForFrame( GetWebContents()->GetMainFrame()); } @@ -179,7 +179,7 @@ DCHECK(example_url_.is_empty()); example_url_ = url; ui_test_utils::NavigateToURL(browser(), example_url_); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); } @@ -282,7 +282,7 @@ ContentSettingsType::MEDIASTREAM_MIC)); EXPECT_FALSE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_MIC)); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(example_audio_id(), GetContentSettings()->media_stream_requested_audio_device()); @@ -309,7 +309,7 @@ ContentSettingsType::MEDIASTREAM_CAMERA)); EXPECT_FALSE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_CAMERA)); - EXPECT_EQ(TabSpecificContentSettings::CAMERA_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::CAMERA_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(std::string(), GetContentSettings()->media_stream_requested_audio_device()); @@ -336,8 +336,8 @@ ContentSettingsType::MEDIASTREAM_MIC)); EXPECT_TRUE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_MIC)); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(example_audio_id(), GetContentSettings()->media_stream_requested_audio_device()); @@ -364,8 +364,8 @@ ContentSettingsType::MEDIASTREAM_CAMERA)); EXPECT_TRUE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_CAMERA)); - EXPECT_EQ(TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED, + EXPECT_EQ(PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(std::string(), GetContentSettings()->media_stream_requested_audio_device()); @@ -399,8 +399,8 @@ ContentSettingsType::MEDIASTREAM_CAMERA)); EXPECT_FALSE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_CAMERA)); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::CAMERA_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::CAMERA_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(example_audio_id(), GetContentSettings()->media_stream_requested_audio_device()); @@ -434,10 +434,10 @@ ContentSettingsType::MEDIASTREAM_CAMERA)); EXPECT_TRUE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_CAMERA)); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(example_audio_id(), GetContentSettings()->media_stream_requested_audio_device()); @@ -472,10 +472,10 @@ ContentSettingsType::MEDIASTREAM_CAMERA)); EXPECT_TRUE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_CAMERA)); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(example_audio_id(), GetContentSettings()->media_stream_requested_audio_device()); @@ -510,10 +510,10 @@ ContentSettingsType::MEDIASTREAM_CAMERA)); EXPECT_TRUE(GetContentSettings()->IsContentBlocked( ContentSettingsType::MEDIASTREAM_CAMERA)); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED, GetContentSettings()->GetMicrophoneCameraState()); EXPECT_EQ(example_audio_id(), GetContentSettings()->media_stream_requested_audio_device()); @@ -591,7 +591,7 @@ GetContentSettings()->media_stream_requested_video_device()); EXPECT_EQ(example_video_id(), GetContentSettings()->media_stream_selected_video_device()); - EXPECT_EQ(TabSpecificContentSettings::CAMERA_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::CAMERA_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); // Simulate that an a video stream is now being captured. @@ -634,16 +634,16 @@ GetContentSettings()->media_stream_requested_video_device()); EXPECT_EQ(example_video_id(), GetContentSettings()->media_stream_selected_video_device()); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); // After ending the camera capture, the camera permission is no longer // relevant, so it should no be included in the mic/cam state. video_stream_ui.reset(); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED, GetContentSettings()->GetMicrophoneCameraState()); } @@ -988,7 +988,7 @@ VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, false, false); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); } @@ -1018,7 +1018,7 @@ VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, false, false); - EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, + EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); }
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc index 883e426..fe81c159 100644 --- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc +++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/permissions/permission_manager.h" #include "components/permissions/permission_result.h" @@ -59,7 +59,7 @@ namespace { -void UpdateTabSpecificContentSettings( +void UpdatePageSpecificContentSettings( content::WebContents* web_contents, const content::MediaStreamRequest& request, ContentSetting audio_setting, @@ -69,13 +69,13 @@ // TODO(https://crbug.com/1103176): We should extract the frame from |request| auto* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()); if (!content_settings) return; - content_settings::TabSpecificContentSettings::MicrophoneCameraState - microphone_camera_state = content_settings::TabSpecificContentSettings:: + content_settings::PageSpecificContentSettings::MicrophoneCameraState + microphone_camera_state = content_settings::PageSpecificContentSettings:: MICROPHONE_CAMERA_NOT_ACCESSED; std::string selected_audio_device; std::string selected_video_device; @@ -92,10 +92,10 @@ ? profile->GetPrefs()->GetString(prefs::kDefaultAudioCaptureDevice) : requested_audio_device; microphone_camera_state |= - content_settings::TabSpecificContentSettings::MICROPHONE_ACCESSED | + content_settings::PageSpecificContentSettings::MICROPHONE_ACCESSED | (audio_setting == CONTENT_SETTING_ALLOW ? 0 - : content_settings::TabSpecificContentSettings:: + : content_settings::PageSpecificContentSettings:: MICROPHONE_BLOCKED); } @@ -105,10 +105,10 @@ ? profile->GetPrefs()->GetString(prefs::kDefaultVideoCaptureDevice) : requested_video_device; microphone_camera_state |= - content_settings::TabSpecificContentSettings::CAMERA_ACCESSED | + content_settings::PageSpecificContentSettings::CAMERA_ACCESSED | (video_setting == CONTENT_SETTING_ALLOW ? 0 - : content_settings::TabSpecificContentSettings::CAMERA_BLOCKED); + : content_settings::PageSpecificContentSettings::CAMERA_BLOCKED); } content_settings->OnMediaStreamPermissionSet( @@ -306,8 +306,8 @@ // policy we don't update the tab context. if (result != blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON && !blocked_by_feature_policy) { - UpdateTabSpecificContentSettings(web_contents, request, audio_setting, - video_setting); + UpdatePageSpecificContentSettings(web_contents, request, audio_setting, + video_setting); } std::unique_ptr<content::MediaStreamUI> ui;
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc index 01debf03..b00598a 100644 --- a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc +++ b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.cc
@@ -110,6 +110,23 @@ upgrade_bandwidth_endpoint_ids_.insert(endpoint_id); } +void FakeNearbyConnectionsManager::OnEndpointFound( + const std::string& endpoint_id, + location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info) { + if (!discovery_listener_) + return; + + discovery_listener_->OnEndpointDiscovered(endpoint_id, info->endpoint_info); +} + +void FakeNearbyConnectionsManager::OnEndpointLost( + const std::string& endpoint_id) { + if (!discovery_listener_) + return; + + discovery_listener_->OnEndpointLost(endpoint_id); +} + bool FakeNearbyConnectionsManager::IsAdvertising() { return advertising_listener_ != nullptr; }
diff --git a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h index fbebd68..2bfbc6cd 100644 --- a/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h +++ b/chrome/browser/nearby_sharing/fake_nearby_connections_manager.h
@@ -12,11 +12,13 @@ #include <vector> #include "chrome/browser/nearby_sharing/nearby_connections_manager.h" +#include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h" // Fake NearbyConnectionsManager for testing. -class FakeNearbyConnectionsManager : public NearbyConnectionsManager { +class FakeNearbyConnectionsManager + : public NearbyConnectionsManager, + public location::nearby::connections::mojom::EndpointDiscoveryListener { public: - FakeNearbyConnectionsManager(); ~FakeNearbyConnectionsManager() override; @@ -50,6 +52,13 @@ const std::string& endpoint_id) override; void UpgradeBandwidth(const std::string& endpoint_id) override; + // mojom::EndpointDiscoveryListener: + void OnEndpointFound( + const std::string& endpoint_id, + location::nearby::connections::mojom::DiscoveredEndpointInfoPtr info) + override; + void OnEndpointLost(const std::string& endpoint_id) override; + // Testing methods bool IsAdvertising(); bool IsDiscovering();
diff --git a/chrome/browser/nearby_sharing/mock_nearby_connections.h b/chrome/browser/nearby_sharing/mock_nearby_connections.h index 7a7170de..4dae0730 100644 --- a/chrome/browser/nearby_sharing/mock_nearby_connections.h +++ b/chrome/browser/nearby_sharing/mock_nearby_connections.h
@@ -11,6 +11,8 @@ using NearbyConnectionsMojom = location::nearby::connections::mojom::NearbyConnections; +using AdvertisingOptionsPtr = + location::nearby::connections::mojom::AdvertisingOptionsPtr; using DiscoveryOptionsPtr = location::nearby::connections::mojom::DiscoveryOptionsPtr; using EndpointDiscoveryListener = @@ -26,27 +28,32 @@ ~MockNearbyConnections() override; MOCK_METHOD(void, + StartAdvertising, + (const std::vector<uint8_t>& endpoint_info, + const std::string& service_id, + AdvertisingOptionsPtr, + mojo::PendingRemote<ConnectionLifecycleListener>, + StartDiscoveryCallback), + (override)); + MOCK_METHOD(void, StopAdvertising, (StopAdvertisingCallback), (override)); + MOCK_METHOD(void, StartDiscovery, (const std::string& service_id, DiscoveryOptionsPtr, mojo::PendingRemote<EndpointDiscoveryListener>, - StartDiscoveryCallback callback), + StartDiscoveryCallback), (override)); - MOCK_METHOD(void, - StopDiscovery, - (StopDiscoveryCallback callback), - (override)); + MOCK_METHOD(void, StopDiscovery, (StopDiscoveryCallback), (override)); MOCK_METHOD(void, RequestConnection, (const std::vector<uint8_t>& endpoint_info, const std::string& endpoint_id, - mojo::PendingRemote<ConnectionLifecycleListener> listener, - RequestConnectionCallback callback), + mojo::PendingRemote<ConnectionLifecycleListener>, + RequestConnectionCallback), (override)); MOCK_METHOD(void, DisconnectFromEndpoint, - (const std::string& endpoint_id, - DisconnectFromEndpointCallback callback), + (const std::string& endpoint_id, DisconnectFromEndpointCallback), (override)); };
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc index 275964c..b93ecf956 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.cc
@@ -9,6 +9,8 @@ #include "chrome/browser/nearby_sharing/logging/logging.h" #include "chrome/services/sharing/public/mojom/nearby_connections_types.mojom.h" #include "crypto/random.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "net/base/network_change_notifier.h" namespace { @@ -16,6 +18,32 @@ const location::nearby::connections::mojom::Strategy kStrategy = location::nearby::connections::mojom::Strategy::kP2pPointToPoint; +bool ShouldEnableWebRtc(bool is_advertising, + DataUsage data_usage, + PowerLevel power_level) { + // We won't use internet if the user requested we don't. + if (data_usage == DataUsage::kOffline) + return false; + + // We won't use internet in a low power mode. + if (power_level == PowerLevel::kLowPower) + return false; + + net::NetworkChangeNotifier::ConnectionType connection_type = + net::NetworkChangeNotifier::GetConnectionType(); + + // Verify that this network has an internet connection. + if (connection_type == net::NetworkChangeNotifier::CONNECTION_NONE) + return false; + + // If the user wants to limit WebRTC, then only use it on unmetered networks. + if (data_usage == DataUsage::kWifiOnly) + return !net::NetworkChangeNotifier::IsConnectionCellular(connection_type); + + // We're online, the user hasn't disabled WebRTC, let's use it! + return true; +} + } // namespace NearbyConnectionsManagerImpl::NearbyConnectionsManagerImpl( @@ -39,17 +67,38 @@ PowerLevel power_level, DataUsage data_usage, ConnectionsCallback callback) { + DCHECK(listener); + DCHECK(!incoming_connection_listener_); + if (!BindNearbyConnections()) { std::move(callback).Run(ConnectionsStatus::kError); return; } - // TOOD(crbug/1076008): nearby_connections_->StartAdvertising + bool is_high_power = power_level == PowerLevel::kHighPower; + auto allowed_mediums = MediumSelection::New( + /*bluetooth=*/is_high_power, + ShouldEnableWebRtc(/*is_advertising=*/true, data_usage, power_level), + /*wifi_lan=*/is_high_power); + + mojo::PendingRemote<ConnectionLifecycleListener> lifecycle_listener; + connection_lifecycle_listeners_.Add( + this, lifecycle_listener.InitWithNewPipeAndPassReceiver()); + + incoming_connection_listener_ = listener; + nearby_connections_->StartAdvertising( + endpoint_info, kServiceId, + AdvertisingOptions::New(kStrategy, std::move(allowed_mediums), + /*auto_upgrade_bandwidth=*/is_high_power, + /*enforce_topology_constraints=*/true), + std::move(lifecycle_listener), std::move(callback)); } void NearbyConnectionsManagerImpl::StopAdvertising() { - if (!nearby_connections_) - return; + if (nearby_connections_) + nearby_connections_->StopAdvertising(base::DoNothing()); + + incoming_connection_listener_ = nullptr; } void NearbyConnectionsManagerImpl::StartDiscovery( @@ -91,10 +140,13 @@ return; } + mojo::PendingRemote<ConnectionLifecycleListener> lifecycle_listener; + connection_lifecycle_listeners_.Add( + this, lifecycle_listener.InitWithNewPipeAndPassReceiver()); + // TODO(crbug/10706008): Add MediumSelector and bluetooth_mac_address. nearby_connections_->RequestConnection( - endpoint_info, endpoint_id, - connection_lifecycle_listener_.BindNewPipeAndPassRemote(), + endpoint_info, endpoint_id, std::move(lifecycle_listener), base::BindOnce(&NearbyConnectionsManagerImpl::OnConnectionRequested, weak_ptr_factory_.GetWeakPtr(), endpoint_id, std::move(callback))); @@ -260,7 +312,17 @@ return; if (it->second->is_incoming_connection) { - // TOOD(crbug/1076008): Handle incoming connection. + if (!incoming_connection_listener_) { + // Not in advertising mode. + Disconnect(endpoint_id); + return; + } + + auto result = connections_.emplace( + endpoint_id, std::make_unique<NearbyConnectionImpl>(this, endpoint_id)); + DCHECK(result.second); + incoming_connection_listener_->OnIncomingConnection( + endpoint_id, it->second->endpoint_info, result.first->second.get()); } else { auto it = pending_outgoing_connections_.find(endpoint_id); if (it == pending_outgoing_connections_.end()) { @@ -324,5 +386,6 @@ nearby_connections_ = nullptr; discovered_endpoints_.clear(); discovery_listener_ = nullptr; + incoming_connection_listener_ = nullptr; endpoint_discovery_listener_.reset(); }
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h index 1c4e3745..0d824bf 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h +++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl.h
@@ -15,6 +15,7 @@ #include "chrome/browser/nearby_sharing/nearby_process_manager.h" #include "chrome/services/sharing/public/mojom/nearby_connections.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" class Profile; @@ -63,6 +64,9 @@ void UpgradeBandwidth(const std::string& endpoint_id) override; private: + using AdvertisingOptions = + location::nearby::connections::mojom::AdvertisingOptions; + using MediumSelection = location::nearby::connections::mojom::MediumSelection; using DiscoveryOptions = location::nearby::connections::mojom::DiscoveryOptions; using EndpointDiscoveryListener = @@ -106,6 +110,7 @@ NearbyProcessManager* process_manager_; Profile* profile_; + IncomingConnectionListener* incoming_connection_listener_ = nullptr; DiscoveryListener* discovery_listener_ = nullptr; base::flat_set<std::string> discovered_endpoints_; // A map of endpoint_id to NearbyConnectionCallback. @@ -120,8 +125,8 @@ ScopedObserver<NearbyProcessManager, NearbyProcessManager::Observer> nearby_process_observer_{this}; mojo::Receiver<EndpointDiscoveryListener> endpoint_discovery_listener_{this}; - mojo::Receiver<ConnectionLifecycleListener> connection_lifecycle_listener_{ - this}; + mojo::ReceiverSet<ConnectionLifecycleListener> + connection_lifecycle_listeners_; location::nearby::connections::mojom::NearbyConnections* nearby_connections_ = nullptr;
diff --git a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc index 31d6f3c..867a734 100644 --- a/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc
@@ -17,6 +17,7 @@ #include "chrome/test/base/testing_profile.h" #include "content/public/test/browser_task_environment.h" #include "mojo/public/cpp/bindings/remote.h" +#include "net/base/mock_network_change_notifier.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -40,6 +41,7 @@ using DiscoveredEndpointInfo = location::nearby::connections::mojom::DiscoveredEndpointInfo; using ConnectionInfo = location::nearby::connections::mojom::ConnectionInfo; +using MediumSelection = location::nearby::connections::mojom::MediumSelection; class MockDiscoveryListener : public NearbyConnectionsManager::DiscoveryListener { @@ -55,6 +57,17 @@ (override)); }; +class MockIncomingConnectionListener + : public NearbyConnectionsManager::IncomingConnectionListener { + public: + MOCK_METHOD(void, + OnIncomingConnection, + (const std::string& endpoint_id, + const std::vector<uint8_t>& endpoint_info, + NearbyConnection* connection), + (override)); +}; + class NearbyConnectionsManagerImplTest : public testing::Test { public: void SetUp() override { @@ -85,6 +98,33 @@ callback.Get()); } + void StartAdvertising( + mojo::Remote<ConnectionLifecycleListener>& listener_remote, + testing::NiceMock<MockIncomingConnectionListener>& + incoming_connection_listener) { + const std::vector<uint8_t> local_endpoint_info(std::begin(kEndpointInfo), + std::end(kEndpointInfo)); + EXPECT_CALL(nearby_connections_, StartAdvertising) + .WillOnce( + [&](const std::vector<uint8_t>& endpoint_info, + const std::string& service_id, AdvertisingOptionsPtr options, + mojo::PendingRemote<ConnectionLifecycleListener> listener, + NearbyConnectionsMojom::StartAdvertisingCallback callback) { + EXPECT_EQ(local_endpoint_info, endpoint_info); + EXPECT_EQ(kServiceId, service_id); + EXPECT_EQ(kStrategy, options->strategy); + EXPECT_TRUE(options->enforce_topology_constraints); + + listener_remote.Bind(std::move(listener)); + std::move(callback).Run(Status::kSuccess); + }); + base::MockCallback<NearbyConnectionsManager::ConnectionsCallback> callback; + EXPECT_CALL(callback, Run(testing::Eq(Status::kSuccess))); + nearby_connections_manager_.StartAdvertising( + local_endpoint_info, &incoming_connection_listener, + PowerLevel::kHighPower, DataUsage::kOnline, callback.Get()); + } + enum class ConnectionResponse { kAccepted, kRejceted, kDisconnected }; NearbyConnection* Connect( @@ -145,6 +185,8 @@ content::BrowserTaskEnvironment task_environment_; TestingProfile profile_; + std::unique_ptr<net::test::MockNetworkChangeNotifier> network_notifier_ = + net::test::MockNetworkChangeNotifier::Create(); testing::NiceMock<MockNearbyConnections> nearby_connections_; testing::NiceMock<MockNearbyProcessManager> nearby_process_manager_; NearbyConnectionsManagerImpl nearby_connections_manager_{ @@ -254,7 +296,7 @@ nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId)); } -TEST_F(NearbyConnectionsManagerImplTest, ConnectDisconnted) { +TEST_F(NearbyConnectionsManagerImplTest, ConnectDisconnected) { // StartDiscovery will succeed. mojo::Remote<EndpointDiscoveryListener> discovery_listener_remote; testing::NiceMock<MockDiscoveryListener> discovery_listener; @@ -481,3 +523,117 @@ EXPECT_FALSE( nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId)); } + +TEST_F(NearbyConnectionsManagerImplTest, StartAdvertising) { + mojo::Remote<ConnectionLifecycleListener> listener_remote; + testing::NiceMock<MockIncomingConnectionListener> + incoming_connection_listener; + StartAdvertising(listener_remote, incoming_connection_listener); + + const std::vector<uint8_t> remote_endpoint_info( + std::begin(kRemoteEndpointInfo), std::end(kRemoteEndpointInfo)); + const std::vector<uint8_t> raw_authentication_token( + std::begin(kRawAuthenticationToken), std::end(kRawAuthenticationToken)); + + base::RunLoop run_loop; + EXPECT_CALL( + incoming_connection_listener, + OnIncomingConnection(kRemoteEndpointId, remote_endpoint_info, testing::_)) + .WillOnce([&](const std::string&, const std::vector<uint8_t>&, + NearbyConnection* connection) { + EXPECT_TRUE(connection); + run_loop.Quit(); + }); + + listener_remote->OnConnectionInitiated( + kRemoteEndpointId, + ConnectionInfo::New(kAuthenticationToken, raw_authentication_token, + remote_endpoint_info, + /*is_incoming_connection=*/true)); + + listener_remote->OnConnectionAccepted(kRemoteEndpointId); + + run_loop.Run(); + + EXPECT_EQ( + raw_authentication_token, + nearby_connections_manager_.GetRawAuthenticationToken(kRemoteEndpointId)); +} + +using MediumsTestParam = std:: + tuple<PowerLevel, DataUsage, net::NetworkChangeNotifier::ConnectionType>; +class NearbyConnectionsManagerImplTestMediums + : public NearbyConnectionsManagerImplTest, + public testing::WithParamInterface<MediumsTestParam> {}; + +TEST_P(NearbyConnectionsManagerImplTestMediums, + StartAdvertising_MediumSelection) { + const MediumsTestParam& param = GetParam(); + PowerLevel power_level = std::get<0>(param); + DataUsage data_usage = std::get<1>(param); + net::NetworkChangeNotifier::ConnectionType connection_type = + std::get<2>(param); + + network_notifier_->SetConnectionType(connection_type); + bool should_use_web_rtc = + data_usage != DataUsage::kOffline && + power_level != PowerLevel::kLowPower && + connection_type != net::NetworkChangeNotifier::CONNECTION_NONE && + (data_usage != DataUsage::kWifiOnly || + !net::NetworkChangeNotifier::IsConnectionCellular(connection_type)); + + bool is_high_power = power_level == PowerLevel::kHighPower; + auto expected_mediums = MediumSelection::New( + /*bluetooth=*/is_high_power, + /*web_rtc=*/should_use_web_rtc, + /*wifi_lan=*/is_high_power); + + const std::vector<uint8_t> local_endpoint_info(std::begin(kEndpointInfo), + std::end(kEndpointInfo)); + base::MockCallback<NearbyConnectionsManager::ConnectionsCallback> callback; + testing::NiceMock<MockIncomingConnectionListener> + incoming_connection_listener; + + EXPECT_CALL(nearby_connections_, StartAdvertising) + .WillOnce([&](const std::vector<uint8_t>& endpoint_info, + const std::string& service_id, + AdvertisingOptionsPtr options, + mojo::PendingRemote<ConnectionLifecycleListener> listener, + NearbyConnectionsMojom::StartAdvertisingCallback callback) { + EXPECT_EQ(is_high_power, options->auto_upgrade_bandwidth); + EXPECT_EQ(expected_mediums, options->allowed_mediums); + std::move(callback).Run(Status::kSuccess); + }); + EXPECT_CALL(callback, Run(testing::Eq(Status::kSuccess))); + + nearby_connections_manager_.StartAdvertising( + local_endpoint_info, &incoming_connection_listener, power_level, + data_usage, callback.Get()); +} + +INSTANTIATE_TEST_SUITE_P( + NearbyConnectionsManagerImplTestMediums, + NearbyConnectionsManagerImplTestMediums, + testing::Combine( + testing::Values(PowerLevel::kLowPower, PowerLevel::kHighPower), + testing::Values(DataUsage::kWifiOnly, + DataUsage::kOffline, + DataUsage::kOnline), + testing::Values(net::NetworkChangeNotifier::CONNECTION_NONE, + net::NetworkChangeNotifier::CONNECTION_WIFI, + net::NetworkChangeNotifier::CONNECTION_3G))); + +TEST_F(NearbyConnectionsManagerImplTest, StopAdvertising_BeforeStart) { + EXPECT_CALL(nearby_connections_, StopAdvertising).Times(0); + nearby_connections_manager_.StopAdvertising(); +} + +TEST_F(NearbyConnectionsManagerImplTest, StopAdvertising) { + mojo::Remote<ConnectionLifecycleListener> listener_remote; + testing::NiceMock<MockIncomingConnectionListener> + incoming_connection_listener; + StartAdvertising(listener_remote, incoming_connection_listener); + + EXPECT_CALL(nearby_connections_, StopAdvertising); + nearby_connections_manager_.StopAdvertising(); +}
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service.h b/chrome/browser/nearby_sharing/nearby_sharing_service.h index e1807fc..f897f4819 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service.h +++ b/chrome/browser/nearby_sharing/nearby_sharing_service.h
@@ -33,6 +33,14 @@ kOk, // The operation failed since it was called in an invalid order. kOutOfOrderApiCall, + // Tried to stop something that was already stopped. + kStatusAlreadyStopped, + // Tried to register an opposite foreground surface in the midst of a + // transfer or connection. + // (Tried to register Send Surface when receiving a file or tried to + // register Receive Surface when + // sending a file.) + kTransferAlreadyInProgress, }; enum class ReceiveSurfaceState {
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 057bb77..911f61f 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -7,8 +7,10 @@ #include <utility> #include "base/bind.h" +#include "base/logging.h" +#include "base/task/post_task.h" #include "base/task_runner_util.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.h" #include "chrome/browser/nearby_sharing/client/nearby_share_client_impl.h" #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" @@ -34,6 +36,9 @@ base::TimeDelta::FromSeconds(60); constexpr base::TimeDelta kIncomingRejectionDelay = base::TimeDelta::FromSeconds(2); +// Time to delay running the task to invalidate send and receive surfaces. +constexpr base::TimeDelta kInvalidateDelay = + base::TimeDelta::FromMilliseconds(500); std::string ReceiveSurfaceStateToString( NearbySharingService::ReceiveSurfaceState state) { @@ -130,8 +135,7 @@ Profile* profile, std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager, NearbyProcessManager* process_manager) - : prefs_(prefs), - profile_(profile), + : profile_(profile), settings_(prefs), nearby_connections_manager_(std::move(nearby_connections_manager)), process_manager_(process_manager), @@ -146,7 +150,6 @@ contact_manager_(NearbyShareContactManagerImpl::Factory::Create()), certificate_manager_( NearbyShareCertificateManagerImpl::Factory::Create()) { - DCHECK(prefs_); DCHECK(profile_); DCHECK(nearby_connections_manager_); @@ -178,7 +181,61 @@ ShareTargetDiscoveredCallback* discovery_callback, SendSurfaceState state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crrbug.com/1084644): Implement send surface logic. + DCHECK(transfer_callback); + DCHECK(discovery_callback); + DCHECK_NE(state, SendSurfaceState::kUnknown); + + if (!process_manager_->IsActiveProfile(profile_)) { + NS_LOG(VERBOSE) << __func__ + << ": RegisterSendSurface failed, since profile not active"; + return StatusCodes::kError; + } + + if (foreground_send_transfer_callbacks_.HasObserver(transfer_callback) || + background_send_transfer_callbacks_.HasObserver(transfer_callback)) { + NS_LOG(VERBOSE) << __func__ + << ": RegisterSendSurface failed. Already registered."; + return StatusCodes::kError; + } + + if (state == SendSurfaceState::kForeground) { + foreground_send_transfer_callbacks_.AddObserver(transfer_callback); + foreground_send_discovery_callbacks_.AddObserver(discovery_callback); + } else { + background_send_transfer_callbacks_.AddObserver(transfer_callback); + background_send_discovery_callbacks_.AddObserver(discovery_callback); + } + + NS_LOG(VERBOSE) << __func__ << ": RegisterSendSurface"; + + if (is_receiving_files_) { + UnregisterSendSurface(transfer_callback, discovery_callback); + NS_LOG(VERBOSE) + << __func__ + << ": Ignore registering (and unregistering if registered) send " + "surface because we're currently receiving files."; + return StatusCodes::kTransferAlreadyInProgress; + } + + // If the share sheet to be registered is a foreground surface, let it catch + // up with most recent transfer metadata immediately. + if (state == SendSurfaceState::kForeground && last_outgoing_metadata_) { + // When a new share sheet is registered, we want to immediately show the + // in-progress bar. + discovery_callback->OnShareTargetDiscovered(last_outgoing_metadata_->first); + transfer_callback->OnTransferUpdate(last_outgoing_metadata_->first, + last_outgoing_metadata_->second); + } + + // Let newly registered send surface catch up with discovered share targets + // from current scanning session. + for (const std::pair<std::string, ShareTarget>& item : + outgoing_share_target_map_) { + discovery_callback->OnShareTargetDiscovered(item.second); + } + + NS_LOG(VERBOSE) << __func__ << ": A SendSurface has been registered."; + InvalidateSendSurfaceState(); if (state == SendSurfaceState::kForeground) StartFastInitiationAdvertising(); return StatusCodes::kOk; @@ -189,6 +246,46 @@ TransferUpdateCallback* transfer_callback, ShareTargetDiscoveredCallback* discovery_callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(transfer_callback); + DCHECK(discovery_callback); + if (!foreground_send_transfer_callbacks_.HasObserver(transfer_callback) && + !background_send_transfer_callbacks_.HasObserver(transfer_callback)) { + NS_LOG(VERBOSE) + << __func__ + << ": unregisterSendSurface failed. Unknown TransferUpdateCallback"; + return StatusCodes::kError; + } + + if (foreground_send_transfer_callbacks_.might_have_observers() && + last_outgoing_metadata_ && + last_outgoing_metadata_->second.is_final_status()) { + // We already saw the final status in the foreground + // Nullify it so the next time the user opens sharing, it starts the UI from + // the beginning + last_outgoing_metadata_.reset(); + } + + if (foreground_send_transfer_callbacks_.HasObserver(transfer_callback)) { + foreground_send_transfer_callbacks_.RemoveObserver(transfer_callback); + foreground_send_discovery_callbacks_.RemoveObserver(discovery_callback); + } else { + background_send_transfer_callbacks_.RemoveObserver(transfer_callback); + background_send_discovery_callbacks_.RemoveObserver(discovery_callback); + } + + // Displays the most recent payload status processed by foreground surfaces on + // background surfaces. + if (!foreground_send_transfer_callbacks_.might_have_observers() && + last_outgoing_metadata_) { + for (TransferUpdateCallback& background_transfer_callback : + background_send_transfer_callbacks_) { + background_transfer_callback.OnTransferUpdate( + last_outgoing_metadata_->first, last_outgoing_metadata_->second); + } + } + + NS_LOG(VERBOSE) << __func__ << ": A SendSurface has been unregistered"; + InvalidateSurfaceState(); StopFastInitiationAdvertising(); return StatusCodes::kOk; } @@ -200,6 +297,14 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(transfer_callback); DCHECK_NE(state, ReceiveSurfaceState::kUnknown); + + if (!process_manager_->IsActiveProfile(profile_)) { + NS_LOG(VERBOSE) + << __func__ + << ": registerReceiveSurface failed, since profile not active"; + return StatusCodes::kError; + } + if (foreground_receive_callbacks_.HasObserver(transfer_callback) || background_receive_callbacks_.HasObserver(transfer_callback)) { NS_LOG(VERBOSE) << __func__ @@ -272,8 +377,7 @@ NS_LOG(VERBOSE) << __func__ << ": A ReceiveSurface(" << (is_foreground ? "foreground" : "background") << ") has been unregistered"; - - InvalidateReceiveSurfaceState(); + InvalidateSurfaceState(); return StatusCodes::kOk; } @@ -363,6 +467,8 @@ void NearbySharingServiceImpl::OnNearbyProfileChanged(Profile* profile) { // TODO(crbug.com/1084576): Notify UI about the new active profile. + NS_LOG(VERBOSE) << __func__ << ": Nearby profile changed to " + << process_manager_->IsActiveProfile(profile_); } void NearbySharingServiceImpl::OnNearbyProcessStarted() { @@ -384,7 +490,6 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(connection); // TODO(crbug/1085068): Handle incoming connection; use CertificateManager - // TODO(himanshujaju) - Update placeholder implementation ShareTarget share_target; share_target.is_incoming = true; @@ -398,15 +503,128 @@ ReceiveIntroduction(std::move(share_target), /*token=*/base::nullopt); } +void NearbySharingServiceImpl::OnEndpointDiscovered( + const std::string& endpoint_id, + const std::vector<uint8_t>& endpoint_info) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!is_scanning_) { + NS_LOG(VERBOSE) + << __func__ + << ": Ignoring discovered endpoint because we're no longer scanning"; + return; + } + + process_manager_->GetOrStartNearbySharingDecoder(profile_) + ->DecodeAdvertisement( + endpoint_info, + base::BindOnce( + &NearbySharingServiceImpl::OnOutgoingAdvertisementDecoded, + weak_ptr_factory_.GetWeakPtr(), endpoint_id)); +} + +void NearbySharingServiceImpl::OnOutgoingAdvertisementDecoded( + const std::string& endpoint_id, + sharing::mojom::AdvertisementPtr advertisement) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!advertisement) { + NS_LOG(VERBOSE) << __func__ + << ": Failed to parse discovered advertisement."; + return; + } + + // Now we will report endpoints met before in NearbyConnectionsManager. + // Check outgoingShareTargetInfoMap first and pass the same shareTarget if we + // found one. + + // Looking for the ShareTarget based on endpoint id. + if (outgoing_share_target_map_.find(endpoint_id) != + outgoing_share_target_map_.end()) { + return; + } + + // Once get the advertisement, first thing to do is to decrypt its device name + // based on its visibility and create a ShareTarget to represent this remote + // device. + base::Optional<ShareTarget> share_target = + CreateShareTarget(endpoint_id, std::move(advertisement), + /*is_incoming=*/false); + if (!share_target) { + NS_LOG(VERBOSE) << __func__ + << ": Failed to convert advertisement to share target from " + "discovered advertisement. Ignoring endpoint."; + return; + } + + // Update the endpoint id for the share target. + NS_LOG(VERBOSE) << __func__ + << ": An endpoint has been discovered, with an advertisement " + "containing a valid share target."; + GetOrCreateOutgoingShareTargetInfo(*share_target, endpoint_id) + .set_endpoint_id(endpoint_id); + + // Notifies the user that we discovered a device. + for (ShareTargetDiscoveredCallback& discovery_callback : + foreground_send_discovery_callbacks_) { + discovery_callback.OnShareTargetDiscovered(*share_target); + } + for (ShareTargetDiscoveredCallback& discovery_callback : + background_send_discovery_callbacks_) { + discovery_callback.OnShareTargetDiscovered(*share_target); + } + + NS_LOG(VERBOSE) << __func__ << ": Reported OnShareTargetDiscovered " + << (base::Time::Now() - scanning_start_timestamp_); + + // TODO(crbug/1108348) CachingManager should cache known and non-external + // share targets. +} + +void NearbySharingServiceImpl::OnEndpointLost(const std::string& endpoint_id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!is_scanning_) { + NS_LOG(VERBOSE) + << __func__ + << ": Ignoring lost endpoint because we're no longer scanning"; + return; + } + + // Remove the share target with this endpoint id. + auto it = outgoing_share_target_map_.find(endpoint_id); + if (it == outgoing_share_target_map_.end()) { + NS_LOG(VERBOSE) << __func__ + << ": Ignoring lost endpoint because we don't have an " + "associated ShareTarget"; + return; + } + + ShareTarget share_target = std::move(it->second); + outgoing_share_target_info_map_.erase(share_target.id); + outgoing_share_target_map_.erase(it); + + for (ShareTargetDiscoveredCallback& discovery_callback : + foreground_send_discovery_callbacks_) { + discovery_callback.OnShareTargetLost(share_target); + } + for (ShareTargetDiscoveredCallback& discovery_callback : + background_send_discovery_callbacks_) { + discovery_callback.OnShareTargetLost(share_target); + } + + NS_LOG(VERBOSE) << __func__ << ": Reported onShareTargetLost"; +} + void NearbySharingServiceImpl::OnEnabledChanged(bool enabled) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (enabled) { NS_LOG(VERBOSE) << __func__ << ": Nearby sharing enabled!"; } else { NS_LOG(VERBOSE) << __func__ << ": Nearby sharing disabled!"; StopAdvertising(); + StopScanning(); // TODO(crbug/1085067): Stop discovery. nearby_connections_manager_->Shutdown(); } + InvalidateSurfaceState(); } void NearbySharingServiceImpl::FlushMojoForTesting() { @@ -437,25 +655,43 @@ } void NearbySharingServiceImpl::OnVisibilityChanged(Visibility new_visibility) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); NS_LOG(VERBOSE) << __func__ << ": Nearby sharing visibility changed to " << VisibilityToString(new_visibility); - - if (advertising_power_level_ != PowerLevel::kUnknown) { + if (advertising_power_level_ != PowerLevel::kUnknown) StopAdvertising(); - } - InvalidateReceiveSurfaceState(); + InvalidateSurfaceState(); } void NearbySharingServiceImpl::OnDataUsageChanged(DataUsage data_usage) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); NS_LOG(VERBOSE) << __func__ << ": Nearby sharing data usage changed to " << DataUsageToString(data_usage); - if (advertising_power_level_ != PowerLevel::kUnknown) { + if (advertising_power_level_ != PowerLevel::kUnknown) StopAdvertising(); - } - InvalidateReceiveSurfaceState(); + InvalidateSurfaceState(); +} + +const base::Optional<std::vector<uint8_t>> +NearbySharingServiceImpl::CreateEndpointInfo( + const base::Optional<std::string>& device_name) { + // TODO(nmusgrave) fill values from CertificateManager + std::vector<uint8_t> salt(sharing::Advertisement::kSaltSize, 0); + std::vector<uint8_t> encrypted_metadata_key( + sharing::Advertisement::kMetadataEncryptionKeyHashByteSize, 0); + + // TODO(nmusgrave) fill value from local device data manager + std::unique_ptr<sharing::Advertisement> advertisement = + sharing::Advertisement::NewInstance( + std::move(salt), std::move(encrypted_metadata_key), device_name); + if (advertisement) { + return advertisement->ToEndpointInfo(); + } else { + return base::nullopt; + } } void NearbySharingServiceImpl::OnDeviceNameChanged( @@ -557,6 +793,19 @@ return IsBluetoothPresent() && bluetooth_adapter_->IsPowered(); } +bool NearbySharingServiceImpl::HasAvailableConnectionMediums() { + // Check if Wifi or Ethernet LAN is off. Advertisements won't work, so + // disable them, unless bluetooth is known to be enabled. Not all platforms + // have bluetooth, so wifi LAN is a platform-agnostic check. + net::NetworkChangeNotifier::ConnectionType connection_type = + net::NetworkChangeNotifier::GetConnectionType(); + return IsBluetoothPresent() || + (connection_type == + net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI || + connection_type == + net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET); +} + void NearbySharingServiceImpl::AdapterPresentChanged( device::BluetoothAdapter* adapter, bool present) { @@ -571,9 +820,14 @@ StopFastInitiationAdvertising(); } +void NearbySharingServiceImpl::InvalidateSurfaceState() { + InvalidateSendSurfaceState(); + InvalidateReceiveSurfaceState(); +} + void NearbySharingServiceImpl::InvalidateReceiveSurfaceState() { InvalidateAdvertisingState(); - // TODO(crbug/154846208) InvalidateFastInitScan(); + // TODO(b/161889067) InvalidateFastInitScan(); } void NearbySharingServiceImpl::InvalidateAdvertisingState() { @@ -585,16 +839,7 @@ return; } - // Check if Wifi or Ethernet LAN is off. Advertisements won't work, so - // disable them, unless bluetooth is known to be enabled. Not all platforms - // have bluetooth, so wifi LAN is a platform-agnostic check. - net::NetworkChangeNotifier::ConnectionType connection_type = - net::NetworkChangeNotifier::GetConnectionType(); - if (!IsBluetoothPresent() && - !(connection_type == - net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI || - connection_type == - net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET)) { + if (!HasAvailableConnectionMediums()) { StopAdvertising(); NS_LOG(VERBOSE) << __func__ @@ -621,7 +866,7 @@ return; } - if (is_transferring_files_) { + if (is_transferring_) { StopAdvertising(); NS_LOG(VERBOSE) << __func__ @@ -664,10 +909,10 @@ if (power_level == advertising_power_level_) { NS_LOG(VERBOSE) << __func__ - << "Failed to advertise because we're already advertising with power" - << " level " << PowerLevelToString(advertising_power_level_) - << " and data usage preference " - << DataUsageToString(settings_.GetDataUsage()); + << ": Failed to advertise because we're already advertising with " + "power level " + << PowerLevelToString(advertising_power_level_) + << " and data usage preference " << DataUsageToString(data_usage); return; } @@ -678,23 +923,23 @@ << DataUsageToString(data_usage); } + base::Optional<std::string> device_name; + if (foreground_receive_callbacks_.might_have_observers()) + device_name = local_device_data_manager_->GetDeviceName(); + // Starts advertising through Nearby Connections. Caller is expected to ensure // |listener| remains valid until StopAdvertising is called. + base::Optional<std::vector<uint8_t>> endpoint_info = + CreateEndpointInfo(device_name); + if (!endpoint_info) { + NS_LOG(VERBOSE) << __func__ + << ": Unable to advertise since could not parse the " + "endpoint info from the advertisement."; + return; + } - // TODO(nmusgrave) fill values from CertificateManager - std::vector<uint8_t> salt(sharing::Advertisement::kSaltSize, 0); - std::vector<uint8_t> encrypted_metadata_key( - sharing::Advertisement::kMetadataEncryptionKeyHashByteSize, 0); - - // TODO(nmusgrave) fill value from local device data manager - base::Optional<std::string> device_name = "todo_device_name"; - std::vector<uint8_t> endpoint_info = - sharing::Advertisement::NewInstance(std::move(salt), - std::move(encrypted_metadata_key), - std::move(device_name)) - ->ToEndpointInfo(); nearby_connections_manager_->StartAdvertising( - std::move(endpoint_info), + *endpoint_info, /* listener= */ this, power_level, data_usage, base::BindOnce([](NearbyConnectionsManager::ConnectionsStatus status) { NS_LOG(VERBOSE) @@ -722,11 +967,139 @@ } nearby_connections_manager_->StopAdvertising(); - advertising_power_level_ = PowerLevel::kUnknown; NS_LOG(VERBOSE) << __func__ << ": Advertising has stopped"; } +void NearbySharingServiceImpl::InvalidateSendSurfaceState() { + InvalidateScanningState(); + // TODO(b/161889067) InvalidateFastInitAdvertisement(); +} + +void NearbySharingServiceImpl::InvalidateScanningState() { + // Screen is off. Do no work. + if (ui::CheckIdleStateIsLocked()) { + StopScanning(); + NS_LOG(VERBOSE) << __func__ + << ": Stopping discovery because the screen is locked."; + return; + } + + if (!HasAvailableConnectionMediums()) { + StopScanning(); + NS_LOG(VERBOSE) + << __func__ + << ": Stopping scanning because both bluetooth and wifi LAN are " + "disabled."; + return; + } + + // Nearby Sharing is disabled. Don't advertise. + if (!settings_.GetEnabled()) { + StopScanning(); + NS_LOG(VERBOSE) + << __func__ + << ": Stopping discovery because Nearby Sharing is disabled."; + return; + } + + if (is_transferring_ || is_connecting_) { + StopScanning(); + NS_LOG(VERBOSE) + << __func__ + << ": Stopping discovery because we're currently in the midst of a " + "transfer."; + return; + } + + if (!foreground_send_transfer_callbacks_.might_have_observers()) { + StopScanning(); + NS_LOG(VERBOSE) + << __func__ + << ": Stopping discovery because no scanning surface has been " + "registered."; + return; + } + + // Screen is on, Bluetooth is enabled, and Nearby Sharing is enabled! Start + // discovery. + StartScanning(); +} + +void NearbySharingServiceImpl::StartScanning() { + if (!settings_.GetEnabled()) { + NS_LOG(VERBOSE) << __func__ + << ": Failed to scan because we're not enabled."; + return; + } + + if (ui::CheckIdleStateIsLocked()) { + NS_LOG(VERBOSE) << __func__ + << ": Failed to scan because the user's screen is locked."; + return; + } + + if (!HasAvailableConnectionMediums()) { + NS_LOG(VERBOSE) << __func__ << ": Failed to scan because Bluetooth is off."; + return; + } + + if (is_scanning_) { + NS_LOG(VERBOSE) << __func__ + << ": Failed to scan because we're currently scanning."; + return; + } + + if (!foreground_send_transfer_callbacks_.might_have_observers()) { + NS_LOG(VERBOSE) + << __func__ + << ": Failed to scan because there's no scanning send surface " + "registered."; + return; + } + + scanning_start_timestamp_ = base::Time::Now(); + is_scanning_ = true; + InvalidateReceiveSurfaceState(); + + ClearOutgoingShareTargetInfoMap(); + + nearby_connections_manager_->StartDiscovery( + /* listener= */ this, + base::BindOnce([](NearbyConnectionsManager::ConnectionsStatus status) { + NS_LOG(VERBOSE) << __func__ + << ": Scanning start attempted over Nearby Connections " + "with result " + << ConnectionsStatusToString(status); + })); + + InvalidateSendSurfaceState(); + NS_LOG(VERBOSE) << __func__ << ": Scanning has started"; +} + +NearbySharingService::StatusCodes NearbySharingServiceImpl::StopScanning() { + if (!is_scanning_) { + NS_LOG(VERBOSE) << __func__ + << ": Failed to stop scanning because weren't scanning."; + return StatusCodes::kStatusAlreadyStopped; + } + + nearby_connections_manager_->StopDiscovery(); + is_scanning_ = false; + + // Note: We don't know if we stopped scanning in preparation to send a file, + // or we stopped because the user left the page. We'll invalidate after a + // short delay. + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&NearbySharingServiceImpl::InvalidateSurfaceState, + weak_ptr_factory_.GetWeakPtr()), + kInvalidateDelay); + + NS_LOG(VERBOSE) << __func__ << ": Scanning has stopped."; + return StatusCodes::kOk; +} + void NearbySharingServiceImpl::OnIncomingTransferUpdate( const ShareTarget& share_target, TransferMetadata metadata) { @@ -1074,17 +1447,6 @@ UnregisterShareTarget(share_target); } -void NearbySharingServiceImpl::UnregisterShareTarget( - const ShareTarget& share_target) { - if (share_target.is_incoming) { - incoming_share_target_info_map_.erase(share_target.id); - nearby_connections_manager_->ClearIncomingPayloads(); - } else { - // TODO(crbug.com/1084644) - Clear from outgoing map. - } - mutual_acceptance_timeout_alarm_.Cancel(); -} - bool NearbySharingServiceImpl::IsOutOfStorage(const ShareTarget& share_target) { // TODO(himanshujaju) - Check storage space based on file path. return false; @@ -1116,13 +1478,68 @@ return GetIncomingShareTargetInfo(share_target).connection(); } -OutgoingShareTargetInfo& NearbySharingServiceImpl::GetOutgoingShareTargetInfo( - const ShareTarget& share_target) { +OutgoingShareTargetInfo& +NearbySharingServiceImpl::GetOrCreateOutgoingShareTargetInfo( + const ShareTarget& share_target, + const std::string& endpoint_id) { + // Default initialize outgoing_share_target_map_ as well, since Share Target + // needs to have fields explicitly set. + outgoing_share_target_map_.emplace(endpoint_id, share_target); return outgoing_share_target_info_map_[share_target.id]; } void NearbySharingServiceImpl::ClearOutgoingShareTargetInfoMap() { + // TODO(crbug.com/1085068) close file payloads outgoing_share_target_info_map_.clear(); + outgoing_share_target_map_.clear(); +} + +base::Optional<ShareTarget> NearbySharingServiceImpl::CreateShareTarget( + const std::string& endpoint_id, + sharing::mojom::AdvertisementPtr advertisement, + bool is_incoming) { + if (!advertisement->device_name) { + // TODO(crbug/1085068): Handle incoming connection; relies upon + // CertificateManager + return base::nullopt; + } + + return ShareTarget(*advertisement->device_name, /* image_url= */ GURL(), + nearby_share::mojom::ShareTargetType::kUnknown, + std::vector<TextAttachment>(), + std::vector<FileAttachment>(), is_incoming, + /* full_name= */ base::nullopt, /* is_known= */ false); +} + +void NearbySharingServiceImpl::UnregisterShareTarget( + const ShareTarget& share_target) { + if (share_target.is_incoming) { + incoming_share_target_info_map_.erase(share_target.id); + // Clear legacy incoming payloads to release resource + nearby_connections_manager_->ClearIncomingPayloads(); + } else { + // Find the endpoint id that matches the given share target. + base::Optional<std::string> endpoint_id; + auto it = outgoing_share_target_info_map_.find(share_target.id); + if (it != outgoing_share_target_info_map_.end()) + endpoint_id = it->second.endpoint_id(); + + // Remove info except for this endpoint id, if present. + ClearOutgoingShareTargetInfoMap(); + + if (endpoint_id) { + NS_LOG(VERBOSE) << __func__ << ": Unregister share target: " + << share_target.device_name; + GetOrCreateOutgoingShareTargetInfo(share_target, *endpoint_id) + .set_endpoint_id(*endpoint_id); + } else { + NS_LOG(VERBOSE) + << __func__ + << ": Cannot unregister share target since none registered: " + << share_target.device_name; + } + } + mutual_acceptance_timeout_alarm_.Cancel(); } void NearbySharingServiceImpl::SetAttachmentPayloadId(
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h index 5089cd2..de8cbc8 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "base/sequence_checker.h" +#include "base/time/time.h" #include "base/unguessable_token.h" #include "chrome/browser/nearby_sharing/attachment.h" #include "chrome/browser/nearby_sharing/attachment_info.h" @@ -23,6 +24,7 @@ #include "chrome/browser/nearby_sharing/common/nearby_share_enums.h" #include "chrome/browser/nearby_sharing/incoming_frames_reader.h" #include "chrome/browser/nearby_sharing/incoming_share_target_info.h" +#include "chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager.h" #include "chrome/browser/nearby_sharing/nearby_notification_manager.h" #include "chrome/browser/nearby_sharing/nearby_process_manager.h" @@ -52,7 +54,8 @@ public nearby_share::mojom::NearbyShareSettingsObserver, public NearbyProcessManager::Observer, public device::BluetoothAdapter::Observer, - public NearbyConnectionsManager::IncomingConnectionListener { + public NearbyConnectionsManager::IncomingConnectionListener, + public NearbyConnectionsManager::DiscoveryListener { public: explicit NearbySharingServiceImpl( PrefService* prefs, @@ -117,8 +120,15 @@ NearbyShareContactManager* GetContactManager() override; NearbyShareCertificateManager* GetCertificateManager() override; + // NearbyConnectionsManager::DiscoveryListener: + void OnEndpointDiscovered(const std::string& endpoint_id, + const std::vector<uint8_t>& endpoint_info) override; + void OnEndpointLost(const std::string& endpoint_id) override; + private: bool IsVisibleInBackground(Visibility visibility); + const base::Optional<std::vector<uint8_t>> CreateEndpointInfo( + const base::Optional<std::string>& device_name); void StartFastInitiationAdvertising(); void StopFastInitiationAdvertising(); void GetBluetoothAdapter(); @@ -126,12 +136,19 @@ void OnStartFastInitiationAdvertising(); void OnStartFastInitiationAdvertisingError(); void OnStopFastInitiationAdvertising(); + void OnOutgoingAdvertisementDecoded( + const std::string& endpoint_id, + sharing::mojom::AdvertisementPtr advertisement); bool IsBluetoothPresent() const; bool IsBluetoothPowered() const; + bool HasAvailableConnectionMediums(); void AdapterPresentChanged(device::BluetoothAdapter* adapter, bool present) override; void AdapterPoweredChanged(device::BluetoothAdapter* adapter, bool powered) override; + void InvalidateSurfaceState(); + void InvalidateSendSurfaceState(); + void InvalidateScanningState(); void InvalidateReceiveSurfaceState(); void InvalidateAdvertisingState(); void StopAdvertising(); @@ -143,6 +160,10 @@ NearbyConnection& connection, sharing::nearby::ConnectionResponseFrame::Status reponse_status); void Fail(const ShareTarget& share_target, TransferMetadata::Status status); + void StartScanning( + base::Optional<ShareTargetDiscoveredCallback*> discovery_callback); + void StartScanning(); + StatusCodes StopScanning(); void OnIncomingTransferUpdate(const ShareTarget& share_target, TransferMetadata metadata); void CloseConnection(const ShareTarget& share_target); @@ -158,7 +179,6 @@ const sharing::mojom::CertificateInfoFramePtr& certificate_frame); void OnIncomingConnectionDisconnected(const ShareTarget& share_target); - void UnregisterShareTarget(const ShareTarget& share_target); bool IsOutOfStorage(const ShareTarget& share_target); void OnIncomingMutualAcceptanceTimeout(const ShareTarget& share_target); @@ -166,14 +186,19 @@ IncomingShareTargetInfo& GetIncomingShareTargetInfo( const ShareTarget& share_target); NearbyConnection* GetIncomingConnection(const ShareTarget& share_target); - OutgoingShareTargetInfo& GetOutgoingShareTargetInfo( - const ShareTarget& share_target); + OutgoingShareTargetInfo& GetOrCreateOutgoingShareTargetInfo( + const ShareTarget& share_target, + const std::string& endpoint_id); void ClearOutgoingShareTargetInfoMap(); void SetAttachmentPayloadId(const Attachment& attachment, int64_t payload_id); base::Optional<int64_t> GetAttachmentPayloadId( const base::UnguessableToken& attachment_id); + base::Optional<ShareTarget> CreateShareTarget( + const std::string& endpoint_id, + sharing::mojom::AdvertisementPtr advertisement, + bool is_incoming); + void UnregisterShareTarget(const ShareTarget& share_target); - PrefService* prefs_; Profile* profile_; NearbyShareSettings settings_; std::unique_ptr<NearbyConnectionsManager> nearby_connections_manager_; @@ -193,6 +218,20 @@ base::ObserverList<TransferUpdateCallback> foreground_receive_callbacks_; // A list of foreground receivers. base::ObserverList<TransferUpdateCallback> background_receive_callbacks_; + // A list of foreground receivers for transfer updates on the send surface. + base::ObserverList<TransferUpdateCallback> + foreground_send_transfer_callbacks_; + // A list of foreground receivers for discovered device updates on the send + // surface. + base::ObserverList<ShareTargetDiscoveredCallback> + foreground_send_discovery_callbacks_; + // A list of background receivers for transfer updates on the send surface. + base::ObserverList<TransferUpdateCallback> + background_send_transfer_callbacks_; + // A list of background receivers for discovered device updates on the send + // surface. + base::ObserverList<ShareTargetDiscoveredCallback> + background_send_discovery_callbacks_; // Registers the most recent TransferMetadata and ShareTarget used for // transitioning notifications between foreground surfaces and background @@ -207,6 +246,10 @@ // incoming share target. base::flat_map<base::UnguessableToken, IncomingShareTargetInfo> incoming_share_target_info_map_; + // A map of endpoint id to ShareTarget, where each ShareTarget entry + // directly corresponds to a OutgoingShareTargetInfo entry in + // outgoing_share_target_info_map_; + base::flat_map<std::string, ShareTarget> outgoing_share_target_map_; // A map of ShareTarget id to OutgoingShareTargetInfo. This lets us know which // endpoint and public certificate are related to the outgoing share target. // TODO(crbug/1085068) update this map when handling payloads @@ -227,7 +270,13 @@ // True if we are currently scanning for remote devices. bool is_scanning_ = false; // True if we're currently sending or receiving a file. - bool is_transferring_files_ = false; + bool is_transferring_ = false; + // True if we're currently receiving a file. + bool is_receiving_files_ = false; + // True if we're currently attempting to connect to a remote device. + bool is_connecting_ = false; + // The time scanning began. + base::Time scanning_start_timestamp_; mojo::Receiver<nearby_share::mojom::NearbyShareSettingsObserver> settings_receiver_{this};
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc index 026e5af..70699f66 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/nearby_sharing/nearby_connections_manager.h" #include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/services/sharing/public/cpp/advertisement.h" #include "chrome/services/sharing/public/proto/wire_format.pb.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -43,6 +44,8 @@ using NetConnectionType = net::NetworkChangeNotifier::ConnectionType; +using SendSurfaceState = NearbySharingService::SendSurfaceState; + class FakeFastInitiationManager : public FastInitiationManager { public: explicit FakeFastInitiationManager( @@ -112,7 +115,10 @@ } size_t StartAdvertisingCount() { - return last_fake_fast_initiation_manager_->start_advertising_call_count(); + return last_fake_fast_initiation_manager_ + ? last_fake_fast_initiation_manager_ + ->start_advertising_call_count() + : 0; } bool StopAdvertisingCalledAndManagerDestroyed() { @@ -139,9 +145,22 @@ (override)); }; +class MockShareTargetDiscoveredCallback : public ShareTargetDiscoveredCallback { + public: + ~MockShareTargetDiscoveredCallback() override = default; + + MOCK_METHOD(void, + OnShareTargetDiscovered, + (ShareTarget shareTarget), + (override)); + MOCK_METHOD(void, OnShareTargetLost, (ShareTarget shareTarget), (override)); +}; + namespace { +const char kServiceId[] = "NearbySharing"; const char kEndpointId[] = "endpoint_id"; +const char kDeviceName[] = "device_name"; sharing::mojom::FramePtr GetValidIntroductionFrame() { std::vector<sharing::mojom::TextMetadataPtr> mojo_text_metadatas; @@ -162,6 +181,19 @@ return mojo_frame; } +// Length sharing::Advertisement::kSaltSize +const uint8_t kSalt[] = {0x0c, 0x08}; +// Length sharing::Advertisement::kMetadataEncryptionKeyHashByteSize +const uint8_t kMetadataEncryptionKeyHashByte[] = {0x07, 0x01, 0x08, 0x08, 0x04, + 0x09, 0x06, 0x00, 0x0b, 0x0f, + 0x0c, 0x09, 0x03, 0x0d}; +const int kEndpointInfoSize = + 1 + sharing::Advertisement::kSaltSize + + sharing::Advertisement::kMetadataEncryptionKeyHashByteSize; +const uint8_t kEndpointInfo[] = {0x00, 0x0c, 0x08, 0x07, 0x01, 0x08, + 0x08, 0x04, 0x09, 0x06, 0x00, 0x0b, + 0x0f, 0x0c, 0x09, 0x03, 0x0d}; + class NearbySharingServiceImplTest : public testing::Test { public: NearbySharingServiceImplTest() { @@ -206,6 +238,8 @@ &prefs_, notification_display_service, profile, base::WrapUnique(fake_nearby_connections_manager_), &mock_nearby_process_manager_); + NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance(); + process_manager.SetActiveProfile(profile); // Allow the posted task to fetch the BluetoothAdapter to finish. base::RunLoop().RunUntilIdle(); @@ -259,6 +293,47 @@ net::test::MockNetworkChangeNotifier::Create(); }; +struct ValidSendSurfaceTestData { + ui::IdleState idle_state; + bool bluetooth_enabled; + net::NetworkChangeNotifier::ConnectionType connection_type; +} kValidSendSurfaceTestData[] = { + // No network connection, only bluetooth available + {ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_NONE}, + // Wifi available + {ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_WIFI}, + // Ethernet available + {ui::IDLE_STATE_IDLE, true, + net::NetworkChangeNotifier::CONNECTION_ETHERNET}, + // 3G available + {ui::IDLE_STATE_IDLE, true, net::NetworkChangeNotifier::CONNECTION_3G}, + // Wifi available and no bluetooth + {ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_WIFI}, + // Ethernet available and no bluetooth + {ui::IDLE_STATE_IDLE, false, + net::NetworkChangeNotifier::CONNECTION_ETHERNET}}; + +class NearbySharingServiceImplValidSendTest + : public NearbySharingServiceImplTest, + public testing::WithParamInterface<ValidSendSurfaceTestData> {}; + +struct InvalidSendSurfaceTestData { + ui::IdleState idle_state; + bool bluetooth_enabled; + net::NetworkChangeNotifier::ConnectionType connection_type; +} kInvalidSendSurfaceTestData[] = { + // Screen locked + {ui::IDLE_STATE_LOCKED, true, net::NetworkChangeNotifier::CONNECTION_WIFI}, + // No network connection and no bluetooth + {ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_NONE}, + // 3G available and no bluetooth + {ui::IDLE_STATE_IDLE, false, net::NetworkChangeNotifier::CONNECTION_3G}, +}; + +class NearbySharingServiceImplInvalidSendTest + : public NearbySharingServiceImplTest, + public testing::WithParamInterface<InvalidSendSurfaceTestData> {}; + } // namespace TEST_F(NearbySharingServiceImplTest, AddsNearbyProcessObserver) { @@ -272,79 +347,111 @@ } TEST_F(NearbySharingServiceImplTest, DisableNearbyShutdownConnections) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false); service_->FlushMojoForTesting(); EXPECT_TRUE(fake_nearby_connections_manager_->IsShutdown()); } TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising) { - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); EXPECT_EQ(1u, fast_initiation_manager_factory_->StartAdvertisingCount()); - // Call RegisterSendSurface() a second time and make sure StartAdvertising is + // Call RegisterSendSurface a second time and make sure StartAdvertising is // not called again. - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + EXPECT_EQ( + NearbySharingService::StatusCodes::kError, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); EXPECT_EQ(1u, fast_initiation_manager_factory_->StartAdvertisingCount()); } TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertisingError) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); SetFakeFastInitiationManagerFactory(/*should_succeed_on_start=*/false); - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); +} + +TEST_F(NearbySharingServiceImplTest, + BackgroundStartFastInitiationAdvertisingError) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kBackground)); + EXPECT_EQ(0u, fast_initiation_manager_factory_->StartAdvertisingCount()); } TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising_BluetoothNotPresent) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); is_bluetooth_present_ = false; - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); } TEST_F(NearbySharingServiceImplTest, StartFastInitiationAdvertising_BluetoothNotPowered) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); is_bluetooth_powered_ = false; - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); } TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising) { - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); EXPECT_EQ(1u, fast_initiation_manager_factory_->StartAdvertisingCount()); - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->UnregisterSendSurface(/*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr)); + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->UnregisterSendSurface(&transfer_callback, &discovery_callback)); EXPECT_TRUE(fast_initiation_manager_factory_ ->StopAdvertisingCalledAndManagerDestroyed()); } TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising_BluetoothBecomesNotPresent) { - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); adapter_observer_->AdapterPresentChanged(mock_bluetooth_adapter_.get(), false); EXPECT_TRUE(fast_initiation_manager_factory_ @@ -353,11 +460,14 @@ TEST_F(NearbySharingServiceImplTest, StopFastInitiationAdvertising_BluetoothBecomesNotPowered) { - EXPECT_EQ(NearbySharingService::StatusCodes::kOk, - service_->RegisterSendSurface( - /*transfer_callback=*/nullptr, - /*discovery_callback=*/nullptr, - NearbySharingService::SendSurfaceState::kForeground)); + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); adapter_observer_->AdapterPoweredChanged(mock_bluetooth_adapter_.get(), false); EXPECT_TRUE(fast_initiation_manager_factory_ @@ -365,6 +475,286 @@ } TEST_F(NearbySharingServiceImplTest, + RegisterSendSurfaceNoActiveProfilesNotDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + NearbyProcessManager& process_manager = NearbyProcessManager::GetInstance(); + process_manager.ClearActiveProfile(); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kError, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); +} + +TEST_F(NearbySharingServiceImplTest, + ForegroundRegisterSendSurfaceStartsDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); +} + +TEST_F(NearbySharingServiceImplTest, + ForegroundRegisterSendSurfaceTwiceKeepsDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + EXPECT_EQ( + NearbySharingService::StatusCodes::kError, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); +} + +TEST_F(NearbySharingServiceImplTest, + RegisterSendSurfaceAlreadyReceivingNotDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + // TODO(himanshujaju) is_receiving_files_ should be set to true when + // receiving. Test that WHEN receiving files, THEN below passes. + // EXPECT_EQ(NearbySharingService::StatusCodes::kTransferAlreadyInProgress, + // RegisterSendSurface(SendSurfaceState::kForeground)); + // EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + // EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown()); +} + +TEST_F(NearbySharingServiceImplTest, + BackgroundRegisterSendSurfaceNotDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kBackground)); + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown()); +} + +TEST_F(NearbySharingServiceImplTest, + DifferentSurfaceRegisterSendSurfaceTwiceKeepsDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + EXPECT_EQ( + NearbySharingService::StatusCodes::kError, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kBackground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); +} + +TEST_F(NearbySharingServiceImplTest, + RegisterSendSurfaceEndpointFoundDiscoveryCallbackNotified) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + + // Ensure decoder parses a valid endpoint advertisement. + NiceMock<MockNearbySharingDecoder> mock_decoder; + std::vector<uint8_t> endpoint_info(kEndpointInfo, + kEndpointInfo + kEndpointInfoSize); + std::vector<uint8_t> metadata_encryption_key( + kMetadataEncryptionKeyHashByte, + kMetadataEncryptionKeyHashByte + + sharing::Advertisement::kMetadataEncryptionKeyHashByteSize); + std::vector<uint8_t> salt(kSalt, kSalt + sharing::Advertisement::kSaltSize); + EXPECT_CALL(mock_decoder, + DecodeAdvertisement(testing::Eq(endpoint_info), testing::_)) + .WillOnce(testing::Invoke( + [&salt, &metadata_encryption_key]( + const std::vector<uint8_t>& data, + MockNearbySharingDecoder::DecodeAdvertisementCallback callback) { + sharing::mojom::AdvertisementPtr mojo_adv = + sharing::mojom::Advertisement::New( + salt, metadata_encryption_key, kDeviceName); + std::move(callback).Run(std::move(mojo_adv)); + })); + EXPECT_CALL(mock_nearby_process_manager(), + GetOrStartNearbySharingDecoder(testing::_)) + .WillRepeatedly(testing::Return(&mock_decoder)); + + // Start discovering, to ensure a discovery listener is registered. + base::RunLoop run_loop; + MockTransferUpdateCallback transfer_callback; + NiceMock<MockShareTargetDiscoveredCallback> discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + // Discover a new endpoint. + EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) + .WillOnce([&run_loop](ShareTarget share_target) { + EXPECT_EQ(kDeviceName, share_target.device_name); + run_loop.Quit(); + }); + fake_nearby_connections_manager_->OnEndpointFound( + kEndpointId, + location::nearby::connections::mojom::DiscoveredEndpointInfo::New( + endpoint_info, kServiceId)); + run_loop.Run(); + + // Register another send surface, which will automatically catch up discovered + // endpoints. + base::RunLoop run_loop2; + MockTransferUpdateCallback transfer_callback2; + NiceMock<MockShareTargetDiscoveredCallback> discovery_callback2; + EXPECT_CALL(discovery_callback2, OnShareTargetDiscovered) + .WillOnce([&run_loop2](ShareTarget share_target) { + EXPECT_EQ(kDeviceName, share_target.device_name); + run_loop2.Quit(); + }); + + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback2, &discovery_callback2, + SendSurfaceState::kForeground)); + run_loop2.Run(); +} + +TEST_P(NearbySharingServiceImplValidSendTest, + RegisterSendSurfaceIsDiscovering) { + ui::ScopedSetIdleState idle_state(GetParam().idle_state); + is_bluetooth_present_ = GetParam().bluetooth_enabled; + SetConnectionType(GetParam().connection_type); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); +} + +INSTANTIATE_TEST_SUITE_P(NearbySharingServiceImplTest, + NearbySharingServiceImplValidSendTest, + testing::ValuesIn(kValidSendSurfaceTestData)); + +TEST_P(NearbySharingServiceImplInvalidSendTest, + RegisterSendSurfaceNotDiscovering) { + ui::ScopedSetIdleState idle_state(GetParam().idle_state); + is_bluetooth_present_ = GetParam().bluetooth_enabled; + SetConnectionType(GetParam().connection_type); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown()); +} + +INSTANTIATE_TEST_SUITE_P(NearbySharingServiceImplTest, + NearbySharingServiceImplInvalidSendTest, + testing::ValuesIn(kInvalidSendSurfaceTestData)); + +TEST_F(NearbySharingServiceImplTest, DisableFeatureSendSurfaceNotDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false); + service_->FlushMojoForTesting(); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + EXPECT_TRUE(fake_nearby_connections_manager_->IsShutdown()); +} + +TEST_F(NearbySharingServiceImplTest, + DisableFeatureSendSurfaceStopsDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + prefs_.SetBoolean(prefs::kNearbySharingEnabledPrefName, false); + service_->FlushMojoForTesting(); + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + EXPECT_TRUE(fake_nearby_connections_manager_->IsShutdown()); +} + +TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceStopsDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->UnregisterSendSurface(&transfer_callback, &discovery_callback)); + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); + EXPECT_FALSE(fake_nearby_connections_manager_->IsShutdown()); +} + +TEST_F(NearbySharingServiceImplTest, + UnregisterSendSurfaceDifferentCallbackKeepDiscovering) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + MockTransferUpdateCallback transfer_callback2; + MockShareTargetDiscoveredCallback discovery_callback2; + EXPECT_EQ(NearbySharingService::StatusCodes::kError, + service_->UnregisterSendSurface(&transfer_callback2, + &discovery_callback2)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); +} + +TEST_F(NearbySharingServiceImplTest, UnregisterSendSurfaceNeverRegistered) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + MockTransferUpdateCallback transfer_callback; + MockShareTargetDiscoveredCallback discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kError, + service_->UnregisterSendSurface(&transfer_callback, &discovery_callback)); + EXPECT_FALSE(fake_nearby_connections_manager_->IsDiscovering()); +} + +TEST_F(NearbySharingServiceImplTest, ForegroundRegisterReceiveSurfaceIsAdvertising) { ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
diff --git a/chrome/browser/nfc/nfc_permission_context.cc b/chrome/browser/nfc/nfc_permission_context.cc index 672805a..f72f597 100644 --- a/chrome/browser/nfc/nfc_permission_context.cc +++ b/chrome/browser/nfc/nfc_permission_context.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/nfc/nfc_permission_context.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_request_id.h" NfcPermissionContext::NfcPermissionContext( @@ -45,7 +45,7 @@ const GURL& requesting_frame, bool allowed) { auto* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings::GetForFrame( id.render_process_id(), id.render_frame_id()); if (!content_settings) return;
diff --git a/chrome/browser/nfc/nfc_permission_context_unittest.cc b/chrome/browser/nfc/nfc_permission_context_unittest.cc index 165ba47..510d8ff1 100644 --- a/chrome/browser/nfc/nfc_permission_context_unittest.cc +++ b/chrome/browser/nfc/nfc_permission_context_unittest.cc
@@ -6,10 +6,10 @@ #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_manager.h" #include "components/permissions/permission_request_id.h" #include "components/permissions/permission_request_manager.h" @@ -115,9 +115,9 @@ void NfcPermissionContextTests::SetUp() { ChromeRenderViewHostTestHarness::SetUp(); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); nfc_permission_context_ = static_cast<NfcPermissionContext*>( PermissionManagerFactory::GetForProfile(profile())
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java index 54613d6b..be71c982 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java
@@ -142,8 +142,8 @@ */ void destroy() { if (mNativePasswordCheckBridge != 0) { - mNativePasswordCheckBridge = 0; PasswordCheckBridgeJni.get().destroy(mNativePasswordCheckBridge); + mNativePasswordCheckBridge = 0; } }
diff --git a/chrome/browser/payments/BUILD.gn b/chrome/browser/payments/BUILD.gn index 29cc6a1ea..210ab7e1 100644 --- a/chrome/browser/payments/BUILD.gn +++ b/chrome/browser/payments/BUILD.gn
@@ -20,6 +20,7 @@ "payment_handler_enforce_full_delegation_browsertest.cc", "payment_handler_exploit_browsertest.cc", "payment_handler_just_in_time_installation_browsertest.cc", + "payment_handler_uninstall_browsertest.cc", "payment_request_app_store_billing_browsertest.cc", "payment_request_can_make_payment_browsertest.cc", "payment_request_can_make_payment_event_browsertest.cc",
diff --git a/chrome/browser/payments/payment_handler_uninstall_browsertest.cc b/chrome/browser/payments/payment_handler_uninstall_browsertest.cc new file mode 100644 index 0000000..e66c316 --- /dev/null +++ b/chrome/browser/payments/payment_handler_uninstall_browsertest.cc
@@ -0,0 +1,67 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/test/payments/payment_request_platform_browsertest_base.h" +#include "content/public/test/browser_test.h" + +namespace payments { + +namespace { + +class PaymentHandlerUninstallTest + : public PaymentRequestPlatformBrowserTestBase { + protected: + PaymentHandlerUninstallTest() = default; + ~PaymentHandlerUninstallTest() override = default; + + void SetUpOnMainThread() override { + PaymentRequestPlatformBrowserTestBase::SetUpOnMainThread(); + NavigateTo("/payment_handler.html"); + } +}; + +IN_PROC_BROWSER_TEST_F(PaymentHandlerUninstallTest, URLBasedPaymentMethod) { + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), "install()")); + + // Launch the payment request and confirm checkout completion. + ResetEventWaiterForSingleEvent(TestEvent::kPaymentCompleted); + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), "launch()")); + WaitForObservedEvent(); + + // Uninstall the payment app and verify that a new request.show() gets + // rejected after the app uninstallation. + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), "uninstall()")); + ResetEventWaiterForSingleEvent(TestEvent::kNotSupportedError); + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), + "launchWithoutWaitForResponse()")); + WaitForObservedEvent(); +} + +IN_PROC_BROWSER_TEST_F(PaymentHandlerUninstallTest, BasicCard) { + EXPECT_EQ("success", + content::EvalJs(GetActiveWebContents(), "install('basic-card')")); + + // Launch the payment request and validate that one app is available. + ResetEventWaiterForSingleEvent(TestEvent::kAppListReady); + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), + "launchWithoutWaitForResponse()")); + WaitForObservedEvent(); + EXPECT_EQ(1u, test_controller()->app_descriptions().size()); + + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), "abort()")); + + // Uninstall the payment app and verify that there is no payment app + // available. A new request.show() will not get rejected though since the user + // will still have the option to add a credit card. + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), "uninstall()")); + ResetEventWaiterForSingleEvent(TestEvent::kAppListReady); + EXPECT_EQ("success", content::EvalJs(GetActiveWebContents(), + "launchWithoutWaitForResponse()")); + WaitForObservedEvent(); + EXPECT_EQ(0u, test_controller()->app_descriptions().size()); +} + +} // namespace + +} // namespace payments
diff --git a/chrome/browser/pepper_broker_infobar_delegate.cc b/chrome/browser/pepper_broker_infobar_delegate.cc index 9f5e8cd..2a88ab3f 100644 --- a/chrome/browser/pepper_broker_infobar_delegate.cc +++ b/chrome/browser/pepper_broker_infobar_delegate.cc
@@ -9,7 +9,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/grit/generated_resources.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/infobars/core/infobar.h" #include "components/strings/grit/components_strings.h" @@ -26,11 +26,11 @@ const GURL& url, const base::string16& plugin_name, HostContentSettingsMap* content_settings, - content_settings::TabSpecificContentSettings* tab_content_settings, + content_settings::PageSpecificContentSettings* page_content_settings, base::OnceCallback<void(bool)> callback) { infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar( base::WrapUnique(new PepperBrokerInfoBarDelegate( - url, plugin_name, content_settings, tab_content_settings, + url, plugin_name, content_settings, page_content_settings, std::move(callback))))); } @@ -38,13 +38,13 @@ const GURL& url, const base::string16& plugin_name, HostContentSettingsMap* content_settings, - content_settings::TabSpecificContentSettings* tab_content_settings, + content_settings::PageSpecificContentSettings* page_content_settings, base::OnceCallback<void(bool)> callback) : url_(url), plugin_name_(plugin_name), content_settings_(content_settings), - tab_content_settings_( - tab_content_settings ? tab_content_settings->AsWeakPtr() : nullptr), + page_content_settings_( + page_content_settings ? page_content_settings->AsWeakPtr() : nullptr), callback_(std::move(callback)) {} PepperBrokerInfoBarDelegate::~PepperBrokerInfoBarDelegate() { @@ -100,7 +100,7 @@ content_settings_->SetContentSettingDefaultScope( url_, GURL(), ContentSettingsType::PPAPI_BROKER, std::string(), result ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK); - if (tab_content_settings_) { - tab_content_settings_->SetPepperBrokerAllowed(result); + if (page_content_settings_) { + page_content_settings_->SetPepperBrokerAllowed(result); } }
diff --git a/chrome/browser/pepper_broker_infobar_delegate.h b/chrome/browser/pepper_broker_infobar_delegate.h index dbea1b0..a379542 100644 --- a/chrome/browser/pepper_broker_infobar_delegate.h +++ b/chrome/browser/pepper_broker_infobar_delegate.h
@@ -15,7 +15,7 @@ class InfoBarService; namespace content_settings { -class TabSpecificContentSettings; +class PageSpecificContentSettings; } // Shows an infobar that asks the user whether a Pepper plugin is allowed @@ -30,7 +30,7 @@ const GURL& url, const base::string16& plugin_name, HostContentSettingsMap* content_settings, - content_settings::TabSpecificContentSettings* tab_content_settings, + content_settings::PageSpecificContentSettings* page_content_settings, base::OnceCallback<void(bool)> callback); ~PepperBrokerInfoBarDelegate() override; @@ -39,7 +39,7 @@ const GURL& url, const base::string16& plugin_name, HostContentSettingsMap* content_settings, - content_settings::TabSpecificContentSettings* tab_content_settings, + content_settings::PageSpecificContentSettings* page_content_settings, base::OnceCallback<void(bool)> callback); // ConfirmInfoBarDelegate: @@ -57,8 +57,8 @@ const GURL url_; const base::string16 plugin_name_; HostContentSettingsMap* content_settings_; - base::WeakPtr<content_settings::TabSpecificContentSettings> - tab_content_settings_; + base::WeakPtr<content_settings::PageSpecificContentSettings> + page_content_settings_; base::OnceCallback<void(bool)> callback_; DISALLOW_COPY_AND_ASSIGN(PepperBrokerInfoBarDelegate);
diff --git a/chrome/browser/plugins/flash_download_interception.cc b/chrome/browser/plugins/flash_download_interception.cc index 689c74c..1eb0e399 100644 --- a/chrome/browser/plugins/flash_download_interception.cc +++ b/chrome/browser/plugins/flash_download_interception.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/plugins/plugin_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/navigation_interception/intercept_navigation_throttle.h" #include "components/navigation_interception/navigation_params.h" @@ -90,7 +90,7 @@ ContentSettingsType::PLUGINS, web_contents->GetMainFrame(), web_contents->GetLastCommittedURL(), true, base::DoNothing()); } else if (flash_setting == CONTENT_SETTING_BLOCK) { - auto* settings = content_settings::TabSpecificContentSettings::GetForFrame( + auto* settings = content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()); if (settings) settings->FlashDownloadBlocked();
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 910322e..991a13c 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -114,7 +114,7 @@ #include "ash/public/cpp/ash_pref_names.h" #include "chrome/browser/chromeos/accessibility/magnifier_type.h" #include "chrome/browser/chromeos/crostini/crostini_pref_names.h" -#include "chrome/browser/chromeos/platform_keys/key_permissions_policy_handler.h" +#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_policy_handler.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h" #include "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h" #include "chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.h" @@ -1725,7 +1725,8 @@ SimpleSchemaValidatingPolicyHandler::RECOMMENDED_ALLOWED, SimpleSchemaValidatingPolicyHandler::MANDATORY_PROHIBITED)); handlers->AddHandler( - std::make_unique<chromeos::KeyPermissionsPolicyHandler>(chrome_schema)); + std::make_unique<chromeos::platform_keys::KeyPermissionsPolicyHandler>( + chrome_schema)); handlers->AddHandler(std::make_unique<DefaultGeolocationPolicyHandler>()); handlers->AddHandler(std::make_unique<extensions::ExtensionListPolicyHandler>( key::kNoteTakingAppsLockScreenAllowlist,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index ab4ae7979..5344b93 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -300,7 +300,7 @@ #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h" #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" #include "chrome/browser/chromeos/net/network_throttling_observer.h" -#include "chrome/browser/chromeos/platform_keys/key_permissions.h" +#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h" #include "chrome/browser/chromeos/policy/app_install_event_log_manager_wrapper.h" #include "chrome/browser/chromeos/policy/app_install_event_logger.h" @@ -1059,7 +1059,7 @@ chromeos::first_run::RegisterProfilePrefs(registry); chromeos::file_system_provider::RegisterProfilePrefs(registry); chromeos::KerberosCredentialsManager::RegisterProfilePrefs(registry); - chromeos::KeyPermissions::RegisterProfilePrefs(registry); + chromeos::platform_keys::KeyPermissions::RegisterProfilePrefs(registry); chromeos::multidevice_setup::MultiDeviceSetupService::RegisterProfilePrefs( registry); chromeos::MultiProfileUserController::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index d8677fd..d2300291 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -944,7 +944,7 @@ chrome.fileSystem.chooseEntry( { type: 'saveFile', - accepts: [{extensions: ['pdf']}], + accepts: [{description: '*.pdf', extensions: ['pdf']}], suggestedName: fileName }, entry => {
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js index eb92cf1..8001c8b 100644 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js +++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.js
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off // #import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; -// #import {AmbientModeTopicSource, AmbientModeSettings} from './constants.m.js'; +// #import {AmbientModeTopicSource, AmbientModeTemperatureUnit, AmbientModeSettings} from './constants.m.js'; +// clang-format on /** * @fileoverview A helper object used from the ambient mode section to interact @@ -14,10 +16,11 @@ /** @interface */ /* #export */ class AmbientModeBrowserProxy { /** - * Retrieves the AmbientModeTopicSource from server. As a response, the C++ - * sends the 'topic-source-changed' event. + * Retrieves the AmbientModeTopicSource and AmbientModeTemperatureUnit from + * server. As a response, the C++ sends the 'topic-source-changed' and + * 'temperature-unit-changed' events. */ - requestTopicSource() {} + requestSettings() {} /** * Retrieves the albums from server. As a response, the C++ sends either the @@ -28,6 +31,12 @@ requestAlbums(topicSource) {} /** + * Updates the selected temperature unit to server. + * @param {!AmbientModeTemperatureUnit} temperatureUnit + */ + setSelectedTemperatureUnit(temperatureUnit) {} + + /** * Updates the selected topic source to server. * @param {!AmbientModeTopicSource} topicSource the selected topic source. */ @@ -43,8 +52,8 @@ /** @implements {settings.AmbientModeBrowserProxy} */ /* #export */ class AmbientModeBrowserProxyImpl { /** @override */ - requestTopicSource() { - chrome.send('requestTopicSource'); + requestSettings() { + chrome.send('requestSettings'); } /** @override */ @@ -53,6 +62,11 @@ } /** @override */ + setSelectedTemperatureUnit(temperatureUnit) { + chrome.send('setSelectedTemperatureUnit', [temperatureUnit]); + } + + /** @override */ setSelectedTopicSource(topicSource) { chrome.send('setSelectedTopicSource', [topicSource]); }
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html index 90e6e622..49a9d1f 100644 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html +++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.html
@@ -35,12 +35,23 @@ /* Set padding on children instead of the container itself to ensure that * separator lines can fill the entire width of the page. */ - #topicSourceListDiv > * { + #topicSourceListDiv > *, + #weatherDiv > * { /* Padded to the right to allow space for a ripple */ padding-inline-end: calc(var(--cr-section-padding) - var(--cr-icon-ripple-padding)); padding-inline-start: var(--cr-section-padding); } + + #weatherTitle { + padding-bottom: 16px; + padding-top: 16px; + } + + .list-item { + padding-inline-start: var(--cr-section-padding); + } + </style> <h2 id="pageDescription"> $i18n{ambientModePageDescription} @@ -60,6 +71,29 @@ disabled="[[!isValidTopicSource_(selectedTopicSource_)]]"> </topic-source-list> </div> + <div id="weatherDiv" class="layout vertical flex"> + <h2 id="weatherTitle" aria-hidden="true"> + $i18n{ambientModeWeatherTitle} + </h2> + <div class="list-frame"> + <cr-radio-group + id="ambientTemperatureUnit" + selected="{{selectedTemperatureUnit_}}" + disabled$="[[!isValidTemperatureUnit_(selectedTemperatureUnit_)]]" + aria-labelledby="weatherTitle"> + <cr-radio-button + name="[[AmbientModeTemperatureUnit_.FAHRENHEIT]]" + class="list-item underbar" + label="$i18n{ambientModeTemperatureUnitFahrenheit}"> + </cr-radio-button> + <cr-radio-button + name="[[AmbientModeTemperatureUnit_.CELSIUS]]" + class="list-item" + label="$i18n{ambientModeTemperatureUnitCelsius}"> + </cr-radio-button> + </cr-radio-group> + </div> + </div> </template> </template> <script src="ambient_mode_page.js"></script>
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js index 116cbeea..12bef93 100644 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js +++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_page.js
@@ -27,6 +27,15 @@ value: AmbientModeTopicSource, }, + /** + * Used to refer to the enum values in the HTML. + * @private {!Object<string, AmbientModeTemperatureUnit>} + */ + AmbientModeTemperatureUnit_: { + type: Object, + value: AmbientModeTemperatureUnit, + }, + // TODO(b/160632748): Dynamically generate topic source of Google Photos. /** @private {!Array<!AmbientModeTopicSource>} */ topicSources_: { @@ -41,6 +50,13 @@ type: AmbientModeTopicSource, value: AmbientModeTopicSource.UNKNOWN, }, + + /** @private {!AmbientModeTemperatureUnit} */ + selectedTemperatureUnit_: { + type: AmbientModeTemperatureUnit, + value: AmbientModeTemperatureUnit.UNKNOWN, + observer: 'onSelectedTemperatureUnitChanged_' + }, }, listeners: { @@ -58,9 +74,18 @@ /** @override */ ready() { - this.addWebUIListener('topic-source-changed', (topicSource) => { - this.selectedTopicSource_ = topicSource; - }); + this.addWebUIListener( + 'topic-source-changed', + (/** @type {!AmbientModeTopicSource} */ topicSource) => { + this.selectedTopicSource_ = topicSource; + }, + ); + this.addWebUIListener( + 'temperature-unit-changed', + (/** @type {!AmbientModeTemperatureUnit} */ temperatureUnit) => { + this.selectedTemperatureUnit_ = temperatureUnit; + }, + ); }, /** @@ -73,7 +98,7 @@ return; } - this.browserProxy_.requestTopicSource(); + this.browserProxy_.requestSettings(); }, /** @@ -86,6 +111,16 @@ }, /** + * @param {!AmbientModeTemperatureUnit} temperatureUnit + * @return {boolean} + * @private + */ + isValidTemperatureUnit_(temperatureUnit) { + return temperatureUnit === AmbientModeTemperatureUnit.FAHRENHEIT || + temperatureUnit === AmbientModeTemperatureUnit.CELSIUS; + }, + + /** * @param {number} topicSource * @return {boolean} * @private @@ -95,6 +130,18 @@ }, /** + * @param {!AmbientModeTemperatureUnit} newValue + * @param {!AmbientModeTemperatureUnit} oldValue + * @private + */ + onSelectedTemperatureUnitChanged_(newValue, oldValue) { + if (newValue && newValue !== AmbientModeTemperatureUnit.UNKNOWN && + newValue !== oldValue) { + this.browserProxy_.setSelectedTemperatureUnit(newValue); + } + }, + + /** * @param {!CustomEvent<{item: !AmbientModeTopicSource}>} event * @private */
diff --git a/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js b/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js index 81272cb..c41138848 100644 --- a/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js +++ b/chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.js
@@ -13,6 +13,13 @@ ART_GALLERY: 1, }; +/** @enum {string} */ +/* #export */ const AmbientModeTemperatureUnit = { + UNKNOWN: 'unknown', + FAHRENHEIT: 'fahrenheit', + CELSIUS: 'celsius', +}; + /** * Album metadata for UI. *
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index f6bef2a4..054c597 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -66,7 +66,7 @@ cr_components_chromeos_auto_imports + cr_elements_chromeos_auto_imports + [ "chrome/browser/resources/settings/chromeos/ambient_mode_page/ambient_mode_browser_proxy.html|AmbientModeBrowserProxy,AmbientModeBrowserProxyImpl", - "chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.html|AmbientModeTopicSource,AmbientModeAlbum,AmbientModeSettings", + "chrome/browser/resources/settings/chromeos/ambient_mode_page/constants.html|AmbientModeTopicSource,AmbientModeTemperatureUnit,AmbientModeAlbum,AmbientModeSettings", "chrome/browser/resources/settings/chromeos/deep_linking_behavior.html|DeepLinkingBehavior", "chrome/browser/resources/settings/chromeos/metrics_recorder.html|recordSettingChange", "chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.html|MultiDeviceBrowserProxy,MultiDeviceBrowserProxyImpl",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js index 4e38396..66ea8fb 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.js +++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -26,6 +26,7 @@ export {CrSettingsPrefs} from '../prefs/prefs_types.m.js'; export {Route, Router} from '../router.m.js'; export {AmbientModeBrowserProxyImpl} from './ambient_mode_page/ambient_mode_browser_proxy.m.js'; +export {AmbientModeTemperatureUnit, AmbientModeTopicSource} from './ambient_mode_page/constants.m.js'; export {bluetoothApis} from './bluetooth_page/bluetooth_page.m.js'; export {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_page/multidevice_browser_proxy.m.js'; export {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, SmartLockSignInEnabledState} from './multidevice_page/multidevice_constants.m.js';
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc index 43e3a9aa..d838d1a 100644 --- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc +++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc
@@ -77,7 +77,8 @@ return ::safe_browsing::GetDMToken(profile_); } -std::string ChromeEnterpriseRealTimeUrlLookupService::GetDMTokenString() const { +base::Optional<std::string> +ChromeEnterpriseRealTimeUrlLookupService::GetDMTokenString() const { DCHECK(GetDMToken().is_valid()) << "Get a dm token string only if the dm token is valid."; return GetDMToken().value();
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h index 53824ef..8215f8f 100644 --- a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h +++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h
@@ -64,7 +64,7 @@ void GetAccessToken(const GURL& url, RTLookupRequestCallback request_callback, RTLookupResponseCallback response_callback) override; - std::string GetDMTokenString() const override; + base::Optional<std::string> GetDMTokenString() const override; std::string GetMetricSuffix() const override; policy::DMToken GetDMToken() const;
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc index 831f353..83891d48 100644 --- a/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc +++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_browsertest.cc
@@ -6,14 +6,18 @@ #include "base/base64.h" #include "base/path_service.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/values.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h" +#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service_factory.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.h" +#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h" #include "chrome/browser/safe_browsing/dm_token_utils.h" #include "chrome/browser/safe_browsing/download_protection/ppapi_download_request.h" #include "chrome/browser/safe_browsing/test_safe_browsing_service.h" @@ -24,6 +28,7 @@ #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" #include "components/download/public/common/download_danger_type.h" #include "components/enterprise/common/proto/connectors.pb.h" +#include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/safe_browsing/core/db/test_database_manager.h" @@ -110,6 +115,16 @@ download_items_.erase(item); } + void SetUpReporting() { + SetUnsafeEventsReportingPolicy(true); + client_ = std::make_unique<policy::MockCloudPolicyClient>(); + extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile( + browser()->profile()) + ->SetCloudPolicyClientForTesting(client_.get()); + } + + policy::MockCloudPolicyClient* client() { return client_.get(); } + protected: void SetUp() override { test_sb_factory_ = std::make_unique<TestSafeBrowsingServiceFactory>(); @@ -340,6 +355,8 @@ base::OnceClosure waiting_for_upload_closure_; base::flat_set<download::DownloadItem*> download_items_; + + std::unique_ptr<policy::MockCloudPolicyClient> client_; }; INSTANTIATE_TEST_SUITE_P(, DownloadDeepScanningBrowserTest, testing::Bool()); @@ -657,6 +674,119 @@ EXPECT_EQ(item->GetState(), download::DownloadItem::INTERRUPTED); } +IN_PROC_BROWSER_TEST_P(DownloadDeepScanningBrowserTest, MultipleFCMResponses) { + SetUpReporting(); + base::HistogramTester histograms; + + // The file is SAFE according to the metadata check + ClientDownloadResponse metadata_response; + metadata_response.set_verdict(ClientDownloadResponse::SAFE); + ExpectMetadataResponse(metadata_response); + + // No scan runs synchronously. + if (use_legacy_policies()) { + DeepScanningClientResponse sync_response; + ExpectDeepScanSynchronousResponse(/*is_advanced_protection=*/false, + sync_response); + } else { + enterprise_connectors::ContentAnalysisResponse sync_response; + ExpectContentAnalysisSynchronousResponse(/*is_advanced_protection=*/false, + sync_response, {"dlp", "malware"}); + } + + GURL url = embedded_test_server()->GetURL( + "/safe_browsing/download_protection/zipfile_two_archives.zip"); + ui_test_utils::NavigateToURLWithDisposition( + browser(), url, WindowOpenDisposition::CURRENT_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + + WaitForDeepScanRequest(/*is_advanced_protection=*/false); + + // The malware scan finishes asynchronously, and finds malware. + if (use_legacy_policies()) { + DeepScanningClientResponse async_response; + async_response.set_token(last_enterprise_request().request_token()); + async_response.mutable_malware_scan_verdict()->set_verdict( + MalwareDeepScanningVerdict::MALWARE); + SendFcmMessage(async_response); + } else { + enterprise_connectors::ContentAnalysisResponse async_response; + async_response.set_request_token( + last_enterprise_content_analysis_request().request_token()); + auto* result = async_response.add_results(); + result->set_tag("malware"); + result->set_status( + enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS); + auto* malware_rule = result->add_triggered_rules(); + malware_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK); + malware_rule->set_rule_name("malware"); + SendFcmMessage(async_response); + } + + // A single unsafe event should be recorded for this request. + std::set<std::string> zip_types = {"application/zip", + "application/x-zip-compressed"}; + EventReportValidator validator(client()); + validator.ExpectDangerousDeepScanningResult( + /*url*/ url.spec(), + /*filename*/ + (*download_items().begin())->GetTargetFilePath().AsUTF8Unsafe(), + // sha256sum chrome/test/data/safe_browsing/download_protection/\ + // zipfile_two_archives.zip | tr '[:lower:]' '[:upper:]' + /*sha*/ + "339C8FFDAE735C4F1846D0E6FF07FBD85CAEE6D96045AAEF5B30F3220836643C", + /*threat_type*/ "DANGEROUS", + /*trigger*/ + extensions::SafeBrowsingPrivateEventRouter::kTriggerFileDownload, + /*mimetypes*/ &zip_types, + /*size*/ 276, + /*result*/ EventResultToString(EventResult::WARNED)); + + // The DLP scan finishes asynchronously, and finds nothing. The malware result + // is attached to the response again. + if (use_legacy_policies()) { + DeepScanningClientResponse async_response; + async_response.set_token(last_enterprise_request().request_token()); + async_response.mutable_malware_scan_verdict()->set_verdict( + MalwareDeepScanningVerdict::MALWARE); + async_response.mutable_dlp_scan_verdict()->set_status( + DlpDeepScanningVerdict::SUCCESS); + SendFcmMessage(async_response); + } else { + enterprise_connectors::ContentAnalysisResponse async_response; + async_response.set_request_token( + last_enterprise_content_analysis_request().request_token()); + auto* malware_result = async_response.add_results(); + malware_result->set_tag("malware"); + malware_result->set_status( + enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS); + auto* malware_rule = malware_result->add_triggered_rules(); + malware_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK); + malware_rule->set_rule_name("malware"); + auto* dlp_result = async_response.add_results(); + dlp_result->set_tag("dlp"); + dlp_result->set_status( + enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS); + SendFcmMessage(async_response); + } + + // The file should be blocked. + ASSERT_EQ(download_items().size(), 1u); + download::DownloadItem* item = *download_items().begin(); + EXPECT_EQ( + item->GetDangerType(), + download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT); + EXPECT_EQ(item->GetState(), download::DownloadItem::IN_PROGRESS); + + // UMAs for this request should only be recorded once. + histograms.ExpectUniqueSample("SafeBrowsingBinaryUploadRequest.Result", + BinaryUploadService::Result::SUCCESS, 1); + histograms.ExpectUniqueSample("SafeBrowsingBinaryUploadRequest.DlpResult", + true, 1); + histograms.ExpectUniqueSample("SafeBrowsingBinaryUploadRequest.MalwareResult", + true, 1); +} + class WhitelistedUrlDeepScanningBrowserTest : public DownloadDeepScanningBrowserTest { public:
diff --git a/chrome/browser/safe_browsing/download_protection/download_reporter.cc b/chrome/browser/safe_browsing/download_protection/download_reporter.cc index bdcaac9..9588410a 100644 --- a/chrome/browser/safe_browsing/download_protection/download_reporter.cc +++ b/chrome/browser/safe_browsing/download_protection/download_reporter.cc
@@ -154,6 +154,7 @@ download::DownloadDangerType current_danger_type = download->GetDangerType(); if (!DangerTypeIsDangerous(old_danger_type) && + old_danger_type != download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING && DangerTypeIsDangerous(current_danger_type)) { ReportDangerousDownloadWarning(download); }
diff --git a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc index 58a7b9e..67bb6ca 100644 --- a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc +++ b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
@@ -119,14 +119,13 @@ return; } - bool has_valid_primary_sync_account = HasValidPrimarySyncAccount(); switch (primary_sync_account_wait_) { case PrimarySyncAccountWait::kWaitForAdded: - if (!has_valid_primary_sync_account) + if (!HasValidPrimarySyncAccount()) return; break; case PrimarySyncAccountWait::kWaitForCleared: - if (has_valid_primary_sync_account) + if (identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync)) return; break; case PrimarySyncAccountWait::kNotWait: @@ -179,6 +178,8 @@ }; // Live tests for SignIn. +// These tests can be run with: +// browser_tests --gtest_filter=LiveSignInTest.* --run-live-tests --run-manual class LiveSignInTest : public signin::test::LiveTest { public: LiveSignInTest() = default; @@ -409,6 +410,31 @@ EXPECT_FALSE(identity_manager()->HasPrimaryAccount()); } +// In "Sync paused" state, when the primary account is invalid, turns off sync +// from settings. Checks that the account is removed from Chrome. +// Regression test for https://crbug.com/1114646 +IN_PROC_BROWSER_TEST_F(LiveSignInTest, MANUAL_TurnOffSyncWhenPaused) { + TestAccount test_account_1; + CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1)); + TurnOnSync(test_account_1, 0); + + // Get in sync paused state. + SignOutFromWeb(); + + const CoreAccountInfo& primary_account = + identity_manager()->GetPrimaryAccountInfo(); + EXPECT_FALSE(primary_account.IsEmpty()); + EXPECT_TRUE(gaia::AreEmailsSame(test_account_1.user, primary_account.email)); + EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled()); + EXPECT_TRUE( + identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState( + primary_account.account_id)); + + TurnOffSync(); + EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty()); + EXPECT_FALSE(identity_manager()->HasPrimaryAccount()); +} + // This test can pass. Marked as manual because it TIMED_OUT on Win7. // See crbug.com/1025335. // Signs in an account on the web. Goes to the Chrome settings to enable Sync
diff --git a/chrome/browser/signin/signin_features.cc b/chrome/browser/signin/signin_features.cc index 34a745b..04c9c495 100644 --- a/chrome/browser/signin/signin_features.cc +++ b/chrome/browser/signin/signin_features.cc
@@ -8,6 +8,3 @@ const base::Feature kDiceWebSigninInterceptionFeature{ "DiceWebSigninInterception", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // ENABLE_DICE_SUPPORT - -const base::Feature kSigninReauthPrompt = {"SigninReauthPrompt", - base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/signin/signin_features.h b/chrome/browser/signin/signin_features.h index 258cb70c..6b258b77 100644 --- a/chrome/browser/signin/signin_features.h +++ b/chrome/browser/signin/signin_features.h
@@ -12,6 +12,4 @@ extern const base::Feature kDiceWebSigninInterceptionFeature; #endif // ENABLE_DICE_SUPPORT -extern const base::Feature kSigninReauthPrompt; - #endif // CHROME_BROWSER_SIGNIN_SIGNIN_FEATURES_H_
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 0fafb9b3..fcde182 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -75,7 +75,7 @@ #include "chrome/test/base/test_launcher_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/certificate_transparency/pref_names.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/common/content_settings_agent.mojom.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -3508,7 +3508,7 @@ } EXPECT_EQ(expected_show_blocked, - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings::GetForFrame( tab->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::MIXEDSCRIPT)); ssl_test_util::CheckSecurityState( @@ -3532,7 +3532,7 @@ } EXPECT_EQ(expected_show_blocked_after_allow, - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings::GetForFrame( tab->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::MIXEDSCRIPT)); ssl_test_util::CheckSecurityState( @@ -3558,7 +3558,7 @@ void CheckErrorStateIsCleared() { WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_FALSE(content_settings::PageSpecificContentSettings::GetForFrame( tab->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::MIXEDSCRIPT)); ssl_test_util::CheckSecurityState(tab, CertError::NONE,
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc index 4f395895..1c797e29e 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h" #include "chrome/browser/subresource_filter/subresource_filter_profile_context.h" #include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/safe_browsing/core/db/database_manager.h" @@ -165,8 +165,8 @@ // (it comes from // ContentSubresourceFilterThrottleManager::DidDisallowFirstSubresource, which // comes from a specific frame). - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::ADS);
diff --git a/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc index d5dda04..03030433 100644 --- a/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_popup_browsertest.cc
@@ -21,7 +21,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/blocked_content/safe_browsing_triggered_popup_blocker.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/safe_browsing/core/db/util.h" @@ -135,7 +135,7 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &opened_window)); EXPECT_TRUE(opened_window); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_FALSE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); @@ -184,7 +184,7 @@ EXPECT_FALSE(opened_window); tester.ExpectTotalCount(kSubresourceFilterActionsHistogram, 0); // Make sure the popup UI was shown. - EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_TRUE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); @@ -203,7 +203,7 @@ &opened_window)); EXPECT_TRUE(opened_window); // Popup UI should not be shown. - EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_FALSE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -344,7 +344,7 @@ EXPECT_TRUE(content::ExecuteScript(web_contents, "openWindow()")); tester.ExpectTotalCount(kSubresourceFilterActionsHistogram, 0); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_TRUE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); const bool enable_adblock_on_abusive_sites = GetParam(); @@ -360,7 +360,7 @@ navigation_observer.Wait(); // Popup UI should not be shown. - EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_FALSE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); EXPECT_FALSE(AreDisallowedRequestsBlocked()); @@ -382,7 +382,7 @@ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, "openWindow()", &sent_open)); EXPECT_TRUE(sent_open); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_TRUE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); const bool enable_adblock_on_abusive_sites = GetParam(); @@ -405,7 +405,7 @@ content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_FALSE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); const bool enable_adblock_on_abusive_sites = GetParam();
diff --git a/chrome/browser/subresource_filter/subresource_filter_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc index 496fa4b..eda4f880 100644 --- a/chrome/browser/subresource_filter/subresource_filter_test_harness.cc +++ b/chrome/browser/subresource_filter/subresource_filter_test_harness.cc
@@ -10,7 +10,7 @@ #include "base/task/post_task.h" #include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/test_safe_browsing_service.h" @@ -22,7 +22,7 @@ #include "chrome/browser/subresource_filter/test_ruleset_publisher.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/safe_browsing/core/db/v4_protocol_manager_util.h" #include "components/subresource_filter/content/browser/ruleset_service.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h" @@ -99,9 +99,9 @@ // Set up the tab helpers. InfoBarService::CreateForWebContents(web_contents()); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); ChromeSubresourceFilterClient::CreateForWebContents(web_contents());
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 953788b..c460a5f 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1089,6 +1089,12 @@ <message name="IDS_LANGUAGES_ITEM_OPTION_OFFER_TO_TRANSLATE" desc="Option in language item menu. User can click the 'Offer to translate' option to toggle whether they want Chrome to translate pages in this language. [CHAR-LIMIT=32]"> Offer to translate </message> + <message name="IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT" desc="Option in language item menu. User can click the 'App Language' option to toggle whether or not the Chrome user interface should be displayed in this language. [CHAR-LIMIT=32]"> + Use as Chrome’s language + </message> + <message name="IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE" desc="Toast to display after selecting language to use for Chrome's user interface."> + <ph name="APP_NAME">%1$s<ex>Chrome</ex></ph> will use <ph name="language">%2$s<ex>Hindi</ex></ph> on restart. + </message> <message name="IDS_LANGUAGES_EXPLICIT_ASK_TITLE" desc="Title of the dialog that explicitly asks the user which languages they can read."> What languages do you read? </message> @@ -2416,6 +2422,9 @@ <message name="IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SUBTITLE" desc="The subtitle for the account picker bottom sheet that tells the user what happens if the button 'Continue as John Doe' is clicked"> You’ll be signed in with your Google Account\n(this won’t turn on Chrome Sync) </message> + <message name="IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SIGNIN_TITLE" desc="The title of the account picker bottom sheet tells that the user is in the process of signing in with their Google Account"> + Signing in... + </message> <!-- Personalized Signin Promos Strings --> <message name="IDS_SIGNIN_PROMO_CONTINUE_AS" desc="Button that the user can press to login without asking the password and continue using Chrome with this acccount."> @@ -3339,8 +3348,11 @@ <message name="IDS_TWA_CLEAR_DATA_SITE_SELECTION_TITLE" desc="Title of screen showing the sites linked to TWA, allowing the user to clean data in any of them."> Linked sites </message> - <message name="IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_ERROR" desc="Text shown on a toast when TWA violation."> - TWA error: <ph name="ERROR_CODE">%1$s<ex>404</ex></ph> on <ph name="VIOLATED_URL">%2$s<ex>https://google.com/</ex></ph> + <message name="IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_ERROR" desc="Text shown on a toast when TWA violation 404."> + <ph name="ERROR_CODE">%1$s<ex>404</ex></ph> on <ph name="VIOLATED_URL">%2$s<ex>https://example.com/</ex></ph> + </message> + <message name="IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_OFFLINE" desc="Text shown on a toast when TWA violate the quality enforcement criteria: page unavailable offline."> + Page unavailable offline: <ph name="VIOLATED_URL">%1$s<ex>https://example.com/</ex></ph> </message> <message name="IDS_WEBAPP_TAP_TO_COPY_URL" desc="Message on the notification that indicates that taping it will copy a Web App's URL into the clipboard.">
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT.png.sha1 new file mode 100644 index 0000000..c74c1dec --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT.png.sha1
@@ -0,0 +1 @@ +a06a8a932e9e708294c314558f6e1ec468967cb4 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE.png.sha1 new file mode 100644 index 0000000..ee6ed33 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE.png.sha1
@@ -0,0 +1 @@ +1b9eb3ffd36ca1e5fcd298fdd008adee701e88bb \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SIGNIN_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SIGNIN_TITLE.png.sha1 new file mode 100644 index 0000000..cf0d86c --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_ACCOUNT_PICKER_BOTTOM_SHEET_SIGNIN_TITLE.png.sha1
@@ -0,0 +1 @@ +06b7cfe92a89ece7130c3fa62661dafc75ab32ce \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_ERROR.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_ERROR.png.sha1 index 6e89e7a..c6186f3 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_ERROR.png.sha1 +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_ERROR.png.sha1
@@ -1 +1 @@ -42a7c0f54c737869a0c657bafeaada04a98d3f11 \ No newline at end of file +ca08321ce7674bbe3013f114a68574bc50dd9494 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_OFFLINE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_OFFLINE.png.sha1 new file mode 100644 index 0000000..0cb3f0e08 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TWA_QUALITY_ENFORCEMENT_VIOLATION_OFFLINE.png.sha1
@@ -0,0 +1 @@ +078ec0828bc1dab55a2c57950060e7838989398a \ No newline at end of file
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc index 624fa5f..5ab8350 100644 --- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc +++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -18,7 +18,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h" #include "chrome/common/pref_names.h" @@ -27,7 +27,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/blocked_content/list_item_position.h" #include "components/blocked_content/popup_tracker.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/ukm/content/source_url_recorder.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/web_contents.h" @@ -67,9 +67,9 @@ web_contents(), &raw_clock_, HostContentSettingsMapFactory::GetForProfile(profile())); InfoBarService::CreateForWebContents(web_contents()); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); #if !defined(OS_ANDROID) FramebustBlockTabHelper::CreateForWebContents(web_contents());
diff --git a/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc index 9312c47e2..5854becb 100644 --- a/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc
@@ -21,7 +21,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/blocked_content/popup_blocker_tab_helper.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/safe_browsing/core/db/v4_embedded_test_server_util.h" #include "components/safe_browsing/core/db/v4_test_util.h" #include "components/ukm/test_ukm_recorder.h" @@ -290,7 +290,7 @@ // Is blocked by the popup blocker. ui_test_utils::NavigateToURL(browser(), url); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_TRUE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS));
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc index 1d3e081f..0ead9a4 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_browsertest.cc
@@ -28,7 +28,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/blocked_content/popup_blocker_tab_helper.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/policy/core/browser/browser_policy_connector.h" @@ -52,7 +52,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; using safe_browsing::SubresourceFilterLevel; using safe_browsing::SubresourceFilterType; @@ -248,7 +248,7 @@ &opened_window)); EXPECT_TRUE(opened_window); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -268,7 +268,7 @@ &opened_window)); EXPECT_TRUE(opened_window); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); RoundTripAndVerifyLogMessages(console_observer, web_contents, {}, @@ -299,7 +299,7 @@ &opened_window)); EXPECT_TRUE(opened_window); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); // Since the policy change can take effect without browser restart, verify @@ -325,7 +325,7 @@ EXPECT_FALSE(opened_window); // Make sure the popup UI was shown. EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents1->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents1->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -348,7 +348,7 @@ &opened_window)); EXPECT_TRUE(opened_window); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -366,7 +366,7 @@ &opened_window)); EXPECT_TRUE(opened_window); EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -387,7 +387,7 @@ EXPECT_FALSE(opened_window); // Make sure the popup UI was shown. EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); // Block again. @@ -403,7 +403,7 @@ EXPECT_TRUE(opened_window); // Popup UI should not be shown. EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -426,7 +426,7 @@ // Make sure the popup UI was shown. EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); // Click through. @@ -511,7 +511,7 @@ EXPECT_TRUE(content::ExecuteScript(web_contents, "openWindow()")); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); // Navigate to |b_url|, which should successfully open the popup. @@ -525,7 +525,7 @@ // Popup UI should not be shown. EXPECT_FALSE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -544,7 +544,7 @@ &sent_open)); EXPECT_TRUE(sent_open); EXPECT_TRUE( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); } @@ -564,7 +564,7 @@ EXPECT_EQ(expect_block, !opened_window); EXPECT_EQ( expect_block, - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); };
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 66c4158..6689b358 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -41,8 +41,8 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/content_settings/sound_content_setting_observer.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #include "chrome/browser/custom_handlers/register_protocol_handler_permission_request.h" @@ -163,7 +163,7 @@ #include "components/bookmarks/browser/bookmark_utils.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/captive_portal/core/buildflags.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/favicon/content/content_favicon_driver.h" #include "components/find_in_page/find_tab_helper.h" @@ -1440,11 +1440,11 @@ // TODO(https://crbug.com/1103176): Plumb the actual frame reference here // (MixedContentNavigationThrottle::ShouldBlockNavigation has // |mixed_content_frame| reference) - content_settings::TabSpecificContentSettings* tab_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* page_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()); - DCHECK(tab_settings); - tab_settings->OnContentBlocked(ContentSettingsType::MIXEDSCRIPT); + DCHECK(page_settings); + page_settings->OnContentBlocked(ContentSettingsType::MIXEDSCRIPT); } return allowed; } @@ -1996,11 +1996,12 @@ // TODO(carlscab): This should probably be FromFrame() once it becomes // PageSpecificContentSettingsDelegate - auto* tab_content_settings_delegate = - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents); + auto* page_content_settings_delegate = + chrome::PageSpecificContentSettingsDelegate::FromWebContents( + web_contents); if (!user_gesture && window_) { - tab_content_settings_delegate->set_pending_protocol_handler(handler); - tab_content_settings_delegate->set_previous_protocol_handler( + page_content_settings_delegate->set_pending_protocol_handler(handler); + page_content_settings_delegate->set_previous_protocol_handler( registry->GetHandlerFor(handler.protocol())); window_->GetLocationBar()->UpdateContentSettingsIcons(); return; @@ -2009,7 +2010,7 @@ // Make sure content-setting icon is turned off in case the page does // ungestured and gestured RPH calls. if (window_) { - tab_content_settings_delegate->ClearPendingProtocolHandler(); + page_content_settings_delegate->ClearPendingProtocolHandler(); window_->GetLocationBar()->UpdateContentSettingsIcons(); } @@ -2133,8 +2134,8 @@ } // TODO(https://crbug.com/1103176): Plumb the actual frame reference here - content_settings::TabSpecificContentSettings* tab_content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* tab_content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()); HostContentSettingsMap* content_settings =
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index a779ecc..211a514 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1360,13 +1360,7 @@ } // Regression test for crbug.com/702505. -// Fails occasionally on Mac. http://crbug.com/852697 -#if defined(OS_MAC) -#define MAYBE_ReattachDevToolsWindow DISABLED_ReattachDevToolsWindow -#else -#define MAYBE_ReattachDevToolsWindow ReattachDevToolsWindow -#endif -IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_ReattachDevToolsWindow) { +IN_PROC_BROWSER_TEST_F(BrowserTest, ReattachDevToolsWindow) { ASSERT_TRUE(embedded_test_server()->Start()); WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); @@ -1394,7 +1388,7 @@ // Re-attach the dev tools window. This resets its Browser*. devtools_delegate->SetIsDocked(true); // Wait until the browser actually gets closed. - content::RunAllPendingInMessageLoop(); + ui_test_utils::WaitForBrowserToClose(); ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile())); // Do something that will make SearchTabHelper access its OmniboxView. This
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index 7180227..496a456 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -20,7 +20,7 @@ #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #include "chrome/browser/download/download_request_limiter.h" @@ -45,7 +45,7 @@ #include "chrome/grit/theme_resources.h" #include "components/blocked_content/popup_blocker_tab_helper.h" #include "components/content_settings/browser/content_settings_usages_state.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/common/content_settings_agent.mojom.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/browser/cookie_settings.h" @@ -83,11 +83,11 @@ using base::UserMetricsAction; using content::WebContents; +using content_settings::PageSpecificContentSettings; using content_settings::SETTING_SOURCE_NONE; using content_settings::SETTING_SOURCE_USER; using content_settings::SettingInfo; using content_settings::SettingSource; -using content_settings::TabSpecificContentSettings; namespace { @@ -209,8 +209,8 @@ void ContentSettingSimpleBubbleModel::SetTitle() { // TODO(https://crbug.com/1103176): Plumb the actual frame reference here - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = { {ContentSettingsType::COOKIES, IDS_BLOCKED_COOKIES_TITLE}, @@ -244,8 +244,8 @@ } void ContentSettingSimpleBubbleModel::SetMessage() { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // TODO(https://crbug.com/978882): Make the two arrays below static again once // we no longer need to check base::FeatureList. @@ -401,7 +401,8 @@ pending_handler_(ProtocolHandler::EmptyProtocolHandler()), previous_handler_(ProtocolHandler::EmptyProtocolHandler()) { auto* content_settings = - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents); + chrome::PageSpecificContentSettingsDelegate::FromWebContents( + web_contents); pending_handler_ = content_settings->pending_protocol_handler(); previous_handler_ = content_settings->previous_protocol_handler(); @@ -451,7 +452,7 @@ // The user has one chance to deal with the RPH content setting UI, // then we remove it. - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents()) + chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents()) ->ClearPendingProtocolHandler(); content_settings::UpdateLocationBarUiForWebContents(web_contents()); } @@ -462,20 +463,20 @@ registry_->RemoveIgnoredHandler(pending_handler_); registry_->OnAcceptRegisterProtocolHandler(pending_handler_); - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents()) + chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents()) ->set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW); } void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() { registry_->OnDenyRegisterProtocolHandler(pending_handler_); - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents()) + chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents()) ->set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK); ClearOrSetPreviousHandler(); } void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() { registry_->OnIgnoreRegisterProtocolHandler(pending_handler_); - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents()) + chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents()) ->set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT); ClearOrSetPreviousHandler(); } @@ -537,8 +538,8 @@ } void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState& usages_state = content_settings->midi_usages_state(); ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state; @@ -567,8 +568,8 @@ // Reset this embedder's entry to default for each of the requesting // origins currently on the page. const GURL& embedder_url = web_contents()->GetURL(); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState::StateMap& state_map = content_settings->midi_usages_state().state_map(); HostContentSettingsMap* map = @@ -630,8 +631,8 @@ } void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState& usages = content_settings->geolocation_usages_state(); ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state; @@ -660,8 +661,8 @@ // Reset this embedder's entry to default for each of the requesting // origins currently on the page. const GURL& embedder_url = web_contents()->GetURL(); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const ContentSettingsUsagesState::StateMap& state_map = content_settings->geolocation_usages_state().state_map(); HostContentSettingsMap* map = @@ -721,7 +722,7 @@ // Disable the "Run all plugins this time" link if the user already clicked // on the link and ran all plugins. set_custom_link_enabled( - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->load_plugins_link_enabled()); } @@ -754,7 +755,7 @@ web_contents(), true, std::string()); #endif set_custom_link_enabled(false); - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) ->set_load_plugins_link_enabled(false); } @@ -792,12 +793,12 @@ const GURL& url = web_contents()->GetURL(); base::string16 display_host = url_formatter::FormatUrlForSecurityDisplay(url); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); bool allowed = !content_settings->IsContentBlocked(content_type()); // For the frame busting case the content is blocked but its content type is - // popup, and the popup TabSpecificContentSettings is unaware of the frame + // popup, and the popup PageSpecificContentSettings is unaware of the frame // busting block. Since the popup bubble won't happen without blocking, it's // safe to manually set this. if (content_type() == ContentSettingsType::POPUPS) @@ -1039,7 +1040,7 @@ Delegate* delegate, WebContents* web_contents) : ContentSettingBubbleModel(delegate, web_contents), - state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) { + state_(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) { // TODO(msramek): The media bubble has three states - mic only, camera only, // and both. There is a lot of duplicated code which does the same thing // for camera and microphone separately. Consider refactoring it to avoid @@ -1050,8 +1051,8 @@ radio_item_setting_[0] = CONTENT_SETTING_ASK; radio_item_setting_[1] = CONTENT_SETTING_BLOCK; - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); state_ = content_settings->GetMicrophoneCameraState(); DCHECK(CameraAccessed() || MicrophoneAccessed()); @@ -1130,19 +1131,19 @@ } bool ContentSettingMediaStreamBubbleModel::MicrophoneAccessed() const { - return (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) != 0; + return (state_ & PageSpecificContentSettings::MICROPHONE_ACCESSED) != 0; } bool ContentSettingMediaStreamBubbleModel::CameraAccessed() const { - return (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) != 0; + return (state_ & PageSpecificContentSettings::CAMERA_ACCESSED) != 0; } bool ContentSettingMediaStreamBubbleModel::MicrophoneBlocked() const { - return (state_ & TabSpecificContentSettings::MICROPHONE_BLOCKED) != 0; + return (state_ & PageSpecificContentSettings::MICROPHONE_BLOCKED) != 0; } bool ContentSettingMediaStreamBubbleModel::CameraBlocked() const { - return (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) != 0; + return (state_ & PageSpecificContentSettings::CAMERA_BLOCKED) != 0; } void ContentSettingMediaStreamBubbleModel::SetTitle() { @@ -1186,8 +1187,8 @@ } void ContentSettingMediaStreamBubbleModel::SetRadioGroup() { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); GURL url = content_settings->media_stream_access_origin(); RadioGroup radio_group; radio_group.url = url; @@ -1197,8 +1198,8 @@ DCHECK(CameraAccessed() || MicrophoneAccessed()); int radio_allow_label_id = 0; int radio_block_label_id = 0; - if (state_ & (TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_BLOCKED)) { + if (state_ & (PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_BLOCKED)) { if (content::IsOriginSecure(url)) { radio_item_setting_[0] = CONTENT_SETTING_ALLOW; radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW; @@ -1265,8 +1266,8 @@ void ContentSettingMediaStreamBubbleModel::UpdateSettings( ContentSetting setting) { - TabSpecificContentSettings* tab_content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* page_content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // The same urls must be used as in other places (e.g. the infobar) in // order to override the existing rule. Otherwise a new rule is created. // TODO(markusheintz): Extract to a helper so that there is only a single @@ -1276,21 +1277,21 @@ if (MicrophoneAccessed()) { permissions::PermissionUmaUtil::ScopedRevocationReporter scoped_revocation_reporter( - GetProfile(), tab_content_settings->media_stream_access_origin(), + GetProfile(), page_content_settings->media_stream_access_origin(), GURL(), ContentSettingsType::MEDIASTREAM_MIC, permissions::PermissionSourceUI::PAGE_ACTION); map->SetContentSettingDefaultScope( - tab_content_settings->media_stream_access_origin(), GURL(), + page_content_settings->media_stream_access_origin(), GURL(), ContentSettingsType::MEDIASTREAM_MIC, std::string(), setting); } if (CameraAccessed()) { permissions::PermissionUmaUtil::ScopedRevocationReporter scoped_revocation_reporter( - GetProfile(), tab_content_settings->media_stream_access_origin(), + GetProfile(), page_content_settings->media_stream_access_origin(), GURL(), ContentSettingsType::MEDIASTREAM_CAMERA, permissions::PermissionSourceUI::PAGE_ACTION); map->SetContentSettingDefaultScope( - tab_content_settings->media_stream_access_origin(), GURL(), + page_content_settings->media_stream_access_origin(), GURL(), ContentSettingsType::MEDIASTREAM_CAMERA, std::string(), setting); } } @@ -1367,8 +1368,8 @@ } void ContentSettingMediaStreamBubbleModel::SetMediaMenus() { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const std::string& requested_microphone = content_settings->media_stream_requested_audio_device(); const std::string& requested_camera = @@ -1437,8 +1438,8 @@ } void ContentSettingMediaStreamBubbleModel::SetCustomLink() { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); if (content_settings->IsMicrophoneCameraStateChanged()) { set_custom_link( l10n_util::GetStringUTF16(IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE));
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.h b/chrome/browser/ui/content_settings/content_setting_bubble_model.h index b590e11..afb07a2 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.h +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.h
@@ -21,7 +21,7 @@ #include "chrome/browser/ui/blocked_content/framebust_block_tab_helper.h" #include "chrome/common/custom_handlers/protocol_handler.h" #include "components/blocked_content/url_list_manager.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "third_party/blink/public/common/mediastream/media_stream_request.h" @@ -406,7 +406,7 @@ // buttons. ContentSetting radio_item_setting_[2]; // The state of the microphone and camera access. - content_settings::TabSpecificContentSettings::MicrophoneCameraState state_; + content_settings::PageSpecificContentSettings::MicrophoneCameraState state_; DISALLOW_COPY_AND_ASSIGN(ContentSettingMediaStreamBubbleModel); };
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc index 324a40b..d128e537 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_browsertest.cc
@@ -22,7 +22,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/network_session_configurator/common/network_switches.h" #include "components/url_formatter/elide_url.h" @@ -37,7 +37,7 @@ #include "third_party/blink/public/common/features.h" #include "ui/events/event_constants.h" -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; class ContentSettingBubbleModelMixedScriptTest : public InProcessBrowserTest { public: @@ -56,8 +56,8 @@ ASSERT_TRUE(https_server_->Start()); } - TabSpecificContentSettings* GetActiveTabSpecificContentSettings() { - return TabSpecificContentSettings::GetForFrame( + PageSpecificContentSettings* GetActivePageSpecificContentSettings() { + return PageSpecificContentSettings::GetForFrame( browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); } @@ -75,7 +75,7 @@ // the title string. ui_test_utils::NavigateToURL(browser(), url); - EXPECT_TRUE(GetActiveTabSpecificContentSettings()->IsContentBlocked( + EXPECT_TRUE(GetActivePageSpecificContentSettings()->IsContentBlocked( ContentSettingsType::MIXEDSCRIPT)); // Emulate link clicking on the mixed script bubble. @@ -91,7 +91,7 @@ browser()->tab_strip_model()->GetActiveWebContents()); observer.Wait(); - EXPECT_FALSE(GetActiveTabSpecificContentSettings()->IsContentBlocked( + EXPECT_FALSE(GetActivePageSpecificContentSettings()->IsContentBlocked( ContentSettingsType::MIXEDSCRIPT)); } @@ -117,7 +117,7 @@ // the title string. ui_test_utils::NavigateToURL(browser(), url); - EXPECT_TRUE(GetActiveTabSpecificContentSettings()->IsContentBlocked( + EXPECT_TRUE(GetActivePageSpecificContentSettings()->IsContentBlocked( ContentSettingsType::MIXEDSCRIPT)); // Emulate link clicking on the mixed script bubble. @@ -133,7 +133,7 @@ browser()->tab_strip_model()->GetActiveWebContents()); observer.Wait(); - EXPECT_FALSE(GetActiveTabSpecificContentSettings()->IsContentBlocked( + EXPECT_FALSE(GetActivePageSpecificContentSettings()->IsContentBlocked( ContentSettingsType::MIXEDSCRIPT)); } @@ -149,14 +149,14 @@ // Blink does not ask the browser to handle mixed content in the case // of active subresources in an iframe, so the content type should not // be marked as blocked. - EXPECT_FALSE(GetActiveTabSpecificContentSettings()->IsContentBlocked( + EXPECT_FALSE(GetActivePageSpecificContentSettings()->IsContentBlocked( ContentSettingsType::MIXEDSCRIPT)); } class ContentSettingBubbleModelMediaStreamTest : public InProcessBrowserTest { public: void ManageMediaStreamSettings( - TabSpecificContentSettings::MicrophoneCameraState state) { + PageSpecificContentSettings::MicrophoneCameraState state) { content::WebContents* original_tab = OpenTab(); std::unique_ptr<ContentSettingBubbleModel> bubble = ShowBubble(state); @@ -169,11 +169,11 @@ } std::unique_ptr<ContentSettingBubbleModel> ShowBubble( - TabSpecificContentSettings::MicrophoneCameraState state) { + PageSpecificContentSettings::MicrophoneCameraState state) { content::WebContents* web_contents = GetActiveTab(); // Create a bubble with the given camera and microphone access state. - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()) ->OnMediaStreamPermissionSet(web_contents->GetLastCommittedURL(), state, std::string(), std::string(), std::string(), std::string()); @@ -217,19 +217,19 @@ // active tab loads the correct internal url. // The microphone bubble links to microphone exceptions. - ManageMediaStreamSettings(TabSpecificContentSettings::MICROPHONE_ACCESSED); + ManageMediaStreamSettings(PageSpecificContentSettings::MICROPHONE_ACCESSED); EXPECT_EQ(GURL("chrome://settings/contentExceptions#media-stream-mic"), GetActiveTab()->GetLastCommittedURL()); // The bubble for both media devices links to the the first section of the // default media content settings, which is the microphone section. - ManageMediaStreamSettings(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::CAMERA_ACCESSED); + ManageMediaStreamSettings(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::CAMERA_ACCESSED); EXPECT_EQ(GURL("chrome://settings/content#media-stream-mic"), GetActiveTab()->GetLastCommittedURL()); // The camera bubble links to camera exceptions. - ManageMediaStreamSettings(TabSpecificContentSettings::CAMERA_ACCESSED); + ManageMediaStreamSettings(PageSpecificContentSettings::CAMERA_ACCESSED); EXPECT_EQ(GURL("chrome://settings/contentExceptions#media-stream-camera"), GetActiveTab()->GetLastCommittedURL()); } @@ -249,8 +249,8 @@ // The mic & camera bubble content does not include camera PTZ. std::unique_ptr<ContentSettingBubbleModel> mic_and_camera_bubble = - ShowBubble(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::CAMERA_ACCESSED); + ShowBubble(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::CAMERA_ACCESSED); EXPECT_EQ(mic_and_camera_bubble->bubble_content().radio_group.radio_items[0], l10n_util::GetStringFUTF16( IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION, @@ -258,7 +258,7 @@ // The camera bubble content does not include camera PTZ. std::unique_ptr<ContentSettingBubbleModel> camera_bubble = - ShowBubble(TabSpecificContentSettings::CAMERA_ACCESSED); + ShowBubble(PageSpecificContentSettings::CAMERA_ACCESSED); EXPECT_EQ(camera_bubble->bubble_content().radio_group.radio_items[0], l10n_util::GetStringFUTF16( IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION, @@ -272,8 +272,8 @@ // The mic & camera bubble content includes camera PTZ. std::unique_ptr<ContentSettingBubbleModel> mic_and_camera_ptz_bubble = - ShowBubble(TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::CAMERA_ACCESSED); + ShowBubble(PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::CAMERA_ACCESSED); EXPECT_EQ( mic_and_camera_ptz_bubble->bubble_content().radio_group.radio_items[0], l10n_util::GetStringFUTF16( @@ -282,7 +282,7 @@ // The camera bubble content includes camera PTZ. std::unique_ptr<ContentSettingBubbleModel> camera_ptz_bubble = - ShowBubble(TabSpecificContentSettings::CAMERA_ACCESSED); + ShowBubble(PageSpecificContentSettings::CAMERA_ACCESSED); EXPECT_EQ(camera_ptz_bubble->bubble_content().radio_group.radio_items[0], l10n_util::GetStringFUTF16( IDS_ALLOWED_CAMERA_PAN_TILT_ZOOM_NO_ACTION, @@ -382,7 +382,7 @@ // Load a page with mixed content and verify that mixed content didn't get // executed. ui_test_utils::NavigateToURL(browser(), main_url); - EXPECT_TRUE(GetActiveTabSpecificContentSettings()->IsContentBlocked( + EXPECT_TRUE(GetActivePageSpecificContentSettings()->IsContentBlocked( ContentSettingsType::MIXEDSCRIPT)); std::string title; @@ -403,7 +403,7 @@ // Wait for reload and verify that mixed content is allowed. observer.Wait(); - EXPECT_FALSE(GetActiveTabSpecificContentSettings()->IsContentBlocked( + EXPECT_FALSE(GetActivePageSpecificContentSettings()->IsContentBlocked( ContentSettingsType::MIXEDSCRIPT)); // Ensure that the script actually executed by checking the title of the
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc index 27bbd02..2182ebe 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
@@ -11,7 +11,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/custom_handlers/test_protocol_handler_registry_delegate.h" #include "chrome/browser/infobars/infobar_service.h" @@ -31,7 +31,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/blocked_content/popup_blocker.h" #include "components/blocked_content/popup_blocker_tab_helper.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/infobars/core/infobar_delegate.h" @@ -47,16 +47,16 @@ #include "ui/base/l10n/l10n_util.h" using content::WebContentsTester; -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; class ContentSettingBubbleModelTest : public ChromeRenderViewHostTestHarness { protected: void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); InfoBarService::CreateForWebContents(web_contents()); } @@ -93,8 +93,8 @@ TEST_F(ContentSettingBubbleModelTest, ImageRadios) { WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::IMAGES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -112,8 +112,8 @@ TEST_F(ContentSettingBubbleModelTest, Cookies) { WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::COOKIES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -131,7 +131,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentAllowed(ContentSettingsType::COOKIES); content_setting_bubble_model = ContentSettingBubbleModel::CreateContentSettingBubbleModel( @@ -159,13 +159,13 @@ MediaCaptureDevicesDispatcher::GetInstance()-> DisableDeviceEnumerationForTesting(); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::CAMERA_ACCESSED; + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state = + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::CAMERA_ACCESSED; content_settings->OnMediaStreamPermissionSet(security_origin, microphone_camera_state, GetDefaultAudioDevice(), @@ -215,13 +215,13 @@ url, GURL(), ContentSettingsType::MEDIASTREAM_CAMERA, std::string(), setting); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED; + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state = + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED; content_settings->OnMediaStreamPermissionSet(url, microphone_camera_state, GetDefaultAudioDevice(), @@ -282,11 +282,11 @@ url, GURL(), ContentSettingsType::MEDIASTREAM_MIC, std::string(), setting); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED; + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state = + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED; content_settings->OnMediaStreamPermissionSet(url, microphone_camera_state, GetDefaultAudioDevice(), @@ -374,11 +374,11 @@ MediaCaptureDevicesDispatcher::GetInstance()->SetTestAudioCaptureDevices( audio_devices); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED; + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state = + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED; content_settings->OnMediaStreamPermissionSet(url, microphone_camera_state, GetDefaultAudioDevice(), @@ -437,7 +437,7 @@ indicator->RegisterMediaStream(web_contents(), audio_devices); media_stream_ui->OnStarted(base::OnceClosure(), content::MediaStreamUI::SourceCallback()); - microphone_camera_state &= ~TabSpecificContentSettings::MICROPHONE_BLOCKED; + microphone_camera_state &= ~PageSpecificContentSettings::MICROPHONE_BLOCKED; content_settings->OnMediaStreamPermissionSet(url, microphone_camera_state, GetDefaultAudioDevice(), @@ -485,7 +485,7 @@ } // Simulate that yet another audio stream capture request was initiated. - microphone_camera_state |= TabSpecificContentSettings::MICROPHONE_BLOCKED; + microphone_camera_state |= PageSpecificContentSettings::MICROPHONE_BLOCKED; content_settings->OnMediaStreamPermissionSet(url, microphone_camera_state, GetDefaultAudioDevice(), @@ -520,12 +520,12 @@ MediaCaptureDevicesDispatcher::GetInstance()-> DisableDeviceEnumerationForTesting(); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = - TabSpecificContentSettings::MICROPHONE_ACCESSED; + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state = + PageSpecificContentSettings::MICROPHONE_ACCESSED; content_settings->OnMediaStreamPermissionSet(security_origin, microphone_camera_state, GetDefaultAudioDevice(), @@ -557,7 +557,7 @@ bubble_content.media_menus.begin()->first); // Change the microphone access. - microphone_camera_state |= TabSpecificContentSettings::MICROPHONE_BLOCKED; + microphone_camera_state |= PageSpecificContentSettings::MICROPHONE_BLOCKED; content_settings->OnMediaStreamPermissionSet(security_origin, microphone_camera_state, GetDefaultAudioDevice(), @@ -593,12 +593,12 @@ MediaCaptureDevicesDispatcher::GetInstance()-> DisableDeviceEnumerationForTesting(); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = - TabSpecificContentSettings::CAMERA_ACCESSED; + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state = + PageSpecificContentSettings::CAMERA_ACCESSED; content_settings->OnMediaStreamPermissionSet(security_origin, microphone_camera_state, std::string(), @@ -630,7 +630,7 @@ bubble_content.media_menus.begin()->first); // Change the camera access. - microphone_camera_state |= TabSpecificContentSettings::CAMERA_BLOCKED; + microphone_camera_state |= PageSpecificContentSettings::CAMERA_BLOCKED; content_settings->OnMediaStreamPermissionSet(security_origin, microphone_camera_state, std::string(), @@ -667,14 +667,14 @@ MediaCaptureDevicesDispatcher::GetInstance()-> DisableDeviceEnumerationForTesting(); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); std::string request_host = "google.com"; GURL security_origin("http://" + request_host); // Firstly, add microphone access. - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = - TabSpecificContentSettings::MICROPHONE_ACCESSED; + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state = + PageSpecificContentSettings::MICROPHONE_ACCESSED; content_settings->OnMediaStreamPermissionSet(security_origin, microphone_camera_state, GetDefaultAudioDevice(), @@ -703,7 +703,7 @@ bubble_content.media_menus.begin()->first); // Then add camera access. - microphone_camera_state |= TabSpecificContentSettings::CAMERA_ACCESSED; + microphone_camera_state |= PageSpecificContentSettings::CAMERA_ACCESSED; content_settings->OnMediaStreamPermissionSet(security_origin, microphone_camera_state, GetDefaultAudioDevice(), @@ -734,8 +734,8 @@ TEST_F(ContentSettingBubbleModelTest, Plugins) { WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const base::string16 plugin_name = base::ASCIIToUTF16("plugin_name"); content_settings->OnContentBlocked(ContentSettingsType::PLUGINS); @@ -757,8 +757,8 @@ TEST_F(ContentSettingBubbleModelTest, PepperBroker) { WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::PPAPI_BROKER); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -778,7 +778,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentAllowed(ContentSettingsType::PPAPI_BROKER); content_setting_bubble_model = ContentSettingBubbleModel::CreateContentSettingBubbleModel( @@ -801,8 +801,8 @@ const GURL frame2_url("http://host2.example:999/"); NavigateAndCommit(page_url); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // One permitted frame, but not in the content map: requires reload. content_settings->OnGeolocationPermissionSet(frame1_url, true); @@ -847,8 +847,8 @@ } NavigateAndCommit(origin_to_embargo); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnGeolocationPermissionSet(origin_to_embargo, false); // |origin_to_embargo| is not blocked or embargoed. Verify no clear link @@ -896,7 +896,7 @@ TEST_F(ContentSettingBubbleModelTest, FileURL) { std::string file_url("file:///tmp/test.html"); NavigateAndCommit(GURL(file_url)); - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) ->OnContentBlocked(ContentSettingsType::IMAGES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( ContentSettingBubbleModel::CreateContentSettingBubbleModel( @@ -909,7 +909,7 @@ TEST_F(ContentSettingBubbleModelTest, RegisterProtocolHandler) { const GURL page_url("http://toplevel.example/"); NavigateAndCommit(page_url); - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents()) + chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents()) ->set_pending_protocol_handler(ProtocolHandler::CreateProtocolHandler( "mailto", GURL("http://www.toplevel.example/"))); @@ -935,7 +935,7 @@ const GURL page_url("http://toplevel.example/"); NavigateAndCommit(page_url); auto* content_settings = - chrome::TabSpecificContentSettingsDelegate::FromWebContents( + chrome::PageSpecificContentSettingsDelegate::FromWebContents( web_contents()); ProtocolHandler test_handler = ProtocolHandler::CreateProtocolHandler( "mailto", GURL("http://www.toplevel.example/")); @@ -1002,7 +1002,7 @@ const GURL page_url("http://toplevel.example/"); NavigateAndCommit(page_url); auto* content_settings = - chrome::TabSpecificContentSettingsDelegate::FromWebContents( + chrome::PageSpecificContentSettingsDelegate::FromWebContents( web_contents()); ProtocolHandler test_handler = ProtocolHandler::CreateProtocolHandler( "mailto", GURL("http://www.toplevel.example/")); @@ -1056,8 +1056,8 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); HostContentSettingsMap* settings_map = HostContentSettingsMapFactory::GetForProfile(profile()); @@ -1135,7 +1135,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Go from block by default to allow by default to block by default. { @@ -1211,7 +1211,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Block by default but allow a specific site. { @@ -1244,7 +1244,7 @@ WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Clear site-specific exceptions. settings_map->ClearSettingsForOneType(ContentSettingsType::SENSORS); @@ -1280,8 +1280,8 @@ TEST_F(ContentSettingBubbleModelTest, PopupBubbleModelListItems) { const GURL url("https://www.example.test/"); WebContentsTester::For(web_contents())->NavigateAndCommit(url); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::POPUPS); blocked_content::PopupBlockerTabHelper::CreateForWebContents(web_contents()); @@ -1314,8 +1314,8 @@ WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("https://www.example.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::COOKIES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model( @@ -1331,8 +1331,8 @@ WebContentsTester::For(web_contents())-> NavigateAndCommit(GURL("about:blank")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); content_settings->OnContentBlocked(ContentSettingsType::COOKIES); std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model(
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc index 84a6366..6d75d3d 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -16,7 +16,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/permissions/quiet_notification_permission_ui_config.h" #include "chrome/browser/permissions/quiet_notification_permission_ui_state.h" @@ -28,7 +28,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/content_settings/browser/content_settings_usages_state.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -52,7 +52,7 @@ #endif using content::WebContents; -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; // The image models hierarchy: // @@ -156,7 +156,7 @@ WebContents* web_contents) override; private: - TabSpecificContentSettings::MicrophoneCameraState state_; + PageSpecificContentSettings::MicrophoneCameraState state_; DISALLOW_COPY_AND_ASSIGN(ContentSettingMediaImageModel); }; @@ -419,8 +419,8 @@ // If a content type is blocked by default and was accessed, display the // content blocked page action. - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; @@ -483,8 +483,8 @@ bool ContentSettingGeolocationImageModel::UpdateAndGetVisibility( WebContents* web_contents) { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; const ContentSettingsUsagesState& usages_state = @@ -518,7 +518,8 @@ bool ContentSettingRPHImageModel::UpdateAndGetVisibility( WebContents* web_contents) { auto* content_settings_delegate = - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents); + chrome::PageSpecificContentSettingsDelegate::FromWebContents( + web_contents); if (!content_settings_delegate) return false; if (content_settings_delegate->pending_protocol_handler().IsEmpty()) @@ -535,8 +536,8 @@ bool ContentSettingMIDISysExImageModel::UpdateAndGetVisibility( WebContents* web_contents) { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; const ContentSettingsUsagesState& usages_state = @@ -602,8 +603,8 @@ bool ContentSettingClipboardReadWriteImageModel::UpdateAndGetVisibility( WebContents* web_contents) { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; ContentSettingsType content_type = ContentSettingsType::CLIPBOARD_READ_WRITE; @@ -627,15 +628,15 @@ bool ContentSettingMediaImageModel::UpdateAndGetVisibility( WebContents* web_contents) { set_should_auto_open_bubble(false); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; state_ = content_settings->GetMicrophoneCameraState(); // If neither the microphone nor the camera stream was accessed then no icon // is displayed in the omnibox. - if (state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) + if (state_ == PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) return false; #if defined(OS_MAC) @@ -735,19 +736,19 @@ } bool ContentSettingMediaImageModel::IsMicAccessed() { - return ((state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) != 0); + return ((state_ & PageSpecificContentSettings::MICROPHONE_ACCESSED) != 0); } bool ContentSettingMediaImageModel::IsCamAccessed() { - return ((state_ & TabSpecificContentSettings::CAMERA_ACCESSED) != 0); + return ((state_ & PageSpecificContentSettings::CAMERA_ACCESSED) != 0); } bool ContentSettingMediaImageModel::IsMicBlockedOnSiteLevel() { - return ((state_ & TabSpecificContentSettings::MICROPHONE_BLOCKED) != 0); + return ((state_ & PageSpecificContentSettings::MICROPHONE_BLOCKED) != 0); } bool ContentSettingMediaImageModel::IsCameraBlockedOnSiteLevel() { - return ((state_ & TabSpecificContentSettings::CAMERA_BLOCKED) != 0); + return ((state_ & PageSpecificContentSettings::CAMERA_BLOCKED) != 0); } #if defined(OS_MAC) @@ -820,7 +821,7 @@ bool ContentSettingSensorsImageModel::UpdateAndGetVisibility( WebContents* web_contents) { auto* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings) return false; @@ -860,8 +861,8 @@ bool ContentSettingPopupImageModel::UpdateAndGetVisibility( WebContents* web_contents) { - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame()); if (!content_settings || !content_settings->IsContentBlocked(content_type())) return false; set_icon(kWebIcon, vector_icons::kBlockedBadgeIcon);
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc b/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc index 914d8add..df2b343 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model_browsertest.cc
@@ -27,8 +27,8 @@ IN_PROC_BROWSER_TEST_F(ContentSettingImageModelBrowserTest, CreateBubbleModel) { WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()); content_settings->BlockAllContentForTesting();
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc index d871b538..58f7534 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model_unittest.cc
@@ -14,7 +14,7 @@ #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/permissions/quiet_notification_permission_ui_state.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -24,7 +24,7 @@ #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/pref_names.h" #include "components/permissions/features.h" @@ -47,7 +47,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/color_palette.h" -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; namespace { @@ -114,12 +114,12 @@ } TEST_F(ContentSettingImageModelTest, Update) { - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( ContentSettingImageModel::ImageType::IMAGES); @@ -135,9 +135,9 @@ } TEST_F(ContentSettingImageModelTest, RPHUpdate) { - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( @@ -145,7 +145,7 @@ content_setting_image_model->Update(web_contents()); EXPECT_FALSE(content_setting_image_model->is_visible()); - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents()) + chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents()) ->set_pending_protocol_handler(ProtocolHandler::CreateProtocolHandler( "mailto", GURL("http://www.google.com/"))); content_setting_image_model->Update(web_contents()); @@ -153,9 +153,9 @@ } TEST_F(ContentSettingImageModelTest, CookieAccessed) { - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); HostContentSettingsMapFactory::GetForProfile(profile()) ->SetDefaultContentSetting(ContentSettingsType::COOKIES, @@ -170,7 +170,7 @@ std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create( origin, "A=B", base::Time::Now(), base::nullopt /* server_time */)); ASSERT_TRUE(cookie); - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()) ->OnCookiesAccessed({content::CookieAccessDetails::Type::kChange, origin, origin, @@ -188,12 +188,12 @@ base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(features::kGenericSensorExtraClasses); - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( @@ -213,7 +213,7 @@ NavigateAndCommit(controller_, GURL("http://www.google.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Allowing by default but blocking (e.g. due to a feature policy) causes the // indicator to be shown. @@ -230,7 +230,7 @@ NavigateAndCommit(controller_, GURL("http://www.google.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Blocking by default but allowing (e.g. via a site-specific exception) // causes the indicator to be shown. @@ -247,7 +247,7 @@ NavigateAndCommit(controller_, GURL("http://www.google.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Blocking access by default also causes the indicator to be shown so users // can set an exception. @@ -271,13 +271,13 @@ base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(features::kGenericSensorExtraClasses); - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); NavigateAndCommit(controller_, GURL("https://www.example.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); HostContentSettingsMap* settings_map = HostContentSettingsMapFactory::GetForProfile(profile()); @@ -317,7 +317,7 @@ NavigateAndCommit(controller_, GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Go from block by default to allow by default to block by default. { @@ -352,7 +352,7 @@ NavigateAndCommit(controller_, GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Block by default but allow a specific site. { @@ -373,7 +373,7 @@ NavigateAndCommit(controller_, GURL("https://www.example.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Clear site-specific exceptions. settings_map->ClearSettingsForOneType(ContentSettingsType::SENSORS); @@ -396,9 +396,9 @@ } // Regression test for http://crbug.com/161854. -TEST_F(ContentSettingImageModelTest, NULLTabSpecificContentSettings) { - TabSpecificContentSettings::DeleteForWebContentsForTest(web_contents()); - EXPECT_EQ(nullptr, TabSpecificContentSettings::GetForFrame( +TEST_F(ContentSettingImageModelTest, NULLPageSpecificContentSettings) { + PageSpecificContentSettings::DeleteForWebContentsForTest(web_contents()); + EXPECT_EQ(nullptr, PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame())); // Should not crash. ContentSettingImageModel::CreateForContentType( @@ -407,12 +407,12 @@ } TEST_F(ContentSettingImageModelTest, SubresourceFilter) { - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( ContentSettingImageModel::ImageType::ADS); @@ -428,12 +428,12 @@ } TEST_F(ContentSettingImageModelTest, NotificationsIconVisibility) { - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( ContentSettingImageModel::ImageType::NOTIFICATIONS_QUIET_PROMPT);
diff --git a/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm b/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm index 3198501..b541ff8 100644 --- a/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm +++ b/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm
@@ -9,7 +9,7 @@ #include "base/mac/mac_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h" #include "chrome/browser/profiles/profile.h" @@ -19,7 +19,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/prefs/pref_service.h" #include "components/prerender/browser/prerender_manager.h" #include "components/vector_icons/vector_icons.h" @@ -34,7 +34,7 @@ struct VectorIcon; } -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; namespace { @@ -61,9 +61,9 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); InfoBarService::CreateForWebContents(web_contents()); } @@ -86,12 +86,12 @@ base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(features::kMacSystemMediaPermissionsInfoUi); - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); auto* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); const GURL kTestOrigin("https://www.example.com"); auto content_setting_image_model = ContentSettingImageModel::CreateForContentType( @@ -103,8 +103,8 @@ // Camera allowed per site: Test for system level permissions. { content_settings->OnMediaStreamPermissionSet( - kTestOrigin, TabSpecificContentSettings::CAMERA_ACCESSED, std::string(), - GetDefaultVideoDevice(), std::string(), std::string()); + kTestOrigin, PageSpecificContentSettings::CAMERA_ACCESSED, + std::string(), GetDefaultVideoDevice(), std::string(), std::string()); auth_wrapper.SetMockMediaPermissionStatus(kAllowed); content_setting_image_model->Update(web_contents()); ExpectImageModelState( @@ -124,7 +124,7 @@ // Microphone allowed per site: Test for system level permissions. { content_settings->OnMediaStreamPermissionSet( - kTestOrigin, TabSpecificContentSettings::MICROPHONE_ACCESSED, + kTestOrigin, PageSpecificContentSettings::MICROPHONE_ACCESSED, std::string(), GetDefaultVideoDevice(), std::string(), std::string()); auth_wrapper.SetMockMediaPermissionStatus(kAllowed); content_setting_image_model->Update(web_contents()); @@ -146,8 +146,8 @@ { content_settings->OnMediaStreamPermissionSet( kTestOrigin, - (TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::CAMERA_ACCESSED), + (PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::CAMERA_ACCESSED), std::string(), GetDefaultVideoDevice(), std::string(), std::string()); auth_wrapper.SetMockMediaPermissionStatus(kAllowed); auth_wrapper.SetMockMediaPermissionStatus(kAllowed); @@ -180,8 +180,8 @@ { content_settings->OnMediaStreamPermissionSet( kTestOrigin, - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED, + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED, GetDefaultAudioDevice(), GetDefaultVideoDevice(), std::string(), std::string()); content_setting_image_model->Update(web_contents()); @@ -195,8 +195,8 @@ { content_settings->OnMediaStreamPermissionSet( kTestOrigin, - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED, + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED, GetDefaultAudioDevice(), GetDefaultVideoDevice(), std::string(), std::string()); content_setting_image_model->Update(web_contents()); @@ -210,10 +210,10 @@ { content_settings->OnMediaStreamPermissionSet( kTestOrigin, - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED | - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED, + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED | + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED, GetDefaultAudioDevice(), GetDefaultVideoDevice(), std::string(), std::string()); content_setting_image_model->Update(web_contents());
diff --git a/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc b/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc index 554338f..507b4da 100644 --- a/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc +++ b/chrome/browser/ui/cookie_controls/cookie_controls_controller_unittest.cc
@@ -5,11 +5,11 @@ #include "components/content_settings/browser/ui/cookie_controls_controller.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/ui/cookie_controls/cookie_controls_service.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/browser/ui/cookie_controls_view.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/common/cookie_controls_enforcement.h" @@ -63,9 +63,9 @@ protected: void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); profile()->GetPrefs()->SetInteger( prefs::kCookieControlsMode, @@ -92,9 +92,9 @@ MockCookieControlsView* mock() { return &mock_; } - content_settings::TabSpecificContentSettings* - tab_specific_content_settings() { - return content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* + page_specific_content_settings() { + return content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); } @@ -121,7 +121,7 @@ // Accessing cookies should be notified. EXPECT_CALL(*mock(), OnCookiesCountChanged(1, 0)); - tab_specific_content_settings()->OnWebDatabaseAccessed( + page_specific_content_settings()->OnWebDatabaseAccessed( GURL("https://example.com"), /*blocked=*/false); testing::Mock::VerifyAndClearExpectations(mock()); @@ -134,7 +134,7 @@ // Blocking cookies should update the blocked cookie count. EXPECT_CALL(*mock(), OnCookiesCountChanged(1, 1)); - tab_specific_content_settings()->OnWebDatabaseAccessed( + page_specific_content_settings()->OnWebDatabaseAccessed( GURL("https://thirdparty.com"), /*blocked=*/true); testing::Mock::VerifyAndClearExpectations(mock()); @@ -223,9 +223,9 @@ std::unique_ptr<content::WebContents> incognito_web_contents = content::WebContentsTester::CreateTestWebContents( profile()->GetPrimaryOTRProfile(), nullptr); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( incognito_web_contents.get(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( incognito_web_contents.get())); auto* tester = content::WebContentsTester::For(incognito_web_contents.get()); MockCookieControlsView incognito_mock_;
diff --git a/chrome/browser/ui/page_info/chrome_page_info_delegate.cc b/chrome/browser/ui/page_info/chrome_page_info_delegate.cc index 82cd90d..222e964 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_delegate.cc +++ b/chrome/browser/ui/page_info/chrome_page_info_delegate.cc
@@ -8,7 +8,7 @@ #include "chrome/browser/bluetooth/bluetooth_chooser_context.h" #include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" #include "chrome/browser/permissions/permission_manager_factory.h" @@ -20,7 +20,7 @@ #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/browser/vr/vr_tab_helper.h" #include "chrome/common/url_constants.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_manager.h" #include "components/permissions/permission_result.h" @@ -198,9 +198,9 @@ return *helper->GetVisibleSecurityState(); } -std::unique_ptr<content_settings::TabSpecificContentSettings::Delegate> -ChromePageInfoDelegate::GetTabSpecificContentSettingsDelegate() { - auto delegate = std::make_unique<chrome::TabSpecificContentSettingsDelegate>( +std::unique_ptr<content_settings::PageSpecificContentSettings::Delegate> +ChromePageInfoDelegate::GetPageSpecificContentSettingsDelegate() { + auto delegate = std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents_); return std::move(delegate); }
diff --git a/chrome/browser/ui/page_info/chrome_page_info_delegate.h b/chrome/browser/ui/page_info/chrome_page_info_delegate.h index 970978b..81bbdd9 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_delegate.h +++ b/chrome/browser/ui/page_info/chrome_page_info_delegate.h
@@ -15,7 +15,7 @@ class StatefulSSLHostStateDelegate; namespace content_settings { -class TabSpecificContentSettings; +class PageSpecificContentSettings; } namespace permissions { @@ -63,8 +63,8 @@ bool IsContentDisplayedInVrHeadset() override; security_state::SecurityLevel GetSecurityLevel() override; security_state::VisibleSecurityState GetVisibleSecurityState() override; - std::unique_ptr<content_settings::TabSpecificContentSettings::Delegate> - GetTabSpecificContentSettingsDelegate() override; + std::unique_ptr<content_settings::PageSpecificContentSettings::Delegate> + GetPageSpecificContentSettingsDelegate() override; #if defined(OS_ANDROID) const base::string16 GetClientApplicationName() override;
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc index 2e3271a..5a83305 100644 --- a/chrome/browser/ui/page_info/page_info_unittest.cc +++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -18,7 +18,7 @@ #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/infobars/mock_infobar_service.h" #include "chrome/browser/ssl/stateful_ssl_host_state_delegate_factory.h" #include "chrome/browser/ssl/tls_deprecation_test_utils.h" @@ -149,9 +149,9 @@ ASSERT_TRUE(cert_); MockInfoBarService::CreateForWebContents(web_contents()); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents())); // Setup mock ui. @@ -249,9 +249,9 @@ content::WebContentsTester::CreateTestWebContents( profile()->GetPrimaryOTRProfile(), nullptr); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( incognito_web_contents_.get(), - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( incognito_web_contents_.get())); incognito_mock_ui_ = std::make_unique<MockPageInfoUI>(); @@ -1252,7 +1252,13 @@ // Tests that metrics are recorded on a PageInfo for pages with // various Safety Tip statuses. -TEST_F(PageInfoTest, SafetyTipMetrics) { +// See https://crbug.com/1114659 for why the test is disabled on Android. +#if defined(OS_ANDROID) +#define MAYBE_SafetyTipMetrics DISABLED_SafetyTipMetrics +#else +#define MAYBE_SafetyTipMetrics SafetyTipMetrics +#endif +TEST_F(PageInfoTest, MAYBE_SafetyTipMetrics) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature( security_state::features::kSafetyTipUI);
diff --git a/chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h b/chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h index f1250f9..0536c58b 100644 --- a/chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h +++ b/chrome/browser/ui/passwords/bubble_controllers/password_bubble_controller_base.h
@@ -21,7 +21,7 @@ // This is the base class for all bubble controllers. There should be a bubble // controller per view. Bubble controller provides the data and controls the -// password management actions for the coressponding view. +// password management actions for the corresponding view. class PasswordBubbleControllerBase { public: enum class PasswordAction { kRemovePassword, kAddPassword };
diff --git a/chrome/browser/ui/signin_reauth_view_controller.cc b/chrome/browser/ui/signin_reauth_view_controller.cc index 4a466c7..b5d08bc 100644 --- a/chrome/browser/ui/signin_reauth_view_controller.cc +++ b/chrome/browser/ui/signin_reauth_view_controller.cc
@@ -67,15 +67,6 @@ // show it in some cases in the future. ShowReauthConfirmationDialog(); - if (!base::FeatureList::IsEnabled(kSigninReauthPrompt)) { - // Approve reauth automatically. - gaia_reauth_type_ = GaiaReauthType::kAutoApproved; - gaia_reauth_page_state_ = GaiaReauthPageState::kDone; - gaia_reauth_page_result_ = signin::ReauthResult::kSuccess; - OnStateChanged(); - return; - } - // Navigate to the Gaia reauth challenge page in background. reauth_web_contents_ = content::WebContents::Create(content::WebContents::CreateParams(
diff --git a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc index 2b4c7b9..4d84afc 100644 --- a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc +++ b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
@@ -138,10 +138,6 @@ // Browser tests for SigninReauthViewController. class SigninReauthViewControllerBrowserTest : public InProcessBrowserTest { public: - SigninReauthViewControllerBrowserTest() { - scoped_feature_list_.InitAndEnableFeature(kSigninReauthPrompt); - } - void SetUp() override { ASSERT_TRUE(https_server()->InitializeAndListen()); InProcessBrowserTest::SetUp(); @@ -225,7 +221,6 @@ base::HistogramTester* histogram_tester() { return &histogram_tester_; } private: - base::test::ScopedFeatureList scoped_feature_list_; net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS}; base::HistogramTester histogram_tester_; std::unique_ptr<net::test_server::ControllableHttpResponse>
diff --git a/chrome/browser/ui/signin_view_controller_interactive_uitest.cc b/chrome/browser/ui/signin_view_controller_interactive_uitest.cc index 12819c9..b38d0f8 100644 --- a/chrome/browser/ui/signin_view_controller_interactive_uitest.cc +++ b/chrome/browser/ui/signin_view_controller_interactive_uitest.cc
@@ -200,34 +200,3 @@ dialog_observer.WaitForDialogClosed(); EXPECT_FALSE(browser()->signin_view_controller()->ShowsModalDialog()); } - -// Tests that the confirm button is focused by default in the reauth dialog. -IN_PROC_BROWSER_TEST_F(SignInViewControllerBrowserTest, ReauthDefaultFocus) { - const auto kAccessPoint = - signin_metrics::ReauthAccessPoint::kAutofillDropdown; - content::TestNavigationObserver content_observer( - signin::GetReauthConfirmationURL(kAccessPoint)); - content_observer.StartWatchingNewWebContents(); - CoreAccountId account_id = signin::SetUnconsentedPrimaryAccount( - GetIdentityManager(), "alice@gmail.com") - .account_id; - - signin::ReauthResult reauth_result; - base::RunLoop run_loop; - std::unique_ptr<SigninViewController::ReauthAbortHandle> abort_handle = - browser()->signin_view_controller()->ShowReauthPrompt( - account_id, kAccessPoint, - base::BindLambdaForTesting([&](signin::ReauthResult result) { - reauth_result = result; - run_loop.Quit(); - })); - EXPECT_TRUE(browser()->signin_view_controller()->ShowsModalDialog()); - content_observer.Wait(); - ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_RETURN, - /*control=*/false, - /*shift=*/false, /*alt=*/false, - /*command=*/false)); - run_loop.Run(); - EXPECT_EQ(reauth_result, signin::ReauthResult::kSuccess); - EXPECT_FALSE(browser()->signin_view_controller()->ShowsModalDialog()); -}
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index f888e94..f1837fb 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -20,8 +20,8 @@ #include "chrome/browser/complex_tasks/task_tab_helper.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/content_settings/sound_content_setting_observer.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_tab_helper.h" #include "chrome/browser/engagement/site_engagement_helper.h" #include "chrome/browser/engagement/site_engagement_service.h" @@ -92,7 +92,7 @@ #include "components/blocked_content/popup_blocker_tab_helper.h" #include "components/blocked_content/popup_opener_tab_helper.h" #include "components/captive_portal/core/buildflags.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/dom_distiller/core/dom_distiller_features.h" #include "components/download/content/factory/navigation_monitor_factory.h" #include "components/download/content/public/download_navigation_observer.h" @@ -306,9 +306,9 @@ web_contents, sync_sessions::SyncSessionsWebContentsRouterFactory::GetForProfile( profile)); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents, - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents)); TabUIHelper::CreateForWebContents(web_contents); tasks::TaskTabHelper::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc index 41e5431..fbbc45c 100644 --- a/chrome/browser/ui/views/collected_cookies_views.cc +++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -27,7 +27,7 @@ #include "components/browsing_data/content/local_shared_objects_container.h" #include "components/browsing_data/content/local_storage_helper.h" #include "components/constrained_window/constrained_window_views.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/strings/grit/components_strings.h" #include "components/vector_icons/vector_icons.h" @@ -421,8 +421,8 @@ std::unique_ptr<views::View> CollectedCookiesViews::CreateAllowedPane() { // This captures a snapshot of the allowed cookies of the current page so we // are fine using WebContents::GetMainFrame() here - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents_->GetMainFrame()); // Create the controls that go into the pane. @@ -478,8 +478,8 @@ } std::unique_ptr<views::View> CollectedCookiesViews::CreateBlockedPane() { - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents_->GetMainFrame()); Profile* profile =
diff --git a/chrome/browser/ui/views/crostini/crostini_uninstaller_view.h b/chrome/browser/ui/views/crostini/crostini_uninstaller_view.h index 6031ed4..2ea12df 100644 --- a/chrome/browser/ui/views/crostini/crostini_uninstaller_view.h +++ b/chrome/browser/ui/views/crostini/crostini_uninstaller_view.h
@@ -39,6 +39,9 @@ gfx::Size CalculatePreferredSize() const override; static CrostiniUninstallerView* GetActiveViewForTesting(); + void set_destructor_callback_for_testing(base::OnceClosure callback) { + destructor_callback_for_testing_.ReplaceClosure(std::move(callback)); + } private: enum class State { @@ -61,6 +64,8 @@ bool has_logged_result_ = false; Profile* profile_; + base::ScopedClosureRunner destructor_callback_for_testing_; + base::WeakPtrFactory<CrostiniUninstallerView> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(CrostiniUninstallerView);
diff --git a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc index d3c7baa..eac030b 100644 --- a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc +++ b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
@@ -76,7 +76,9 @@ bool HasCancelButton() { return ActiveView()->GetCancelButton() != nullptr; } void WaitForViewDestroyed() { - base::RunLoop().RunUntilIdle(); + base::RunLoop run_loop; + ActiveView()->set_destructor_callback_for_testing(run_loop.QuitClosure()); + run_loop.Run(); EXPECT_EQ(nullptr, ActiveView()); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 721629a..4381608 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -917,8 +917,8 @@ ContentSettingImageView* GrantGeolocationPermission() { content::RenderFrameHost* frame = app_browser_->tab_strip_model()->GetActiveWebContents()->GetMainFrame(); - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( frame->GetProcess()->GetID(), frame->GetRoutingID()); content_settings->OnGeolocationPermissionSet(GetAppURL().GetOrigin(), true);
diff --git a/chrome/browser/ui/views/hats/hats_browsertest.cc b/chrome/browser/ui/views/hats/hats_browsertest.cc index 20a27d1..76c7ce6 100644 --- a/chrome/browser/ui/views/hats/hats_browsertest.cc +++ b/chrome/browser/ui/views/hats/hats_browsertest.cc
@@ -267,3 +267,26 @@ }); run_loop.Run(); } + +IN_PROC_BROWSER_TEST_F(HatsNextWebDialogBrowserTest, NewWebContents) { + ASSERT_TRUE(embedded_test_server()->Start()); + + auto* dialog = new MockHatsNextWebDialog( + browser(), "open_new_web_contents_for_testing", + embedded_test_server()->GetURL("/hats/hats_next_mock.html"), + base::TimeDelta::FromSeconds(100)); + + // The mock hats dialog will push a loaded state after it has attempted to + // open another web contents. + base::RunLoop run_loop; + EXPECT_CALL(*dialog, ShowWidget).WillOnce(testing::Invoke([&run_loop]() { + run_loop.Quit(); + })); + run_loop.Run(); + + // Check that a tab with http://foo.com (defined in hats_next_mock.html) has + // been opened in the regular browser and is active. + EXPECT_EQ( + GURL("http://foo.com"), + browser()->tab_strip_model()->GetActiveWebContents()->GetVisibleURL()); +}
diff --git a/chrome/browser/ui/views/hats/hats_next_web_dialog.cc b/chrome/browser/ui/views/hats/hats_next_web_dialog.cc index fbdeb26b..d937fa3 100644 --- a/chrome/browser/ui/views/hats/hats_next_web_dialog.cc +++ b/chrome/browser/ui/views/hats/hats_next_web_dialog.cc
@@ -26,6 +26,45 @@ #include "ui/views/controls/webview/web_dialog_view.h" #include "ui/views/layout/fill_layout.h" +// A delegate used to intercept the creation of new WebContents by the HaTS +// Next dialog. +class HatsNextWebDialog::WebContentsDelegate + : public content::WebContentsDelegate { + public: + explicit WebContentsDelegate(Browser* browser) : browser_(browser) {} + + bool IsWebContentsCreationOverridden( + content::SiteInstance* source_site_instance, + content::mojom::WindowContainerType window_container_type, + const GURL& opener_url, + const std::string& frame_name, + const GURL& target_url) override { + return true; + } + + content::WebContents* CreateCustomWebContents( + content::RenderFrameHost* opener, + content::SiteInstance* source_site_instance, + bool is_new_browsing_instance, + const GURL& opener_url, + const std::string& frame_name, + const GURL& target_url, + const std::string& partition_id, + content::SessionStorageNamespace* session_storage_namespace) override { + // The HaTS Next WebDialog runs with a non-primary OTR profile. This profile + // cannot open new browser windows, so they are instead opened in the + // regular browser that initiated the HaTS survey. + browser_->OpenURL( + content::OpenURLParams(target_url, content::Referrer(), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_LINK, false)); + return nullptr; + } + + private: + Browser* browser_; +}; + // A thin wrapper that forwards the reference part of the URL associated with // navigation events to the enclosing web dialog. class HatsNextWebDialog::WebContentsObserver @@ -130,10 +169,10 @@ views::BubbleBorder::TOP_RIGHT), otr_profile_(browser->profile()->GetOffTheRecordProfile( Profile::OTRProfileID::CreateUnique("HaTSNext:WebDialog"))), + browser_(browser), trigger_id_(trigger_id), hats_survey_url_(hats_survey_url), - timeout_(timeout), - close_bubble_helper_(this, browser) { + timeout_(timeout) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); otr_profile_->AddObserver(this); set_close_on_deactivate(false); @@ -141,13 +180,16 @@ SetButtons(ui::DIALOG_BUTTON_NONE); SetLayoutManager(std::make_unique<views::FillLayout>()); - auto* web_view = AddChildView(std::make_unique<views::WebDialogView>( + web_view_ = AddChildView(std::make_unique<views::WebDialogView>( otr_profile_, this, std::make_unique<ChromeWebContentsHandler>(), /* use_dialog_frame */ true)); widget_ = views::BubbleDialogDelegateView::CreateBubble(this); web_contents_observer_ = - std::make_unique<WebContentsObserver>(web_view->web_contents(), this); + std::make_unique<WebContentsObserver>(web_view_->web_contents(), this); + + web_contents_delegate_ = std::make_unique<WebContentsDelegate>(browser_); + web_view_->web_contents()->SetDelegate(web_contents_delegate_.get()); loading_timer_.Start(FROM_HERE, timeout_, base::BindOnce(&HatsNextWebDialog::CloseWidget, @@ -160,6 +202,9 @@ otr_profile_->RemoveObserver(this); ProfileDestroyer::DestroyProfileWhenAppropriate(otr_profile_); } + // Explicitly clear the delegate to ensure it is not invalid between now and + // when the web contents is destroyed in the base class. + web_view_->web_contents()->SetDelegate(nullptr); } void HatsNextWebDialog::OnSurveyStateUpdateReceived(std::string state) {
diff --git a/chrome/browser/ui/views/hats/hats_next_web_dialog.h b/chrome/browser/ui/views/hats/hats_next_web_dialog.h index dcb2babf..afd5ea0 100644 --- a/chrome/browser/ui/views/hats/hats_next_web_dialog.h +++ b/chrome/browser/ui/views/hats/hats_next_web_dialog.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_UI_VIEWS_HATS_HATS_NEXT_WEB_DIALOG_H_ #include "chrome/browser/profiles/profile_observer.h" -#include "chrome/browser/ui/views/close_bubble_on_tab_activation_helper.h" #include "content/public/browser/web_contents_observer.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/controls/webview/web_dialog_view.h" @@ -67,6 +66,7 @@ const GURL& hats_survey_url_, const base::TimeDelta& timeout); + class WebContentsDelegate; class WebContentsObserver; // Fired by the observer when the survey page has pushed state to the window @@ -95,18 +95,20 @@ // The off-the-record profile used for browsing to the Chrome HaTS webpage. Profile* otr_profile_; + Browser* browser_; + // The HaTS Next survey trigger ID that is provided to the HaTS webpage. const std::string& trigger_id_; + views::WebDialogView* web_view_ = nullptr; views::Widget* widget_ = nullptr; + std::unique_ptr<WebContentsDelegate> web_contents_delegate_; std::unique_ptr<WebContentsObserver> web_contents_observer_; GURL hats_survey_url_; base::TimeDelta timeout_; - CloseBubbleOnTabActivationHelper close_bubble_helper_; - base::WeakPtrFactory<HatsNextWebDialog> weak_factory_{this}; };
diff --git a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc index abb8e0da..e68b1a6a 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
@@ -8,7 +8,7 @@ #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -24,7 +24,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/blocked_content/popup_blocker_tab_helper.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/permissions/notification_permission_ui_selector.h" #include "components/permissions/permission_request_manager.h" @@ -99,14 +99,14 @@ bool camera_accessed) { const int mic_setting = mic_accessed - ? content_settings::TabSpecificContentSettings::MICROPHONE_ACCESSED + ? content_settings::PageSpecificContentSettings::MICROPHONE_ACCESSED : 0; const int camera_setting = camera_accessed - ? content_settings::TabSpecificContentSettings::CAMERA_ACCESSED + ? content_settings::PageSpecificContentSettings::CAMERA_ACCESSED : 0; - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame()); content_settings->OnMediaStreamPermissionSet( GURL("https://example.com/"), mic_setting | camera_setting, std::string(), @@ -117,8 +117,8 @@ ContentSettingsType content_type) { content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents->GetMainFrame()); switch (content_type) { case ContentSettingsType::AUTOMATIC_DOWNLOADS: { @@ -151,7 +151,7 @@ break; } case ContentSettingsType::PROTOCOL_HANDLERS: - chrome::TabSpecificContentSettingsDelegate::FromWebContents(web_contents) + chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents) ->set_pending_protocol_handler(ProtocolHandler::CreateProtocolHandler( "mailto", GURL("https://example.com/"))); break;
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc index 86ddab6..870b8bd 100644 --- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
@@ -11,7 +11,7 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/profiles/profile.h" @@ -30,7 +30,7 @@ #include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_manager.h" #include "components/blocked_content/popup_blocker_tab_helper.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/omnibox/browser/location_bar_model_impl.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_constants.h" @@ -164,9 +164,9 @@ InfoBarService::CreateForWebContents(web_contents); MixedContentSettingsTabHelper::CreateForWebContents(web_contents); blocked_content::PopupBlockerTabHelper::CreateForWebContents(web_contents); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents, - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents)); auto* profile =
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index 0b2a107..cffc64f 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -18,7 +18,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/certificate_viewer.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc index 853e3b62..eaaf631 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
@@ -9,7 +9,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" @@ -202,9 +202,9 @@ parent_window_->Init(std::move(parent_params)); content::WebContents* web_contents = web_contents_helper_.web_contents(); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents, - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents)); api_ = std::make_unique<test::PageInfoBubbleViewTestApi>( parent_window_->GetNativeView(), web_contents_helper_.profile(),
diff --git a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_unittest.cc b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_unittest.cc index f275d60..e53d766 100644 --- a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_unittest.cc
@@ -5,10 +5,10 @@ #include "chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.h" #include "base/bind_helpers.h" -#include "chrome/browser/content_settings/tab_specific_content_settings_delegate.h" +#include "chrome/browser/content_settings/page_specific_content_settings_delegate.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/views/chrome_test_views_delegate.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/security_state/core/security_state.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_contents_factory.h" @@ -50,9 +50,9 @@ parent_window_->Init(std::move(parent_params)); content::WebContents* web_contents = web_contents_helper_.web_contents(); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents, - std::make_unique<chrome::TabSpecificContentSettingsDelegate>( + std::make_unique<chrome::PageSpecificContentSettingsDelegate>( web_contents)); bubble_ = CreateSafetyTipBubbleForTesting(
diff --git a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc index f37c3fcc..2606b34 100644 --- a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc
@@ -25,6 +25,32 @@ constexpr int kBannerWidth = 512; constexpr int kBannerHeight = 512; +// Strings for converting to and from AmbientModeTemperatureUnit enum. +constexpr char kCelsius[] = "celsius"; +constexpr char kFahrenheit[] = "fahrenheit"; + +ash::AmbientModeTemperatureUnit ExtractTemperatureUnit( + const base::ListValue* args) { + auto temperature_unit = args->GetList()[0].GetString(); + if (temperature_unit == kCelsius) { + return ash::AmbientModeTemperatureUnit::kCelsius; + } else if (temperature_unit == kFahrenheit) { + return ash::AmbientModeTemperatureUnit::kFahrenheit; + } + NOTREACHED() << "Unknown temperature unit"; + return ash::AmbientModeTemperatureUnit::kFahrenheit; +} + +std::string TemperatureUnitToString( + ash::AmbientModeTemperatureUnit temperature_unit) { + switch (temperature_unit) { + case ash::AmbientModeTemperatureUnit::kFahrenheit: + return kFahrenheit; + case ash::AmbientModeTemperatureUnit::kCelsius: + return kCelsius; + } +} + ash::AmbientModeTopicSource ExtractTopicSource(const base::Value& value) { ash::AmbientModeTopicSource topic_source = static_cast<ash::AmbientModeTopicSource>(value.GetInt()); @@ -47,8 +73,8 @@ void AmbientModeHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( - "requestTopicSource", - base::BindRepeating(&AmbientModeHandler::HandleRequestTopicSource, + "requestSettings", + base::BindRepeating(&AmbientModeHandler::HandleRequestSettings, base::Unretained(this))); web_ui()->RegisterMessageCallback( @@ -62,6 +88,11 @@ base::Unretained(this))); web_ui()->RegisterMessageCallback( + "setSelectedTemperatureUnit", + base::BindRepeating(&AmbientModeHandler::HandleSetSelectedTemperatureUnit, + base::Unretained(this))); + + web_ui()->RegisterMessageCallback( "setSelectedAlbums", base::BindRepeating(&AmbientModeHandler::HandleSetSelectedAlbums, base::Unretained(this))); @@ -72,7 +103,7 @@ ui_update_weak_factory_.InvalidateWeakPtrs(); } -void AmbientModeHandler::HandleRequestTopicSource(const base::ListValue* args) { +void AmbientModeHandler::HandleRequestSettings(const base::ListValue* args) { CHECK(args); CHECK(args->empty()); @@ -103,10 +134,21 @@ ui_update_weak_factory_.GetWeakPtr(), ExtractTopicSource(args))); } +void AmbientModeHandler::HandleSetSelectedTemperatureUnit( + const base::ListValue* args) { + DCHECK(settings_); + CHECK_EQ(1U, args->GetSize()); + + settings_->temperature_unit = ExtractTemperatureUnit(args); + UpdateSettings(); +} + void AmbientModeHandler::HandleSetSelectedTopicSource( const base::ListValue* args) { - ash::AmbientModeTopicSource topic_source = ExtractTopicSource(args); - settings_->topic_source = topic_source; + DCHECK(settings_); + CHECK_EQ(1U, args->GetSize()); + + settings_->topic_source = ExtractTopicSource(args); UpdateSettings(); } @@ -156,6 +198,13 @@ UpdateSettings(); } +void AmbientModeHandler::SendTemperatureUnit() { + DCHECK(settings_); + FireWebUIListener( + "temperature-unit-changed", + base::Value(TemperatureUnitToString(settings_->temperature_unit))); +} + void AmbientModeHandler::SendTopicSource() { DCHECK(settings_); FireWebUIListener("topic-source-changed", @@ -237,6 +286,7 @@ } SendTopicSource(); + SendTemperatureUnit(); } } // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h index 3e8308cc..b9047e2 100644 --- a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h
@@ -41,20 +41,26 @@ private: friend class AmbientModeHandlerTest; - // WebUI call to request topic source related data. - void HandleRequestTopicSource(const base::ListValue* args); + // WebUI call to request topic source and temperature unit related data. + void HandleRequestSettings(const base::ListValue* args); // WebUI call to request albums related data. void HandleRequestAlbums(const base::ListValue* args); + // WebUI call to sync temperature unit with server. + void HandleSetSelectedTemperatureUnit(const base::ListValue* args); + // WebUI call to sync topic source with server. void HandleSetSelectedTopicSource(const base::ListValue* args); // WebUI call to sync albums with server. void HandleSetSelectedAlbums(const base::ListValue* args); - // Send the "topic-source-changed" WebUIListener event when the initial - // settings is retrieved. + // Send the "temperature-unit-changed" WebUIListener event to update the + // WebUI. + void SendTemperatureUnit(); + + // Send the "topic-source-changed" WebUIListener event to update the WebUI. void SendTopicSource(); // Send the "albums-changed" WebUIListener event with albums info
diff --git a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc index d54803a..5591be1 100644 --- a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc
@@ -47,9 +47,9 @@ std::make_unique<ash::FakeAmbientBackendControllerImpl>(); } - void RequestTopicSource() { + void RequestSettings() { base::ListValue args; - handler_->HandleRequestTopicSource(&args); + handler_->HandleRequestSettings(&args); } void RequestAlbums(int topic_source) { @@ -58,19 +58,32 @@ handler_->HandleRequestAlbums(&args); } - void VerifyTopicSourceSent(base::RunLoop* run_loop) { - EXPECT_EQ(1U, web_ui_->call_data().size()); + std::string BoolToString(bool x) { return x ? "true" : "false"; } - const content::TestWebUI::CallData& call_data = - *web_ui_->call_data().back(); + void VerifySettingsSent(base::RunLoop* run_loop) { + EXPECT_EQ(2U, web_ui_->call_data().size()); // The call is structured such that the function name is the "web callback" // name and the first argument is the name of the message being sent. - EXPECT_EQ(kWebCallbackFunctionName, call_data.function_name()); - EXPECT_EQ("topic-source-changed", call_data.arg1()->GetString()); + const auto& topic_source_call_data = *web_ui_->call_data().front(); + const auto& temperature_unit_call_data = *web_ui_->call_data().back(); + + // Topic Source + EXPECT_EQ(kWebCallbackFunctionName, topic_source_call_data.function_name()); + EXPECT_EQ("topic-source-changed", + topic_source_call_data.arg1()->GetString()); // In FakeAmbientBackendControllerImpl, the |topic_source| is // kGooglePhotos. - EXPECT_EQ(0, call_data.arg2()->GetInt()); + EXPECT_EQ(0, topic_source_call_data.arg2()->GetInt()); + + // Temperature Unit + EXPECT_EQ(kWebCallbackFunctionName, + temperature_unit_call_data.function_name()); + EXPECT_EQ("temperature-unit-changed", + temperature_unit_call_data.arg1()->GetString()); + // In FakeAmbientBackendControllerImpl, the |temperature_unit| is kCelsius. + EXPECT_EQ("celsius", temperature_unit_call_data.arg2()->GetString()); + run_loop->Quit(); } @@ -128,13 +141,13 @@ std::unique_ptr<TestAmbientModeHandler> handler_; }; -TEST_F(AmbientModeHandlerTest, TestSendTopicSource) { - RequestTopicSource(); +TEST_F(AmbientModeHandlerTest, TestSendTemperatureUnitAndTopicSource) { + RequestSettings(); base::RunLoop run_loop; base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, - base::BindOnce(&AmbientModeHandlerTest::VerifyTopicSourceSent, + base::BindOnce(&AmbientModeHandlerTest::VerifySettingsSent, base::Unretained(this), &run_loop), base::TimeDelta::FromSeconds(1)); run_loop.Run();
diff --git a/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc b/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc index a49f06c..8db3fdc 100644 --- a/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc
@@ -180,6 +180,11 @@ IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_SUBPAGE}, {"ambientModeAlbumsSubpageGooglePhotosNoAlbum", IDS_OS_SETTINGS_AMBIENT_MODE_ALBUMS_SUBPAGE_GOOGLE_PHOTOS_NO_ALBUM}, + {"ambientModeWeatherTitle", IDS_OS_SETTINGS_AMBIENT_MODE_WEATHER_TITLE}, + {"ambientModeTemperatureUnitFahrenheit", + IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_FAHRENHEIT}, + {"ambientModeTemperatureUnitCelsius", + IDS_OS_SETTINGS_AMBIENT_MODE_TEMPERATURE_UNIT_CELSIUS}, {"changePictureTitle", IDS_OS_SETTINGS_CHANGE_PICTURE_TITLE}, {"openWallpaperApp", IDS_OS_SETTINGS_OPEN_WALLPAPER_APP}, {"personalizationPageTitle", IDS_OS_SETTINGS_PERSONALIZATION},
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc index 30844c9..702dce69 100644 --- a/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -702,10 +702,13 @@ delete_profile ? signin_metrics::SignoutDelete::DELETED : signin_metrics::SignoutDelete::KEEPING; - // Do not remove the accounts: the Gaia logout tab will remove them in a - // better way (see http://crbug.com/1068978). + // Use ClearAccountsAction::kDefault: if the primary account is still + // valid, it will be removed by the Gaia logout tab + // (see http://crbug.com/1068978). If the account is already invalid, drop + // the token now (because it's already invalid on the web, so the Gaia + // logout tab won't affect it, see http://crbug.com/1114646). identity_manager->GetPrimaryAccountMutator()->ClearPrimaryAccount( - signin::PrimaryAccountMutator::ClearAccountsAction::kKeepAll, + signin::PrimaryAccountMutator::ClearAccountsAction::kDefault, signin_metrics::USER_CLICKED_SIGNOUT_SETTINGS, delete_metric); } else { DCHECK(!delete_profile)
diff --git a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc index 35dc73d..bb26020 100644 --- a/chrome/browser/vr/ui_host/vr_ui_host_impl.cc +++ b/chrome/browser/vr/ui_host/vr_ui_host_impl.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/vr/vr_tab_helper.h" #include "chrome/browser/vr/win/vr_browser_renderer_thread_win.h" #include "components/content_settings/browser/content_settings_usages_state.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_manager.h" #include "components/permissions/permission_result.h" #include "content/public/browser/device_service.h" @@ -393,8 +393,8 @@ CapturingStateModel active_capturing = active_capturing_; // TODO(https://crbug.com/1103176): Plumb the actual frame reference here (we // should get a RFH from VRServiceImpl instead of WebContents) - content_settings::TabSpecificContentSettings* settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* settings = + content_settings::PageSpecificContentSettings::GetForFrame( web_contents_->GetMainFrame()); if (settings) { const ContentSettingsUsagesState& usages_state = @@ -408,15 +408,15 @@ active_capturing.audio_capture_enabled = (settings->GetMicrophoneCameraState() & - content_settings::TabSpecificContentSettings::MICROPHONE_ACCESSED) && + content_settings::PageSpecificContentSettings::MICROPHONE_ACCESSED) && !(settings->GetMicrophoneCameraState() & - content_settings::TabSpecificContentSettings::MICROPHONE_BLOCKED); + content_settings::PageSpecificContentSettings::MICROPHONE_BLOCKED); active_capturing.video_capture_enabled = (settings->GetMicrophoneCameraState() & - content_settings::TabSpecificContentSettings::CAMERA_ACCESSED) & + content_settings::PageSpecificContentSettings::CAMERA_ACCESSED) & !(settings->GetMicrophoneCameraState() & - content_settings::TabSpecificContentSettings::CAMERA_BLOCKED); + content_settings::PageSpecificContentSettings::CAMERA_BLOCKED); active_capturing.midi_connected = settings->IsContentAllowed(ContentSettingsType::MIDI_SYSEX);
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 678128f..6b6c84d 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1597037945-c748d93b7b3b8df201950e67d57a776238968dea.profdata +chrome-mac-master-1597060771-94a7300bd1819f6d10eaf4c394bfbc10cebf8f71.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index fa4daa47..76204d1 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -404,6 +404,8 @@ if (is_android) { sources -= [ "media_galleries/metadata_types.h" ] sources += [ + "android/cpu_affinity_experiments.cc", + "android/cpu_affinity_experiments.h", "media/chrome_media_drm_bridge_client.cc", "media/chrome_media_drm_bridge_client.h", ]
diff --git a/chrome/common/android/cpu_affinity_experiments.cc b/chrome/common/android/cpu_affinity_experiments.cc new file mode 100644 index 0000000..e3a3a048 --- /dev/null +++ b/chrome/common/android/cpu_affinity_experiments.cc
@@ -0,0 +1,37 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/android/cpu_affinity_experiments.h" + +#include "base/cpu_affinity_posix.h" +#include "base/feature_list.h" +#include "base/metrics/histogram_functions.h" +#include "base/process/process_handle.h" + +namespace chrome { + +namespace { + +const base::Feature kCpuAffinityRestrictToLittleCores{ + "CpuAffinityRestrictToLittleCores", base::FEATURE_DISABLED_BY_DEFAULT}; + +} // namespace + +void InitializeCpuAffinityExperiments() { + if (!base::FeatureList::IsEnabled(kCpuAffinityRestrictToLittleCores)) + return; + + // Restrict affinity of all existing threads of the current process. The + // affinity is inherited by any subsequently created thread. While + // InitializeThreadAffinityExperiments() is called early during startup, other + // threads (e.g. Java threads like the RenderThread) may already exist, so + // setting the affinity only for the current thread is not enough here. + bool success = base::SetProcessCpuAffinityMode( + base::GetCurrentProcessHandle(), base::CpuAffinityMode::kLittleCoresOnly); + + base::UmaHistogramBoolean( + "Power.CpuAffinityExperiments.ProcessAffinityUpdateSuccess", success); +} + +} // namespace chrome
diff --git a/chrome/common/android/cpu_affinity_experiments.h b/chrome/common/android/cpu_affinity_experiments.h new file mode 100644 index 0000000..bf43645 --- /dev/null +++ b/chrome/common/android/cpu_affinity_experiments.h
@@ -0,0 +1,17 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_ANDROID_CPU_AFFINITY_EXPERIMENTS_H_ +#define CHROME_COMMON_ANDROID_CPU_AFFINITY_EXPERIMENTS_H_ + +namespace chrome { + +// Setup CPU-affinity restriction experiments (e.g. to restrict execution to +// little cores only) for the current process, based on the feature list. Should +// be called during process startup after feature list initialization. +void InitializeCpuAffinityExperiments(); + +} // namespace chrome + +#endif // CHROME_COMMON_ANDROID_CPU_AFFINITY_EXPERIMENTS_H_
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base.cc b/chrome/credential_provider/gaiacp/gaia_credential_base.cc index 9ad1166e..39336eb 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_base.cc +++ b/chrome/credential_provider/gaiacp/gaia_credential_base.cc
@@ -308,6 +308,7 @@ std::vector<base::string16> filtered_local_account_names_no_sn; for (auto local_account_name : local_account_names) { + LOGFN(VERBOSE) << "CD local account name : " << local_account_name; // The format for local_account_name custom attribute is // "un:abcd,sn:1234" where "un:abcd" would always exist and "sn:1234" is // optional. @@ -315,12 +316,16 @@ std::string serial_number; // Note: "?:" is used to signify non-capturing groups. For more details, // look at https://github.com/google/re2/wiki/Syntax link. - re2::RE2::FullMatch(local_account_name, "un:([^,]+)(?:,sn:(\\w+))?", + re2::RE2::FullMatch(local_account_name, "un:([^,]+)(?:,sn:([^,]+))?", &username, &serial_number); + LOGFN(VERBOSE) << "RE2 username : " << username; + LOGFN(VERBOSE) << "RE2 serial_number : " << serial_number; + if (!username.empty() && !serial_number.empty()) { std::string device_serial_number = base::UTF16ToUTF8(GetSerialNumber().c_str()); + LOGFN(VERBOSE) << "Device serial_number : " << device_serial_number; if (base::EqualsCaseInsensitiveASCII(serial_number, device_serial_number)) filtered_local_account_names.push_back(base::UTF8ToUTF16(username)); @@ -2325,6 +2330,14 @@ if (FAILED(hr)) LOGFN(ERROR) << "SetUserFullname hr=" << putHR(hr); } + + // Set disable password change policy here as well. This flow would + // make sure password change is disabled even if any end user tries + // to enable it via registry after user create or association flow. + // Note: We donot fail the login flow if password policies were not + // applied for unknown reasons. + OSUserManager::Get()->SetDefaultPasswordChangePolicies(found_domain, + found_username); } else { LOGFN(ERROR) << "GetUserFullname hr=" << putHR(hr); }
diff --git a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc index 2f0c3c5..9387b7d 100644 --- a/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc +++ b/chrome/credential_provider/gaiacp/gaia_credential_base_unittests.cc
@@ -2029,10 +2029,11 @@ // logged in. class GaiaCredentialBaseCloudLocalAccountSuccessTest : public GcpGaiaCredentialBaseCloudLocalAccountTest, - public ::testing::WithParamInterface<bool> {}; + public ::testing::WithParamInterface<std::tuple<bool, const wchar_t*>> {}; TEST_P(GaiaCredentialBaseCloudLocalAccountSuccessTest, SerialNumber) { - bool set_serial_number = GetParam(); + bool set_serial_number = std::get<0>(GetParam()); + const wchar_t* serial_number = std::get<1>(GetParam()); // Add the user as a local user. const wchar_t user_name[] = L"local_user"; @@ -2052,7 +2053,6 @@ std::string admin_sdk_response; // Set a fake serial number. - base::string16 serial_number = L"1234"; GoogleRegistrationDataForTesting g_registration_data(serial_number); if (set_serial_number) { @@ -2061,7 +2061,7 @@ "{\"customSchemas\": {\"Enhanced_desktop_security\": " "{\"Local_Windows_accounts\":" "[{ \"value\": \"un:%ls,sn:%ls\"}]}}}", - user_name, serial_number.c_str()); + user_name, serial_number); } else { // Set valid response from admin sdk. admin_sdk_response = base::StringPrintf( @@ -2108,9 +2108,15 @@ ASSERT_TRUE(test->IsAuthenticationResultsEmpty()); } -INSTANTIATE_TEST_SUITE_P(All, - GaiaCredentialBaseCloudLocalAccountSuccessTest, - ::testing::Values(true, false)); +INSTANTIATE_TEST_SUITE_P( + All, + GaiaCredentialBaseCloudLocalAccountSuccessTest, + ::testing::Combine( + ::testing::Bool(), + ::testing::Values(L"!@#!", // All non alphanumeric characters + L"serial#123", // Contains non-alphanumeric chars. + L"serial123!" // Ends with non alphanumeric chars. + ))); // Existing cloud local account login scenario that was configured incorrectly. class GaiaCredentialBaseCDUsernameSuccessTest @@ -2196,6 +2202,9 @@ ASSERT_EQ(S_OK, hr); ASSERT_EQ(0u, error); + // Set fake serial number. + GoogleRegistrationDataForTesting g_registration_data(serial_number); + // Set token result as a valid access token. fake_http_url_fetcher_factory()->SetFakeResponse( GURL(gaia_urls_->oauth2_token_url().spec().c_str()), @@ -2232,10 +2241,9 @@ INSTANTIATE_TEST_SUITE_P( All, GaiaCredentialBaseCDSerialNumberFailureTest, - ::testing::Values(L"!@#!", // All non alphanumeric characters - L"serial#123", // Contains non-alphanumeric chars. - L"serial123!", // Ends with non alphanumeric chars. - L"")); + ::testing::Values( + L"" // Except for empty string all other characters are allowed chars. + )); // Tests various sign in scenarios with consumer and non-consumer domains. // Parameters are:
diff --git a/chrome/credential_provider/gaiacp/os_user_manager.cc b/chrome/credential_provider/gaiacp/os_user_manager.cc index 07bc5ae..c7912e03 100644 --- a/chrome/credential_provider/gaiacp/os_user_manager.cc +++ b/chrome/credential_provider/gaiacp/os_user_manager.cc
@@ -318,6 +318,22 @@ return (nsts == NERR_Success ? S_OK : HRESULT_FROM_WIN32(nsts)); } +HRESULT OSUserManager::SetDefaultPasswordChangePolicies( + const wchar_t* domain, + const wchar_t* username) { + USER_INFO_1008 info1008; + DWORD error; + memset(&info1008, 0, sizeof(info1008)); + info1008.usri1008_flags = + UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD | UF_NORMAL_ACCOUNT; + NET_API_STATUS nsts = ::NetUserSetInfo( + domain, username, 1008, reinterpret_cast<LPBYTE>(&info1008), &error); + if (nsts != NERR_Success) { + LOGFN(ERROR) << "NetUserSetInfo(set password policies) nsts=" << nsts; + } + return HRESULT_FROM_WIN32(nsts); +} + HRESULT OSUserManager::ChangeUserPassword(const wchar_t* domain, const wchar_t* username, const wchar_t* old_password,
diff --git a/chrome/credential_provider/gaiacp/os_user_manager.h b/chrome/credential_provider/gaiacp/os_user_manager.h index bfba5f9..d21239b 100644 --- a/chrome/credential_provider/gaiacp/os_user_manager.h +++ b/chrome/credential_provider/gaiacp/os_user_manager.h
@@ -91,6 +91,10 @@ virtual HRESULT GetUserFullname( const wchar_t* domain, const wchar_t* username, base::string16* fullname); + // Sets restrictive password change policies for the end user account. + virtual HRESULT SetDefaultPasswordChangePolicies(const wchar_t* domain, + const wchar_t* username); + // Changes the user's valid access hours to effectively allow or disallow them // from signing in to the system. If |allow| is false then the user is not // allowed to sign on at any hour of the day. If |allow| is true, then the
diff --git a/chrome/credential_provider/test/gcp_fakes.cc b/chrome/credential_provider/test/gcp_fakes.cc index 5113a1d..67f3bb5 100644 --- a/chrome/credential_provider/test/gcp_fakes.cc +++ b/chrome/credential_provider/test/gcp_fakes.cc
@@ -389,6 +389,12 @@ return S_OK; } +HRESULT FakeOSUserManager::SetDefaultPasswordChangePolicies( + const wchar_t* domain, + const wchar_t* username) { + return S_OK; +} + FakeOSUserManager::UserInfo::UserInfo(const wchar_t* domain, const wchar_t* password, const wchar_t* fullname,
diff --git a/chrome/credential_provider/test/gcp_fakes.h b/chrome/credential_provider/test/gcp_fakes.h index c4ccbafd..eba5478 100644 --- a/chrome/credential_provider/test/gcp_fakes.h +++ b/chrome/credential_provider/test/gcp_fakes.h
@@ -131,6 +131,9 @@ const wchar_t* username, bool allow) override; + HRESULT SetDefaultPasswordChangePolicies(const wchar_t* domain, + const wchar_t* username) override; + bool IsDeviceDomainJoined() override; void SetIsDeviceDomainJoined(bool is_device_domain_joined) {
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn index 047b71e..7c7af8c 100644 --- a/chrome/installer/mini_installer/BUILD.gn +++ b/chrome/installer/mini_installer/BUILD.gn
@@ -76,7 +76,6 @@ "mini_file_test.cc", "mini_installer_unittest.cc", "mini_string_test.cc", - "pe_resource_test.cc", ] public_deps = [ ":lib" ]
diff --git a/chrome/installer/mini_installer/decompress.cc b/chrome/installer/mini_installer/decompress.cc index 7ace7a94..de58600 100644 --- a/chrome/installer/mini_installer/decompress.cc +++ b/chrome/installer/mini_installer/decompress.cc
@@ -22,7 +22,7 @@ const wchar_t* const dest_path; // The destination file; valid once the destination is created. - mini_installer::MiniFile& dest_file; + mini_installer::MiniFile dest_file; // Set to true if the file was extracted to |dest_path|. Note that |dest_file| // may be valid even in case of failure. @@ -247,7 +247,7 @@ namespace mini_installer { -bool Expand(const wchar_t* source, const wchar_t* destination, MiniFile& file) { +bool Expand(const wchar_t* source, const wchar_t* destination) { if (!InitializeFdi()) return false; @@ -274,7 +274,7 @@ if (!fdi) return false; - ExpandContext context = {destination, file, /*succeeded=*/false}; + ExpandContext context = {destination, {}, /*succeeded=*/false}; g_FDICopy(fdi, source_name_utf8, source_path_utf8, 0, &Notify, nullptr, &context); g_FDIDestroy(fdi); @@ -282,7 +282,8 @@ return true; // Delete the output file if it was created. - file.Close(); + if (context.dest_file.IsValid()) + context.dest_file.DeleteOnClose(); return false; }
diff --git a/chrome/installer/mini_installer/decompress.h b/chrome/installer/mini_installer/decompress.h index 1a57754..5e11af8d 100644 --- a/chrome/installer/mini_installer/decompress.h +++ b/chrome/installer/mini_installer/decompress.h
@@ -7,14 +7,11 @@ namespace mini_installer { -class MiniFile; - -// Expands the first file in |source| to the file |destination| using -// Microsoft's MSCF compression algorithm (a la expand.exe). Returns true on -// success, in which case |file| holds an open handle to the destination file. -// |file| will be opened with exclusive write access and shared read and delete -// access, and will be marked as delete-on-close. -bool Expand(const wchar_t* source, const wchar_t* destination, MiniFile& file); +// Same as the tool, expand.exe. Decompresses a file that was compressed +// using Microsoft's MSCF compression algorithm. +// |source| is the full path of the file to decompress and |destination| +// is the full path of the target file. +bool Expand(const wchar_t* source, const wchar_t* destination); } // namespace mini_installer
diff --git a/chrome/installer/mini_installer/decompress_test.cc b/chrome/installer/mini_installer/decompress_test.cc index ab77a29..3dd0c97d 100644 --- a/chrome/installer/mini_installer/decompress_test.cc +++ b/chrome/installer/mini_installer/decompress_test.cc
@@ -5,11 +5,9 @@ #include <windows.h> #include "base/files/file_path.h" -#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/path_service.h" #include "chrome/installer/mini_installer/decompress.h" -#include "chrome/installer/mini_installer/mini_file.h" #include "testing/gtest/include/gtest/gtest.h" TEST(MiniDecompressTest, ExpandTest) { @@ -29,21 +27,11 @@ temp_dir.GetPath().Append(FILE_PATH_LITERAL("setup.exe"))); // Decompress our test file. - mini_installer::MiniFile file(mini_installer::MiniFile::DeleteOnClose::kYes); - ASSERT_TRUE(mini_installer::Expand(source_path.value().c_str(), - dest_path.value().c_str(), file)); - ASSERT_TRUE(file.IsValid()); - ASSERT_PRED1(base::PathExists, dest_path); - - // Drop write permission so that the call below can open the file. - ASSERT_TRUE(file.DropWritePermission()); + EXPECT_TRUE(mini_installer::Expand(source_path.value().c_str(), + dest_path.value().c_str())); // Check if the expanded file is a valid executable. DWORD type = static_cast<DWORD>(-1); EXPECT_TRUE(GetBinaryType(dest_path.value().c_str(), &type)); EXPECT_EQ(static_cast<DWORD>(SCS_32BIT_BINARY), type); - - // Closing the handle should delete the file. - file.Close(); - EXPECT_FALSE(base::PathExists(dest_path)); }
diff --git a/chrome/installer/mini_installer/exit_code.h b/chrome/installer/mini_installer/exit_code.h index 6d864e67..729c1b8 100644 --- a/chrome/installer/mini_installer/exit_code.h +++ b/chrome/installer/mini_installer/exit_code.h
@@ -42,11 +42,6 @@ RUN_SETUP_FAILED_FILE_NOT_FOUND = 122, // ERROR_FILE_NOT_FOUND. RUN_SETUP_FAILED_PATH_NOT_FOUND = 123, // ERROR_PATH_NOT_FOUND. RUN_SETUP_FAILED_COULD_NOT_CREATE_PROCESS = 124, // All other errors. - UNABLE_TO_OPEN_PATCHED_SETUP = 125, - DROP_WRITE_ON_EXTRACTED_ARCHIVE_FAILED = 126, - DROP_WRITE_ON_EXTRACTED_SETUP_PATCH_FAILED = 127, - DROP_WRITE_ON_EXTRACTED_SETUP_FAILED = 128, - DROP_WRITE_ON_EXPANDED_SETUP_FAILED = 129, }; } // namespace mini_installer
diff --git a/chrome/installer/mini_installer/mini_file.cc b/chrome/installer/mini_installer/mini_file.cc index 790d097..2e04f68 100644 --- a/chrome/installer/mini_installer/mini_file.cc +++ b/chrome/installer/mini_installer/mini_file.cc
@@ -8,10 +8,7 @@ namespace mini_installer { -MiniFile::MiniFile(DeleteOnClose delete_on_close) - : delete_on_close_flag_(delete_on_close != DeleteOnClose::kNo - ? FILE_FLAG_DELETE_ON_CLOSE - : 0) {} +MiniFile::MiniFile() = default; MiniFile::~MiniFile() { Close(); @@ -29,11 +26,9 @@ Close(); if (!path_.assign(path)) return false; - handle_ = ::CreateFileW(path_.get(), GENERIC_WRITE, - FILE_SHARE_DELETE | FILE_SHARE_READ, - /*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | delete_on_close_flag_, - /*hTemplateFile=*/nullptr); + handle_ = + ::CreateFileW(path_.get(), DELETE | GENERIC_WRITE, FILE_SHARE_DELETE, + nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (handle_ != INVALID_HANDLE_VALUE) return true; path_.clear(); @@ -44,76 +39,11 @@ return handle_ != INVALID_HANDLE_VALUE; } -bool MiniFile::DropWritePermission() { - // The original file was opened with write access (of course), so it will take - // a little hoop jumping to get a handle without it. First, get a new handle - // that doesn't have write access. This one must allow others to write on - // account of the fact that the original handle has write access. - HANDLE without_write = - ::ReOpenFile(handle_, GENERIC_READ, - FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ, - delete_on_close_flag_); - if (without_write == INVALID_HANDLE_VALUE) { - const auto error = ::GetLastError(); - Close(); - ::SetLastError(error); - return false; - } - - // Next, close the original handle so that there are no longer any writers. - // This will mark the file for deletion if the original handle was opened with - // FILE_FLAG_DELETE_ON_CLOSE. - ::CloseHandle(std::exchange(handle_, INVALID_HANDLE_VALUE)); - - // Now unmark the file for deletion if needed. - if (delete_on_close_flag_) { - FILE_DISPOSITION_INFO disposition = {/*DeleteFile=*/FALSE}; - if (!::SetFileInformationByHandle(without_write, FileDispositionInfo, - &disposition, sizeof(disposition))) { - const auto error = ::GetLastError(); - ::CloseHandle(std::exchange(without_write, INVALID_HANDLE_VALUE)); - Close(); - ::SetLastError(error); - return false; - } - } - - // Now open a read-only handle (with FILE_FLAG_DELETE_ON_CLOSE as needed) that - // doesn't allow others to write. Note that there is a potential race here: - // another party could open the file for shared write access at this precise - // moment, causing this ReOpenFile to fail. This would likely be an issue - // anyway, as one common thing to do with the file is to execute it, which - // will fail if there are writers. - handle_ = - ::ReOpenFile(without_write, GENERIC_READ, - FILE_SHARE_DELETE | FILE_SHARE_READ, delete_on_close_flag_); - if (handle_ == INVALID_HANDLE_VALUE) { - const auto error = ::GetLastError(); - ::CloseHandle(std::exchange(without_write, INVALID_HANDLE_VALUE)); - Close(); - ::SetLastError(error); - return false; - } - - // Closing the handle that allowed shared writes may once again mark the file - // for deletion. - ::CloseHandle(std::exchange(without_write, INVALID_HANDLE_VALUE)); - - // Everything went according to plan; |handle_| is now lacking write access - // and does not allow other writers. The last step is to unmark the file for - // deletion once again, as the closure of |without_write| has re-marked it. - if (delete_on_close_flag_) { - FILE_DISPOSITION_INFO disposition = {/*DeleteFile=*/FALSE}; - if (!::SetFileInformationByHandle(handle_, FileDispositionInfo, - &disposition, sizeof(disposition))) { - const auto error = ::GetLastError(); - Close(); - ::SetLastError(error); - return false; - } - } - - return true; +bool MiniFile::DeleteOnClose() { + FILE_DISPOSITION_INFO disposition = {/*DeleteFile=*/TRUE}; + return IsValid() && + ::SetFileInformationByHandle(handle_, FileDispositionInfo, + &disposition, sizeof(disposition)); } void MiniFile::Close() { @@ -134,18 +64,6 @@ : INVALID_HANDLE_VALUE; } -bool MiniFile::Open(const PathString& path) { - Close(); - handle_ = ::CreateFileW(path.get(), GENERIC_READ, - FILE_SHARE_DELETE | FILE_SHARE_READ, - /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, - delete_on_close_flag_, /*hTemplateFile=*/nullptr); - if (handle_ == INVALID_HANDLE_VALUE) - return false; - path_.assign(path); - return true; -} - HANDLE MiniFile::GetHandleUnsafe() const { return handle_; }
diff --git a/chrome/installer/mini_installer/mini_file.h b/chrome/installer/mini_installer/mini_file.h index e0989002..16dd702 100644 --- a/chrome/installer/mini_installer/mini_file.h +++ b/chrome/installer/mini_installer/mini_file.h
@@ -14,11 +14,10 @@ // A simple abstraction over a path to a file and a Windows file handle to it. class MiniFile { public: - enum class DeleteOnClose : bool { kNo = false, kYes = true }; - explicit MiniFile(DeleteOnClose delete_on_close); + MiniFile(); // Closes the file if the instance holds a valid handle. The file will be - // deleted if the instance was constructed with |delete_on_close|. + // deleted if directed by a call to DeleteOnClose(). ~MiniFile(); MiniFile(const MiniFile&) = delete; @@ -36,28 +35,17 @@ // Returns true if this object has a path and a handle to an open file. bool IsValid() const; - // Drops write permission on the file handle so that other parties that - // require no writers may open the file. In particular, the Windows loader - // opens files for execution with shared read/delete access, as do the - // extraction operations in Chrome's mini_installer.exe and setup.exe. These - // would fail with sharing violations if mini_installer were to hold files - // open with write permissions. Returns false on failure, in which case the - // instance is no longer valid. The file will have been deleted if the - // instance was created with DeleteOnClose. - bool DropWritePermission(); + // Marks the file for deletion when the handle is closed via Close() or the + // instance's destructor. This state follows the handle when moved. + bool DeleteOnClose(); - // Closes the handle and clears the path. The file will be deleted if the - // instance was constructed with |delete_on_close|. Following this, IsValid() - // will return false. + // Closes the handle and clears the path. Following this, IsValid() will + // return false. void Close(); // Returns a new handle to the file, or INVALID_HANDLE_VALUE on error. HANDLE DuplicateHandle() const; - // Opens the file for read access, disallowing writers (as if Create followed - // by DropWritePermission). - bool Open(const PathString& path); - // Returns the path to the open file, or a pointer to an empty string if // IsValid() is false. const wchar_t* path() const { return path_.get(); } @@ -73,10 +61,6 @@ // A handle to the open file, or INVALID_HANDLE_VALUE. HANDLE handle_ = INVALID_HANDLE_VALUE; - - // Zero or FILE_FLAG_DELETE_ON_CLOSE, according to how the instance was - // constructed. - const DWORD delete_on_close_flag_; }; } // namespace mini_installer
diff --git a/chrome/installer/mini_installer/mini_file_test.cc b/chrome/installer/mini_installer/mini_file_test.cc index 2ef4a6f..32f6ed40 100644 --- a/chrome/installer/mini_installer/mini_file_test.cc +++ b/chrome/installer/mini_installer/mini_file_test.cc
@@ -8,25 +8,16 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "chrome/installer/mini_installer/path_string.h" #include "testing/gtest/include/gtest/gtest.h" namespace mini_installer { -// A test harness for MiniFile. The MiniFile::DeleteOnClose parameter is passed -// to the test instance's constructor. -class MiniFileTest : public ::testing::TestWithParam<MiniFile::DeleteOnClose> { +class MiniFileTest : public ::testing::Test { protected: void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } void TearDown() override { EXPECT_TRUE(temp_dir_.Delete()); } - static MiniFile::DeleteOnClose delete_on_close() { return GetParam(); } - - static bool should_delete_on_close() { - return delete_on_close() != MiniFile::DeleteOnClose::kNo; - } - const base::FilePath& temp_dir() const { return temp_dir_.GetPath(); } private: @@ -34,73 +25,68 @@ }; // Create should create a file. -TEST_P(MiniFileTest, Create) { +TEST_F(MiniFileTest, Create) { const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - MiniFile file(delete_on_close()); + MiniFile file; ASSERT_TRUE(file.Create(file_path.value().c_str())); - EXPECT_TRUE(base::PathExists(file_path)); + ASSERT_TRUE(base::PathExists(file_path)); } // Created files should be deletable by others and should vanish when closed. -TEST_P(MiniFileTest, CreateDeleteIsShared) { +TEST_F(MiniFileTest, CreateDeleteIsShared) { const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - MiniFile file(delete_on_close()); + MiniFile file; ASSERT_TRUE(file.Create(file_path.value().c_str())); // DeleteFile uses POSIX semantics, so the file appears to vanish immediately. ASSERT_TRUE(base::DeleteFile(file_path)); file.Close(); - EXPECT_FALSE(base::PathExists(file_path)); + ASSERT_FALSE(base::PathExists(file_path)); } -// Tests that a file can be opened without shared write access after write -// permissions are dropped. -TEST_P(MiniFileTest, DropWritePermission) { +// DeleteOnClose should work as advertised. +TEST_F(MiniFileTest, DeleteOnClose) { const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - MiniFile file(delete_on_close()); + MiniFile file; ASSERT_TRUE(file.Create(file_path.value().c_str())); - ASSERT_FALSE(base::File(file_path, base::File::FLAG_OPEN | - base::File::FLAG_READ | - base::File::FLAG_EXCLUSIVE_WRITE | - base::File::FLAG_SHARE_DELETE) - .IsValid()); - ASSERT_TRUE(file.DropWritePermission()); - EXPECT_TRUE(base::File(file_path, base::File::FLAG_OPEN | - base::File::FLAG_READ | - base::File::FLAG_EXCLUSIVE_WRITE | - base::File::FLAG_SHARE_DELETE) - .IsValid()); + ASSERT_TRUE(file.DeleteOnClose()); + + // The file can no longer be opened now that it has been marked for deletion. + // Attempts to do so will fail with ERROR_ACCESS_DENIED. Under the covers, the + // NT status code is STATUS_DELETE_PENDING. Since base::PathExists will return + // false in this case, confirm the file's existence by trying to open it. + base::File the_file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ | + base::File::FLAG_SHARE_DELETE); + ASSERT_FALSE(the_file.IsValid()); + ASSERT_EQ(the_file.error_details(), base::File::FILE_ERROR_ACCESS_DENIED); + + file.Close(); + ASSERT_FALSE(base::PathExists(file_path)); } // Close should really close. -TEST_P(MiniFileTest, CreateThenClose) { +TEST_F(MiniFileTest, Close) { const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - MiniFile file(delete_on_close()); + MiniFile file; ASSERT_TRUE(file.Create(file_path.value().c_str())); file.Close(); EXPECT_FALSE(file.IsValid()); EXPECT_EQ(*file.path(), 0); - - ASSERT_NE(base::PathExists(file_path), should_delete_on_close()); - if (!should_delete_on_close()) { - // If closing should not have deleted the file, it should now be possible to - // open it with exclusive access. - EXPECT_TRUE(base::File(file_path, base::File::FLAG_OPEN | - base::File::FLAG_READ | - base::File::FLAG_EXCLUSIVE_READ | - base::File::FLAG_EXCLUSIVE_WRITE) - .IsValid()); - } + ASSERT_TRUE(base::PathExists(file_path)); + base::File f(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ | + base::File::FLAG_EXCLUSIVE_READ | + base::File::FLAG_EXCLUSIVE_WRITE); + ASSERT_TRUE(f.IsValid()); } // DuplicateHandle should work as advertized. -TEST_P(MiniFileTest, DuplicateHandle) { +TEST_F(MiniFileTest, DuplicateHandle) { const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - MiniFile file(delete_on_close()); + MiniFile file; ASSERT_TRUE(file.Create(file_path.value().c_str())); HANDLE dup = file.DuplicateHandle(); ASSERT_NE(dup, INVALID_HANDLE_VALUE); @@ -118,55 +104,10 @@ ::CloseHandle(std::exchange(dup, INVALID_HANDLE_VALUE)); } -// Open should provide access to a file just like Create, but for a file that -// already exists. -TEST_P(MiniFileTest, Open) { +TEST_F(MiniFileTest, Path) { const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - ASSERT_TRUE( - base::File(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE) - .IsValid()); - ASSERT_TRUE(base::PathExists(file_path)); - - PathString path_string; - ASSERT_TRUE(path_string.assign(file_path.value().c_str())); - MiniFile file(delete_on_close()); - ASSERT_TRUE(file.Open(path_string)); -} - -// Close should really close. -TEST_P(MiniFileTest, OpenThenClose) { - const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - - ASSERT_TRUE( - base::File(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE) - .IsValid()); - ASSERT_TRUE(base::PathExists(file_path)); - - MiniFile file(delete_on_close()); - PathString path_string; - ASSERT_TRUE(path_string.assign(file_path.value().c_str())); - ASSERT_TRUE(file.Open(path_string)); - file.Close(); - EXPECT_FALSE(file.IsValid()); - EXPECT_EQ(*file.path(), 0); - - ASSERT_NE(base::PathExists(file_path), should_delete_on_close()); - if (!should_delete_on_close()) { - // If closing should not have deleted the file, it should now be possible to - // open it with exclusive access. - EXPECT_TRUE(base::File(file_path, base::File::FLAG_OPEN | - base::File::FLAG_READ | - base::File::FLAG_EXCLUSIVE_READ | - base::File::FLAG_EXCLUSIVE_WRITE) - .IsValid()); - } -} - -TEST_P(MiniFileTest, Path) { - const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - - MiniFile file(delete_on_close()); + MiniFile file; EXPECT_EQ(*file.path(), 0); ASSERT_TRUE(file.Create(file_path.value().c_str())); @@ -176,10 +117,10 @@ EXPECT_EQ(*file.path(), 0); } -TEST_P(MiniFileTest, GetHandleUnsafe) { +TEST_F(MiniFileTest, GetHandleUnsafe) { const base::FilePath file_path = temp_dir().Append(FILE_PATH_LITERAL("HUM")); - MiniFile file(delete_on_close()); + MiniFile file; EXPECT_EQ(file.GetHandleUnsafe(), INVALID_HANDLE_VALUE); ASSERT_TRUE(file.Create(file_path.value().c_str())); @@ -189,11 +130,4 @@ EXPECT_EQ(file.GetHandleUnsafe(), INVALID_HANDLE_VALUE); } -INSTANTIATE_TEST_SUITE_P(DoNotDeleteOnClose, - MiniFileTest, - ::testing::Values(MiniFile::DeleteOnClose::kNo)); -INSTANTIATE_TEST_SUITE_P(DeleteOnClose, - MiniFileTest, - ::testing::Values(MiniFile::DeleteOnClose::kYes)); - } // namespace mini_installer
diff --git a/chrome/installer/mini_installer/mini_installer.cc b/chrome/installer/mini_installer/mini_installer.cc index 1744608..a032e87 100644 --- a/chrome/installer/mini_installer/mini_installer.cc +++ b/chrome/installer/mini_installer/mini_installer.cc
@@ -36,41 +36,32 @@ #include <stdlib.h> #include <initializer_list> -#include <utility> #include "build/branding_buildflags.h" #include "chrome/installer/mini_installer/appid.h" #include "chrome/installer/mini_installer/configuration.h" #include "chrome/installer/mini_installer/decompress.h" -#include "chrome/installer/mini_installer/mini_file.h" #include "chrome/installer/mini_installer/mini_installer_constants.h" #include "chrome/installer/mini_installer/pe_resource.h" #include "chrome/installer/mini_installer/regkey.h" namespace mini_installer { -namespace { +typedef StackString<MAX_PATH> PathString; // This structure passes data back and forth for the processing // of resource callbacks. struct Context { // Input to the call back method. Specifies the dir to save resources. const wchar_t* base_path; - // First output from call back method; the Chrome archive. - MiniFile& archive; - // Second output from call back method; the Chrome installer. - MiniFile& setup; + // First output from call back method. Full path of Chrome archive. + PathString* chrome_resource_path; + // Second output from call back method. Full path of Setup archive/exe. + PathString* setup_resource_path; // A Windows error code corresponding to an extraction error. DWORD error_code; }; -MiniFile::DeleteOnClose GetDeleteOnCloseOption( - const Configuration& configuration) { - return configuration.should_delete_extracted_files() - ? MiniFile::DeleteOnClose::kYes - : MiniFile::DeleteOnClose::kNo; -} - // TODO(grt): Frame this in terms of whether or not the brand supports // integration with Omaha, where Google Update is the Google-specific fork of // the open-source Omaha project. @@ -178,8 +169,6 @@ return ProcessExitResult(SUCCESS_EXIT_CODE); } -} // namespace - // Gets the path to setup.exe of the previous version. The overall path is found // in the Uninstall string in the registry. A previous version number specified // in |configuration| is used if available. |size| is measured in wchar_t units. @@ -193,8 +182,6 @@ configuration.previous_version(), path, size); } -namespace { - // Calls CreateProcess with good default parameters and waits for the process to // terminate returning the process exit code. In case of CreateProcess failure, // returns a results object with the provided codes as follows: @@ -248,8 +235,6 @@ return ProcessExitResult(exit_code); } -} // namespace - void AppendCommandLineFlags(const wchar_t* command_line, CommandString* buffer) { // The program name (the first argument parsed by CommandLineToArgvW) is @@ -292,15 +277,13 @@ buffer->append(command_line); } -namespace { - // Processes a resource of type |type| in |module| on behalf of a call to // EnumResourceNames. On each call, |name| contains the name of a resource. A // TRUE return value continues the enumeration, whereas FALSE stops it. This // function extracts the first resource starting with "chrome" and/or "setup", // populating |context| (which must be a pointer to a Context struct) with the -// the extracted file(s). Enumeration stops early in case of error, which -// includes any unexpected resources or duplicate matching resources. +// path(s) of the extracted file(s). Enumeration stops early in case of error, +// which includes any unexpected resources or duplicate matching resources. // |context|'s |error_code| member may be populated with a Windows error code // corresponding to an error condition. BOOL CALLBACK OnResourceFound(HMODULE module, @@ -323,16 +306,20 @@ if (!full_path.assign(context.base_path) || !full_path.append(name)) return FALSE; // Break: failed to form the output path. - if (StrStartsWith(name, kChromeArchivePrefix) && !context.archive.IsValid()) { - if (!resource.WriteToDisk(full_path.get(), context.archive)) { + if (StrStartsWith(name, kChromeArchivePrefix) && + context.chrome_resource_path->empty()) { + if (!resource.WriteToDisk(full_path.get())) { context.error_code = ::GetLastError(); return FALSE; // Break: failed to write resource. } - } else if (StrStartsWith(name, kSetupPrefix) && !context.setup.IsValid()) { - if (!resource.WriteToDisk(full_path.get(), context.setup)) { + context.chrome_resource_path->assign(full_path); + } else if (StrStartsWith(name, kSetupPrefix) && + context.setup_resource_path->empty()) { + if (!resource.WriteToDisk(full_path.get())) { context.error_code = ::GetLastError(); return FALSE; // Break: failed to write resource. } + context.setup_resource_path->assign(full_path); } else { // Break: unexpected resource names or multiple {chrome,setup}* resources // are unexpected. @@ -343,41 +330,6 @@ } #if defined(COMPONENT_BUILD) -// Deletes all files in |base_path| (which must have a trailing path separator). -void DeleteAllFilesInDir(const wchar_t* base_path) { - PathString path; - if (!path.assign(base_path)) - return; - - const size_t base_path_length = path.length(); - if (!path.append(L"*")) - return; - - WIN32_FIND_DATA find_data = {}; - HANDLE find_handle = - ::FindFirstFileEx(path.get(), FindExInfoStandard, &find_data, - FindExSearchNameMatch, /*lpSearchFilter=*/nullptr, - /*dwAdditionalFlags=*/0); - if (find_handle == INVALID_HANDLE_VALUE) - return; - - do { - if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - - path.truncate_at(base_path_length); - if (!path.append(*find_data.cAlternateFileName - ? find_data.cAlternateFileName - : find_data.cFileName)) { - continue; - } - - ::DeleteFile(path.get()); - } while (::FindNextFile(find_handle, &find_data)); - - ::FindClose(find_handle); -} - // An EnumResNameProc callback that writes the resource |name| to disk in the // directory |base_path_ptr| (which must end with a path separator). BOOL CALLBACK WriteResourceToDirectory(HMODULE module, @@ -388,10 +340,8 @@ PathString full_path; PEResource resource(name, type, module); - MiniFile file(MiniFile::DeleteOnClose::kNo); return (resource.IsValid() && full_path.assign(base_path) && - full_path.append(name) && - resource.WriteToDisk(full_path.get(), file)); + full_path.append(name) && resource.WriteToDisk(full_path.get())); } #endif @@ -410,8 +360,8 @@ ProcessExitResult UnpackBinaryResources(const Configuration& configuration, HMODULE module, const wchar_t* base_path, - MiniFile& archive, - MiniFile& setup) { + PathString* archive_path, + PathString* setup_path) { // Generate the setup.exe path where we patch/uncompress setup resource. PathString setup_dest_path; if (!setup_dest_path.assign(base_path) || !setup_dest_path.append(kSetupExe)) @@ -419,14 +369,19 @@ // Prepare the input to OnResourceFound method that needs a location where // it will write all the resources. - Context context = {base_path, archive, setup, ERROR_SUCCESS}; + Context context = { + base_path, + archive_path, + setup_path, + ERROR_SUCCESS, + }; // Get the resources of type 'B7' (7zip archive). // We need a chrome archive to do the installation. So if there // is a problem in fetching B7 resource, just return an error. if (!::EnumResourceNames(module, kLZMAResourceType, OnResourceFound, reinterpret_cast<LONG_PTR>(&context)) || - !archive.IsValid()) { + archive_path->empty()) { const DWORD enum_error = ::GetLastError(); return ProcessExitResult(UNABLE_TO_EXTRACT_CHROME_ARCHIVE, enum_error == ERROR_RESOURCE_ENUM_USER_STOP @@ -434,59 +389,45 @@ : enum_error); } - if (!archive.DropWritePermission()) - return {DROP_WRITE_ON_EXTRACTED_ARCHIVE_FAILED, ::GetLastError()}; + ProcessExitResult exit_code = ProcessExitResult(SUCCESS_EXIT_CODE); // If we found setup 'B7' resource (used for differential updates), handle // it. Note that this is only for Chrome; Chromium installs are always // "full" installs. - if (setup.IsValid()) { - if (!setup.DropWritePermission()) - return {DROP_WRITE_ON_EXTRACTED_SETUP_PATCH_FAILED, ::GetLastError()}; - + if (!setup_path->empty()) { CommandString cmd_line; PathString exe_path; // Get the path to setup.exe first. - auto exit_code = GetPreviousSetupExePath(configuration, exe_path.get(), - exe_path.capacity()); - if (!exit_code.IsSuccess()) - return exit_code; - - if (!cmd_line.append(L"\"") || !cmd_line.append(exe_path.get()) || - !cmd_line.append(L"\" --") || !cmd_line.append(kCmdUpdateSetupExe) || - !cmd_line.append(L"=\"") || !cmd_line.append(setup.path()) || - !cmd_line.append(L"\" --") || !cmd_line.append(kCmdNewSetupExe) || - !cmd_line.append(L"=\"") || !cmd_line.append(setup_dest_path.get()) || - !cmd_line.append(L"\"")) { - return ProcessExitResult(COMMAND_STRING_OVERFLOW); + exit_code = GetPreviousSetupExePath(configuration, exe_path.get(), + exe_path.capacity()); + if (exit_code.IsSuccess()) { + if (!cmd_line.append(L"\"") || !cmd_line.append(exe_path.get()) || + !cmd_line.append(L"\" --") || !cmd_line.append(kCmdUpdateSetupExe) || + !cmd_line.append(L"=\"") || !cmd_line.append(setup_path->get()) || + !cmd_line.append(L"\" --") || !cmd_line.append(kCmdNewSetupExe) || + !cmd_line.append(L"=\"") || !cmd_line.append(setup_dest_path.get()) || + !cmd_line.append(L"\"")) { + exit_code = ProcessExitResult(COMMAND_STRING_OVERFLOW); + } } // Get any command line option specified for mini_installer and pass them // on to setup.exe. AppendCommandLineFlags(configuration.command_line(), &cmd_line); - exit_code = RunProcessAndWait(exe_path.get(), cmd_line.get(), - SETUP_PATCH_FAILED_FILE_NOT_FOUND, - SETUP_PATCH_FAILED_PATH_NOT_FOUND, - SETUP_PATCH_FAILED_COULD_NOT_CREATE_PROCESS); - - // The setup patch file is no longer needed. - setup.Close(); - - if (!exit_code.IsSuccess()) - return exit_code; - - // Open the destination file (with delete-on-close) so that it will be - // deleted at process exit. - if (!setup.Open(setup_dest_path)) { - // Try to delete the file if it could not be opened. - const DWORD open_error = ::GetLastError(); - if (configuration.should_delete_extracted_files()) - ::DeleteFile(setup_dest_path.get()); - return {UNABLE_TO_OPEN_PATCHED_SETUP, open_error}; + if (exit_code.IsSuccess()) { + exit_code = RunProcessAndWait( + exe_path.get(), cmd_line.get(), SETUP_PATCH_FAILED_FILE_NOT_FOUND, + SETUP_PATCH_FAILED_PATH_NOT_FOUND, + SETUP_PATCH_FAILED_COULD_NOT_CREATE_PROCESS); } - return ProcessExitResult(SUCCESS_EXIT_CODE); + if (!exit_code.IsSuccess()) + DeleteFile(setup_path->get()); + else + setup_path->assign(setup_dest_path); + + return exit_code; } // setup.exe wasn't sent as 'B7', lets see if it was sent as 'BL' @@ -494,8 +435,7 @@ context.error_code = ERROR_SUCCESS; if (!::EnumResourceNames(module, kLZCResourceType, OnResourceFound, reinterpret_cast<LONG_PTR>(&context)) || - !setup.IsValid()) { - // Neither setup_patch.packed.7z nor setup.ex_ could be extracted. + setup_path->empty()) { const DWORD enum_error = ::GetLastError(); return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, enum_error == ERROR_RESOURCE_ENUM_USER_STOP @@ -503,29 +443,27 @@ : enum_error); } - if (!setup.DropWritePermission()) - return {DROP_WRITE_ON_EXTRACTED_SETUP_FAILED, ::GetLastError()}; - // Uncompress LZ compressed resource. Setup is packed with 'MSCF' // as opposed to old DOS way of 'SZDD'. Hence we don't use LZCopy. - MiniFile setup_dest(GetDeleteOnCloseOption(configuration)); - mini_installer::Expand(setup.path(), setup_dest_path.get(), setup_dest); - setup = std::move(setup_dest); - - if (!setup.IsValid()) - return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_EXE); - if (!setup.DropWritePermission()) - return {DROP_WRITE_ON_EXPANDED_SETUP_FAILED, ::GetLastError()}; + bool success = + mini_installer::Expand(setup_path->get(), setup_dest_path.get()); + ::DeleteFile(setup_path->get()); + if (success) + setup_path->assign(setup_dest_path); + else + exit_code = ProcessExitResult(UNABLE_TO_EXTRACT_SETUP_EXE); #if defined(COMPONENT_BUILD) - // Extract the modules in component build required by setup.exe. - if (!::EnumResourceNames(module, kBinResourceType, WriteResourceToDirectory, - reinterpret_cast<LONG_PTR>(base_path))) { - return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, ::GetLastError()); + if (exit_code.IsSuccess()) { + // Extract the modules in component build required by setup.exe. + if (!::EnumResourceNames(module, kBinResourceType, WriteResourceToDirectory, + reinterpret_cast<LONG_PTR>(base_path))) { + return ProcessExitResult(UNABLE_TO_EXTRACT_SETUP, ::GetLastError()); + } } #endif - return ProcessExitResult(SUCCESS_EXIT_CODE); + return exit_code; } // Executes setup.exe, waits for it to finish and returns the exit code. @@ -587,6 +525,16 @@ RUN_SETUP_FAILED_COULD_NOT_CREATE_PROCESS); } +// Deletes given files and working dir. +void DeleteExtractedFiles(const wchar_t* base_path, + const wchar_t* archive_path, + const wchar_t* setup_path) { + ::DeleteFile(archive_path); + ::DeleteFile(setup_path); + // Delete the temp dir (if it is empty, otherwise fail). + ::RemoveDirectory(base_path); +} + // Returns true if the supplied path supports ACLs. bool IsAclSupportedForPath(const wchar_t* path) { PathString volume; @@ -881,8 +829,6 @@ } } -} // namespace - ProcessExitResult WMain(HMODULE module) { // Always start with deleting potential leftovers from previous installations. // This can make the difference between success and failure. We've seen @@ -921,10 +867,10 @@ SetInstallerFlags(configuration); #endif - MiniFile archive(GetDeleteOnCloseOption(configuration)); - MiniFile setup(GetDeleteOnCloseOption(configuration)); + PathString archive_path; + PathString setup_path; exit_code = UnpackBinaryResources(configuration, module, base_path.get(), - archive, setup); + &archive_path, &setup_path); // While unpacking the binaries, we paged in a whole bunch of memory that // we don't need anymore. Let's give it back to the pool before running @@ -932,22 +878,10 @@ ::SetProcessWorkingSetSize(::GetCurrentProcess(), (SIZE_T)-1, (SIZE_T)-1); if (exit_code.IsSuccess()) - exit_code = RunSetup(configuration, archive.path(), setup.path()); + exit_code = RunSetup(configuration, archive_path.get(), setup_path.get()); - // Closing the files will delete them if should_delete_extracted_files is - // true (the normal case). - archive.Close(); - setup.Close(); - -#if defined(COMPONENT_BUILD) - // |base_path| is full of component DLLs in this case, which are not held - // open for delete-on-close. Manually delete everything in the directory. if (configuration.should_delete_extracted_files()) - DeleteAllFilesInDir(base_path.get()); -#endif - - // Delete the temp dir (if it is empty, otherwise fail). - ::RemoveDirectory(base_path.get()); + DeleteExtractedFiles(base_path.get(), archive_path.get(), setup_path.get()); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) WriteInstallResults(configuration, exit_code);
diff --git a/chrome/installer/mini_installer/pe_resource.cc b/chrome/installer/mini_installer/pe_resource.cc index 65a06a0..7dcd02b5e 100644 --- a/chrome/installer/mini_installer/pe_resource.cc +++ b/chrome/installer/mini_installer/pe_resource.cc
@@ -8,8 +8,6 @@ #include "chrome/installer/mini_installer/mini_file.h" -namespace mini_installer { - PEResource::PEResource(HRSRC resource, HMODULE module) : resource_(resource), module_(module) {} @@ -26,43 +24,42 @@ return ::SizeofResource(module_, resource_); } -bool PEResource::WriteToDisk(const wchar_t* full_path, MiniFile& file) { +bool PEResource::WriteToDisk(const wchar_t* full_path) { // Resource handles are not real HGLOBALs so do not attempt to close them. // Resources are freed when the containing module is unloaded. HGLOBAL data_handle = ::LoadResource(module_, resource_); - if (!data_handle) + if (nullptr == data_handle) return false; const char* data = reinterpret_cast<const char*>(::LockResource(data_handle)); - if (!data) + if (nullptr == data) return false; + mini_installer::MiniFile file; if (!file.Create(full_path)) return false; // Don't write all of the data at once because this can lead to kernel // address-space exhaustion on 32-bit Windows (see https://crbug.com/1001022 // for details). - constexpr DWORD kMaxWriteAmount = 8 * 1024 * 1024; - const DWORD resource_size = Size(); - for (DWORD total_written = 0; total_written < resource_size; /**/) { - const DWORD write_amount = + constexpr size_t kMaxWriteAmount = 8 * 1024 * 1024; + const size_t resource_size = Size(); + for (size_t total_written = 0; total_written < resource_size; /**/) { + const size_t write_amount = std::min(kMaxWriteAmount, resource_size - total_written); DWORD written = 0; - if (!::WriteFile(file.GetHandleUnsafe(), data + total_written, write_amount, - &written, nullptr)) { + if (!::WriteFile(file.GetHandleUnsafe(), data + total_written, + static_cast<DWORD>(write_amount), &written, nullptr)) { const auto write_error = ::GetLastError(); // Delete the file since the write failed. + file.DeleteOnClose(); file.Close(); ::SetLastError(write_error); return false; } - total_written += written; + total_written += write_amount; } - return true; } - -} // namespace mini_installer
diff --git a/chrome/installer/mini_installer/pe_resource.h b/chrome/installer/mini_installer/pe_resource.h index f5e5764..1e61195 100644 --- a/chrome/installer/mini_installer/pe_resource.h +++ b/chrome/installer/mini_installer/pe_resource.h
@@ -9,10 +9,6 @@ #include <stddef.h> -namespace mini_installer { - -class MiniFile; - // This class models a windows PE resource. It does not pretend to be a full // API wrapper and it is just concerned with loading it to memory and writing // it to disk. Each resource is unique only in the context of a loaded module, @@ -34,17 +30,14 @@ // not valid. size_t Size(); - // Writes the resource to the file |path|. Returns true on success, in which - // case |file| holds an open handle to the destination file. |file| will be - // opened with exclusive write access and shared read and delete access, and - // will be marked as delete-on-close. - bool WriteToDisk(const wchar_t* path, MiniFile& file); + // Creates a file in 'path' with a copy of the resource. If the resource can + // not be loaded into memory or if it cannot be written to disk it returns + // false. + bool WriteToDisk(const wchar_t* path); private: HRSRC resource_; HMODULE module_; }; -} // namespace mini_installer - #endif // CHROME_INSTALLER_MINI_INSTALLER_PE_RESOURCE_H_
diff --git a/chrome/installer/mini_installer/pe_resource_test.cc b/chrome/installer/mini_installer/pe_resource_test.cc deleted file mode 100644 index b766308..0000000 --- a/chrome/installer/mini_installer/pe_resource_test.cc +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/installer/mini_installer/pe_resource.h" - -#include <windows.h> - -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "chrome/installer/mini_installer/mini_file.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mini_installer { - -TEST(PEResourceTest, WriteToDisk) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - const base::FilePath manifest_path = - temp_dir.GetPath().Append(FILE_PATH_LITERAL("manifest")); - - PEResource manifest(MAKEINTRESOURCE(1), RT_MANIFEST, - ::GetModuleHandle(nullptr)); - ASSERT_TRUE(manifest.IsValid()); - - MiniFile manifest_file(MiniFile::DeleteOnClose::kYes); - ASSERT_TRUE( - manifest.WriteToDisk(manifest_path.value().c_str(), manifest_file)); - - ASSERT_TRUE(manifest_file.IsValid()); - EXPECT_PRED1(base::PathExists, manifest_path); - - manifest_file.Close(); - EXPECT_FALSE(base::PathExists(manifest_path)); - - EXPECT_TRUE(temp_dir.Delete()); -} - -} // namespace mini_installer
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc index e008a4f..cbd019d 100644 --- a/chrome/services/sharing/nearby/nearby_connections.cc +++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -13,6 +13,65 @@ namespace nearby { namespace connections { +namespace { + +ConnectionRequestInfo CreateConnectionRequestInfo( + const std::vector<uint8_t>& endpoint_info, + mojo::PendingRemote<mojom::ConnectionLifecycleListener> listener) { + mojo::SharedRemote<mojom::ConnectionLifecycleListener> remote( + std::move(listener)); + return ConnectionRequestInfo{ + .name = std::string(endpoint_info.begin(), endpoint_info.end()), + .listener = { + .initiated_cb = + [remote](const std::string& endpoint_id, + const ConnectionResponseInfo& info) { + if (!remote) + return; + + remote->OnConnectionInitiated( + endpoint_id, + mojom::ConnectionInfo::New( + info.authentication_token, + ByteArrayToMojom(info.raw_authentication_token), + ByteArrayToMojom(info.endpoint_info), + info.is_incoming_connection)); + }, + .accepted_cb = + [remote](const std::string& endpoint_id) { + if (!remote) + return; + + remote->OnConnectionAccepted(endpoint_id); + }, + .rejected_cb = + [remote](const std::string& endpoint_id, Status status) { + if (!remote) + return; + + remote->OnConnectionRejected(endpoint_id, + StatusToMojom(status.value)); + }, + .disconnected_cb = + [remote](const std::string& endpoint_id) { + if (!remote) + return; + + remote->OnDisconnected(endpoint_id); + }, + .bandwidth_changed_cb = + [remote](const std::string& endpoint_id, std::int32_t quality) { + if (!remote) + return; + + remote->OnBandwidthChanged(endpoint_id, quality); + }, + }, + }; +} + +} // namespace + // Should only be accessed by objects within lifetime of NearbyConnections. NearbyConnections* g_instance = nullptr; @@ -128,6 +187,34 @@ return webrtc_signaling_messenger_.get(); } +void NearbyConnections::StartAdvertising( + const std::vector<uint8_t>& endpoint_info, + const std::string& service_id, + mojom::AdvertisingOptionsPtr options, + mojo::PendingRemote<mojom::ConnectionLifecycleListener> listener, + StartAdvertisingCallback callback) { + BooleanMediumSelector allowed_mediums = { + .bluetooth = options->allowed_mediums->bluetooth, + .web_rtc = options->allowed_mediums->web_rtc, + .wifi_lan = options->allowed_mediums->wifi_lan, + }; + ConnectionOptions connection_options{ + .strategy = StrategyFromMojom(options->strategy), + .allowed = std::move(allowed_mediums), + .auto_upgrade_bandwidth = options->auto_upgrade_bandwidth, + .enforce_topology_constraints = options->enforce_topology_constraints, + }; + + core_->StartAdvertising( + service_id, std::move(connection_options), + CreateConnectionRequestInfo(endpoint_info, std::move(listener)), + ResultCallbackFromMojom(std::move(callback))); +} + +void NearbyConnections::StopAdvertising(StopAdvertisingCallback callback) { + core_->StopAdvertising(ResultCallbackFromMojom(std::move(callback))); +} + void NearbyConnections::StartDiscovery( const std::string& service_id, mojom::DiscoveryOptionsPtr options, @@ -176,59 +263,10 @@ const std::string& endpoint_id, mojo::PendingRemote<mojom::ConnectionLifecycleListener> listener, RequestConnectionCallback callback) { - mojo::SharedRemote<mojom::ConnectionLifecycleListener> remote( - std::move(listener)); - ConnectionRequestInfo connection_request_info{ - .name = std::string(endpoint_info.begin(), endpoint_info.end()), - .listener = { - .initiated_cb = - [remote](const std::string& endpoint_id, - const ConnectionResponseInfo& info) { - if (!remote) - return; - - remote->OnConnectionInitiated( - endpoint_id, - mojom::ConnectionInfo::New( - info.authentication_token, - ByteArrayToMojom(info.raw_authentication_token), - ByteArrayToMojom(info.endpoint_info), - info.is_incoming_connection)); - }, - .accepted_cb = - [remote](const std::string& endpoint_id) { - if (!remote) - return; - - remote->OnConnectionAccepted(endpoint_id); - }, - .rejected_cb = - [remote](const std::string& endpoint_id, Status status) { - if (!remote) - return; - - remote->OnConnectionRejected(endpoint_id, - StatusToMojom(status.value)); - }, - .disconnected_cb = - [remote](const std::string& endpoint_id) { - if (!remote) - return; - - remote->OnDisconnected(endpoint_id); - }, - .bandwidth_changed_cb = - [remote](const std::string& endpoint_id, std::int32_t quality) { - if (!remote) - return; - - remote->OnBandwidthChanged(endpoint_id, quality); - }, - }}; - ResultCallback result_callback = ResultCallbackFromMojom(std::move(callback)); - - core_->RequestConnection(endpoint_id, std::move(connection_request_info), - std::move(result_callback)); + core_->RequestConnection( + endpoint_id, + CreateConnectionRequestInfo(endpoint_info, std::move(listener)), + ResultCallbackFromMojom(std::move(callback))); } void NearbyConnections::DisconnectFromEndpoint(
diff --git a/chrome/services/sharing/nearby/nearby_connections.h b/chrome/services/sharing/nearby/nearby_connections.h index ca16924..39fc82a 100644 --- a/chrome/services/sharing/nearby/nearby_connections.h +++ b/chrome/services/sharing/nearby/nearby_connections.h
@@ -58,6 +58,13 @@ sharing::mojom::WebRtcSignalingMessenger* GetWebRtcSignalingMessenger(); // mojom::NearbyConnections: + void StartAdvertising( + const std::vector<uint8_t>& endpoint_info, + const std::string& service_id, + mojom::AdvertisingOptionsPtr options, + mojo::PendingRemote<mojom::ConnectionLifecycleListener> listener, + StartAdvertisingCallback callback) override; + void StopAdvertising(StopAdvertisingCallback callback) override; void StartDiscovery( const std::string& service_id, mojom::DiscoveryOptionsPtr options,
diff --git a/chrome/services/sharing/nearby/nearby_connections_unittest.cc b/chrome/services/sharing/nearby/nearby_connections_unittest.cc index f868a22..36c1095 100644 --- a/chrome/services/sharing/nearby/nearby_connections_unittest.cc +++ b/chrome/services/sharing/nearby/nearby_connections_unittest.cc
@@ -38,6 +38,16 @@ const char kRawAuthenticationToken[] = {0x00, 0x05, 0x04, 0x03, 0x02}; const int32_t kQuality = 5201314; +mojom::AdvertisingOptionsPtr CreateAdvertisingOptions() { + auto allowed_mediums = mojom::MediumSelection::New(/*bluetooth=*/true, + /*web_rtc=*/true, + /*wifi_lan=*/true); + return mojom::AdvertisingOptions::New(mojom::Strategy::kP2pPointToPoint, + std::move(allowed_mediums), + /*auto_upgrade_bandwidth=*/true, + /*enforce_topology_constraints=*/true); +} + } // namespace class FakeEndpointDiscoveryListener : public mojom::EndpointDiscoveryListener { @@ -406,6 +416,139 @@ EXPECT_CALL(*service_controller_ptr_, DisconnectFromEndpoint).Times(1); } +TEST_F(NearbyConnectionsTest, StartAdvertising) { + FakeConnectionLifecycleListener fake_connection_life_cycle_listener; + ClientProxy* client_proxy; + ConnectionListener connections_listener; + + EXPECT_CALL(*service_controller_ptr_, StartAdvertising) + .WillOnce([&](ClientProxy* client, const std::string& service_id, + const ConnectionOptions& options, + const ConnectionRequestInfo& info) { + EXPECT_EQ(kServiceId, service_id); + EXPECT_EQ(Strategy::kP2pPointToPoint, options.strategy); + EXPECT_TRUE(options.allowed.bluetooth); + EXPECT_TRUE(options.allowed.web_rtc); + EXPECT_TRUE(options.allowed.wifi_lan); + EXPECT_TRUE(options.auto_upgrade_bandwidth); + EXPECT_TRUE(options.enforce_topology_constraints); + EXPECT_EQ( + std::string(std::begin(kEndpointInfo), std::end(kEndpointInfo)), + info.name); + + client_proxy = client; + connections_listener = info.listener; + + return Status{Status::kSuccess}; + }); + + base::RunLoop start_advertising_run_loop; + nearby_connections_->StartAdvertising( + std::vector<uint8_t>(std::begin(kEndpointInfo), std::end(kEndpointInfo)), + kServiceId, CreateAdvertisingOptions(), + fake_connection_life_cycle_listener.receiver.BindNewPipeAndPassRemote(), + base::BindLambdaForTesting([&](mojom::Status status) { + EXPECT_EQ(mojom::Status::kSuccess, status); + start_advertising_run_loop.Quit(); + })); + start_advertising_run_loop.Run(); + + base::RunLoop initiated_run_loop; + fake_connection_life_cycle_listener.initiated_cb = base::BindLambdaForTesting( + [&](const std::string& endpoint_id, mojom::ConnectionInfoPtr info) { + EXPECT_EQ(kRemoteEndpointId, endpoint_id); + EXPECT_EQ(kAuthenticationToken, info->authentication_token); + EXPECT_EQ(std::vector<uint8_t>(std::begin(kRawAuthenticationToken), + std::end(kRawAuthenticationToken)), + info->raw_authentication_token); + EXPECT_EQ(std::vector<uint8_t>(std::begin(kRemoteEndpointInfo), + std::end(kRemoteEndpointInfo)), + info->endpoint_info); + EXPECT_FALSE(info->is_incoming_connection); + initiated_run_loop.Quit(); + }); + client_proxy->OnConnectionInitiated( + kRemoteEndpointId, + {.authentication_token = kAuthenticationToken, + .raw_authentication_token = + ByteArray(kRawAuthenticationToken, sizeof(kRawAuthenticationToken)), + .endpoint_info = + ByteArray(kRemoteEndpointInfo, sizeof(kRemoteEndpointInfo)), + .is_incoming_connection = false}, + connections_listener); + initiated_run_loop.Run(); + + base::RunLoop rejected_run_loop; + fake_connection_life_cycle_listener.rejected_cb = base::BindLambdaForTesting( + [&](const std::string& endpoint_id, mojom::Status status) { + EXPECT_EQ(kRemoteEndpointId, endpoint_id); + EXPECT_EQ(mojom::Status::kConnectionRejected, status); + rejected_run_loop.Quit(); + }); + client_proxy->OnConnectionRejected(kRemoteEndpointId, + {Status::kConnectionRejected}); + rejected_run_loop.Run(); + + // Initiate connection again to test accepted flow. + base::RunLoop initiated_run_loop_2; + fake_connection_life_cycle_listener.initiated_cb = base::BindLambdaForTesting( + [&](const std::string& endpoint_id, mojom::ConnectionInfoPtr info) { + EXPECT_EQ(kRemoteEndpointId, endpoint_id); + EXPECT_FALSE(info->is_incoming_connection); + initiated_run_loop_2.Quit(); + }); + client_proxy->OnConnectionInitiated(kRemoteEndpointId, + {.is_incoming_connection = false}, + connections_listener); + initiated_run_loop_2.Run(); + + base::RunLoop accepted_run_loop; + fake_connection_life_cycle_listener.accepted_cb = + base::BindLambdaForTesting([&](const std::string& endpoint_id) { + EXPECT_EQ(kRemoteEndpointId, endpoint_id); + accepted_run_loop.Quit(); + }); + client_proxy->OnConnectionAccepted(kRemoteEndpointId); + accepted_run_loop.Run(); +} + +TEST_F(NearbyConnectionsTest, StopAdvertising) { + FakeConnectionLifecycleListener fake_connection_life_cycle_listener; + + EXPECT_CALL(*service_controller_ptr_, StartAdvertising) + .WillOnce([](ClientProxy* client, const std::string& service_id, + const ConnectionOptions& options, + const ConnectionRequestInfo& info) { + client->StartedAdvertising(service_id, options.strategy, info.listener, + /*mediums=*/{}); + return Status{Status::kSuccess}; + }); + + base::RunLoop start_advertising_run_loop; + nearby_connections_->StartAdvertising( + std::vector<uint8_t>(std::begin(kEndpointInfo), std::end(kEndpointInfo)), + kServiceId, CreateAdvertisingOptions(), mojo::NullRemote(), + base::BindLambdaForTesting([&](mojom::Status status) { + EXPECT_EQ(mojom::Status::kSuccess, status); + start_advertising_run_loop.Quit(); + })); + start_advertising_run_loop.Run(); + + EXPECT_CALL(*service_controller_ptr_, StopAdvertising) + .WillOnce([](ClientProxy* client) { client->StoppedAdvertising(); }); + + base::RunLoop stop_advertising_run_loop; + nearby_connections_->StopAdvertising( + base::BindLambdaForTesting([&](mojom::Status status) { + EXPECT_EQ(mojom::Status::kSuccess, status); + stop_advertising_run_loop.Quit(); + })); + stop_advertising_run_loop.Run(); + + // Expect one more call during shutdown. + EXPECT_CALL(*service_controller_ptr_, StopAdvertising); +} + } // namespace connections } // namespace nearby } // namespace location
diff --git a/chrome/services/sharing/public/mojom/nearby_connections.mojom b/chrome/services/sharing/public/mojom/nearby_connections.mojom index ac9379d..dcc010e 100644 --- a/chrome/services/sharing/public/mojom/nearby_connections.mojom +++ b/chrome/services/sharing/public/mojom/nearby_connections.mojom
@@ -97,12 +97,45 @@ // packets is not part of the NearbyConnections library and is done in a // separate interface. interface NearbyConnections { + // Starts advertising an endpoint with the specified service ID. Only one + // advertisement can be active at a time and calling StartAdvertising() while + // advertising will fail and return Status::kAlreadyAdvertising. + // + // endpoint_info - The local info to be broadcasted. May contain a human + // readable name to appear on other devices if broadcasting + // in high visibility mode. + // service_id - An identifier to advertise your app to other endpoints. + // This can be an arbitrary string, so long as it uniquely + // identifies your service. A good default is to use your + // app's package name. + // options - The options for advertising. + // listener - An interface notified when remote endpoints request a + // connection to this endpoint. + // Possible return values include: + // Status::kSuccess if advertising started successfully. + // Status::kAlreadyAdvertising if the app is already advertising. + // Status::kOutOfOrderApiCall if the app is currently connected to remote + // endpoints; call StopAllEndpoints first. + StartAdvertising(array<uint8> endpoint_info, string service_id, + AdvertisingOptions options, + pending_remote<ConnectionLifecycleListener> listener) + => (Status status); + + // Stops advertising the local endpoint. Should be called after calling + // StartAdvertising, as soon as the application no longer needs to advertise + // itself or goes inactive. Payloads can still be sent to connected + // endpoints after advertising ends. + // + // Possible return values include: + // Status::kSuccess returned after advertising got stopped. + StopAdvertising() => (Status status); + // Starts discovery for remote endpoints with the specified service ID. // // service_id - The ID for the service to be discovered, as specified in // the corresponding call to StartAdvertising. // options - The options for discovery. - // listener - A callback notified when a remote endpoint is discovered. + // listener - An interface notified when a remote endpoint is discovered. // Possible status codes include: // Status::kSuccess if discovery started successfully. // Status::kAlreadyDiscovering if the app is already @@ -130,7 +163,7 @@ // connection request will be sent. Should match the value // provided in a call to // EndpointDiscoveryListener::OnEndpointFound(). - // listener - A callback notified when the remote endpoint sends a + // listener - An interface notified when the remote endpoint sends a // response to the connection request. // Possible return values include: // Status::kSuccess if the connection request was sent.
diff --git a/chrome/services/sharing/public/mojom/nearby_connections_types.mojom b/chrome/services/sharing/public/mojom/nearby_connections_types.mojom index d8bf472..fbc4d66 100644 --- a/chrome/services/sharing/public/mojom/nearby_connections_types.mojom +++ b/chrome/services/sharing/public/mojom/nearby_connections_types.mojom
@@ -99,11 +99,25 @@ kP2pPointToPoint, }; +// A selection of on/off toggles to define a set of allowed mediums. +struct MediumSelection { + // Whether Bluetooth should be allowed. + bool bluetooth; + // Whether WebRTC should be allowed. + bool web_rtc; + // Whether WiFi LAN should be allowed. + bool wifi_lan; +}; + // Options for a call to NearbyConnections::StartAdvertising(). struct AdvertisingOptions { // The strategy to use for advertising. Must match the strategy used in // DiscoveryOptions for remote devices to see this advertisement. Strategy strategy; + // Describes which mediums are allowed to be used for advertising. Note that + // allowing an otherwise unsupported medium is ok. Only the intersection of + // allowed and supported mediums will be used to advertise. + MediumSelection allowed_mediums; // By default, this option is true. If false, we will not attempt to upgrade // the bandwidth until a call to InitiateBandwidthUpgrade() is made. bool auto_upgrade_bandwidth = true;
diff --git a/chrome/test/data/hats/hats_next_mock.html b/chrome/test/data/hats/hats_next_mock.html index fd60fe2..0883c853 100644 --- a/chrome/test/data/hats/hats_next_mock.html +++ b/chrome/test/data/hats/hats_next_mock.html
@@ -15,6 +15,11 @@ if (params.get('trigger_id') == "invalid_url_fragment_for_testing") { history.pushState('', '', '#foo'); } + + if (params.get('trigger_id') == "open_new_web_contents_for_testing"){ + window.open('http://foo.com', '_blank'); + history.pushState('', '', '#loaded'); + } </script> </head> <body>
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js index 15ce5b03..0a9058b2 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js +++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_browsertest.js
@@ -9,6 +9,13 @@ GEN('#include "content/public/test/browser_test.h"'); +// Tests are flaky on ChromeOS, debug (crbug.com/1114675). +GEN('#if defined(OS_CHROMEOS) && !defined(NDEBUG)'); +GEN('#define MAYBE_All DISABLED_All'); +GEN('#else'); +GEN('#define MAYBE_All All'); +GEN('#endif'); + // Polymer 2 test list format: // // ['ModuleNameTest', 'module.js', @@ -39,7 +46,7 @@ this[className] = class extends PolymerTest { /** @override */ get browsePreload() { - return `chrome://os-settings/test_loader.html?module=settings/chromeos/${module}`; + return `chrome://os-settings/test_loader.html?module=cr_components/chromeos/${module}`; } /** @override */ @@ -48,5 +55,5 @@ } }; - TEST_F(className, 'All', () => mocha.run()); + TEST_F(className, 'MAYBE_All', () => mocha.run()); }
diff --git a/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.js b/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.js index 0a9875d..1d63e60a 100644 --- a/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.js
@@ -5,7 +5,7 @@ // clang-format off // #import 'chrome://os-settings/chromeos/os_settings.js'; -// #import {AmbientModeBrowserProxyImpl, CrSettingsPrefs} from 'chrome://os-settings/chromeos/os_settings.js'; +// #import {AmbientModeTopicSource, AmbientModeTemperatureUnit, AmbientModeBrowserProxyImpl, CrSettingsPrefs, Router} from 'chrome://os-settings/chromeos/os_settings.js'; // #import {TestBrowserProxy} from '../../test_browser_proxy.m.js'; // #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -17,16 +17,17 @@ class TestAmbientModeBrowserProxy extends TestBrowserProxy { constructor() { super([ - 'requestTopicSource', + 'requestSettings', 'requestAlbums', + 'setSelectedTemperatureUnit', 'setSelectedTopicSource', 'setSelectedAlbums', ]); } /** @override */ - requestTopicSource() { - this.methodCalled('requestTopicSource'); + requestSettings() { + this.methodCalled('requestSettings'); } /** @override */ @@ -35,6 +36,11 @@ } /** @override */ + setSelectedTemperatureUnit(temperatureUnit) { + this.methodCalled('setSelectedTemperatureUnit', [temperatureUnit]); + } + + /** @override */ setSelectedTopicSource(topicSource) { this.methodCalled('setSelectedTopicSource', [topicSource]); } @@ -115,6 +121,34 @@ assertEquals(enabled, enabled_toggled_twice); }); + test('doubleClickTopicSource', () => { + // Select the google photos topic source. + cr.webUIListenerCallback( + 'topic-source-changed', AmbientModeTopicSource.GOOGLE_PHOTOS); + + const topicSourceList = ambientModePage.$$('topic-source-list'); + const ironList = topicSourceList.$$('iron-list'); + const topicSourceItem = + ironList.querySelector('topic-source-item[checked]'); + const clickableDiv = topicSourceItem.$$('#rowContainer'); + + // Verify that the show-albums event is sent when the google photos radio + // button is clicked again. + let showAlbumEventCalls = 0; + topicSourceList.addEventListener('show-albums', (event) => { + assertEquals(AmbientModeTopicSource.GOOGLE_PHOTOS, event.detail); + showAlbumEventCalls++; + }); + + clickableDiv.click(); + assertEquals(1, showAlbumEventCalls); + + // Should navigate to the ambient-mode/photos?topic-source=0 subpage. + const router = settings.Router.getInstance(); + assertEquals('/ambientMode/photos', router.getCurrentRoute().path); + assertEquals('topicSource=0', router.getQueryParameters().toString()); + }); + test('hasTopicSourceItems', function() { const topicSourceListElement = ambientModePage.$$('topic-source-list'); const ironList = topicSourceListElement.$$('iron-list'); @@ -142,4 +176,77 @@ assertFalse(checkbox1.checked); assertEquals('album1', checkbox1.label); }); + + test('temperatureUnitRadioButtonsDisabled', () => { + // When |selectedTemperatureUnit_| is invalid the radio buttons should be + // disabled. This is the initial state. + const radioGroup = ambientModePage.$$('#weatherDiv cr-radio-group'); + + assertTrue(radioGroup.disabled); + + // When |selectedTemperatureUnit_| is valid the radio buttons should be + // enabled. + cr.webUIListenerCallback( + 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); + assertFalse(radioGroup.disabled); + + cr.webUIListenerCallback( + 'temperature-unit-changed', AmbientModeTemperatureUnit.UNKNOWN); + assertTrue(radioGroup.disabled); + }); + + test('temperatureUnitRadioButtons', async () => { + // Simulate C++ setting celsius as the initial temperature unit. + cr.webUIListenerCallback( + 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); + + const celsiusButton = ambientModePage.$$('cr-radio-button[name=celsius]'); + const fahrenheitButton = + ambientModePage.$$('cr-radio-button[name=fahrenheit]'); + + assertTrue(celsiusButton.checked); + assertFalse(fahrenheitButton.checked); + + browserProxy.resetResolver('setSelectedTemperatureUnit'); + + // Click fahrenheit and expect the fahrenheit radio button to be checked and + // the browser proxy to be called with the correct argument. + fahrenheitButton.click(); + + assertFalse(celsiusButton.checked); + assertTrue(fahrenheitButton.checked); + + assertEquals(1, browserProxy.getCallCount('setSelectedTemperatureUnit')); + const fahrenheitArgs = + await browserProxy.whenCalled('setSelectedTemperatureUnit'); + assertDeepEquals(['fahrenheit'], fahrenheitArgs); + + browserProxy.resetResolver('setSelectedTemperatureUnit'); + + // Click celsius and expect the celsius radio button to be checked and the + // browser proxy to be called with the correct argument. + celsiusButton.click(); + + assertTrue(celsiusButton.checked); + assertFalse(fahrenheitButton.checked); + + assertEquals(1, browserProxy.getCallCount('setSelectedTemperatureUnit')); + const celsiusArgs = + await browserProxy.whenCalled('setSelectedTemperatureUnit'); + assertDeepEquals(['celsius'], celsiusArgs); + }); + + test('temperatureUnitRadioButtonsDoubleClick', async () => { + // Simulate C++ setting celsius as the default temperature unit. + cr.webUIListenerCallback( + 'temperature-unit-changed', AmbientModeTemperatureUnit.CELSIUS); + + const celsiusButton = ambientModePage.$$('cr-radio-button[name=celsius]'); + + browserProxy.resetResolver('setSelectedTemperatureUnit'); + + // Nothing should happen. + celsiusButton.click(); + assertEquals(0, browserProxy.getCallCount('setSelectedTemperatureUnit')); + }); });
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index c8c157d..2913bd2 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -127,13 +127,6 @@ "service/cast_service_simple.h", "service_connector.cc", "service_connector.h", - "tts/tts_controller.h", - "tts/tts_controller_impl.cc", - "tts/tts_controller_impl.h", - "tts/tts_platform.cc", - "tts/tts_platform.h", - "tts/tts_platform_stub.cc", - "tts/tts_platform_stub.h", "webui/cast_resource_data_source.cc", "webui/cast_resource_data_source.h", "webui/cast_webui.cc",
diff --git a/chromecast/browser/DEPS b/chromecast/browser/DEPS index 119c5d9..92a7011 100644 --- a/chromecast/browser/DEPS +++ b/chromecast/browser/DEPS
@@ -65,7 +65,7 @@ "+third_party/blink/public/mojom/loader/resource_load_info.mojom.h", "+third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h", "+third_party/blink/public/mojom/messaging", - "+third_party/blink/public/mojom/speech/speech_synthesis.mojom-forward.h", + "+third_party/blink/public/mojom/speech/speech_synthesis.mojom.h", "+third_party/skia/include/core/SkColor.h", "+ui/accessibility", "+ui/aura",
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc index c3458d39..9df36b1d 100644 --- a/chromecast/browser/cast_browser_main_parts.cc +++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -44,8 +44,6 @@ #include "chromecast/browser/media/media_caps_impl.h" #include "chromecast/browser/metrics/cast_browser_metrics.h" #include "chromecast/browser/service_connector.h" -#include "chromecast/browser/tts/tts_controller_impl.h" -#include "chromecast/browser/tts/tts_platform_stub.h" #include "chromecast/chromecast_buildflags.h" #include "chromecast/graphics/cast_window_manager.h" #include "chromecast/media/base/key_systems_common.h" @@ -626,9 +624,6 @@ ::media::InitializeMediaLibrary(); media_caps_->Initialize(); - cast_browser_process_->SetTtsController(std::make_unique<TtsControllerImpl>( - std::make_unique<TtsPlatformImplStub>())); - #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS) user_pref_service_ = extensions::cast_prefs::CreateUserPrefService( cast_browser_process_->browser_context());
diff --git a/chromecast/browser/cast_browser_process.cc b/chromecast/browser/cast_browser_process.cc index 6865e59c..1283fd6 100644 --- a/chromecast/browser/cast_browser_process.cc +++ b/chromecast/browser/cast_browser_process.cc
@@ -13,7 +13,6 @@ #include "chromecast/browser/cast_network_contexts.h" #include "chromecast/browser/devtools/remote_debugging_server.h" #include "chromecast/browser/metrics/cast_browser_metrics.h" -#include "chromecast/browser/tts/tts_controller.h" #include "chromecast/metrics/cast_metrics_service_client.h" #include "chromecast/net/connectivity_checker.h" #include "chromecast/service/cast_service.h" @@ -145,12 +144,6 @@ net_log_ = net_log; } -void CastBrowserProcess::SetTtsController( - std::unique_ptr<TtsController> tts_controller) { - DCHECK(!tts_controller_); - tts_controller_ = std::move(tts_controller); -} - void CastBrowserProcess::SetWebViewFactory( CastWebViewFactory* web_view_factory) { DCHECK(!web_view_factory_);
diff --git a/chromecast/browser/cast_browser_process.h b/chromecast/browser/cast_browser_process.h index 67d9b617..7b50a25 100644 --- a/chromecast/browser/cast_browser_process.h +++ b/chromecast/browser/cast_browser_process.h
@@ -12,7 +12,6 @@ #include "build/build_config.h" #include "chromecast/chromecast_buildflags.h" -class TtsController; class PrefService; namespace net { @@ -76,7 +75,6 @@ void SetConnectivityChecker( scoped_refptr<ConnectivityChecker> connectivity_checker); void SetNetLog(net::NetLog* net_log); - void SetTtsController(std::unique_ptr<TtsController> tts_controller); void SetWebViewFactory(CastWebViewFactory* web_view_factory); CastContentBrowserClient* browser_client() const { @@ -108,7 +106,6 @@ return remote_debugging_server_.get(); } net::NetLog* net_log() const { return net_log_; } - TtsController* tts_controller() const { return tts_controller_.get(); } CastWebViewFactory* web_view_factory() const { return web_view_factory_; } private: @@ -132,7 +129,6 @@ CastWebViewFactory* web_view_factory_; CastContentBrowserClient* cast_content_browser_client_; net::NetLog* net_log_; - std::unique_ptr<TtsController> tts_controller_; // Note: CastService must be destroyed before others. std::unique_ptr<CastService> cast_service_;
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index d6fdf298..a8736241 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -49,7 +49,6 @@ #include "chromecast/browser/media/media_caps_impl.h" #include "chromecast/browser/service/cast_service_simple.h" #include "chromecast/browser/service_connector.h" -#include "chromecast/browser/tts/tts_controller.h" #include "chromecast/common/cast_content_client.h" #include "chromecast/common/global_descriptors.h" #include "chromecast/media/audio/cast_audio_manager.h"
diff --git a/chromecast/browser/extensions/api/tts/tts_extension_api.cc b/chromecast/browser/extensions/api/tts/tts_extension_api.cc index 64ff390..80d2739 100644 --- a/chromecast/browser/extensions/api/tts/tts_extension_api.cc +++ b/chromecast/browser/extensions/api/tts/tts_extension_api.cc
@@ -9,8 +9,7 @@ #include "chromecast/browser/extensions/api/tts/tts_extension_api.h" -#include <stddef.h> - +#include <cstddef> #include <memory> #include <string> #include <utility> @@ -19,9 +18,10 @@ #include "base/values.h" #include "chromecast/browser/cast_browser_process.h" #include "chromecast/browser/extensions/api/tts/tts_extension_api_constants.h" -#include "chromecast/browser/tts/tts_controller.h" +#include "content/public/browser/tts_controller.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_function_registry.h" +#include "third_party/blink/public/mojom/speech/speech_synthesis.mojom.h" #include "ui/base/l10n/l10n_util.h" namespace constants = tts_extension_api_constants; @@ -30,27 +30,27 @@ const char kOnEvent[] = "tts.onEvent"; } // namespace events -const char* TtsEventTypeToString(TtsEventType event_type) { +const char* TtsEventTypeToString(content::TtsEventType event_type) { switch (event_type) { - case TTS_EVENT_START: + case content::TTS_EVENT_START: return constants::kEventTypeStart; - case TTS_EVENT_END: + case content::TTS_EVENT_END: return constants::kEventTypeEnd; - case TTS_EVENT_WORD: + case content::TTS_EVENT_WORD: return constants::kEventTypeWord; - case TTS_EVENT_SENTENCE: + case content::TTS_EVENT_SENTENCE: return constants::kEventTypeSentence; - case TTS_EVENT_MARKER: + case content::TTS_EVENT_MARKER: return constants::kEventTypeMarker; - case TTS_EVENT_INTERRUPTED: + case content::TTS_EVENT_INTERRUPTED: return constants::kEventTypeInterrupted; - case TTS_EVENT_CANCELLED: + case content::TTS_EVENT_CANCELLED: return constants::kEventTypeCancelled; - case TTS_EVENT_ERROR: + case content::TTS_EVENT_ERROR: return constants::kEventTypeError; - case TTS_EVENT_PAUSE: + case content::TTS_EVENT_PAUSE: return constants::kEventTypePause; - case TTS_EVENT_RESUME: + case content::TTS_EVENT_RESUME: return constants::kEventTypeResume; default: NOTREACHED(); @@ -58,49 +58,44 @@ } } -TtsEventType TtsEventTypeFromString(const std::string& str) { +content::TtsEventType TtsEventTypeFromString(const std::string& str) { if (str == constants::kEventTypeStart) - return TTS_EVENT_START; + return content::TTS_EVENT_START; if (str == constants::kEventTypeEnd) - return TTS_EVENT_END; + return content::TTS_EVENT_END; if (str == constants::kEventTypeWord) - return TTS_EVENT_WORD; + return content::TTS_EVENT_WORD; if (str == constants::kEventTypeSentence) - return TTS_EVENT_SENTENCE; + return content::TTS_EVENT_SENTENCE; if (str == constants::kEventTypeMarker) - return TTS_EVENT_MARKER; + return content::TTS_EVENT_MARKER; if (str == constants::kEventTypeInterrupted) - return TTS_EVENT_INTERRUPTED; + return content::TTS_EVENT_INTERRUPTED; if (str == constants::kEventTypeCancelled) - return TTS_EVENT_CANCELLED; + return content::TTS_EVENT_CANCELLED; if (str == constants::kEventTypeError) - return TTS_EVENT_ERROR; + return content::TTS_EVENT_ERROR; if (str == constants::kEventTypePause) - return TTS_EVENT_PAUSE; + return content::TTS_EVENT_PAUSE; if (str == constants::kEventTypeResume) - return TTS_EVENT_RESUME; + return content::TTS_EVENT_RESUME; NOTREACHED(); - return TTS_EVENT_ERROR; + return content::TTS_EVENT_ERROR; } -namespace { -TtsController* GetTtsController() { - return chromecast::shell::CastBrowserProcess::GetInstance()->tts_controller(); -} -} // namespace - namespace extensions { // One of these is constructed for each utterance, and deleted // when the utterance gets any final event. -class TtsExtensionEventHandler : public UtteranceEventDelegate { +class TtsExtensionEventHandler : public content::UtteranceEventDelegate { public: explicit TtsExtensionEventHandler(const std::string& src_extension_id); - void OnTtsEvent(Utterance* utterance, - TtsEventType event_type, + void OnTtsEvent(content::TtsUtterance* utterance, + content::TtsEventType event_type, int char_index, + int length, const std::string& error_message) override; private: @@ -113,21 +108,22 @@ const std::string& src_extension_id) : src_extension_id_(src_extension_id) {} -void TtsExtensionEventHandler::OnTtsEvent(Utterance* utterance, - TtsEventType event_type, +void TtsExtensionEventHandler::OnTtsEvent(content::TtsUtterance* utterance, + content::TtsEventType event_type, int char_index, + int length, const std::string& error_message) { - if (utterance->src_id() < 0) { - if (utterance->finished()) + if (utterance->GetSrcId() < 0) { + if (utterance->IsFinished()) delete this; return; } - const std::set<TtsEventType>& desired_event_types = - utterance->desired_event_types(); - if (desired_event_types.size() > 0 && + const std::set<content::TtsEventType>& desired_event_types = + utterance->GetDesiredEventTypes(); + if (!desired_event_types.empty() && desired_event_types.find(event_type) == desired_event_types.end()) { - if (utterance->finished()) + if (utterance->IsFinished()) delete this; return; } @@ -136,24 +132,26 @@ std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue()); if (char_index >= 0) details->SetInteger(constants::kCharIndexKey, char_index); + if (length >= 0) + details->SetInteger(constants::kLengthKey, length); details->SetString(constants::kEventTypeKey, event_type_string); - if (event_type == TTS_EVENT_ERROR) { + if (event_type == content::TTS_EVENT_ERROR) { details->SetString(constants::kErrorMessageKey, error_message); } - details->SetInteger(constants::kSrcIdKey, utterance->src_id()); - details->SetBoolean(constants::kIsFinalEventKey, utterance->finished()); + details->SetInteger(constants::kSrcIdKey, utterance->GetSrcId()); + details->SetBoolean(constants::kIsFinalEventKey, utterance->IsFinished()); std::unique_ptr<base::ListValue> arguments(new base::ListValue()); arguments->Append(std::move(details)); auto event = std::make_unique<extensions::Event>( ::extensions::events::TTS_ON_EVENT, ::events::kOnEvent, - std::move(arguments), utterance->browser_context()); - event->event_url = utterance->src_url(); - extensions::EventRouter::Get(utterance->browser_context()) + std::move(arguments), utterance->GetBrowserContext()); + event->event_url = utterance->GetSrcUrl(); + extensions::EventRouter::Get(utterance->GetBrowserContext()) ->DispatchEventToExtension(src_extension_id_, std::move(event)); - if (utterance->finished()) + if (utterance->IsFinished()) delete this; } @@ -184,22 +182,7 @@ return RespondNow(Error(constants::kErrorInvalidLang)); } - std::string gender_str; - TtsGenderType gender; - if (options->HasKey(constants::kGenderKey)) - EXTENSION_FUNCTION_VALIDATE( - options->GetString(constants::kGenderKey, &gender_str)); - if (gender_str == constants::kGenderMale) { - gender = TTS_GENDER_MALE; - } else if (gender_str == constants::kGenderFemale) { - gender = TTS_GENDER_FEMALE; - } else if (gender_str.empty()) { - gender = TTS_GENDER_NONE; - } else { - return RespondNow(Error(constants::kErrorInvalidGender)); - } - - double rate = 1.0; + double rate = blink::mojom::kSpeechSynthesisDoublePrefNotSet; if (options->HasKey(constants::kRateKey)) { EXTENSION_FUNCTION_VALIDATE(options->GetDouble(constants::kRateKey, &rate)); if (rate < 0.1 || rate > 10.0) { @@ -207,7 +190,7 @@ } } - double pitch = 1.0; + double pitch = blink::mojom::kSpeechSynthesisDoublePrefNotSet; if (options->HasKey(constants::kPitchKey)) { EXTENSION_FUNCTION_VALIDATE( options->GetDouble(constants::kPitchKey, &pitch)); @@ -216,7 +199,7 @@ } } - double volume = 1.0; + double volume = blink::mojom::kSpeechSynthesisDoublePrefNotSet; if (options->HasKey(constants::kVolumeKey)) { EXTENSION_FUNCTION_VALIDATE( options->GetDouble(constants::kVolumeKey, &volume)); @@ -231,7 +214,7 @@ options->GetBoolean(constants::kEnqueueKey, &can_enqueue)); } - std::set<TtsEventType> required_event_types; + std::set<content::TtsEventType> required_event_types; if (options->HasKey(constants::kRequiredEventTypesKey)) { base::ListValue* list; EXTENSION_FUNCTION_VALIDATE( @@ -243,7 +226,7 @@ } } - std::set<TtsEventType> desired_event_types; + std::set<content::TtsEventType> desired_event_types; if (options->HasKey(constants::kDesiredEventTypesKey)) { base::ListValue* list; EXTENSION_FUNCTION_VALIDATE( @@ -271,71 +254,66 @@ // send the success response to the callback now - this ensures that // the callback response always arrives before events, which makes // the behavior more predictable and easier to write unit tests for too. + Respond(NoArguments()); - Respond(OneArgument(std::make_unique<base::Value>(true))); + std::unique_ptr<content::TtsUtterance> utterance = + content::TtsUtterance::Create(browser_context()); + utterance->SetText(text); + utterance->SetVoiceName(voice_name); + utterance->SetSrcId(src_id); + utterance->SetSrcUrl(source_url()); + utterance->SetLang(lang); + utterance->SetContinuousParameters(rate, pitch, volume); + utterance->SetCanEnqueue(can_enqueue); + utterance->SetRequiredEventTypes(required_event_types); + utterance->SetDesiredEventTypes(desired_event_types); + utterance->SetEngineId(voice_extension_id); + utterance->SetOptions(options.get()); + utterance->SetEventDelegate(new TtsExtensionEventHandler(extension_id())); - Utterance* utterance = new Utterance(browser_context()); - utterance->set_text(text); - utterance->set_voice_name(voice_name); - utterance->set_src_id(src_id); - utterance->set_src_url(source_url()); - utterance->set_lang(lang); - utterance->set_gender(gender); - utterance->set_continuous_parameters(rate, pitch, volume); - utterance->set_can_enqueue(can_enqueue); - utterance->set_required_event_types(required_event_types); - utterance->set_desired_event_types(desired_event_types); - utterance->set_extension_id(voice_extension_id); - utterance->set_options(options.get()); - utterance->set_event_delegate(new TtsExtensionEventHandler(extension_id())); - - GetTtsController()->SpeakOrEnqueue(utterance); - return did_respond() ? AlreadyResponded() : RespondLater(); + content::TtsController* controller = content::TtsController::GetInstance(); + controller->SpeakOrEnqueue(std::move(utterance)); + return AlreadyResponded(); } ExtensionFunction::ResponseAction TtsStopSpeakingFunction::Run() { - GetTtsController()->Stop(); + content::TtsController::GetInstance()->Stop(source_url()); return RespondNow(NoArguments()); } ExtensionFunction::ResponseAction TtsPauseFunction::Run() { - GetTtsController()->Pause(); + content::TtsController::GetInstance()->Pause(); return RespondNow(NoArguments()); } ExtensionFunction::ResponseAction TtsResumeFunction::Run() { - GetTtsController()->Resume(); + content::TtsController::GetInstance()->Resume(); return RespondNow(NoArguments()); } ExtensionFunction::ResponseAction TtsIsSpeakingFunction::Run() { - return RespondNow(OneArgument( - std::make_unique<base::Value>(GetTtsController()->IsSpeaking()))); + return RespondNow(OneArgument(std::make_unique<base::Value>( + content::TtsController::GetInstance()->IsSpeaking()))); } ExtensionFunction::ResponseAction TtsGetVoicesFunction::Run() { - std::vector<VoiceData> voices; - GetTtsController()->GetVoices(browser_context(), &voices); + std::vector<content::VoiceData> voices; + content::TtsController::GetInstance()->GetVoices(browser_context(), &voices); auto result_voices = std::make_unique<base::ListValue>(); for (size_t i = 0; i < voices.size(); ++i) { - const VoiceData& voice = voices[i]; + const content::VoiceData& voice = voices[i]; std::unique_ptr<base::DictionaryValue> result_voice( new base::DictionaryValue()); result_voice->SetString(constants::kVoiceNameKey, voice.name); result_voice->SetBoolean(constants::kRemoteKey, voice.remote); if (!voice.lang.empty()) result_voice->SetString(constants::kLangKey, voice.lang); - if (voice.gender == TTS_GENDER_MALE) - result_voice->SetString(constants::kGenderKey, constants::kGenderMale); - else if (voice.gender == TTS_GENDER_FEMALE) - result_voice->SetString(constants::kGenderKey, constants::kGenderFemale); - if (!voice.extension_id.empty()) - result_voice->SetString(constants::kExtensionIdKey, voice.extension_id); + if (!voice.engine_id.empty()) + result_voice->SetString(constants::kExtensionIdKey, voice.engine_id); auto event_types = std::make_unique<base::ListValue>(); - for (std::set<TtsEventType>::iterator iter = voice.events.begin(); - iter != voice.events.end(); ++iter) { + for (auto iter = voice.events.begin(); iter != voice.events.end(); ++iter) { const char* event_name_constant = TtsEventTypeToString(*iter); event_types->AppendString(event_name_constant); }
diff --git a/chromecast/browser/extensions/api/tts/tts_extension_api.h b/chromecast/browser/extensions/api/tts/tts_extension_api.h index 59f1d8f..7afd353c 100644 --- a/chromecast/browser/extensions/api/tts/tts_extension_api.h +++ b/chromecast/browser/extensions/api/tts/tts_extension_api.h
@@ -12,7 +12,7 @@ #include <string> -#include "chromecast/browser/tts/tts_controller.h" +#include "content/public/browser/tts_controller.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/extension_function.h" @@ -20,8 +20,8 @@ class BrowserContext; } -const char* TtsEventTypeToString(TtsEventType event_type); -TtsEventType TtsEventTypeFromString(const std::string& str); +const char* TtsEventTypeToString(content::TtsEventType event_type); +content::TtsEventType TtsEventTypeFromString(const std::string& str); namespace extensions {
diff --git a/chromecast/browser/extensions/api/tts/tts_extension_api_constants.cc b/chromecast/browser/extensions/api/tts/tts_extension_api_constants.cc index b24dd97..c52e2d7 100644 --- a/chromecast/browser/extensions/api/tts/tts_extension_api_constants.cc +++ b/chromecast/browser/extensions/api/tts/tts_extension_api_constants.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// PLEASE NOTE: this is a copy with modifications from -// /chrome/browser/speech/extension_api -// It is temporary until a refactoring to move the chrome TTS implementation up -// into components and extensions/components can be completed. - #include "chromecast/browser/extensions/api/tts/tts_extension_api_constants.h" namespace tts_extension_api_constants { const char kCharIndexKey[] = "charIndex"; +const char kLengthKey[] = "length"; const char kDesiredEventTypesKey[] = "desiredEventTypes"; const char kEnqueueKey[] = "enqueue"; const char kErrorMessageKey[] = "errorMessage"; @@ -30,9 +26,6 @@ const char kVoiceNameKey[] = "voiceName"; const char kVolumeKey[] = "volume"; -const char kGenderFemale[] = "female"; -const char kGenderMale[] = "male"; - const char kEventTypeCancelled[] = "cancelled"; const char kEventTypeEnd[] = "end"; const char kEventTypeError[] = "error"; @@ -45,7 +38,6 @@ const char kEventTypeWord[] = "word"; const char kErrorExtensionIdMismatch[] = "Extension id mismatch."; -const char kErrorInvalidGender[] = "Invalid gender."; const char kErrorInvalidLang[] = "Invalid lang."; const char kErrorInvalidPitch[] = "Invalid pitch."; const char kErrorInvalidRate[] = "Invalid rate.";
diff --git a/chromecast/browser/extensions/api/tts/tts_extension_api_constants.h b/chromecast/browser/extensions/api/tts/tts_extension_api_constants.h index 6e4f79f..74652ea 100644 --- a/chromecast/browser/extensions/api/tts/tts_extension_api_constants.h +++ b/chromecast/browser/extensions/api/tts/tts_extension_api_constants.h
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// PLEASE NOTE: this is a copy with modifications from -// /chrome/browser/speech/extension_api -// It is temporary until a refactoring to move the chrome TTS implementation up -// into components and extensions/components can be completed. - #ifndef CHROMECAST_BROWSER_EXTENSIONS_API_TTS_TTS_EXTENSION_API_CONSTANTS_H_ #define CHROMECAST_BROWSER_EXTENSIONS_API_TTS_TTS_EXTENSION_API_CONSTANTS_H_ @@ -17,6 +12,7 @@ namespace tts_extension_api_constants { extern const char kCharIndexKey[]; +extern const char kLengthKey[]; extern const char kDesiredEventTypesKey[]; extern const char kEnqueueKey[]; extern const char kErrorMessageKey[]; @@ -35,9 +31,6 @@ extern const char kVoiceNameKey[]; extern const char kVolumeKey[]; -extern const char kGenderFemale[]; -extern const char kGenderMale[]; - extern const char kEventTypeCancelled[]; extern const char kEventTypeEnd[]; extern const char kEventTypeError[]; @@ -50,7 +43,6 @@ extern const char kEventTypeWord[]; extern const char kErrorExtensionIdMismatch[]; -extern const char kErrorInvalidGender[]; extern const char kErrorInvalidLang[]; extern const char kErrorInvalidPitch[]; extern const char kErrorInvalidRate[];
diff --git a/chromecast/browser/tts/tts_controller.h b/chromecast/browser/tts/tts_controller.h deleted file mode 100644 index 30d7e51..0000000 --- a/chromecast/browser/tts/tts_controller.h +++ /dev/null
@@ -1,274 +0,0 @@ -// Copyright (c) 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMECAST_BROWSER_TTS_TTS_CONTROLLER_H_ -#define CHROMECAST_BROWSER_TTS_TTS_CONTROLLER_H_ - -#include <memory> -#include <queue> -#include <set> -#include <string> -#include <vector> - -#include "base/memory/singleton.h" -#include "base/memory/weak_ptr.h" -#include "url/gurl.h" - -class Utterance; -class TtsPlatformImpl; - -namespace base { -class Value; -} // namespace base - -namespace content { -class BrowserContext; -} // namespace content - -// Events sent back from the TTS engine indicating the progress. -enum TtsEventType { - TTS_EVENT_START, - TTS_EVENT_END, - TTS_EVENT_WORD, - TTS_EVENT_SENTENCE, - TTS_EVENT_MARKER, - TTS_EVENT_INTERRUPTED, - TTS_EVENT_CANCELLED, - TTS_EVENT_ERROR, - TTS_EVENT_PAUSE, - TTS_EVENT_RESUME -}; - -enum TtsGenderType { TTS_GENDER_NONE, TTS_GENDER_MALE, TTS_GENDER_FEMALE }; - -// Returns true if this event type is one that indicates an utterance -// is finished and can be destroyed. -bool IsFinalTtsEventType(TtsEventType event_type); - -// The continuous parameters that apply to a given utterance. -struct UtteranceContinuousParameters { - UtteranceContinuousParameters(); - - double rate; - double pitch; - double volume; -}; - -// Information about one voice. -struct VoiceData { - VoiceData(); - VoiceData(const VoiceData& other); - ~VoiceData(); - - std::string name; - std::string lang; - TtsGenderType gender; - std::string extension_id; // Not used in cast. - std::set<TtsEventType> events; - - // If true, the synthesis engine is a remote network resource. - // It may be higher latency and may incur bandwidth costs. - bool remote; - - // If true, this is implemented by this platform's subclass of - // TtsPlatformImpl. If false, this is implemented by an extension. - bool native; - std::string native_voice_identifier; -}; - -// Class that wants to receive events on utterances. -class UtteranceEventDelegate { - public: - virtual ~UtteranceEventDelegate() {} - virtual void OnTtsEvent(Utterance* utterance, - TtsEventType event_type, - int char_index, - const std::string& error_message) = 0; -}; - -// One speech utterance. -class Utterance { - public: - // Construct an utterance given a profile and a completion task to call - // when the utterance is done speaking. Before speaking this utterance, - // its other parameters like text, rate, pitch, etc. should all be set. - explicit Utterance(content::BrowserContext* browser_context); - ~Utterance(); - - // Sends an event to the delegate. If the event type is TTS_EVENT_END - // or TTS_EVENT_ERROR, deletes the utterance. If |char_index| is -1, - // uses the last good value. - void OnTtsEvent(TtsEventType event_type, - int char_index, - const std::string& error_message); - - // Finish an utterance without sending an event to the delegate. - void Finish(); - - // Getters and setters for the text to speak and other speech options. - void set_text(const std::string& text) { text_ = text; } - const std::string& text() const { return text_; } - - void set_options(const base::Value* options); - const base::Value* options() const { return options_.get(); } - - void set_src_id(int src_id) { src_id_ = src_id; } - int src_id() { return src_id_; } - - void set_src_url(const GURL& src_url) { src_url_ = src_url; } - const GURL& src_url() { return src_url_; } - - void set_voice_name(const std::string& voice_name) { - voice_name_ = voice_name; - } - const std::string& voice_name() const { return voice_name_; } - - void set_lang(const std::string& lang) { lang_ = lang; } - const std::string& lang() const { return lang_; } - - void set_gender(TtsGenderType gender) { gender_ = gender; } - TtsGenderType gender() const { return gender_; } - - void set_continuous_parameters(const double rate, - const double pitch, - const double volume) { - continuous_parameters_.rate = rate; - continuous_parameters_.pitch = pitch; - continuous_parameters_.volume = volume; - } - const UtteranceContinuousParameters& continuous_parameters() { - return continuous_parameters_; - } - - void set_can_enqueue(bool can_enqueue) { can_enqueue_ = can_enqueue; } - bool can_enqueue() const { return can_enqueue_; } - - void set_required_event_types(const std::set<TtsEventType>& types) { - required_event_types_ = types; - } - const std::set<TtsEventType>& required_event_types() const { - return required_event_types_; - } - - void set_desired_event_types(const std::set<TtsEventType>& types) { - desired_event_types_ = types; - } - const std::set<TtsEventType>& desired_event_types() const { - return desired_event_types_; - } - - const std::string& extension_id() const { return extension_id_; } - void set_extension_id(const std::string& extension_id) { - extension_id_ = extension_id; - } - - UtteranceEventDelegate* event_delegate() const { return event_delegate_; } - void set_event_delegate(UtteranceEventDelegate* event_delegate) { - event_delegate_ = event_delegate; - } - - // Getters and setters for internal state. - content::BrowserContext* browser_context() const { return browser_context_; } - int id() const { return id_; } - bool finished() const { return finished_; } - - private: - // The BrowserContext that initiated this utterance. - content::BrowserContext* browser_context_; - - // The extension ID of the extension providing TTS for this utterance, or - // empty if native TTS is being used. - std::string extension_id_; - - // The unique ID of this utterance, used to associate callback functions - // with utterances. - int id_; - - // The id of the next utterance, so we can associate requests with - // responses. - static int next_utterance_id_; - - // The text to speak. - std::string text_; - - // The full options arg passed to tts.speak, which may include fields - // other than the ones we explicitly parse, below. - std::unique_ptr<base::Value> options_; - - // The source extension's ID of this utterance, so that it can associate - // events with the appropriate callback. - int src_id_; - - // The URL of the page where the source extension called speak. - GURL src_url_; - - // The delegate to be called when an utterance event is fired. - UtteranceEventDelegate* event_delegate_; - - // The parsed options. - std::string voice_name_; - std::string lang_; - TtsGenderType gender_; - UtteranceContinuousParameters continuous_parameters_; - bool can_enqueue_; - std::set<TtsEventType> required_event_types_; - std::set<TtsEventType> desired_event_types_; - - // The index of the current char being spoken. - int char_index_; - - // True if this utterance received an event indicating it's done. - bool finished_; -}; - -// Singleton class that manages text-to-speech for the TTS extension APIs, -// potentially maintaining a queue of pending utterances and keeping track of -// all state. -class TtsController { - public: - virtual ~TtsController() = default; - - // Set the TTS platform implementation to use. - virtual void SetPlatformImpl( - std::unique_ptr<TtsPlatformImpl> platform_impl) = 0; - - // Returns true if we're currently speaking an utterance. - virtual bool IsSpeaking() = 0; - - // Speak the given utterance. If the utterance's can_enqueue flag is true - // and another utterance is in progress, adds it to the end of the queue. - // Otherwise, interrupts any current utterance and speaks this one - // immediately. - virtual void SpeakOrEnqueue(Utterance* utterance) = 0; - - // Stop all utterances and flush the queue. Implies leaving pause mode - // as well. - virtual void Stop() = 0; - - // Pause the speech queue. Some engines may support pausing in the middle - // of an utterance. - virtual void Pause() = 0; - - // Resume speaking. - virtual void Resume() = 0; - - // Handle events received from the speech engine. Events are forwarded to - // the callback function, and in addition, completion and error events - // trigger finishing the current utterance and starting the next one, if - // any. - virtual void OnTtsEvent(int utterance_id, - TtsEventType event_type, - int char_index, - const std::string& error_message) = 0; - - // Return a list of all available voices, including the native voice, - // if supported, and all voices registered by extensions. - virtual void GetVoices(content::BrowserContext* browser_context, - std::vector<VoiceData>* out_voices) = 0; - - // For unit testing. - virtual int QueueSize() = 0; -}; - -#endif // CHROMECAST_BROWSER_TTS_TTS_CONTROLLER_H_
diff --git a/chromecast/browser/tts/tts_controller_impl.cc b/chromecast/browser/tts/tts_controller_impl.cc deleted file mode 100644 index 2bb8338e..0000000 --- a/chromecast/browser/tts/tts_controller_impl.cc +++ /dev/null
@@ -1,508 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromecast/browser/tts/tts_controller_impl.h" - -#include <stddef.h> - -#include <string> -#include <vector> - -#include "base/containers/queue.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chromecast/browser/tts/tts_platform.h" -#include "chromecast/chromecast_buildflags.h" -#include "third_party/blink/public/mojom/speech/speech_synthesis.mojom-forward.h" - -#if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS) -#include "extensions/browser/extensions_browser_client.h" -#endif - -namespace { -// A value to be used to indicate that there is no char index available. -const int kInvalidCharIndex = -1; - -// Given a language/region code of the form 'fr-FR', returns just the basic -// language portion, e.g. 'fr'. -std::string TrimLanguageCode(const std::string& lang) { - if (lang.size() >= 5 && lang[2] == '-') - return lang.substr(0, 2); - else - return lang; -} - -// IMPORTANT! -// These values are written to logs. Do not renumber or delete -// existing items; add new entries to the end of the list. -enum class UMATextToSpeechEvent { - START = 0, - END = 1, - WORD = 2, - SENTENCE = 3, - MARKER = 4, - INTERRUPTED = 5, - CANCELLED = 6, - SPEECH_ERROR = 7, - PAUSE = 8, - RESUME = 9, - - // This must always be the last enum. It's okay for its value to - // increase, but none of the other enum values may change. - COUNT -}; - -} // namespace - -bool IsFinalTtsEventType(TtsEventType event_type) { - return (event_type == TTS_EVENT_END || event_type == TTS_EVENT_INTERRUPTED || - event_type == TTS_EVENT_CANCELLED || event_type == TTS_EVENT_ERROR); -} - -// -// UtteranceContinuousParameters -// - -UtteranceContinuousParameters::UtteranceContinuousParameters() - : rate(blink::mojom::kSpeechSynthesisDoublePrefNotSet), - pitch(blink::mojom::kSpeechSynthesisDoublePrefNotSet), - volume(blink::mojom::kSpeechSynthesisDoublePrefNotSet) {} - -// -// VoiceData -// - -VoiceData::VoiceData() - : gender(TTS_GENDER_NONE), remote(false), native(false) {} - -VoiceData::VoiceData(const VoiceData& other) = default; - -VoiceData::~VoiceData() {} - -// -// Utterance -// - -// static -int Utterance::next_utterance_id_ = 0; - -Utterance::Utterance(content::BrowserContext* browser_context) - : browser_context_(browser_context), - id_(next_utterance_id_++), - src_id_(-1), - gender_(TTS_GENDER_NONE), - can_enqueue_(false), - char_index_(0), - finished_(false) { - options_.reset(new base::DictionaryValue()); -} - -Utterance::~Utterance() { - // It's an error if an Utterance is destructed without being finished, - // unless |browser_context_| is nullptr because it's a unit test. - DCHECK(finished_ || !browser_context_); -} - -void Utterance::OnTtsEvent(TtsEventType event_type, - int char_index, - const std::string& error_message) { - if (char_index >= 0) - char_index_ = char_index; - if (IsFinalTtsEventType(event_type)) - finished_ = true; - - if (event_delegate_) - event_delegate_->OnTtsEvent(this, event_type, char_index, error_message); - if (finished_) - event_delegate_ = nullptr; -} - -void Utterance::Finish() { - finished_ = true; -} - -void Utterance::set_options(const base::Value* options) { - options_.reset(options->DeepCopy()); -} - -// -// TtsControllerImpl -// - -TtsControllerImpl::TtsControllerImpl( - std::unique_ptr<TtsPlatformImpl> platform_impl) - : current_utterance_(nullptr), - paused_(false), - platform_impl_(std::move(platform_impl)) {} - -TtsControllerImpl::~TtsControllerImpl() { - if (current_utterance_) { - current_utterance_->Finish(); - delete current_utterance_; - } - - // Clear any queued utterances too. - ClearUtteranceQueue(false); // Don't sent events. -} - -void TtsControllerImpl::SpeakOrEnqueue(Utterance* utterance) { - // If we're paused and we get an utterance that can't be queued, - // flush the queue but stay in the paused state. - if (paused_ && !utterance->can_enqueue()) { - utterance_queue_.push(utterance); - Stop(); - paused_ = true; - return; - } - - if (paused_ || (IsSpeaking() && utterance->can_enqueue())) { - utterance_queue_.push(utterance); - } else { - Stop(); - SpeakNow(utterance); - } -} - -void TtsControllerImpl::SpeakNow(Utterance* utterance) { - // Get all available voices and try to find a matching voice. - std::vector<VoiceData> voices; - GetVoices(utterance->browser_context(), &voices); - - // Get the best matching voice. If nothing matches, just set "native" - // to true because that might trigger deferred loading of native voices. - int index = GetMatchingVoice(utterance, voices); - VoiceData voice; - if (index >= 0) - voice = voices[index]; - else - voice.native = true; - - UpdateUtteranceDefaults(utterance); - - GetPlatformImpl()->WillSpeakUtteranceWithVoice(utterance, voice); - - base::RecordAction(base::UserMetricsAction("TextToSpeech.Speak")); - UMA_HISTOGRAM_COUNTS_100000("TextToSpeech.Utterance.TextLength", - utterance->text().size()); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.FromExtensionAPI", - !utterance->src_url().is_empty()); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasVoiceName", - !utterance->voice_name().empty()); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasLang", - !utterance->lang().empty()); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasGender", - utterance->gender() != TTS_GENDER_NONE); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasRate", - utterance->continuous_parameters().rate != 1.0); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasPitch", - utterance->continuous_parameters().pitch != 1.0); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasVolume", - utterance->continuous_parameters().volume != 1.0); - UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.Native", voice.native); - - if (!voice.native) { -#if !defined(OS_ANDROID) - DCHECK(!voice.extension_id.empty()); - current_utterance_ = utterance; - utterance->set_extension_id(voice.extension_id); - bool sends_end_event = - voice.events.find(TTS_EVENT_END) != voice.events.end(); - if (!sends_end_event) { - utterance->Finish(); - delete utterance; - current_utterance_ = nullptr; - SpeakNextUtterance(); - } -#endif - } else { - // It's possible for certain platforms to send start events immediately - // during |speak|. - current_utterance_ = utterance; - GetPlatformImpl()->clear_error(); - bool success = GetPlatformImpl()->Speak(utterance->id(), utterance->text(), - utterance->lang(), voice, - utterance->continuous_parameters()); - if (!success) { - current_utterance_ = nullptr; - utterance->OnTtsEvent(TTS_EVENT_ERROR, kInvalidCharIndex, - GetPlatformImpl()->error()); - delete utterance; - return; - } - } -} - -void TtsControllerImpl::Stop() { - base::RecordAction(base::UserMetricsAction("TextToSpeech.Stop")); - - paused_ = false; - GetPlatformImpl()->clear_error(); - GetPlatformImpl()->StopSpeaking(); - - if (current_utterance_) - current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, - std::string()); - FinishCurrentUtterance(); - ClearUtteranceQueue(true); // Send events. -} - -void TtsControllerImpl::Pause() { - base::RecordAction(base::UserMetricsAction("TextToSpeech.Pause")); - - paused_ = true; - if (current_utterance_) { - GetPlatformImpl()->clear_error(); - GetPlatformImpl()->Pause(); - } -} - -void TtsControllerImpl::Resume() { - base::RecordAction(base::UserMetricsAction("TextToSpeech.Resume")); - - paused_ = false; - if (current_utterance_) { - GetPlatformImpl()->clear_error(); - GetPlatformImpl()->Resume(); - } else { - SpeakNextUtterance(); - } -} - -void TtsControllerImpl::OnTtsEvent(int utterance_id, - TtsEventType event_type, - int char_index, - const std::string& error_message) { - // We may sometimes receive completion callbacks "late", after we've - // already finished the utterance (for example because another utterance - // interrupted or we got a call to Stop). This is normal and we can - // safely just ignore these events. - if (!current_utterance_ || utterance_id != current_utterance_->id()) { - return; - } - - UMATextToSpeechEvent metric; - switch (event_type) { - case TTS_EVENT_START: - metric = UMATextToSpeechEvent::START; - break; - case TTS_EVENT_END: - metric = UMATextToSpeechEvent::END; - break; - case TTS_EVENT_WORD: - metric = UMATextToSpeechEvent::WORD; - break; - case TTS_EVENT_SENTENCE: - metric = UMATextToSpeechEvent::SENTENCE; - break; - case TTS_EVENT_MARKER: - metric = UMATextToSpeechEvent::MARKER; - break; - case TTS_EVENT_INTERRUPTED: - metric = UMATextToSpeechEvent::INTERRUPTED; - break; - case TTS_EVENT_CANCELLED: - metric = UMATextToSpeechEvent::CANCELLED; - break; - case TTS_EVENT_ERROR: - metric = UMATextToSpeechEvent::SPEECH_ERROR; - break; - case TTS_EVENT_PAUSE: - metric = UMATextToSpeechEvent::PAUSE; - break; - case TTS_EVENT_RESUME: - metric = UMATextToSpeechEvent::RESUME; - break; - default: - NOTREACHED(); - return; - } - UMA_HISTOGRAM_ENUMERATION("TextToSpeech.Event", metric, - UMATextToSpeechEvent::COUNT); - - current_utterance_->OnTtsEvent(event_type, char_index, error_message); - if (current_utterance_->finished()) { - FinishCurrentUtterance(); - SpeakNextUtterance(); - } -} - -void TtsControllerImpl::GetVoices(content::BrowserContext* browser_context, - std::vector<VoiceData>* out_voices) { - TtsPlatformImpl* platform_impl = GetPlatformImpl(); - if (platform_impl) { - // Ensure we have all built-in voices loaded. This is a no-op if already - // loaded. - if (platform_impl->PlatformImplAvailable()) - platform_impl->GetVoices(out_voices); - } -} - -bool TtsControllerImpl::IsSpeaking() { - return current_utterance_ != nullptr || GetPlatformImpl()->IsSpeaking(); -} - -void TtsControllerImpl::FinishCurrentUtterance() { - if (current_utterance_) { - if (!current_utterance_->finished()) - current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex, - std::string()); - delete current_utterance_; - current_utterance_ = nullptr; - } -} - -void TtsControllerImpl::SpeakNextUtterance() { - if (paused_) - return; - - // Start speaking the next utterance in the queue. Keep trying in case - // one fails but there are still more in the queue to try. - while (!utterance_queue_.empty() && !current_utterance_) { - Utterance* utterance = utterance_queue_.front(); - utterance_queue_.pop(); - SpeakNow(utterance); - } -} - -void TtsControllerImpl::ClearUtteranceQueue(bool send_events) { - while (!utterance_queue_.empty()) { - Utterance* utterance = utterance_queue_.front(); - utterance_queue_.pop(); - if (send_events) - utterance->OnTtsEvent(TTS_EVENT_CANCELLED, kInvalidCharIndex, - std::string()); - else - utterance->Finish(); - delete utterance; - } -} - -void TtsControllerImpl::SetPlatformImpl( - std::unique_ptr<TtsPlatformImpl> platform_impl) { - platform_impl_ = std::move(platform_impl); -} - -int TtsControllerImpl::QueueSize() { - return static_cast<int>(utterance_queue_.size()); -} - -TtsPlatformImpl* TtsControllerImpl::GetPlatformImpl() { - return platform_impl_.get(); -} - -std::string TtsControllerImpl::GetApplicationLocale() const { - // TODO(rdaum): Delegate back to the platform's mechaninism here. - // For Chrome, use g_browser_process as before. For cast, it's the system - // locale. Hardcoded to system locale for now -#if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS) - return extensions::ExtensionsBrowserClient::Get()->GetApplicationLocale(); -#else - return "en-US"; -#endif -} - -int TtsControllerImpl::GetMatchingVoice(const Utterance* utterance, - std::vector<VoiceData>& voices) { - // Return the index of the voice that best match the utterance parameters. - // - // These criteria are considered mandatory - if they're specified, any voice - // that doesn't match is rejected. - // - // Extension ID - // Voice name - // - // The other criteria are scored based on how well they match, in - // this order of precedence: - // - // Utterange language (exact region preferred, then general language) - // App/system language (exact region preferred, then general language) - // Required event types - // Gender - - std::string app_lang = GetApplicationLocale(); - - // Start with a best score of -1, that way even if none of the criteria - // match, something will be returned if there are any voices. - int best_score = -1; - int best_score_index = -1; - for (size_t i = 0; i < voices.size(); ++i) { - const VoiceData& voice = voices[i]; - int score = 0; - - // If the extension ID is specified, check for an exact match. - if (!utterance->extension_id().empty() && - utterance->extension_id() != voice.extension_id) - continue; - - // If the voice name is specified, check for an exact match. - if (!utterance->voice_name().empty() && - voice.name != utterance->voice_name()) - continue; - - // Prefer the utterance language. - if (!voice.lang.empty() && !utterance->lang().empty()) { - // An exact language match is worth more than a partial match. - if (voice.lang == utterance->lang()) { - score += 32; - } else if (TrimLanguageCode(voice.lang) == - TrimLanguageCode(utterance->lang())) { - score += 16; - } - } - - // Prefer the system language after that. - if (!voice.lang.empty()) { - if (voice.lang == app_lang) - score += 8; - else if (TrimLanguageCode(voice.lang) == TrimLanguageCode(app_lang)) - score += 4; - } - - // Next, prefer required event types. - if (utterance->required_event_types().size() > 0) { - bool has_all_required_event_types = true; - for (std::set<TtsEventType>::const_iterator iter = - utterance->required_event_types().begin(); - iter != utterance->required_event_types().end(); ++iter) { - if (voice.events.find(*iter) == voice.events.end()) { - has_all_required_event_types = false; - break; - } - } - if (has_all_required_event_types) - score += 2; - } - - // Finally prefer the requested gender last. - if (voice.gender != TTS_GENDER_NONE && - utterance->gender() != TTS_GENDER_NONE && - voice.gender == utterance->gender()) { - score += 1; - } - - if (score > best_score) { - best_score = score; - best_score_index = i; - } - } - - return best_score_index; -} - -void TtsControllerImpl::UpdateUtteranceDefaults(Utterance* utterance) { - double rate = utterance->continuous_parameters().rate; - double pitch = utterance->continuous_parameters().pitch; - double volume = utterance->continuous_parameters().volume; - // Update pitch, rate and volume to defaults if not explicity set on - // this utterance. - if (rate == blink::mojom::kSpeechSynthesisDoublePrefNotSet) - rate = blink::mojom::kSpeechSynthesisDefaultRate; - if (pitch == blink::mojom::kSpeechSynthesisDoublePrefNotSet) - pitch = blink::mojom::kSpeechSynthesisDefaultPitch; - if (volume == blink::mojom::kSpeechSynthesisDoublePrefNotSet) - volume = blink::mojom::kSpeechSynthesisDefaultVolume; - utterance->set_continuous_parameters(rate, pitch, volume); -}
diff --git a/chromecast/browser/tts/tts_controller_impl.h b/chromecast/browser/tts/tts_controller_impl.h deleted file mode 100644 index 5282d9d8..0000000 --- a/chromecast/browser/tts/tts_controller_impl.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMECAST_BROWSER_TTS_TTS_CONTROLLER_IMPL_H_ -#define CHROMECAST_BROWSER_TTS_TTS_CONTROLLER_IMPL_H_ - -#include <memory> -#include <set> -#include <string> -#include <vector> - -#include "base/containers/queue.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "chromecast/browser/tts/tts_controller.h" -#include "url/gurl.h" - -namespace content { -class BrowserContext; -} // namespace content - -// Singleton class that manages text-to-speech for the TTS and TTS engine -// extension APIs, maintaining a queue of pending utterances and keeping -// track of all state. -class TtsControllerImpl : public TtsController { - public: - explicit TtsControllerImpl(std::unique_ptr<TtsPlatformImpl> platform_impl); - ~TtsControllerImpl() override; - - // TtsController methods - bool IsSpeaking() override; - void SpeakOrEnqueue(Utterance* utterance) override; - void Stop() override; - void Pause() override; - void Resume() override; - void OnTtsEvent(int utterance_id, - TtsEventType event_type, - int char_index, - const std::string& error_message) override; - void GetVoices(content::BrowserContext* browser_context, - std::vector<VoiceData>* out_voices) override; - void SetPlatformImpl(std::unique_ptr<TtsPlatformImpl> platform_impl) override; - int QueueSize() override; - - std::string GetApplicationLocale() const; - - private: - FRIEND_TEST_ALL_PREFIXES(TtsControllerTest, TestGetMatchingVoice); - FRIEND_TEST_ALL_PREFIXES(TtsControllerTest, - TestTtsControllerUtteranceDefaults); - - // Get the platform TTS implementation (or injected mock). - TtsPlatformImpl* GetPlatformImpl(); - - // Start speaking the given utterance. Will either take ownership of - // |utterance| or delete it if there's an error. Returns true on success. - void SpeakNow(Utterance* utterance); - - // Clear the utterance queue. If send_events is true, will send - // TTS_EVENT_CANCELLED events on each one. - void ClearUtteranceQueue(bool send_events); - - // Finalize and delete the current utterance. - void FinishCurrentUtterance(); - - // Start speaking the next utterance in the queue. - void SpeakNextUtterance(); - - // Given an utterance and a vector of voices, return the - // index of the voice that best matches the utterance. - int GetMatchingVoice(const Utterance* utterance, - std::vector<VoiceData>& voices); - - // Updates the utterance to have default values for rate, pitch, and - // volume if they have not yet been set. On Chrome OS, defaults are - // pulled from user prefs, and may not be the same as other platforms. - void UpdateUtteranceDefaults(Utterance* utterance); - - // The current utterance being spoken. - Utterance* current_utterance_; - - // Whether the queue is paused or not. - bool paused_; - - // A queue of utterances to speak after the current one finishes. - base::queue<Utterance*> utterance_queue_; - - // A pointer to the platform implementation of text-to-speech. - std::unique_ptr<TtsPlatformImpl> platform_impl_; - - DISALLOW_COPY_AND_ASSIGN(TtsControllerImpl); -}; - -#endif // CHROMECAST_BROWSER_TTS_TTS_CONTROLLER_IMPL_H_
diff --git a/chromecast/browser/tts/tts_controller_unittest.cc b/chromecast/browser/tts/tts_controller_unittest.cc deleted file mode 100644 index 0e3a777a..0000000 --- a/chromecast/browser/tts/tts_controller_unittest.cc +++ /dev/null
@@ -1,156 +0,0 @@ -// Copyright (c) 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Unit tests for the TTS Controller. - -#include "base/values.h" -#include "chromecast/browser/tts/tts_controller_impl.h" -#include "chromecast/browser/tts/tts_platform.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/testing_pref_service.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/web_speech_synthesis_constants.h" - -namespace chromecast { - -class TtsControllerTest : public testing::Test {}; - -// Platform Tts implementation that does nothing. -class DummyTtsPlatformImpl : public TtsPlatformImpl { - public: - DummyTtsPlatformImpl() {} - ~DummyTtsPlatformImpl() override {} - bool PlatformImplAvailable() override { return true; } - bool Speak(int utterance_id, - const std::string& utterance, - const std::string& lang, - const VoiceData& voice, - const UtteranceContinuousParameters& params) override { - return true; - } - bool IsSpeaking() override { return false; } - bool StopSpeaking() override { return true; } - void Pause() override {} - void Resume() override {} - void GetVoices(std::vector<VoiceData>* out_voices) override {} - std::string error() override { return std::string(); } - void clear_error() override {} - void set_error(const std::string& error) override {} -}; - -// Subclass of TtsController with a public ctor and dtor. -class TestableTtsController : public TtsControllerImpl { - public: - TestableTtsController() {} - ~TestableTtsController() override {} -}; - -TEST_F(TtsControllerTest, TestTtsControllerShutdown) { - DummyTtsPlatformImpl platform_impl; - TestableTtsController* controller = new TestableTtsController(); - controller->SetPlatformImpl(&platform_impl); - - Utterance* utterance1 = new Utterance(nullptr); - utterance1->set_can_enqueue(true); - utterance1->set_src_id(1); - controller->SpeakOrEnqueue(utterance1); - - Utterance* utterance2 = new Utterance(nullptr); - utterance2->set_can_enqueue(true); - utterance2->set_src_id(2); - controller->SpeakOrEnqueue(utterance2); - - // Make sure that deleting the controller when there are pending - // utterances doesn't cause a crash. - delete controller; -} - -TEST_F(TtsControllerTest, TestGetMatchingVoice) { - TtsControllerImpl* tts_controller = TtsControllerImpl::GetInstance(); - - { - // Calling GetMatchingVoice with no voices returns -1. - Utterance utterance(nullptr); - std::vector<VoiceData> voices; - EXPECT_EQ(-1, tts_controller->GetMatchingVoice(&utterance, voices)); - } - - { - // Calling GetMatchingVoice with any voices returns the first one - // even if there are no criteria that match. - Utterance utterance(nullptr); - std::vector<VoiceData> voices; - voices.push_back(VoiceData()); - voices.push_back(VoiceData()); - EXPECT_EQ(0, tts_controller->GetMatchingVoice(&utterance, voices)); - } - - { - // If nothing else matches, the English voice is returned. - // (In tests the language will always be English.) - Utterance utterance(nullptr); - std::vector<VoiceData> voices; - VoiceData fr_voice; - fr_voice.lang = "fr"; - voices.push_back(fr_voice); - VoiceData en_voice; - en_voice.lang = "en"; - voices.push_back(en_voice); - VoiceData de_voice; - de_voice.lang = "de"; - voices.push_back(de_voice); - EXPECT_EQ(1, tts_controller->GetMatchingVoice(&utterance, voices)); - } - - { - // Check precedence of various matching criteria. - std::vector<VoiceData> voices; - VoiceData voice0; - voices.push_back(voice0); - VoiceData voice1; - voice1.gender = TTS_GENDER_FEMALE; - voices.push_back(voice1); - VoiceData voice2; - voice2.events.insert(TTS_EVENT_WORD); - voices.push_back(voice2); - VoiceData voice3; - voice3.lang = "de-DE"; - voices.push_back(voice3); - VoiceData voice4; - voice4.lang = "fr-CA"; - voices.push_back(voice4); - VoiceData voice5; - voice5.name = "Voice5"; - voices.push_back(voice5); - VoiceData voice6; - voice6.extension_id = "id6"; - voices.push_back(voice6); - - Utterance utterance(nullptr); - EXPECT_EQ(0, tts_controller->GetMatchingVoice(&utterance, voices)); - - utterance.set_gender(TTS_GENDER_FEMALE); - EXPECT_EQ(1, tts_controller->GetMatchingVoice(&utterance, voices)); - - std::set<TtsEventType> types; - types.insert(TTS_EVENT_WORD); - utterance.set_required_event_types(types); - EXPECT_EQ(2, tts_controller->GetMatchingVoice(&utterance, voices)); - - utterance.set_lang("de-DE"); - EXPECT_EQ(3, tts_controller->GetMatchingVoice(&utterance, voices)); - - utterance.set_lang("fr-FR"); - EXPECT_EQ(4, tts_controller->GetMatchingVoice(&utterance, voices)); - - utterance.set_voice_name("Voice5"); - EXPECT_EQ(5, tts_controller->GetMatchingVoice(&utterance, voices)); - - utterance.set_voice_name(""); - utterance.set_extension_id("id6"); - EXPECT_EQ(6, tts_controller->GetMatchingVoice(&utterance, voices)); - } -} - -} // namespace chromecast
diff --git a/chromecast/browser/tts/tts_platform.cc b/chromecast/browser/tts/tts_platform.cc deleted file mode 100644 index 480574f..0000000 --- a/chromecast/browser/tts/tts_platform.cc +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromecast/browser/tts/tts_platform.h" - -#include <string> - -std::string TtsPlatformImpl::error() { - return error_; -} - -void TtsPlatformImpl::clear_error() { - error_ = std::string(); -} - -void TtsPlatformImpl::set_error(const std::string& error) { - error_ = error; -} - -void TtsPlatformImpl::WillSpeakUtteranceWithVoice(const Utterance* utterance, - const VoiceData& voice_data) { -}
diff --git a/chromecast/browser/tts/tts_platform.h b/chromecast/browser/tts/tts_platform.h deleted file mode 100644 index 5820b67..0000000 --- a/chromecast/browser/tts/tts_platform.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright (c) 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMECAST_BROWSER_TTS_TTS_PLATFORM_H_ -#define CHROMECAST_BROWSER_TTS_TTS_PLATFORM_H_ - -#include <string> - -#include "base/macros.h" -#include "chromecast/browser/tts/tts_controller.h" - -// Abstract class that defines the native platform TTS interface, -// subclassed by specific implementations on Win, Mac, etc. -class TtsPlatformImpl { - public: - TtsPlatformImpl() {} - - virtual ~TtsPlatformImpl() {} - - // Returns true if this platform implementation is supported and available. - virtual bool PlatformImplAvailable() = 0; - - // Speak the given utterance with the given parameters if possible, - // and return true on success. Utterance will always be nonempty. - // If rate, pitch, or volume are -1.0, they will be ignored. - // - // The TtsController will only try to speak one utterance at - // a time. If it wants to interrupt speech, it will always call Stop - // before speaking again. - virtual bool Speak(int utterance_id, - const std::string& utterance, - const std::string& lang, - const VoiceData& voice, - const UtteranceContinuousParameters& params) = 0; - - // Stop speaking immediately and return true on success. - virtual bool StopSpeaking() = 0; - - // Returns whether any speech is on going. - virtual bool IsSpeaking() = 0; - - // Append information about voices provided by this platform implementation - // to |out_voices|. - virtual void GetVoices(std::vector<VoiceData>* out_voices) = 0; - - // Pause the current utterance, if any, until a call to Resume, - // Speak, or StopSpeaking. - virtual void Pause() = 0; - - // Resume speaking the current utterance, if it was paused. - virtual void Resume() = 0; - - // Allows the platform to monitor speech commands and the voices used - // for each one. - virtual void WillSpeakUtteranceWithVoice(const Utterance* utterance, - const VoiceData& voice_data); - - virtual std::string error(); - virtual void clear_error(); - virtual void set_error(const std::string& error); - - protected: - std::string error_; - - DISALLOW_COPY_AND_ASSIGN(TtsPlatformImpl); -}; - -#endif // CHROMECAST_BROWSER_TTS_TTS_PLATFORM_H_
diff --git a/chromecast/browser/tts/tts_platform_stub.cc b/chromecast/browser/tts/tts_platform_stub.cc deleted file mode 100644 index 3071fad..0000000 --- a/chromecast/browser/tts/tts_platform_stub.cc +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright (c) 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromecast/browser/tts/tts_platform_stub.h" - -#include "base/logging.h" - -namespace chromecast { - -bool TtsPlatformImplStub::PlatformImplAvailable() { - return true; -} - -bool TtsPlatformImplStub::Speak(int utterance_id, - const std::string& utterance, - const std::string& lang, - const VoiceData& voice, - const UtteranceContinuousParameters& params) { - LOG(INFO) << "Speak: " << utterance; - return true; -} - -bool TtsPlatformImplStub::StopSpeaking() { - LOG(INFO) << "StopSpeaking"; - return true; -} - -void TtsPlatformImplStub::Pause() { - LOG(INFO) << "Pause"; -} - -void TtsPlatformImplStub::Resume() { - LOG(INFO) << "Resume"; -} - -bool TtsPlatformImplStub::IsSpeaking() { - LOG(INFO) << "IsSpeaking"; - return false; -} - -void TtsPlatformImplStub::GetVoices(std::vector<VoiceData>* out_voices) { - LOG(INFO) << "GetVoices"; -} - -} // namespace chromecast
diff --git a/chromecast/browser/tts/tts_platform_stub.h b/chromecast/browser/tts/tts_platform_stub.h deleted file mode 100644 index 4caa2fea..0000000 --- a/chromecast/browser/tts/tts_platform_stub.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright (c) 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromecast/browser/tts/tts_controller.h" -#include "chromecast/browser/tts/tts_platform.h" - -#ifndef CHROMECAST_BROWSER_TTS_TTS_PLATFORM_STUB_H_ -#define CHROMECAST_BROWSER_TTS_TTS_PLATFORM_STUB_H_ - -namespace chromecast { - -// The default stub implementation of TtsPlaform for Cast that merely logs TTS -// events. -class TtsPlatformImplStub : public TtsPlatformImpl { - public: - TtsPlatformImplStub() = default; - ~TtsPlatformImplStub() override = default; - - bool PlatformImplAvailable() override; - - bool Speak(int utterance_id, - const std::string& utterance, - const std::string& lang, - const VoiceData& voice, - const UtteranceContinuousParameters& params) override; - - bool StopSpeaking() override; - - void Pause() override; - - void Resume() override; - - bool IsSpeaking() override; - - void GetVoices(std::vector<VoiceData>* out_voices) override; - - private: - DISALLOW_COPY_AND_ASSIGN(TtsPlatformImplStub); -}; - -} // namespace chromecast - -#endif // CHROMECAST_BROWSER_TTS_TTS_PLATFORM_STUB_H_
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 22c47430..2eaea00 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -312,6 +312,12 @@ # crbug.com/1099695 "platform.Drivefs", + + # crbug.com/1114654 + "crostini.Restart.artifact", + + # crbug.com/1114752 + "arc.ContainerMount", ] }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 54f9bd4..540a706 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13395.0.0 \ No newline at end of file +13398.0.0 \ No newline at end of file
diff --git a/chromeos/components/telemetry_extension_ui/resources/BUILD.gn b/chromeos/components/telemetry_extension_ui/resources/BUILD.gn index 30b19d0..50763739 100644 --- a/chromeos/components/telemetry_extension_ui/resources/BUILD.gn +++ b/chromeos/components/telemetry_extension_ui/resources/BUILD.gn
@@ -13,7 +13,6 @@ deps = [ ":trusted_closure_compile", ":untrusted_closure_compile", - ":untrusted_worker_closure_compile", ] } @@ -27,10 +26,6 @@ deps = [ ":untrusted" ] } -js_type_check("untrusted_worker_closure_compile") { - deps = [ ":untrusted_worker" ] -} - js_library("trusted") { sources = [ "trusted.js" ] deps = [ @@ -50,6 +45,3 @@ js_library("message_types") { } - -js_library("untrusted_worker") { -}
diff --git a/chromeos/components/telemetry_extension_ui/resources/untrusted_scripts.js b/chromeos/components/telemetry_extension_ui/resources/dpsl.js similarity index 71% rename from chromeos/components/telemetry_extension_ui/resources/untrusted_scripts.js rename to chromeos/components/telemetry_extension_ui/resources/dpsl.js index d7f227d..ad702e70 100644 --- a/chromeos/components/telemetry_extension_ui/resources/untrusted_scripts.js +++ b/chromeos/components/telemetry_extension_ui/resources/dpsl.js
@@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** @fileoverview Concatenation of the JS files we use in untrusted.html. */ +/** + * @fileoverview Concatenation of the JS files we use in + * chrome-untrusted://telemetry-extension/index.html. + */ // <include src="../../system_apps/public/js/message_pipe.js"> // <include src="message_types.js">
diff --git a/chromeos/components/telemetry_extension_ui/resources/index.html b/chromeos/components/telemetry_extension_ui/resources/index.html index 5589737..8da03fa2 100644 --- a/chromeos/components/telemetry_extension_ui/resources/index.html +++ b/chromeos/components/telemetry_extension_ui/resources/index.html
@@ -4,7 +4,7 @@ <!DOCTYPE html> <meta charset="utf-8"> <title>Telemetry Extension</title> -<iframe src="chrome-untrusted://telemetry-extension/untrusted.html" +<iframe src="chrome-untrusted://telemetry-extension/index.html" style="position:fixed; top:0; left:0; bottom:0; right:0; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;"></iframe> <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
diff --git a/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd b/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd index d8a32cb6..dc9f2f4c 100644 --- a/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd +++ b/chromeos/components/telemetry_extension_ui/resources/telemetry_extension_resources.grd
@@ -23,9 +23,7 @@ <include name="IDR_TELEMETRY_EXTENSION_PROBE_SERVICE_MOJO_LITE_JS" file="${root_gen_dir}/chromeos/components/telemetry_extension_ui/mojom/probe_service.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" /> <!-- Untrusted app host contents. --> - <include name="IDR_TELEMETRY_EXTENSION_UNTRUSTED_HTML" file="untrusted.html" type="BINDATA" compress="gzip" /> - <include name="IDR_TELEMETRY_EXTENSION_UNTRUSTED_SCRIPTS_JS" file="untrusted_scripts.js" flattenhtml="true" type="BINDATA" compress="gzip" /> - <include name="IDR_TELEMETRY_EXTENSION_UNTRUSTED_WORKER_JS" file="untrusted_worker.js" type="BINDATA" compress="gzip" /> + <include name="IDR_TELEMETRY_EXTENSION_DPSL_JS" file="dpsl.js" flattenhtml="true" type="BINDATA" compress="gzip" /> </if> </includes> </release>
diff --git a/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc b/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc index f2cd474..54052a7f 100644 --- a/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc +++ b/chromeos/components/telemetry_extension_ui/telemetry_extension_ui.cc
@@ -66,12 +66,7 @@ auto untrusted_source = TelemetryExtensionUntrustedSource::Create( chromeos::kChromeUIUntrustedTelemetryExtensionURL); - untrusted_source->AddResourcePath("untrusted.html", - IDR_TELEMETRY_EXTENSION_UNTRUSTED_HTML); - untrusted_source->AddResourcePath( - "untrusted_scripts.js", IDR_TELEMETRY_EXTENSION_UNTRUSTED_SCRIPTS_JS); - untrusted_source->AddResourcePath( - "untrusted_worker.js", IDR_TELEMETRY_EXTENSION_UNTRUSTED_WORKER_JS); + untrusted_source->AddResourcePath("dpsl.js", IDR_TELEMETRY_EXTENSION_DPSL_JS); untrusted_source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::FrameAncestors,
diff --git a/chromeos/components/telemetry_extension_ui/test/BUILD.gn b/chromeos/components/telemetry_extension_ui/test/BUILD.gn index 8926a60..d981b18 100644 --- a/chromeos/components/telemetry_extension_ui/test/BUILD.gn +++ b/chromeos/components/telemetry_extension_ui/test/BUILD.gn
@@ -33,11 +33,13 @@ "../:telemetry_extension_ui", "//chrome/test:test_support_ui", "//chromeos/components/web_applications/test:test_support", + "//chromeos/constants", "//chromeos/dbus/cros_healthd:cros_healthd", ] data = [ "trusted_test_requester.js", + "untrusted_app_resources/", "untrusted_browsertest.js", "untrusted_test_handlers.js", ] @@ -48,6 +50,7 @@ deps = [ ":trusted_browsertest_closure_compile", ":untrusted_browsertest_closure_compile", + "untrusted_app_resources:closure_compile", ] }
diff --git a/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.cc b/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.cc index a3f427a..329b528 100644 --- a/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.cc +++ b/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.cc
@@ -4,9 +4,12 @@ #include "chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.h" +#include "base/base_paths.h" #include "base/files/file_path.h" +#include "base/path_service.h" #include "chromeos/components/telemetry_extension_ui/url_constants.h" #include "chromeos/components/web_applications/test/sandboxed_web_ui_test_base.h" +#include "chromeos/constants/chromeos_switches.h" #include "chromeos/dbus/cros_healthd/cros_healthd_client.h" #include "chromeos/dbus/cros_healthd/fake_cros_healthd_client.h" @@ -20,6 +23,10 @@ constexpr base::FilePath::CharType kCr[] = FILE_PATH_LITERAL("ui/webui/resources/js/cr.js"); +// Folder containing the resources for JS browser tests. +constexpr base::FilePath::CharType kUntrustedAppResources[] = FILE_PATH_LITERAL( + "chromeos/components/telemetry_extension_ui/test/untrusted_app_resources"); + // File containing the query handlers for JS unit tests. constexpr base::FilePath::CharType kUntrustedTestHandlers[] = FILE_PATH_LITERAL( "chromeos/components/telemetry_extension_ui/test/" @@ -41,6 +48,19 @@ TelemetryExtensionUiBrowserTest::~TelemetryExtensionUiBrowserTest() = default; +void TelemetryExtensionUiBrowserTest::SetUpCommandLine( + base::CommandLine* command_line) { + base::FilePath source_root; + base::PathService::Get(base::DIR_SOURCE_ROOT, &source_root); + base::FilePath file_path(kUntrustedAppResources); + + command_line->AppendSwitchASCII( + chromeos::switches::kTelemetryExtensionDirectory, + source_root.Append(file_path).value()); + + SandboxedWebUiAppTestBase::SetUpCommandLine(command_line); +} + void TelemetryExtensionUiBrowserTest::SetUpOnMainThread() { { namespace cros_diagnostics = ::chromeos::cros_healthd::mojom;
diff --git a/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.h b/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.h index cd1c9347..43597adcf 100644 --- a/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.h +++ b/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.h
@@ -5,8 +5,7 @@ #ifndef CHROMEOS_COMPONENTS_TELEMETRY_EXTENSION_UI_TEST_TELEMETRY_EXTENSION_UI_BROWSERTEST_H_ #define CHROMEOS_COMPONENTS_TELEMETRY_EXTENSION_UI_TEST_TELEMETRY_EXTENSION_UI_BROWSERTEST_H_ -#include <string> - +#include "base/command_line.h" #include "chromeos/components/web_applications/test/sandboxed_web_ui_test_base.h" class TelemetryExtensionUiBrowserTest : public SandboxedWebUiAppTestBase { @@ -19,6 +18,8 @@ TelemetryExtensionUiBrowserTest& operator=( const TelemetryExtensionUiBrowserTest&) = delete; + // SandboxedWebUiAppTestBase overrides: + void SetUpCommandLine(base::CommandLine* command_line) override; void SetUpOnMainThread() override; };
diff --git a/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/BUILD.gn b/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/BUILD.gn new file mode 100644 index 0000000..3ab0b1b --- /dev/null +++ b/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/BUILD.gn
@@ -0,0 +1,21 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") + +assert(is_chromeos, "Telemetry Extension is Chrome OS only") +assert(!is_official_build, + "Telemetry Extension is only built for unofficial builds") + +group("closure_compile") { + deps = [ ":worker_closure_compile" ] +} + +js_type_check("worker_closure_compile") { + deps = [ ":worker" ] +} + +js_library("worker") { + sources = [ "worker.js" ] +}
diff --git a/chromeos/components/telemetry_extension_ui/resources/untrusted.html b/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/index.html similarity index 62% rename from chromeos/components/telemetry_extension_ui/resources/untrusted.html rename to chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/index.html index 00291a22..fed740b 100644 --- a/chromeos/components/telemetry_extension_ui/resources/untrusted.html +++ b/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/index.html
@@ -1,10 +1,12 @@ <!-- Copyright 2020 The Chromium Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> - <!DOCTYPE html> <meta charset="utf-8"> <title>Untrusted Telemetry Extension</title> <h1 id='untrusted-title'>Telemetry Extension</h1> -<script src="untrusted_scripts.js"></script> +<!-- This support library is needed so that 3P can access telemetry APIs --> +<script src="chrome-untrusted://telemetry-extension/dpsl.js"></script> + +<script src="index.js"></script>
diff --git a/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/index.js b/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/index.js new file mode 100644 index 0000000..df32184 --- /dev/null +++ b/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/index.js
@@ -0,0 +1,5 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +window.document.title = 'Third-party Telemetry Extension';
diff --git a/chromeos/components/telemetry_extension_ui/resources/untrusted_worker.js b/chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/worker.js similarity index 100% rename from chromeos/components/telemetry_extension_ui/resources/untrusted_worker.js rename to chromeos/components/telemetry_extension_ui/test/untrusted_app_resources/worker.js
diff --git a/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js b/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js index 1ca550c..a5971c9 100644 --- a/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js +++ b/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js
@@ -10,7 +10,7 @@ */ const workerUrlPolicy = trustedTypes.createPolicy( 'telemetry-extension-static', - {createScriptURL: () => 'untrusted_worker.js'}); + {createScriptURL: () => 'worker.js'}); // Tests that web workers can be spawned from // chrome-untrusted://telemetry_extension.
diff --git a/chromeos/dbus/dlcservice/fake_dlcservice_client.cc b/chromeos/dbus/dlcservice/fake_dlcservice_client.cc index 3ff3ff1..98a889f5 100644 --- a/chromeos/dbus/dlcservice/fake_dlcservice_client.cc +++ b/chromeos/dbus/dlcservice/fake_dlcservice_client.cc
@@ -21,8 +21,9 @@ InstallResult install_result{ .error = install_err_, .dlc_id = dlc_id, - .root_path = "", + .root_path = install_root_path_, }; + dlcs_with_content_.add_dlc_infos()->set_id(dlc_id); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), std::move(install_result))); @@ -31,6 +32,15 @@ void FakeDlcserviceClient::Uninstall(const std::string& dlc_id, UninstallCallback callback) { VLOG(1) << "Requesting to uninstall DLC=" << dlc_id; + for (auto iter = dlcs_with_content_.dlc_infos().begin(); + iter != dlcs_with_content_.dlc_infos().end();) { + if (iter->id() != dlc_id) { + iter++; + continue; + } + iter = dlcs_with_content_.mutable_dlc_infos()->erase(iter); + } + base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), uninstall_err_)); }
diff --git a/chromeos/dbus/dlcservice/fake_dlcservice_client.h b/chromeos/dbus/dlcservice/fake_dlcservice_client.h index efdb875..5c77892 100644 --- a/chromeos/dbus/dlcservice/fake_dlcservice_client.h +++ b/chromeos/dbus/dlcservice/fake_dlcservice_client.h
@@ -37,12 +37,13 @@ void NotifyObserversForTest(const dlcservice::DlcState& dlc_state); // Setters: - // TODO(hsuregan/kimjae): Convert setters and at tests that use them to - // underscore style instead of camel case. - void SetInstallError(const std::string& err) { install_err_ = err; } - void SetUninstallError(const std::string& err) { uninstall_err_ = err; } - void SetPurgeError(const std::string& err) { purge_err_ = err; } - void SetGetExistingDlcsError(const std::string& err) { + void set_install_error(const std::string& err) { install_err_ = err; } + void set_install_root_path(const std::string& path) { + install_root_path_ = path; + } + void set_uninstall_error(const std::string& err) { uninstall_err_ = err; } + void set_purge_error(const std::string& err) { purge_err_ = err; } + void set_get_existing_dlcs_error(const std::string& err) { get_existing_dlcs_err_ = err; } void set_dlcs_with_content( @@ -56,6 +57,7 @@ std::string purge_err_ = dlcservice::kErrorNone; std::string get_installed_err_ = dlcservice::kErrorNone; std::string get_existing_dlcs_err_ = dlcservice::kErrorNone; + std::string install_root_path_; dlcservice::DlcsWithContent dlcs_with_content_; // A list of observers that are listening on state changes, etc.
diff --git a/components/autofill/core/browser/autofill_data_util.cc b/components/autofill/core/browser/autofill_data_util.cc index 6579de9..0f91c041 100644 --- a/components/autofill/core/browser/autofill_data_util.cc +++ b/components/autofill/core/browser/autofill_data_util.cc
@@ -19,6 +19,7 @@ #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/geo/autofill_country.h" #include "components/autofill/core/browser/webdata/autofill_table.h" #include "components/grit/components_scaled_resources.h" @@ -246,6 +247,27 @@ return false; } +void AddGroupToBitmask(uint32_t* group_bitmask, ServerFieldType type) { + const FieldTypeGroup group = + AutofillType(AutofillType(type).GetStorableType()).group(); + switch (group) { + case autofill::NAME: + *group_bitmask |= kName; + break; + case autofill::ADDRESS_HOME: + *group_bitmask |= kAddress; + break; + case autofill::EMAIL: + *group_bitmask |= kEmail; + break; + case autofill::PHONE_HOME: + *group_bitmask |= kPhone; + break; + default: + break; + } +} + } // namespace bool ContainsName(uint32_t groups) { @@ -264,27 +286,19 @@ return groups & kPhone; } +uint32_t DetermineGroups(const FormStructure& form) { + uint32_t group_bitmask = 0; + for (const auto& field : form) { + ServerFieldType type = field->Type().GetStorableType(); + AddGroupToBitmask(&group_bitmask, type); + } + return group_bitmask; +} + uint32_t DetermineGroups(const std::vector<ServerFieldType>& types) { uint32_t group_bitmask = 0; - for (const ServerFieldType& type : types) { - const FieldTypeGroup group = - AutofillType(AutofillType(type).GetStorableType()).group(); - switch (group) { - case autofill::NAME: - group_bitmask |= kName; - break; - case autofill::ADDRESS_HOME: - group_bitmask |= kAddress; - break; - case autofill::EMAIL: - group_bitmask |= kEmail; - break; - case autofill::PHONE_HOME: - group_bitmask |= kPhone; - break; - default: - break; - } + for (const auto& type : types) { + AddGroupToBitmask(&group_bitmask, type); } return group_bitmask; }
diff --git a/components/autofill/core/browser/autofill_data_util.h b/components/autofill/core/browser/autofill_data_util.h index 644ab42..cef371d6 100644 --- a/components/autofill/core/browser/autofill_data_util.h +++ b/components/autofill/core/browser/autofill_data_util.h
@@ -15,6 +15,7 @@ namespace autofill { class AutofillProfile; +class FormStructure; namespace data_util { @@ -54,7 +55,9 @@ bool ContainsPhone(uint32_t groups); // Returns a bitmask indicating which of the name, address, email address, and -// phone number FieldTypeGroups are associated with the given |types|. +// phone number FieldTypeGroups are associated with the given |form|'s storable +// types or |types|, respectively. +uint32_t DetermineGroups(const FormStructure& form); uint32_t DetermineGroups(const std::vector<ServerFieldType>& types); // Returns true if a form has address fields or has least two supported
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 2093acec..f2ab07d 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -871,8 +871,7 @@ if (!user_did_type_ || autofill_field->is_autofilled) { form_interactions_ukm_logger_->LogTextFieldDidChange(*form_structure, *autofill_field); - profile_form_bitmask = - data_util::DetermineGroups(form_structure->GetServerFieldTypes()); + profile_form_bitmask = data_util::DetermineGroups(*form_structure); } if (!autofill_field->is_autofilled) { @@ -1198,9 +1197,7 @@ } uint32_t profile_form_bitmask = - form_structure - ? data_util::DetermineGroups(form_structure->GetServerFieldTypes()) - : 0; + form_structure ? data_util::DetermineGroups(*form_structure) : 0; AutofillMetrics::LogUserHappinessMetric( AutofillMetrics::USER_DID_AUTOFILL, form_types, @@ -1233,8 +1230,7 @@ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field)) return; - uint32_t profile_form_bitmask = - data_util::DetermineGroups(form_structure->GetServerFieldTypes()); + uint32_t profile_form_bitmask = data_util::DetermineGroups(*form_structure); AutofillMetrics::LogUserHappinessMetric( AutofillMetrics::SUGGESTIONS_SHOWN, autofill_field->Type().group(), client_->GetSecurityLevelForUmaHistograms(), profile_form_bitmask); @@ -1890,11 +1886,10 @@ // Fill the non-empty value from |data_model| into the result vector, which // will be sent to the renderer. - FillFieldWithValue( - cached_field, data_model, &result.fields[i], should_notify, - optional_cvc ? *optional_cvc : kEmptyCvc, - data_util::DetermineGroups(form_structure->GetServerFieldTypes()), - &failure_to_fill); + FillFieldWithValue(cached_field, data_model, &result.fields[i], + should_notify, optional_cvc ? *optional_cvc : kEmptyCvc, + data_util::DetermineGroups(*form_structure), + &failure_to_fill); bool has_value_after = !result.fields[i].value.empty(); bool is_autofilled_after = result.fields[i].is_autofilled; @@ -2056,8 +2051,7 @@ continue; } - if (data_util::ContainsPhone(data_util::DetermineGroups( - form_structure->GetServerFieldTypes()))) { + if (data_util::ContainsPhone(data_util::DetermineGroups(*form_structure))) { has_observed_phone_number_field_ = true; }
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index a268a80..85760cd 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -1184,7 +1184,7 @@ AutofillMetrics::LogUserHappinessMetric( AutofillMetrics::USER_DID_ENTER_UPI_VPA, field->Type().group(), security_state::SecurityLevel::SECURITY_LEVEL_COUNT, - data_util::DetermineGroups(GetServerFieldTypes())); + data_util::DetermineGroups(*this)); } form_interactions_ukm_logger->LogFieldFillStatus(*this, *field, @@ -2287,14 +2287,6 @@ return form_types; } -std::vector<ServerFieldType> FormStructure::GetServerFieldTypes() const { - std::vector<ServerFieldType> types(field_count()); - std::transform(begin(), end(), types.begin(), [&](const auto& field) { - return field->Type().GetStorableType(); - }); - return types; -} - base::string16 FormStructure::GetIdentifierForRefill() const { if (!form_name().empty()) return form_name();
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index 7e0ceef..a0f583e 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -285,10 +285,6 @@ // Returns the possible form types. std::set<FormType> GetFormTypes() const; - // Returns a collection of ServerFieldTypes corresponding to this - // FormStructure's fields. - std::vector<ServerFieldType> GetServerFieldTypes() const; - bool passwords_were_revealed() const { return passwords_were_revealed_; } void set_passwords_were_revealed(bool passwords_were_revealed) { passwords_were_revealed_ = passwords_were_revealed;
diff --git a/components/autofill/core/browser/metrics/address_form_event_logger.cc b/components/autofill/core/browser/metrics/address_form_event_logger.cc index a5cb728..9513cf2 100644 --- a/components/autofill/core/browser/metrics/address_form_event_logger.cc +++ b/components/autofill/core/browser/metrics/address_form_event_logger.cc
@@ -84,14 +84,7 @@ void AddressFormEventLogger::OnLog(const std::string& name, FormEvent event, const FormStructure& form) const { - std::vector<ServerFieldType> types; - std::transform( - form.begin(), form.end(), std::back_inserter(types), - [&](const std::unique_ptr<AutofillField>& field) -> ServerFieldType { - return field->Type().GetStorableType(); - }); - - uint32_t groups = data_util::DetermineGroups(types); + uint32_t groups = data_util::DetermineGroups(form); base::UmaHistogramEnumeration( name + data_util::GetSuffixForProfileFormType(groups), event, NUM_FORM_EVENTS);
diff --git a/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc b/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc index cd89e47..6361003 100644 --- a/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc +++ b/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc
@@ -10,8 +10,8 @@ #include "components/blocked_content/popup_blocker_tab_helper.h" #include "components/blocked_content/safe_browsing_triggered_popup_blocker.h" #include "components/blocked_content/test/test_popup_navigation_delegate.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" -#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h" +#include "components/content_settings/browser/page_specific_content_settings.h" +#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/infobar.h" @@ -54,10 +54,10 @@ HostContentSettingsMap::RegisterProfilePrefs(pref_service_.registry()); settings_map_ = base::MakeRefCounted<HostContentSettingsMap>( &pref_service_, false, false, false, false); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), std::make_unique< - content_settings::TestTabSpecificContentSettingsDelegate>( + content_settings::TestPageSpecificContentSettingsDelegate>( /*prefs=*/nullptr, settings_map_.get())); PopupBlockerTabHelper::CreateForWebContents(web_contents());
diff --git a/components/blocked_content/popup_blocker_tab_helper.cc b/components/blocked_content/popup_blocker_tab_helper.cc index 97509a4..ef6f2e7 100644 --- a/components/blocked_content/popup_blocker_tab_helper.cc +++ b/components/blocked_content/popup_blocker_tab_helper.cc
@@ -13,7 +13,7 @@ #include "components/blocked_content/popup_navigation_delegate.h" #include "components/blocked_content/popup_tracker.h" #include "components/blocked_content/safe_browsing_triggered_popup_blocker.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "content/public/browser/back_forward_cache.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_handle.h" @@ -75,10 +75,10 @@ } void PopupBlockerTabHelper::HidePopupNotification() { - auto* tscs = content_settings::TabSpecificContentSettings::GetForFrame( + auto* pscs = content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); - if (tscs) - tscs->ClearPopupsBlocked(); + if (pscs) + pscs->ClearPopupsBlocked(); } void PopupBlockerTabHelper::AddBlockedPopup( @@ -95,11 +95,10 @@ blocked_popups_[id] = std::make_unique<BlockedRequest>( std::move(delegate), window_features, block_type); - // TODO(carlscab): TabSpecificContentSettings is really - // PageSpecificContentSettings so it does not matter that we use the - // source_frame here and the main frame in HidePopupNotification + // PageSpecificContentSettings is per page so it does not matter that we use + // the source_frame here and the main frame in HidePopupNotification auto* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame(source_frame); + content_settings::PageSpecificContentSettings::GetForFrame(source_frame); if (content_settings) { content_settings->OnContentBlocked(ContentSettingsType::POPUPS); }
diff --git a/components/blocked_content/popup_blocker_tab_helper_unittest.cc b/components/blocked_content/popup_blocker_tab_helper_unittest.cc index 1720115..bd87de5 100644 --- a/components/blocked_content/popup_blocker_tab_helper_unittest.cc +++ b/components/blocked_content/popup_blocker_tab_helper_unittest.cc
@@ -9,8 +9,8 @@ #include "components/blocked_content/safe_browsing_triggered_popup_blocker.h" #include "components/blocked_content/test/test_popup_navigation_delegate.h" #include "components/blocked_content/url_list_manager.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" -#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h" +#include "components/content_settings/browser/page_specific_content_settings.h" +#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/test_renderer_host.h" @@ -58,10 +58,10 @@ HostContentSettingsMap::RegisterProfilePrefs(pref_service_.registry()); settings_map_ = base::MakeRefCounted<HostContentSettingsMap>( &pref_service_, false, false, false, false); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), std::make_unique< - content_settings::TestTabSpecificContentSettingsDelegate>( + content_settings::TestPageSpecificContentSettingsDelegate>( /*prefs=*/nullptr, settings_map_.get())); PopupBlockerTabHelper::CreateForWebContents(web_contents()); @@ -153,7 +153,7 @@ TEST_F(PopupBlockerTabHelperTest, SetsContentSettingsPopupState) { auto* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); EXPECT_FALSE(content_settings->IsContentBlocked(ContentSettingsType::POPUPS)); @@ -183,12 +183,12 @@ web_contents()->GetMainFrame(), std::make_unique<TestPopupNavigationDelegate>(GURL(kUrl1), &result), blink::mojom::WindowFeatures(), PopupBlockType::kNoGesture); - EXPECT_TRUE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_TRUE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); NavigateAndCommit(GURL(kUrl2)); - EXPECT_FALSE(content_settings::TabSpecificContentSettings::GetForFrame( + EXPECT_FALSE(content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()) ->IsContentBlocked(ContentSettingsType::POPUPS)); }
diff --git a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc index 8277998..d91674a 100644 --- a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc +++ b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
@@ -18,8 +18,8 @@ #include "components/blocked_content/popup_blocker_tab_helper.h" #include "components/blocked_content/popup_navigation_delegate.h" #include "components/blocked_content/test/test_popup_navigation_delegate.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" -#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h" +#include "components/content_settings/browser/page_specific_content_settings.h" +#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h" @@ -83,10 +83,10 @@ subresource_filter::SubresourceFilterObserverManager::CreateForWebContents( web_contents()); PopupBlockerTabHelper::CreateForWebContents(web_contents()); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), std::make_unique< - content_settings::TestTabSpecificContentSettingsDelegate>( + content_settings::TestPageSpecificContentSettingsDelegate>( /*prefs=*/nullptr, settings_map_.get())); popup_blocker_ = SafeBrowsingTriggeredPopupBlocker::FromWebContents(web_contents());
diff --git a/components/content_settings/browser/BUILD.gn b/components/content_settings/browser/BUILD.gn index a4168a9..0670f9c1 100644 --- a/components/content_settings/browser/BUILD.gn +++ b/components/content_settings/browser/BUILD.gn
@@ -8,8 +8,8 @@ "content_settings_manager_impl.h", "content_settings_usages_state.cc", "content_settings_usages_state.h", - "tab_specific_content_settings.cc", - "tab_specific_content_settings.h", + "page_specific_content_settings.cc", + "page_specific_content_settings.h", ] deps = [ "//base", @@ -29,8 +29,8 @@ source_set("test_support") { testonly = true sources = [ - "test_tab_specific_content_settings_delegate.cc", - "test_tab_specific_content_settings_delegate.h", + "test_page_specific_content_settings_delegate.cc", + "test_page_specific_content_settings_delegate.h", ] deps = [ ":browser", @@ -40,7 +40,7 @@ source_set("unit_tests") { testonly = true - sources = [ "tab_specific_content_settings_unittest.cc" ] + sources = [ "page_specific_content_settings_unittest.cc" ] deps = [ ":browser", ":test_support",
diff --git a/components/content_settings/browser/content_settings_manager_impl.cc b/components/content_settings/browser/content_settings_manager_impl.cc index 066dc48..59fb642 100644 --- a/components/content_settings/browser/content_settings_manager_impl.cc +++ b/components/content_settings/browser/content_settings_manager_impl.cc
@@ -5,7 +5,7 @@ #include "components/content_settings/browser/content_settings_manager_impl.h" #include "base/memory/ptr_util.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/page_load_metrics/browser/metrics_web_contents_observer.h" #include "components/page_load_metrics/browser/page_load_metrics_observer.h" @@ -13,7 +13,7 @@ #include "content/public/browser/render_process_host.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" -using content_settings::TabSpecificContentSettings; +using content_settings::PageSpecificContentSettings; namespace content_settings { namespace { @@ -46,8 +46,8 @@ const GURL& top_origin_url, bool local, bool blocked_by_policy) { - TabSpecificContentSettings* settings = - TabSpecificContentSettings::GetForFrame( + PageSpecificContentSettings* settings = + PageSpecificContentSettings::GetForFrame( content::RenderFrameHost::FromID(process_id, frame_id)); if (settings) settings->OnDomStorageAccessed(origin_url, local, blocked_by_policy); @@ -95,7 +95,7 @@ switch (storage_type) { case StorageType::DATABASE: - TabSpecificContentSettings::WebDatabaseAccessed( + PageSpecificContentSettings::WebDatabaseAccessed( render_process_id_, render_frame_id, url, !allowed); break; case StorageType::LOCAL_STORAGE: @@ -114,21 +114,21 @@ break; case StorageType::FILE_SYSTEM: - TabSpecificContentSettings::FileSystemAccessed( + PageSpecificContentSettings::FileSystemAccessed( render_process_id_, render_frame_id, url, !allowed); OnStorageAccessed(render_process_id_, render_frame_id, url, top_frame_origin.GetURL(), !allowed, page_load_metrics::StorageType::kFileSystem); break; case StorageType::INDEXED_DB: - TabSpecificContentSettings::IndexedDBAccessed( + PageSpecificContentSettings::IndexedDBAccessed( render_process_id_, render_frame_id, url, !allowed); OnStorageAccessed(render_process_id_, render_frame_id, url, top_frame_origin.GetURL(), !allowed, page_load_metrics::StorageType::kIndexedDb); break; case StorageType::CACHE: - TabSpecificContentSettings::CacheStorageAccessed( + PageSpecificContentSettings::CacheStorageAccessed( render_process_id_, render_frame_id, url, !allowed); OnStorageAccessed(render_process_id_, render_frame_id, url, top_frame_origin.GetURL(), !allowed, @@ -144,9 +144,9 @@ void ContentSettingsManagerImpl::OnContentBlocked(int32_t render_frame_id, ContentSettingsType type) { - TabSpecificContentSettings* settings = - TabSpecificContentSettings::GetForFrame(render_process_id_, - render_frame_id); + PageSpecificContentSettings* settings = + PageSpecificContentSettings::GetForFrame(render_process_id_, + render_frame_id); if (settings) settings->OnContentBlocked(type); }
diff --git a/components/content_settings/browser/content_settings_usages_state.cc b/components/content_settings/browser/content_settings_usages_state.cc index 63e75f1..03203264 100644 --- a/components/content_settings/browser/content_settings_usages_state.cc +++ b/components/content_settings/browser/content_settings_usages_state.cc
@@ -11,7 +11,7 @@ #include "components/url_formatter/url_formatter.h" ContentSettingsUsagesState::ContentSettingsUsagesState( - content_settings::TabSpecificContentSettings::Delegate* delegate_, + content_settings::PageSpecificContentSettings::Delegate* delegate_, ContentSettingsType type, const GURL& embedder_url) : delegate_(delegate_), type_(type), embedder_url_(embedder_url) {}
diff --git a/components/content_settings/browser/content_settings_usages_state.h b/components/content_settings/browser/content_settings_usages_state.h index 2e68ca9..11c4cdc 100644 --- a/components/content_settings/browser/content_settings_usages_state.h +++ b/components/content_settings/browser/content_settings_usages_state.h
@@ -9,7 +9,7 @@ #include <set> #include "base/macros.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "url/gurl.h" @@ -22,7 +22,7 @@ class ContentSettingsUsagesState { public: ContentSettingsUsagesState( - content_settings::TabSpecificContentSettings::Delegate* delegate_, + content_settings::PageSpecificContentSettings::Delegate* delegate_, ContentSettingsType type, const GURL& embedder_url); @@ -55,7 +55,7 @@ private: std::string GURLToFormattedHost(const GURL& url) const; - content_settings::TabSpecificContentSettings::Delegate* delegate_; + content_settings::PageSpecificContentSettings::Delegate* delegate_; ContentSettingsType type_; StateMap state_map_; GURL embedder_url_;
diff --git a/components/content_settings/browser/tab_specific_content_settings.cc b/components/content_settings/browser/page_specific_content_settings.cc similarity index 79% rename from components/content_settings/browser/tab_specific_content_settings.cc rename to components/content_settings/browser/page_specific_content_settings.cc index 2a667d6..b243d9f 100644 --- a/components/content_settings/browser/tab_specific_content_settings.cc +++ b/components/content_settings/browser/page_specific_content_settings.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include <list> #include <vector> @@ -61,7 +61,7 @@ void MaybeSendRendererContentSettingsRules( content::RenderFrameHost* rfh, const HostContentSettingsMap* map, - TabSpecificContentSettings::Delegate* delegate) { + PageSpecificContentSettings::Delegate* delegate) { DCHECK_EQ(rfh, rfh->GetMainFrame()); // Only send a message to the renderer if it is initialised and not dead. // Otherwise, the IPC messages will be queued in the browser process, @@ -75,7 +75,7 @@ delegate->SetContentSettingRules(process, rules); } -bool WillNavigationCreateNewTabSpecificContentSettingsOnCommit( +bool WillNavigationCreateNewPageSpecificContentSettingsOnCommit( content::NavigationHandle* navigation_handle) { return navigation_handle->IsInMainFrame() && !navigation_handle->IsSameDocument() && @@ -84,67 +84,68 @@ } // namespace -TabSpecificContentSettings::SiteDataObserver::SiteDataObserver( +PageSpecificContentSettings::SiteDataObserver::SiteDataObserver( content::WebContents* web_contents) : web_contents_(web_contents) { // Make sure the handler was attached to the WebContents as some UT might skip // this. auto* handler = - TabSpecificContentSettings::WebContentsHandler::FromWebContents( + PageSpecificContentSettings::WebContentsHandler::FromWebContents( web_contents_); if (handler) handler->AddSiteDataObserver(this); } -TabSpecificContentSettings::SiteDataObserver::~SiteDataObserver() { +PageSpecificContentSettings::SiteDataObserver::~SiteDataObserver() { if (!web_contents_) return; auto* handler = - TabSpecificContentSettings::WebContentsHandler::FromWebContents( + PageSpecificContentSettings::WebContentsHandler::FromWebContents( web_contents_); if (handler) handler->RemoveSiteDataObserver(this); } -void TabSpecificContentSettings::SiteDataObserver::WebContentsDestroyed() { +void PageSpecificContentSettings::SiteDataObserver::WebContentsDestroyed() { web_contents_ = nullptr; } // static -void TabSpecificContentSettings::WebContentsHandler::CreateForWebContents( +void PageSpecificContentSettings::WebContentsHandler::CreateForWebContents( content::WebContents* web_contents, std::unique_ptr<Delegate> delegate) { DCHECK(web_contents); - if (TabSpecificContentSettings::WebContentsHandler::FromWebContents( + if (PageSpecificContentSettings::WebContentsHandler::FromWebContents( web_contents)) { return; } web_contents->SetUserData( - TabSpecificContentSettings::WebContentsHandler::UserDataKey(), - base::WrapUnique(new TabSpecificContentSettings::WebContentsHandler( + PageSpecificContentSettings::WebContentsHandler::UserDataKey(), + base::WrapUnique(new PageSpecificContentSettings::WebContentsHandler( web_contents, std::move(delegate)))); } -TabSpecificContentSettings::WebContentsHandler::WebContentsHandler( +PageSpecificContentSettings::WebContentsHandler::WebContentsHandler( content::WebContents* web_contents, std::unique_ptr<Delegate> delegate) : WebContentsObserver(web_contents), delegate_(std::move(delegate)), map_(delegate_->GetSettingsMap()) { - DCHECK(!TabSpecificContentSettings::GetForCurrentDocument( + DCHECK(!PageSpecificContentSettings::GetForCurrentDocument( web_contents->GetMainFrame())); content::SetRenderDocumentHostUserData( - web_contents->GetMainFrame(), TabSpecificContentSettings::UserDataKey(), - base::WrapUnique(new TabSpecificContentSettings(*this, delegate_.get()))); + web_contents->GetMainFrame(), PageSpecificContentSettings::UserDataKey(), + base::WrapUnique( + new PageSpecificContentSettings(*this, delegate_.get()))); } -TabSpecificContentSettings::WebContentsHandler::~WebContentsHandler() { +PageSpecificContentSettings::WebContentsHandler::~WebContentsHandler() { for (SiteDataObserver& observer : observer_list_) observer.WebContentsDestroyed(); } -void TabSpecificContentSettings::WebContentsHandler:: +void PageSpecificContentSettings::WebContentsHandler:: TransferNavigationContentSettingsToCommittedDocument( const InflightNavigationContentSettings& navigation_settings, content::RenderFrameHost* rfh) { @@ -158,7 +159,7 @@ } } -void TabSpecificContentSettings::WebContentsHandler::OnCookiesAccessed( +void PageSpecificContentSettings::WebContentsHandler::OnCookiesAccessed( content::NavigationHandle* navigation, const content::CookieAccessDetails& details) { auto it = inflight_navigation_settings_.find(navigation); @@ -167,23 +168,23 @@ return; } // TODO(carlscab): We should be able to - // DHECK(!WillNavigationCreateNewTabSpecificContentSettingsOnCommit) here, but - // there is still code that starts a navigation before attaching the tab + // DHECK(!WillNavigationCreateNewPageSpecificContentSettingsOnCommit) here, + // but there is still code that starts a navigation before attaching the tab // helpers in DevConsole related code. So we miss the DidStartNavigation event // for those navigations. (https://crbug.com/1095576) OnCookiesAccessed(web_contents()->GetMainFrame(), details); } -void TabSpecificContentSettings::WebContentsHandler::OnCookiesAccessed( +void PageSpecificContentSettings::WebContentsHandler::OnCookiesAccessed( content::RenderFrameHost* rfh, const content::CookieAccessDetails& details) { auto* tscs = - TabSpecificContentSettings::GetForCurrentDocument(rfh->GetMainFrame()); + PageSpecificContentSettings::GetForCurrentDocument(rfh->GetMainFrame()); if (tscs) tscs->OnCookiesAccessed(details); } -void TabSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed( +void PageSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed( content::NavigationHandle* navigation, const GURL& scope, content::AllowServiceWorkerResult allowed) { @@ -196,24 +197,24 @@ return; } // TODO(carlscab): We should be able to - // DHECK(!WillNavigationCreateNewTabSpecificContentSettingsOnCommit) here, but - // there is still code that starts a navigation before attaching the tab + // DHECK(!WillNavigationCreateNewPageSpecificContentSettingsOnCommit) here, + // but there is still code that starts a navigation before attaching the tab // helpers in DevConsole related code. So we miss the DidStartNavigation event // for those navigations. OnServiceWorkerAccessed(web_contents()->GetMainFrame(), scope, allowed); } -void TabSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed( +void PageSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed( content::RenderFrameHost* frame, const GURL& scope, content::AllowServiceWorkerResult allowed) { auto* tscs = - TabSpecificContentSettings::GetForCurrentDocument(frame->GetMainFrame()); + PageSpecificContentSettings::GetForCurrentDocument(frame->GetMainFrame()); if (tscs) tscs->OnServiceWorkerAccessed(scope, allowed); } -void TabSpecificContentSettings::WebContentsHandler:: +void PageSpecificContentSettings::WebContentsHandler:: RenderFrameForInterstitialPageCreated( content::RenderFrameHost* render_frame_host) { // We want to tell the renderer-side code to ignore content settings for this @@ -225,9 +226,9 @@ content_settings_agent->SetAsInterstitial(); } -void TabSpecificContentSettings::WebContentsHandler::DidStartNavigation( +void PageSpecificContentSettings::WebContentsHandler::DidStartNavigation( content::NavigationHandle* navigation_handle) { - if (!WillNavigationCreateNewTabSpecificContentSettingsOnCommit( + if (!WillNavigationCreateNewPageSpecificContentSettingsOnCommit( navigation_handle)) { return; } @@ -236,9 +237,9 @@ std::make_pair(navigation_handle, InflightNavigationContentSettings())); } -void TabSpecificContentSettings::WebContentsHandler::ReadyToCommitNavigation( +void PageSpecificContentSettings::WebContentsHandler::ReadyToCommitNavigation( content::NavigationHandle* navigation_handle) { - if (!WillNavigationCreateNewTabSpecificContentSettingsOnCommit( + if (!WillNavigationCreateNewPageSpecificContentSettingsOnCommit( navigation_handle)) { return; } @@ -251,9 +252,9 @@ delegate_.get()); } -void TabSpecificContentSettings::WebContentsHandler::DidFinishNavigation( +void PageSpecificContentSettings::WebContentsHandler::DidFinishNavigation( content::NavigationHandle* navigation_handle) { - if (!WillNavigationCreateNewTabSpecificContentSettingsOnCommit( + if (!WillNavigationCreateNewPageSpecificContentSettingsOnCommit( navigation_handle)) { return; } @@ -264,13 +265,13 @@ } auto tscs = - base::WrapUnique(new TabSpecificContentSettings(*this, delegate_.get())); + base::WrapUnique(new PageSpecificContentSettings(*this, delegate_.get())); // TODO(carlscab): This sort of internal. Maybe add a // RenderDocumentHostUserData::Create(RenderFrameHost* rfh, Params...) content::SetRenderDocumentHostUserData( navigation_handle->GetRenderFrameHost(), - TabSpecificContentSettings::UserDataKey(), std::move(tscs)); + PageSpecificContentSettings::UserDataKey(), std::move(tscs)); auto it = inflight_navigation_settings_.find(navigation_handle); if (it != inflight_navigation_settings_.end()) { @@ -282,54 +283,55 @@ delegate_->UpdateLocationBar(); } -void TabSpecificContentSettings::WebContentsHandler::AppCacheAccessed( +void PageSpecificContentSettings::WebContentsHandler::AppCacheAccessed( const GURL& manifest_url, bool blocked_by_policy) { - auto* tscs = TabSpecificContentSettings::GetForCurrentDocument( + auto* tscs = PageSpecificContentSettings::GetForCurrentDocument( web_contents()->GetMainFrame()); if (tscs) tscs->AppCacheAccessed(manifest_url, blocked_by_policy); } -void TabSpecificContentSettings::WebContentsHandler::AddSiteDataObserver( +void PageSpecificContentSettings::WebContentsHandler::AddSiteDataObserver( SiteDataObserver* observer) { observer_list_.AddObserver(observer); } -void TabSpecificContentSettings::WebContentsHandler::RemoveSiteDataObserver( +void PageSpecificContentSettings::WebContentsHandler::RemoveSiteDataObserver( SiteDataObserver* observer) { observer_list_.RemoveObserver(observer); } -void TabSpecificContentSettings::WebContentsHandler::NotifySiteDataObservers() { +void PageSpecificContentSettings::WebContentsHandler:: + NotifySiteDataObservers() { for (SiteDataObserver& observer : observer_list_) observer.OnSiteDataAccessed(); } -TabSpecificContentSettings::WebContentsHandler:: +PageSpecificContentSettings::WebContentsHandler:: InflightNavigationContentSettings::InflightNavigationContentSettings() = default; -TabSpecificContentSettings::WebContentsHandler:: +PageSpecificContentSettings::WebContentsHandler:: InflightNavigationContentSettings::InflightNavigationContentSettings( const InflightNavigationContentSettings&) = default; -TabSpecificContentSettings::WebContentsHandler:: +PageSpecificContentSettings::WebContentsHandler:: InflightNavigationContentSettings::InflightNavigationContentSettings( InflightNavigationContentSettings&&) = default; -TabSpecificContentSettings::WebContentsHandler:: +PageSpecificContentSettings::WebContentsHandler:: InflightNavigationContentSettings::~InflightNavigationContentSettings() = default; -TabSpecificContentSettings::WebContentsHandler:: +PageSpecificContentSettings::WebContentsHandler:: InflightNavigationContentSettings& - TabSpecificContentSettings::WebContentsHandler:: + PageSpecificContentSettings::WebContentsHandler:: InflightNavigationContentSettings::operator=( InflightNavigationContentSettings&&) = default; -WEB_CONTENTS_USER_DATA_KEY_IMPL(TabSpecificContentSettings::WebContentsHandler) +WEB_CONTENTS_USER_DATA_KEY_IMPL(PageSpecificContentSettings::WebContentsHandler) -TabSpecificContentSettings::TabSpecificContentSettings( - TabSpecificContentSettings::WebContentsHandler& handler, +PageSpecificContentSettings::PageSpecificContentSettings( + PageSpecificContentSettings::WebContentsHandler& handler, Delegate* delegate) : handler_(handler), main_frame_(handler_.web_contents()->GetMainFrame()), @@ -357,30 +359,30 @@ observer_.Add(map_); } -TabSpecificContentSettings::~TabSpecificContentSettings() = default; +PageSpecificContentSettings::~PageSpecificContentSettings() = default; // static -void TabSpecificContentSettings::CreateForWebContents( +void PageSpecificContentSettings::CreateForWebContents( content::WebContents* web_contents, std::unique_ptr<Delegate> delegate) { - TabSpecificContentSettings::WebContentsHandler::CreateForWebContents( + PageSpecificContentSettings::WebContentsHandler::CreateForWebContents( web_contents, std::move(delegate)); } // static -void TabSpecificContentSettings::DeleteForWebContentsForTest( +void PageSpecificContentSettings::DeleteForWebContentsForTest( content::WebContents* web_contents) { if (web_contents->GetMainFrame()) { - TabSpecificContentSettings::DeleteForCurrentDocument( + PageSpecificContentSettings::DeleteForCurrentDocument( web_contents->GetMainFrame()); } web_contents->RemoveUserData( - TabSpecificContentSettings::WebContentsHandler::UserDataKey()); + PageSpecificContentSettings::WebContentsHandler::UserDataKey()); } // static -TabSpecificContentSettings* TabSpecificContentSettings::GetForFrame( +PageSpecificContentSettings* PageSpecificContentSettings::GetForFrame( int render_process_id, int render_frame_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -389,74 +391,74 @@ } // static -TabSpecificContentSettings* TabSpecificContentSettings::GetForFrame( +PageSpecificContentSettings* PageSpecificContentSettings::GetForFrame( content::RenderFrameHost* rfh) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - return rfh ? TabSpecificContentSettings::GetForCurrentDocument( + return rfh ? PageSpecificContentSettings::GetForCurrentDocument( rfh->GetMainFrame()) : nullptr; } // static -TabSpecificContentSettings::Delegate* -TabSpecificContentSettings::GetDelegateForWebContents( +PageSpecificContentSettings::Delegate* +PageSpecificContentSettings::GetDelegateForWebContents( content::WebContents* web_contents) { auto* handler = - TabSpecificContentSettings::WebContentsHandler::FromWebContents( + PageSpecificContentSettings::WebContentsHandler::FromWebContents( web_contents); return handler ? handler->delegate() : nullptr; } // static -void TabSpecificContentSettings::WebDatabaseAccessed(int render_process_id, - int render_frame_id, - const GURL& url, - bool blocked_by_policy) { +void PageSpecificContentSettings::WebDatabaseAccessed(int render_process_id, + int render_frame_id, + const GURL& url, + bool blocked_by_policy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - TabSpecificContentSettings* settings = + PageSpecificContentSettings* settings = GetForFrame(render_process_id, render_frame_id); if (settings) settings->OnWebDatabaseAccessed(url, blocked_by_policy); } // static -void TabSpecificContentSettings::IndexedDBAccessed(int render_process_id, - int render_frame_id, - const GURL& url, - bool blocked_by_policy) { +void PageSpecificContentSettings::IndexedDBAccessed(int render_process_id, + int render_frame_id, + const GURL& url, + bool blocked_by_policy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - TabSpecificContentSettings* settings = + PageSpecificContentSettings* settings = GetForFrame(render_process_id, render_frame_id); if (settings) settings->OnIndexedDBAccessed(url, blocked_by_policy); } // static -void TabSpecificContentSettings::CacheStorageAccessed(int render_process_id, - int render_frame_id, - const GURL& url, - bool blocked_by_policy) { +void PageSpecificContentSettings::CacheStorageAccessed(int render_process_id, + int render_frame_id, + const GURL& url, + bool blocked_by_policy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - TabSpecificContentSettings* settings = + PageSpecificContentSettings* settings = GetForFrame(render_process_id, render_frame_id); if (settings) settings->OnCacheStorageAccessed(url, blocked_by_policy); } // static -void TabSpecificContentSettings::FileSystemAccessed(int render_process_id, - int render_frame_id, - const GURL& url, - bool blocked_by_policy) { +void PageSpecificContentSettings::FileSystemAccessed(int render_process_id, + int render_frame_id, + const GURL& url, + bool blocked_by_policy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - TabSpecificContentSettings* settings = + PageSpecificContentSettings* settings = GetForFrame(render_process_id, render_frame_id); if (settings) settings->OnFileSystemAccessed(url, blocked_by_policy); } // static -void TabSpecificContentSettings::SharedWorkerAccessed( +void PageSpecificContentSettings::SharedWorkerAccessed( int render_process_id, int render_frame_id, const GURL& worker_url, @@ -464,7 +466,7 @@ const url::Origin& constructor_origin, bool blocked_by_policy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - TabSpecificContentSettings* settings = + PageSpecificContentSettings* settings = GetForFrame(render_process_id, render_frame_id); if (settings) settings->OnSharedWorkerAccessed(worker_url, name, constructor_origin, @@ -473,13 +475,13 @@ // static content::WebContentsObserver* -TabSpecificContentSettings::GetWebContentsObserverForTest( +PageSpecificContentSettings::GetWebContentsObserverForTest( content::WebContents* web_contents) { - return TabSpecificContentSettings::WebContentsHandler::FromWebContents( + return PageSpecificContentSettings::WebContentsHandler::FromWebContents( web_contents); } -bool TabSpecificContentSettings::IsContentBlocked( +bool PageSpecificContentSettings::IsContentBlocked( ContentSettingsType content_type) const { DCHECK_NE(ContentSettingsType::GEOLOCATION, content_type) << "Geolocation settings handled by ContentSettingGeolocationImageModel"; @@ -511,7 +513,7 @@ return false; } -bool TabSpecificContentSettings::IsContentAllowed( +bool PageSpecificContentSettings::IsContentAllowed( ContentSettingsType content_type) const { DCHECK_NE(ContentSettingsType::AUTOMATIC_DOWNLOADS, content_type) << "Automatic downloads handled by DownloadRequestLimiter"; @@ -535,7 +537,7 @@ return false; } -void TabSpecificContentSettings::OnContentBlocked(ContentSettingsType type) { +void PageSpecificContentSettings::OnContentBlocked(ContentSettingsType type) { DCHECK(type != ContentSettingsType::GEOLOCATION) << "Geolocation settings handled by OnGeolocationPermissionSet"; DCHECK(type != ContentSettingsType::MEDIASTREAM_MIC && @@ -553,7 +555,7 @@ } } -void TabSpecificContentSettings::OnContentAllowed(ContentSettingsType type) { +void PageSpecificContentSettings::OnContentAllowed(ContentSettingsType type) { DCHECK(type != ContentSettingsType::GEOLOCATION) << "Geolocation settings handled by OnGeolocationPermissionSet"; DCHECK(type != ContentSettingsType::MEDIASTREAM_MIC && @@ -597,9 +599,9 @@ delegate_->UpdateLocationBar(); } -void TabSpecificContentSettings::OnDomStorageAccessed(const GURL& url, - bool local, - bool blocked_by_policy) { +void PageSpecificContentSettings::OnDomStorageAccessed(const GURL& url, + bool local, + bool blocked_by_policy) { browsing_data::LocalSharedObjectsContainer& container = blocked_by_policy ? blocked_local_shared_objects_ : allowed_local_shared_objects_; @@ -615,7 +617,7 @@ handler_.NotifySiteDataObservers(); } -void TabSpecificContentSettings::OnCookiesAccessed( +void PageSpecificContentSettings::OnCookiesAccessed( const content::CookieAccessDetails& details) { if (details.cookie_list.empty()) return; @@ -631,8 +633,8 @@ handler_.NotifySiteDataObservers(); } -void TabSpecificContentSettings::OnIndexedDBAccessed(const GURL& url, - bool blocked_by_policy) { +void PageSpecificContentSettings::OnIndexedDBAccessed(const GURL& url, + bool blocked_by_policy) { if (blocked_by_policy) { blocked_local_shared_objects_.indexed_dbs()->Add(url::Origin::Create(url)); OnContentBlocked(ContentSettingsType::COOKIES); @@ -644,7 +646,7 @@ handler_.NotifySiteDataObservers(); } -void TabSpecificContentSettings::OnCacheStorageAccessed( +void PageSpecificContentSettings::OnCacheStorageAccessed( const GURL& url, bool blocked_by_policy) { if (blocked_by_policy) { @@ -660,7 +662,7 @@ handler_.NotifySiteDataObservers(); } -void TabSpecificContentSettings::OnServiceWorkerAccessed( +void PageSpecificContentSettings::OnServiceWorkerAccessed( const GURL& scope, content::AllowServiceWorkerResult allowed) { DCHECK(scope.is_valid()); @@ -684,7 +686,7 @@ } } -void TabSpecificContentSettings::OnSharedWorkerAccessed( +void PageSpecificContentSettings::OnSharedWorkerAccessed( const GURL& worker_url, const std::string& name, const url::Origin& constructor_origin, @@ -701,8 +703,9 @@ } } -void TabSpecificContentSettings::OnWebDatabaseAccessed(const GURL& url, - bool blocked_by_policy) { +void PageSpecificContentSettings::OnWebDatabaseAccessed( + const GURL& url, + bool blocked_by_policy) { if (blocked_by_policy) { blocked_local_shared_objects_.databases()->Add(url::Origin::Create(url)); OnContentBlocked(ContentSettingsType::COOKIES); @@ -714,8 +717,8 @@ handler_.NotifySiteDataObservers(); } -void TabSpecificContentSettings::OnFileSystemAccessed(const GURL& url, - bool blocked_by_policy) { +void PageSpecificContentSettings::OnFileSystemAccessed(const GURL& url, + bool blocked_by_policy) { // Note that all sandboxed file system access is recorded here as // kTemporary; the distinction between temporary (default) and persistent // storage is not made in the UI that presents this data. @@ -730,7 +733,7 @@ handler_.NotifySiteDataObservers(); } -void TabSpecificContentSettings::OnGeolocationPermissionSet( +void PageSpecificContentSettings::OnGeolocationPermissionSet( const GURL& requesting_origin, bool allowed) { geolocation_usages_state_->OnPermissionSet(requesting_origin, allowed); @@ -738,7 +741,7 @@ } #if defined(OS_ANDROID) || defined(OS_CHROMEOS) -void TabSpecificContentSettings::OnProtectedMediaIdentifierPermissionSet( +void PageSpecificContentSettings::OnProtectedMediaIdentifierPermissionSet( const GURL& requesting_origin, bool allowed) { if (allowed) { @@ -749,12 +752,12 @@ } #endif -TabSpecificContentSettings::MicrophoneCameraState -TabSpecificContentSettings::GetMicrophoneCameraState() const { +PageSpecificContentSettings::MicrophoneCameraState +PageSpecificContentSettings::GetMicrophoneCameraState() const { return microphone_camera_state_ | delegate_->GetMicrophoneCameraState(); } -bool TabSpecificContentSettings::IsMicrophoneCameraStateChanged() const { +bool PageSpecificContentSettings::IsMicrophoneCameraStateChanged() const { if ((microphone_camera_state_ & MICROPHONE_ACCESSED) && ((microphone_camera_state_ & MICROPHONE_BLOCKED) ? !IsContentBlocked(ContentSettingsType::MEDIASTREAM_MIC) @@ -772,7 +775,7 @@ media_stream_selected_video_device()); } -void TabSpecificContentSettings::OnMediaStreamPermissionSet( +void PageSpecificContentSettings::OnMediaStreamPermissionSet( const GURL& request_origin, MicrophoneCameraState new_microphone_camera_state, const std::string& media_stream_selected_audio_device, @@ -807,34 +810,34 @@ } } -void TabSpecificContentSettings::OnMidiSysExAccessed( +void PageSpecificContentSettings::OnMidiSysExAccessed( const GURL& requesting_origin) { midi_usages_state_->OnPermissionSet(requesting_origin, true); OnContentAllowed(ContentSettingsType::MIDI_SYSEX); } -void TabSpecificContentSettings::OnMidiSysExAccessBlocked( +void PageSpecificContentSettings::OnMidiSysExAccessBlocked( const GURL& requesting_origin) { midi_usages_state_->OnPermissionSet(requesting_origin, false); OnContentBlocked(ContentSettingsType::MIDI_SYSEX); } -void TabSpecificContentSettings::FlashDownloadBlocked() { +void PageSpecificContentSettings::FlashDownloadBlocked() { OnContentBlocked(ContentSettingsType::PLUGINS); } -void TabSpecificContentSettings::ClearPopupsBlocked() { +void PageSpecificContentSettings::ClearPopupsBlocked() { ContentSettingsStatus& status = content_settings_status_[ContentSettingsType::POPUPS]; status.blocked = false; delegate_->UpdateLocationBar(); } -void TabSpecificContentSettings::OnAudioBlocked() { +void PageSpecificContentSettings::OnAudioBlocked() { OnContentBlocked(ContentSettingsType::SOUND); } -void TabSpecificContentSettings::SetPepperBrokerAllowed(bool allowed) { +void PageSpecificContentSettings::SetPepperBrokerAllowed(bool allowed) { if (allowed) { OnContentAllowed(ContentSettingsType::PPAPI_BROKER); } else { @@ -842,7 +845,7 @@ } } -void TabSpecificContentSettings::OnContentSettingChanged( +void PageSpecificContentSettings::OnContentSettingChanged( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, ContentSettingsType content_type, @@ -915,8 +918,8 @@ MaybeSendRendererContentSettingsRules(main_frame_, map_, delegate_); } -void TabSpecificContentSettings::AppCacheAccessed(const GURL& manifest_url, - bool blocked_by_policy) { +void PageSpecificContentSettings::AppCacheAccessed(const GURL& manifest_url, + bool blocked_by_policy) { if (blocked_by_policy) { blocked_local_shared_objects_.appcaches()->Add( url::Origin::Create(manifest_url)); @@ -928,11 +931,11 @@ } } -void TabSpecificContentSettings::ClearContentSettingsChangedViaPageInfo() { +void PageSpecificContentSettings::ClearContentSettingsChangedViaPageInfo() { content_settings_changed_via_page_info_.clear(); } -void TabSpecificContentSettings::BlockAllContentForTesting() { +void PageSpecificContentSettings::BlockAllContentForTesting() { content_settings::ContentSettingsRegistry* registry = content_settings::ContentSettingsRegistry::GetInstance(); for (const content_settings::ContentSettingsInfo* info : *registry) { @@ -945,30 +948,30 @@ } // Geolocation and media must be blocked separately, as the generic - // TabSpecificContentSettings::OnContentBlocked does not apply to them. + // PageSpecificContentSettings::OnContentBlocked does not apply to them. OnGeolocationPermissionSet(main_frame_->GetLastCommittedURL(), false); MicrophoneCameraStateFlags media_blocked = static_cast<MicrophoneCameraStateFlags>( - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED); + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED); OnMediaStreamPermissionSet(main_frame_->GetLastCommittedURL(), media_blocked, std::string(), std::string(), std::string(), std::string()); } -void TabSpecificContentSettings::ContentSettingChangedViaPageInfo( +void PageSpecificContentSettings::ContentSettingChangedViaPageInfo( ContentSettingsType type) { content_settings_changed_via_page_info_.insert(type); } -bool TabSpecificContentSettings::HasContentSettingChangedViaPageInfo( +bool PageSpecificContentSettings::HasContentSettingChangedViaPageInfo( ContentSettingsType type) const { return content_settings_changed_via_page_info_.find(type) != content_settings_changed_via_page_info_.end(); } -RENDER_DOCUMENT_HOST_USER_DATA_KEY_IMPL(TabSpecificContentSettings) +RENDER_DOCUMENT_HOST_USER_DATA_KEY_IMPL(PageSpecificContentSettings) } // namespace content_settings
diff --git a/components/content_settings/browser/tab_specific_content_settings.h b/components/content_settings/browser/page_specific_content_settings.h similarity index 93% rename from components/content_settings/browser/tab_specific_content_settings.h rename to components/content_settings/browser/page_specific_content_settings.h index 6c3d78e..e7b267e 100644 --- a/components/content_settings/browser/tab_specific_content_settings.h +++ b/components/content_settings/browser/page_specific_content_settings.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_CONTENT_SETTINGS_BROWSER_TAB_SPECIFIC_CONTENT_SETTINGS_H_ -#define COMPONENTS_CONTENT_SETTINGS_BROWSER_TAB_SPECIFIC_CONTENT_SETTINGS_H_ +#ifndef COMPONENTS_CONTENT_SETTINGS_BROWSER_PAGE_SPECIFIC_CONTENT_SETTINGS_H_ +#define COMPONENTS_CONTENT_SETTINGS_BROWSER_PAGE_SPECIFIC_CONTENT_SETTINGS_H_ #include <stdint.h> @@ -42,7 +42,7 @@ namespace content_settings { -// TODO(msramek): Media is storing their state in TabSpecificContentSettings: +// TODO(msramek): Media is storing their state in PageSpecificContentSettings: // |microphone_camera_state_| without being tied to a single content setting. // This state is not ideal, potential solution is to save this information via // content::WebContentsUserData @@ -59,17 +59,15 @@ // keep references to objects of this class. // // When a page enters the back-forward cache its associated -// TabSpecificContentSettings are not cleared and will be restored along with +// PageSpecificContentSettings are not cleared and will be restored along with // the document when navigating back. These stored instances still listen to // content settings updates and keep their internal state up to date. // // Events tied to a main frame navigation will be associated with the newly // loaded page once the navigation commits or discarded if it does not. -// -// TODO(carlscab): Rename this class to PageSpecificContentSettings -class TabSpecificContentSettings +class PageSpecificContentSettings : public content_settings::Observer, - public content::RenderDocumentHostUserData<TabSpecificContentSettings> { + public content::RenderDocumentHostUserData<PageSpecificContentSettings> { public: // Fields describing the current mic/camera state. If a page has attempted to // access a device, the XXX_ACCESSED bit will be set. If access was blocked, @@ -138,7 +136,7 @@ // Classes that want to be notified about site data events must implement // this abstract class and add themselves as observer to the - // |TabSpecificContentSettings|. + // |PageSpecificContentSettings|. class SiteDataObserver { public: explicit SiteDataObserver(content::WebContents* web_contents); @@ -159,26 +157,27 @@ DISALLOW_COPY_AND_ASSIGN(SiteDataObserver); }; - ~TabSpecificContentSettings() override; + ~PageSpecificContentSettings() override; static void CreateForWebContents(content::WebContents* web_contents, std::unique_ptr<Delegate> delegate); static void DeleteForWebContentsForTest(content::WebContents* web_contents); // Returns the object given a RenderFrameHost ids. Returns nullptr if the - // frame no longer exist or there are no TabSpecificContentSettings attached + // frame no longer exist or there are no PageSpecificContentSettings attached // to the document. - static TabSpecificContentSettings* GetForFrame(int render_process_id, - int render_frame_id); + static PageSpecificContentSettings* GetForFrame(int render_process_id, + int render_frame_id); // Returns the object given a RenderFrameHost. Returns nullptr if the frame - // is nullptr or there are no TabSpecificContentSettings attached to the + // is nullptr or there are no PageSpecificContentSettings attached to the // document. - static TabSpecificContentSettings* GetForFrame(content::RenderFrameHost* rfh); + static PageSpecificContentSettings* GetForFrame( + content::RenderFrameHost* rfh); // Returns the Delegate that was associated to |web_contents| in // CreateForWebContents. Null if CreateForWebContents was not called for // |web_contents|. - static TabSpecificContentSettings::Delegate* GetDelegateForWebContents( + static PageSpecificContentSettings::Delegate* GetDelegateForWebContents( content::WebContents* web_contents); // Called when a specific Web database in the current page was accessed. If @@ -228,10 +227,10 @@ static content::WebContentsObserver* GetWebContentsObserverForTest( content::WebContents* web_contents); - // Returns a WeakPtr to this instance. Given that TabSpecificContentSettings + // Returns a WeakPtr to this instance. Given that PageSpecificContentSettings // instances are tied to a page it is generally unsafe to store these // references, instead a WeakPtr should be used instead. - base::WeakPtr<TabSpecificContentSettings> AsWeakPtr() { + base::WeakPtr<PageSpecificContentSettings> AsWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -379,10 +378,10 @@ bool HasContentSettingChangedViaPageInfo(ContentSettingsType type) const; private: - friend class content::RenderDocumentHostUserData<TabSpecificContentSettings>; + friend class content::RenderDocumentHostUserData<PageSpecificContentSettings>; // This class attaches to WebContents to listen to events and route them to - // appropriate TabSpecificContentSettings, store navigation related events + // appropriate PageSpecificContentSettings, store navigation related events // until the navigation finishes and then transferring the // navigation-associated state to the newly-created page. class WebContentsHandler @@ -488,8 +487,8 @@ WEB_CONTENTS_USER_DATA_KEY_DECL(); }; - explicit TabSpecificContentSettings( - TabSpecificContentSettings::WebContentsHandler& handler, + explicit PageSpecificContentSettings( + PageSpecificContentSettings::WebContentsHandler& handler, Delegate* delegate); void AppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy); @@ -564,11 +563,11 @@ RENDER_DOCUMENT_HOST_USER_DATA_KEY_DECL(); - base::WeakPtrFactory<TabSpecificContentSettings> weak_factory_{this}; + base::WeakPtrFactory<PageSpecificContentSettings> weak_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(TabSpecificContentSettings); + DISALLOW_COPY_AND_ASSIGN(PageSpecificContentSettings); }; } // namespace content_settings -#endif // COMPONENTS_CONTENT_SETTINGS_BROWSER_TAB_SPECIFIC_CONTENT_SETTINGS_H_ +#endif // COMPONENTS_CONTENT_SETTINGS_BROWSER_PAGE_SPECIFIC_CONTENT_SETTINGS_H_
diff --git a/components/content_settings/browser/tab_specific_content_settings_unittest.cc b/components/content_settings/browser/page_specific_content_settings_unittest.cc similarity index 87% rename from components/content_settings/browser/tab_specific_content_settings_unittest.cc rename to components/content_settings/browser/page_specific_content_settings_unittest.cc index 806028e..0d3212f 100644 --- a/components/content_settings/browser/tab_specific_content_settings_unittest.cc +++ b/components/content_settings/browser/page_specific_content_settings_unittest.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "base/macros.h" #include "base/optional.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h" +#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/security_state/core/security_state.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -26,7 +26,7 @@ namespace { class MockSiteDataObserver - : public TabSpecificContentSettings::SiteDataObserver { + : public PageSpecificContentSettings::SiteDataObserver { public: explicit MockSiteDataObserver(content::WebContents* web_contents) : SiteDataObserver(web_contents) {} @@ -41,7 +41,7 @@ } // namespace -class TabSpecificContentSettingsTest +class PageSpecificContentSettingsTest : public content::RenderViewHostTestHarness { public: void SetUp() override { @@ -49,9 +49,9 @@ HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry()); settings_map_ = base::MakeRefCounted<HostContentSettingsMap>( &prefs_, false, false, false, false); - TabSpecificContentSettings::CreateForWebContents( + PageSpecificContentSettings::CreateForWebContents( web_contents(), - std::make_unique<TestTabSpecificContentSettingsDelegate>( + std::make_unique<TestPageSpecificContentSettingsDelegate>( &prefs_, settings_map_.get())); } @@ -63,7 +63,7 @@ HostContentSettingsMap* settings_map() { return settings_map_.get(); } content::WebContentsObserver* GetHandle() { - return TabSpecificContentSettings::GetWebContentsObserverForTest( + return PageSpecificContentSettings::GetWebContentsObserverForTest( web_contents()); } @@ -72,10 +72,10 @@ scoped_refptr<HostContentSettingsMap> settings_map_; }; -TEST_F(TabSpecificContentSettingsTest, BlockedContent) { +TEST_F(PageSpecificContentSettingsTest, BlockedContent) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Check that after initializing, nothing is blocked. #if !defined(OS_ANDROID) @@ -107,17 +107,17 @@ {*cookie1}, false}); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); #if !defined(OS_ANDROID) content_settings->OnContentBlocked(ContentSettingsType::IMAGES); #endif content_settings->OnContentBlocked(ContentSettingsType::POPUPS); - TabSpecificContentSettings::MicrophoneCameraState + PageSpecificContentSettings::MicrophoneCameraState blocked_microphone_camera_state = - TabSpecificContentSettings::MICROPHONE_ACCESSED | - TabSpecificContentSettings::MICROPHONE_BLOCKED | - TabSpecificContentSettings::CAMERA_ACCESSED | - TabSpecificContentSettings::CAMERA_BLOCKED; + PageSpecificContentSettings::MICROPHONE_ACCESSED | + PageSpecificContentSettings::MICROPHONE_BLOCKED | + PageSpecificContentSettings::CAMERA_ACCESSED | + PageSpecificContentSettings::CAMERA_BLOCKED; content_settings->OnMediaStreamPermissionSet( GURL("http://google.com"), blocked_microphone_camera_state, std::string(), std::string(), std::string(), std::string()); @@ -168,12 +168,12 @@ simulator->GetNavigationHandle(), GURL("http://google.com"), content::AllowServiceWorkerResult::FromPolicy(true, false)); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); EXPECT_FALSE( content_settings->IsContentBlocked(ContentSettingsType::JAVASCRIPT)); simulator->Commit(); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Block a javascript when page starts to start ServiceWorker. GetHandle()->OnServiceWorkerAccessed( @@ -185,7 +185,7 @@ // Reset blocked content settings. NavigateAndCommit(GURL("http://google.com")); content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); #if !defined(OS_ANDROID) EXPECT_FALSE(content_settings->IsContentBlocked(ContentSettingsType::IMAGES)); EXPECT_FALSE( @@ -202,10 +202,10 @@ ContentSettingsType::MEDIASTREAM_CAMERA)); } -TEST_F(TabSpecificContentSettingsTest, BlockedFileSystems) { +TEST_F(PageSpecificContentSettingsTest, BlockedFileSystems) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Access a file system. content_settings->OnFileSystemAccessed(GURL("http://google.com"), false); @@ -217,10 +217,10 @@ EXPECT_TRUE(content_settings->IsContentBlocked(ContentSettingsType::COOKIES)); } -TEST_F(TabSpecificContentSettingsTest, AllowedContent) { +TEST_F(PageSpecificContentSettingsTest, AllowedContent) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // Test default settings. ASSERT_FALSE(content_settings->IsContentAllowed(ContentSettingsType::IMAGES)); @@ -262,10 +262,10 @@ ASSERT_TRUE(content_settings->IsContentBlocked(ContentSettingsType::COOKIES)); } -TEST_F(TabSpecificContentSettingsTest, EmptyCookieList) { +TEST_F(PageSpecificContentSettingsTest, EmptyCookieList) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); ASSERT_FALSE( content_settings->IsContentAllowed(ContentSettingsType::COOKIES)); @@ -281,10 +281,10 @@ content_settings->IsContentBlocked(ContentSettingsType::COOKIES)); } -TEST_F(TabSpecificContentSettingsTest, SiteDataObserver) { +TEST_F(PageSpecificContentSettingsTest, SiteDataObserver) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); MockSiteDataObserver mock_observer(web_contents()); EXPECT_CALL(mock_observer, OnSiteDataAccessed()).Times(6); @@ -322,10 +322,10 @@ blocked_by_policy); } -TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainer) { +TEST_F(PageSpecificContentSettingsTest, LocalSharedObjectsContainer) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); bool blocked_by_policy = false; auto cookie = net::CanonicalCookie::Create(GURL("http://google.com"), "k=v", base::Time::Now(), @@ -359,10 +359,10 @@ EXPECT_EQ(4u, objects.GetDomainCount()); } -TEST_F(TabSpecificContentSettingsTest, LocalSharedObjectsContainerCookie) { +TEST_F(PageSpecificContentSettingsTest, LocalSharedObjectsContainerCookie) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); bool blocked_by_policy = false; auto cookie1 = net::CanonicalCookie::Create(GURL("http://google.com"), "k1=v", base::Time::Now(), @@ -399,11 +399,12 @@ EXPECT_EQ(1u, objects.GetDomainCount()); } -TEST_F(TabSpecificContentSettingsTest, IndicatorChangedOnContentSettingChange) { +TEST_F(PageSpecificContentSettingsTest, + IndicatorChangedOnContentSettingChange) { NavigateAndCommit(GURL("http://google.com")); - TabSpecificContentSettings* content_settings = - TabSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); + PageSpecificContentSettings* content_settings = + PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame()); // First trigger OnContentBlocked. EXPECT_FALSE(content_settings->IsContentBlocked(
diff --git a/components/content_settings/browser/test_page_specific_content_settings_delegate.cc b/components/content_settings/browser/test_page_specific_content_settings_delegate.cc new file mode 100644 index 0000000..7e22ac1c --- /dev/null +++ b/components/content_settings/browser/test_page_specific_content_settings_delegate.cc
@@ -0,0 +1,67 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" + +namespace content_settings { + +TestPageSpecificContentSettingsDelegate:: + TestPageSpecificContentSettingsDelegate( + PrefService* prefs, + HostContentSettingsMap* settings_map) + : prefs_(prefs), settings_map_(settings_map) {} + +TestPageSpecificContentSettingsDelegate:: + ~TestPageSpecificContentSettingsDelegate() = default; + +void TestPageSpecificContentSettingsDelegate::UpdateLocationBar() {} + +void TestPageSpecificContentSettingsDelegate::SetContentSettingRules( + content::RenderProcessHost* process, + const RendererContentSettingRules& rules) {} + +PrefService* TestPageSpecificContentSettingsDelegate::GetPrefs() { + return prefs_; +} + +HostContentSettingsMap* +TestPageSpecificContentSettingsDelegate::GetSettingsMap() { + return settings_map_.get(); +} + +ContentSetting TestPageSpecificContentSettingsDelegate::GetEmbargoSetting( + const GURL& request_origin, + ContentSettingsType permission) { + return ContentSetting::CONTENT_SETTING_ASK; +} + +std::vector<storage::FileSystemType> +TestPageSpecificContentSettingsDelegate::GetAdditionalFileSystemTypes() { + return {}; +} + +browsing_data::CookieHelper::IsDeletionDisabledCallback +TestPageSpecificContentSettingsDelegate::GetIsDeletionDisabledCallback() { + return base::NullCallback(); +} + +bool TestPageSpecificContentSettingsDelegate::IsMicrophoneCameraStateChanged( + PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state, + const std::string& media_stream_selected_audio_device, + const std::string& media_stream_selected_video_device) { + return false; +} + +PageSpecificContentSettings::MicrophoneCameraState +TestPageSpecificContentSettingsDelegate::GetMicrophoneCameraState() { + return PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED; +} + +void TestPageSpecificContentSettingsDelegate::OnContentBlocked( + ContentSettingsType type) {} + +void TestPageSpecificContentSettingsDelegate::OnCookieAccessAllowed( + const net::CookieList& accessed_cookies) {} + +} // namespace content_settings
diff --git a/components/content_settings/browser/test_page_specific_content_settings_delegate.h b/components/content_settings/browser/test_page_specific_content_settings_delegate.h new file mode 100644 index 0000000..9918d1c --- /dev/null +++ b/components/content_settings/browser/test_page_specific_content_settings_delegate.h
@@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ +#define COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ + +#include "base/memory/scoped_refptr.h" +#include "components/content_settings/browser/page_specific_content_settings.h" + +namespace content_settings { + +class TestPageSpecificContentSettingsDelegate + : public PageSpecificContentSettings::Delegate { + public: + TestPageSpecificContentSettingsDelegate(PrefService* prefs, + HostContentSettingsMap* settings_map); + ~TestPageSpecificContentSettingsDelegate() override; + + // PageSpecificContentSettings::Delegate: + void UpdateLocationBar() override; + void SetContentSettingRules( + content::RenderProcessHost* process, + const RendererContentSettingRules& rules) override; + PrefService* GetPrefs() override; + HostContentSettingsMap* GetSettingsMap() override; + ContentSetting GetEmbargoSetting(const GURL& request_origin, + ContentSettingsType permission) override; + std::vector<storage::FileSystemType> GetAdditionalFileSystemTypes() override; + browsing_data::CookieHelper::IsDeletionDisabledCallback + GetIsDeletionDisabledCallback() override; + bool IsMicrophoneCameraStateChanged( + PageSpecificContentSettings::MicrophoneCameraState + microphone_camera_state, + const std::string& media_stream_selected_audio_device, + const std::string& media_stream_selected_video_device) override; + PageSpecificContentSettings::MicrophoneCameraState GetMicrophoneCameraState() + override; + void OnContentBlocked(ContentSettingsType type) override; + void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override; + + private: + PrefService* prefs_; + scoped_refptr<HostContentSettingsMap> settings_map_; +}; + +} // namespace content_settings + +#endif // COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
diff --git a/components/content_settings/browser/test_tab_specific_content_settings_delegate.cc b/components/content_settings/browser/test_tab_specific_content_settings_delegate.cc deleted file mode 100644 index 68e107a..0000000 --- a/components/content_settings/browser/test_tab_specific_content_settings_delegate.cc +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h" - -namespace content_settings { - -TestTabSpecificContentSettingsDelegate::TestTabSpecificContentSettingsDelegate( - PrefService* prefs, - HostContentSettingsMap* settings_map) - : prefs_(prefs), settings_map_(settings_map) {} - -TestTabSpecificContentSettingsDelegate:: - ~TestTabSpecificContentSettingsDelegate() = default; - -void TestTabSpecificContentSettingsDelegate::UpdateLocationBar() {} - -void TestTabSpecificContentSettingsDelegate::SetContentSettingRules( - content::RenderProcessHost* process, - const RendererContentSettingRules& rules) {} - -PrefService* TestTabSpecificContentSettingsDelegate::GetPrefs() { - return prefs_; -} - -HostContentSettingsMap* -TestTabSpecificContentSettingsDelegate::GetSettingsMap() { - return settings_map_.get(); -} - -ContentSetting TestTabSpecificContentSettingsDelegate::GetEmbargoSetting( - const GURL& request_origin, - ContentSettingsType permission) { - return ContentSetting::CONTENT_SETTING_ASK; -} - -std::vector<storage::FileSystemType> -TestTabSpecificContentSettingsDelegate::GetAdditionalFileSystemTypes() { - return {}; -} - -browsing_data::CookieHelper::IsDeletionDisabledCallback -TestTabSpecificContentSettingsDelegate::GetIsDeletionDisabledCallback() { - return base::NullCallback(); -} - -bool TestTabSpecificContentSettingsDelegate::IsMicrophoneCameraStateChanged( - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state, - const std::string& media_stream_selected_audio_device, - const std::string& media_stream_selected_video_device) { - return false; -} - -TabSpecificContentSettings::MicrophoneCameraState -TestTabSpecificContentSettingsDelegate::GetMicrophoneCameraState() { - return TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED; -} - -void TestTabSpecificContentSettingsDelegate::OnContentBlocked( - ContentSettingsType type) {} - -void TestTabSpecificContentSettingsDelegate::OnCookieAccessAllowed( - const net::CookieList& accessed_cookies) {} - -} // namespace content_settings
diff --git a/components/content_settings/browser/test_tab_specific_content_settings_delegate.h b/components/content_settings/browser/test_tab_specific_content_settings_delegate.h deleted file mode 100644 index 5060613..0000000 --- a/components/content_settings/browser/test_tab_specific_content_settings_delegate.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ -#define COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ - -#include "base/memory/scoped_refptr.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" - -namespace content_settings { - -class TestTabSpecificContentSettingsDelegate - : public TabSpecificContentSettings::Delegate { - public: - TestTabSpecificContentSettingsDelegate(PrefService* prefs, - HostContentSettingsMap* settings_map); - ~TestTabSpecificContentSettingsDelegate() override; - - // TabSpecificContentSettings::Delegate: - void UpdateLocationBar() override; - void SetContentSettingRules( - content::RenderProcessHost* process, - const RendererContentSettingRules& rules) override; - PrefService* GetPrefs() override; - HostContentSettingsMap* GetSettingsMap() override; - ContentSetting GetEmbargoSetting(const GURL& request_origin, - ContentSettingsType permission) override; - std::vector<storage::FileSystemType> GetAdditionalFileSystemTypes() override; - browsing_data::CookieHelper::IsDeletionDisabledCallback - GetIsDeletionDisabledCallback() override; - bool IsMicrophoneCameraStateChanged( - TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state, - const std::string& media_stream_selected_audio_device, - const std::string& media_stream_selected_video_device) override; - TabSpecificContentSettings::MicrophoneCameraState GetMicrophoneCameraState() - override; - void OnContentBlocked(ContentSettingsType type) override; - void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override; - - private: - PrefService* prefs_; - scoped_refptr<HostContentSettingsMap> settings_map_; -}; - -} // namespace content_settings - -#endif // COMPONENTS_CONTENT_SETTINGS_BROWSER_TEST_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
diff --git a/components/content_settings/browser/ui/cookie_controls_controller.cc b/components/content_settings/browser/ui/cookie_controls_controller.cc index 2b49667..69b81482 100644 --- a/components/content_settings/browser/ui/cookie_controls_controller.cc +++ b/components/content_settings/browser/ui/cookie_controls_controller.cc
@@ -10,7 +10,7 @@ #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "components/browsing_data/content/local_shared_objects_container.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/browser/ui/cookie_controls_view.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/browser/cookie_settings.h" @@ -108,21 +108,21 @@ } int CookieControlsController::GetAllowedCookieCount() { - auto* tscs = - content_settings::TabSpecificContentSettings::GetForCurrentDocument( + auto* pscs = + content_settings::PageSpecificContentSettings::GetForCurrentDocument( tab_observer_->web_contents()->GetMainFrame()); - if (tscs) { - return tscs->allowed_local_shared_objects().GetObjectCount(); + if (pscs) { + return pscs->allowed_local_shared_objects().GetObjectCount(); } else { return 0; } } int CookieControlsController::GetBlockedCookieCount() { - auto* tscs = - content_settings::TabSpecificContentSettings::GetForCurrentDocument( + auto* pscs = + content_settings::PageSpecificContentSettings::GetForCurrentDocument( tab_observer_->web_contents()->GetMainFrame()); - if (tscs) { - return tscs->blocked_local_shared_objects().GetObjectCount(); + if (pscs) { + return pscs->blocked_local_shared_objects().GetObjectCount(); } else { return 0; } @@ -163,7 +163,7 @@ CookieControlsController::TabObserver::TabObserver( CookieControlsController* cookie_controls, content::WebContents* web_contents) - : content_settings::TabSpecificContentSettings::SiteDataObserver( + : content_settings::PageSpecificContentSettings::SiteDataObserver( web_contents), cookie_controls_(cookie_controls) {}
diff --git a/components/content_settings/browser/ui/cookie_controls_controller.h b/components/content_settings/browser/ui/cookie_controls_controller.h index a049880..bdb1a78 100644 --- a/components/content_settings/browser/ui/cookie_controls_controller.h +++ b/components/content_settings/browser/ui/cookie_controls_controller.h
@@ -7,7 +7,7 @@ #include "base/memory/scoped_refptr.h" #include "base/observer_list.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/common/cookie_controls_enforcement.h" #include "components/content_settings/core/common/cookie_controls_status.h" @@ -54,12 +54,12 @@ // TODO(dullweber): Make it possible to change the observed class and maybe // convert SiteDataObserver to a pure virtual interface. class TabObserver - : public content_settings::TabSpecificContentSettings::SiteDataObserver { + : public content_settings::PageSpecificContentSettings::SiteDataObserver { public: TabObserver(CookieControlsController* cookie_controls, content::WebContents* web_contents); - // TabSpecificContentSettings::SiteDataObserver: + // PageSpecificContentSettings::SiteDataObserver: void OnSiteDataAccessed() override; private:
diff --git a/components/favicon/core/favicon_driver_impl.cc b/components/favicon/core/favicon_driver_impl.cc index 67ecbf2..730121a 100644 --- a/components/favicon/core/favicon_driver_impl.cc +++ b/components/favicon/core/favicon_driver_impl.cc
@@ -27,9 +27,6 @@ FaviconDriverImpl::FaviconDriverImpl(CoreFaviconService* favicon_service) : favicon_service_(favicon_service) { - if (!favicon_service_) - return; - if (kEnableTouchIcon) { handlers_.push_back(std::make_unique<FaviconHandler>( favicon_service_, this, FaviconDriverObserver::NON_TOUCH_LARGEST));
diff --git a/components/favicon/core/favicon_driver_impl.h b/components/favicon/core/favicon_driver_impl.h index a0338a3..c985be4 100644 --- a/components/favicon/core/favicon_driver_impl.h +++ b/components/favicon/core/favicon_driver_impl.h
@@ -37,6 +37,7 @@ bool HasPendingTasksForTest(); protected: + // |favicon_service| may be null, which means favicons are not saved. explicit FaviconDriverImpl(CoreFaviconService* favicon_service); ~FaviconDriverImpl() override; @@ -54,8 +55,8 @@ CoreFaviconService* favicon_service() { return favicon_service_; } private: - // KeyedService used by FaviconDriverImpl. It may be null during testing, - // but if it is defined, it must outlive the FaviconDriverImpl. + // KeyedService used by FaviconDriverImpl. It may be null, if non-null, it + // must outlive FaviconDriverImpl. CoreFaviconService* favicon_service_; // FaviconHandlers used to download the different kind of favicons.
diff --git a/components/favicon/core/favicon_handler.cc b/components/favicon/core/favicon_handler.cc index 0ab34fe..3d278c8 100644 --- a/components/favicon/core/favicon_handler.cc +++ b/components/favicon/core/favicon_handler.cc
@@ -230,12 +230,16 @@ // possible values in |page_urls_|) because we want to use the most // up-to-date / latest URL for DB lookups, which is the page URL for which // we get <link rel="icon"> candidates (FaviconHandler::OnUpdateCandidates()). - service_->GetFaviconForPageURL( - last_page_url_, icon_types_, preferred_icon_size(), - base::BindOnce( - &FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, - base::Unretained(this)), - &cancelable_task_tracker_for_page_url_); + if (service_) { + service_->GetFaviconForPageURL( + last_page_url_, icon_types_, preferred_icon_size(), + base::BindOnce( + &FaviconHandler::OnFaviconDataForInitialURLFromFaviconService, + base::Unretained(this)), + &cancelable_task_tracker_for_page_url_); + } else { + OnFaviconDataForInitialURLFromFaviconService({}); + } } bool FaviconHandler::ShouldDownloadNextCandidate() const { @@ -263,7 +267,7 @@ // Associate the icon to all URLs in |page_urls_|, which contains page URLs // within the same site/document that have been considered to reliably share // the same icon candidates. - if (!delegate_->IsOffTheRecord()) + if (service_ && !delegate_->IsOffTheRecord()) service_->SetFavicons(page_urls_, icon_url, icon_type, image); NotifyFaviconUpdated(icon_url, icon_type, image); @@ -277,7 +281,7 @@ // state to be checked at the very end. if (!error_other_than_404_found_ && notification_icon_type_ != favicon_base::IconType::kInvalid) { - if (!delegate_->IsOffTheRecord()) + if (service_ && !delegate_->IsOffTheRecord()) service_->DeleteFaviconMappings(page_urls_, notification_icon_type_); delegate_->OnFaviconDeleted(last_page_url_, handler_type_); @@ -349,9 +353,8 @@ best_favicon_ = DownloadedFavicon(); manifest_url_ = manifest_url; - // Check if the manifest was previously blacklisted (e.g. returned a 404) and - // ignore the manifest URL if that's the case. - if (!manifest_url_.is_empty() && + // If the manifest couldn't be downloaded (or there is no service), ignore it. + if (!manifest_url_.is_empty() && service_ && service_->WasUnableToDownloadFavicon(manifest_url_)) { DVLOG(1) << "Skip failed Manifest: " << manifest_url; manifest_url_ = GURL(); @@ -363,6 +366,11 @@ return; } + if (!service_) { + OnFaviconDataForManifestFromFaviconService({}); + return; + } + // See if there is a cached favicon for the manifest. This will update the DB // mappings only if the manifest URL is cached. GetFaviconAndUpdateMappingsUnlessIncognito( @@ -419,7 +427,9 @@ << ", falling back to inlined ones, which are " << non_manifest_original_candidates_.size(); - service_->UnableToDownloadFavicon(manifest_url_); + if (service_) + service_->UnableToDownloadFavicon(manifest_url_); + manifest_url_ = GURL(); OnGotFinalIconURLCandidates(non_manifest_original_candidates_); @@ -503,7 +513,8 @@ if (bitmaps.empty()) { if (http_status_code == 404) { DVLOG(1) << "Failed to Download Favicon:" << image_url; - service_->UnableToDownloadFavicon(image_url); + if (service_) + service_->UnableToDownloadFavicon(image_url); } else if (http_status_code != 0) { error_other_than_404_found_ = true; } @@ -596,7 +607,7 @@ // - The favicon in the database is expired. // AND // - Redownloading the favicon fails with a non-404 error code. - if (!delegate_->IsOffTheRecord()) { + if (service_ && !delegate_->IsOffTheRecord()) { service_->CloneFaviconMappingsForPages(last_page_url_, icon_types_, page_urls_); } @@ -622,7 +633,7 @@ // If the icons listed in a manifest are being processed, skip the cache // lookup for |icon_url| since the manifest's URL is used for caching, not the // icon URL, and this lookup has happened earlier. - if (redownload_icons_ || !manifest_url_.is_empty()) { + if (!service_ || redownload_icons_ || !manifest_url_.is_empty()) { // We have the mapping, but the favicon is out of date. Download it now. ScheduleImageDownload(icon_url, icon_type); } else { @@ -636,6 +647,10 @@ const GURL& icon_url, favicon_base::IconType icon_type, favicon_base::FaviconResultsCallback callback) { + // This should only be called if |service_| is available. If this is called + // with no |service_|, then |callback| is never run. + DCHECK(service_); + // We don't know the favicon, but we may have previously downloaded the // favicon for another page that shares the same favicon. Ask for the // favicon given the favicon URL. @@ -682,7 +697,7 @@ // Note that CancelableCallback starts cancelled. DCHECK(image_download_request_.IsCancelled()) << "More than one ongoing download"; - if (service_->WasUnableToDownloadFavicon(image_url)) { + if (service_ && service_->WasUnableToDownloadFavicon(image_url)) { DVLOG(1) << "Skip Failed FavIcon: " << image_url; OnDidDownloadFavicon(icon_type, 0, 0, image_url, std::vector<SkBitmap>(), std::vector<gfx::Size>());
diff --git a/components/favicon/core/favicon_handler.h b/components/favicon/core/favicon_handler.h index 8b8d2a3..98706de 100644 --- a/components/favicon/core/favicon_handler.h +++ b/components/favicon/core/favicon_handler.h
@@ -126,7 +126,9 @@ FaviconDriverObserver::NotificationIconType notification_icon_type) = 0; }; - // |service| and |delegate| must not be nullptr and must outlive this class. + // |service| may be null (which means favicons are not saved). If |service| + // is non-null it must outlive this class. |delegate| must not be nullptr and + // must outlive this class. FaviconHandler(CoreFaviconService* service, Delegate* delegate, FaviconDriverObserver::NotificationIconType handler_type); @@ -358,8 +360,7 @@ GURL notification_icon_url_; favicon_base::IconType notification_icon_type_; - // The CoreFaviconService which implements favicon operations. May be null - // during testing. + // The CoreFaviconService which implements favicon operations. May be null. CoreFaviconService* service_; // This handler's delegate.
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc index 5c0e5bd..100a595c 100644 --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc
@@ -25,7 +25,7 @@ #include "build/build_config.h" #include "components/browser_ui/util/android/url_constants.h" #include "components/browsing_data/content/local_storage_helper.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -435,7 +435,7 @@ ui_ = ui; DCHECK(ui_); // TabSpecificContentSetting needs to be created before page load. - DCHECK(GetTabSpecificContentSettings()); + DCHECK(GetPageSpecificContentSettings()); ComputeUIInputs(site_url_); PresentSitePermissions(); @@ -1001,7 +1001,7 @@ // Add first party cookie and site data counts. // TODO(crbug.com/1058597): Remove the calls to the |delegate_| once - // TabSpecificContentSettings has been componentized. + // PageSpecificContentSettings has been componentized. PageInfoUI::CookieInfo cookie_info; cookie_info.allowed = GetFirstPartyAllowedCookiesCount(site_url_); cookie_info.blocked = GetFirstPartyBlockedCookiesCount(site_url_); @@ -1132,16 +1132,16 @@ } } -content_settings::TabSpecificContentSettings* -PageInfo::GetTabSpecificContentSettings() const { +content_settings::PageSpecificContentSettings* +PageInfo::GetPageSpecificContentSettings() const { // TODO(https://crbug.com/1103176): PageInfo should be per page. Why is it // a WebContentsObserver if it is not observing anything? - return content_settings::TabSpecificContentSettings::GetForFrame( + return content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); } bool PageInfo::HasContentSettingChangedViaPageInfo(ContentSettingsType type) { - auto* settings = GetTabSpecificContentSettings(); + auto* settings = GetPageSpecificContentSettings(); if (!settings) return false; @@ -1149,7 +1149,7 @@ } void PageInfo::ContentSettingChangedViaPageInfo(ContentSettingsType type) { - auto* settings = GetTabSpecificContentSettings(); + auto* settings = GetPageSpecificContentSettings(); if (!settings) return; @@ -1157,7 +1157,7 @@ } int PageInfo::GetFirstPartyAllowedCookiesCount(const GURL& site_url) { - auto* settings = GetTabSpecificContentSettings(); + auto* settings = GetPageSpecificContentSettings(); if (!settings) return 0; return settings->allowed_local_shared_objects().GetObjectCountForDomain( @@ -1165,7 +1165,7 @@ } int PageInfo::GetFirstPartyBlockedCookiesCount(const GURL& site_url) { - auto* settings = GetTabSpecificContentSettings(); + auto* settings = GetPageSpecificContentSettings(); if (!settings) return 0; @@ -1174,7 +1174,7 @@ } int PageInfo::GetThirdPartyAllowedCookiesCount(const GURL& site_url) { - auto* settings = GetTabSpecificContentSettings(); + auto* settings = GetPageSpecificContentSettings(); if (!settings) return 0; @@ -1183,7 +1183,7 @@ } int PageInfo::GetThirdPartyBlockedCookiesCount(const GURL& site_url) { - auto* settings = GetTabSpecificContentSettings(); + auto* settings = GetPageSpecificContentSettings(); if (!settings) return 0;
diff --git a/components/page_info/page_info.h b/components/page_info/page_info.h index 8acef48..cd7aa9c 100644 --- a/components/page_info/page_info.h +++ b/components/page_info/page_info.h
@@ -25,7 +25,7 @@ } namespace content_settings { -class TabSpecificContentSettings; +class PageSpecificContentSettings; } namespace net { @@ -260,10 +260,10 @@ // Exposed for testing. static std::vector<ContentSettingsType> GetAllPermissionsForTesting(); - // Returns TabSpecificContentSettings for the observed WebContents if present, - // nullptr otherwise. - content_settings::TabSpecificContentSettings* GetTabSpecificContentSettings() - const; + // Returns PageSpecificContentSettings for the observed WebContents if + // present, nullptr otherwise. + content_settings::PageSpecificContentSettings* + GetPageSpecificContentSettings() const; // Whether the content setting of type |type| has changed via Page Info UI. bool HasContentSettingChangedViaPageInfo(ContentSettingsType type);
diff --git a/components/page_info/page_info_delegate.h b/components/page_info/page_info_delegate.h index acd53050..a40745f 100644 --- a/components/page_info/page_info_delegate.h +++ b/components/page_info/page_info_delegate.h
@@ -7,7 +7,7 @@ #include "base/strings/string16.h" #include "build/build_config.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/permissions/permission_result.h" #include "components/permissions/permission_uma_util.h" @@ -71,8 +71,8 @@ virtual HostContentSettingsMap* GetContentSettings() = 0; virtual std::unique_ptr< - content_settings::TabSpecificContentSettings::Delegate> - GetTabSpecificContentSettingsDelegate() = 0; + content_settings::PageSpecificContentSettings::Delegate> + GetPageSpecificContentSettingsDelegate() = 0; virtual bool IsContentDisplayedInVrHeadset() = 0; virtual security_state::SecurityLevel GetSecurityLevel() = 0; virtual security_state::VisibleSecurityState GetVisibleSecurityState() = 0;
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 70c77cfc..28b0b49 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -44,6 +44,7 @@ "android_affiliation/affiliation_fetcher.cc", "android_affiliation/affiliation_fetcher.h", "android_affiliation/affiliation_fetcher_delegate.h", + "android_affiliation/affiliation_fetcher_interface.h", "android_affiliation/android_affiliation_service.cc", "android_affiliation/android_affiliation_service.h", "android_affiliation/facet_manager.cc", @@ -451,6 +452,8 @@ "android_affiliation/mock_affiliated_match_helper.h", "android_affiliation/mock_affiliation_consumer.cc", "android_affiliation/mock_affiliation_consumer.h", + "android_affiliation/mock_affiliation_fetcher.cc", + "android_affiliation/mock_affiliation_fetcher.h", "fake_form_fetcher.cc", "fake_form_fetcher.h", "mock_bulk_leak_check_service.cc",
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc b/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc index be99b64..71ad3bb 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliation_backend.cc
@@ -256,9 +256,8 @@ if (requested_facet_uris.empty()) return false; - fetcher_.reset(AffiliationFetcher::Create(url_loader_factory_, - requested_facet_uris, this)); - fetcher_->StartRequest(); + fetcher_.reset(AffiliationFetcher::Create(url_loader_factory_, this)); + fetcher_->StartRequest(requested_facet_uris); ReportStatistics(requested_facet_uris.size()); return true; }
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc index 404fba42..8827cfc 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.cc
@@ -44,10 +44,8 @@ AffiliationFetcher::AffiliationFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_uris, AffiliationFetcherDelegate* delegate) : url_loader_factory_(std::move(url_loader_factory)), - requested_facet_uris_(facet_uris), delegate_(delegate) { for (const FacetURI& uri : requested_facet_uris_) { DCHECK(uri.is_valid()); @@ -59,14 +57,12 @@ // static AffiliationFetcher* AffiliationFetcher::Create( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_uris, AffiliationFetcherDelegate* delegate) { if (g_testing_factory) { return g_testing_factory->CreateInstance(std::move(url_loader_factory), - facet_uris, delegate); + delegate); } - return new AffiliationFetcher(std::move(url_loader_factory), facet_uris, - delegate); + return new AffiliationFetcher(std::move(url_loader_factory), delegate); } // static @@ -75,8 +71,9 @@ g_testing_factory = factory; } -void AffiliationFetcher::StartRequest() { +void AffiliationFetcher::StartRequest(const std::vector<FacetURI>& facet_uris) { DCHECK(!simple_url_loader_); + requested_facet_uris_ = facet_uris; net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("affiliation_lookup", R"( @@ -125,6 +122,14 @@ base::Unretained(this))); } +const std::vector<FacetURI>& AffiliationFetcher::GetRequestedFacetURIs() const { + return requested_facet_uris_; +} + +AffiliationFetcherDelegate* AffiliationFetcher::delegate() const { + return delegate_; +} + // static GURL AffiliationFetcher::BuildQueryURL() { return net::AppendQueryParameter(
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.h b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.h index 2c220e0..9caf03a 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.h +++ b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher.h
@@ -11,8 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "components/password_manager/core/browser/android_affiliation/affiliation_fetcher_delegate.h" -#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" +#include "components/password_manager/core/browser/android_affiliation/affiliation_fetcher_interface.h" class GURL; @@ -31,16 +30,15 @@ // // An instance is good for exactly one fetch, and may be used from any thread // that runs a message loop (i.e. not a worker pool thread). -class AffiliationFetcher { +class AffiliationFetcher : public AffiliationFetcherInterface { public: - ~AffiliationFetcher(); + ~AffiliationFetcher() override; - // Constructs a fetcher to retrieve affiliations for each facet in |facet_ids| - // using the specified |url_loader_factory|, and will provide the results - // to the |delegate| on the same thread that creates the instance. + // Constructs a fetcher using the specified |url_loader_factory|, and will + // provide the results to the |delegate| on the same thread that creates the + // instance. static AffiliationFetcher* Create( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_uris, AffiliationFetcherDelegate* delegate); // Builds the URL for the Affiliation API's lookup method. @@ -53,25 +51,22 @@ // calls. The caller may pass in NULL to resume using the default factory. static void SetFactoryForTesting(TestAffiliationFetcherFactory* factory); - // Actually starts the request, and will call the delegate with the results on - // the same thread when done. If |this| is destroyed before completion, the - // in-flight request is cancelled, and the delegate will not be called. - // Further details: + // Actually starts the request to retrieve affiliations for each facet in + // |facet_uris|, and will call the delegate with the results on the same + // thread when done. If |this| is destroyed before completion, the in-flight + // request is cancelled, and the delegate will not be called. Further details: // * No cookies are sent/saved with the request. // * In case of network/server errors, the request will not be retried. // * Results are guaranteed to be always fresh and will never be cached. - void StartRequest(); + void StartRequest(const std::vector<FacetURI>& facet_uris) override; - const std::vector<FacetURI>& requested_facet_uris() const { - return requested_facet_uris_; - } + const std::vector<FacetURI>& GetRequestedFacetURIs() const override; - AffiliationFetcherDelegate* delegate() const { return delegate_; } + AffiliationFetcherDelegate* delegate() const; protected: AffiliationFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_uris, AffiliationFetcherDelegate* delegate); private: @@ -91,7 +86,7 @@ void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body); scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; - const std::vector<FacetURI> requested_facet_uris_; + std::vector<FacetURI> requested_facet_uris_; AffiliationFetcherDelegate* const delegate_; std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_interface.h b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_interface.h new file mode 100644 index 0000000..dbeb4d5b --- /dev/null +++ b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_interface.h
@@ -0,0 +1,38 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_AFFILIATION_FETCHER_INTERFACE_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_AFFILIATION_FETCHER_INTERFACE_H_ + +#include <vector> + +#include "components/password_manager/core/browser/android_affiliation/affiliation_fetcher_delegate.h" +#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h" + +namespace password_manager { + +class AffiliationFetcherInterface { + public: + AffiliationFetcherInterface() = default; + virtual ~AffiliationFetcherInterface() = default; + + // Not copyable or movable + AffiliationFetcherInterface(const AffiliationFetcherInterface&) = delete; + AffiliationFetcherInterface& operator=(const AffiliationFetcherInterface&) = + delete; + AffiliationFetcherInterface(AffiliationFetcherInterface&&) = delete; + AffiliationFetcherInterface& operator=(AffiliationFetcherInterface&&) = + delete; + + // Starts the request to retrieve affiliations for each facet in + // |facet_uris|. + virtual void StartRequest(const std::vector<FacetURI>& facet_uris) = 0; + + // Returns requested facet uris. + virtual const std::vector<FacetURI>& GetRequestedFacetURIs() const = 0; +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_AFFILIATION_FETCHER_INTERFACE_H_
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc index b3bbda15..9e824e86 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc +++ b/components/password_manager/core/browser/android_affiliation/affiliation_fetcher_unittest.cc
@@ -146,9 +146,9 @@ SetupSuccessfulResponse(test_response.SerializeAsString()); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchSucceededProxy()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), requested_uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(requested_uris); WaitForResponse(); ASSERT_NO_FATAL_FAILURE(VerifyRequestPayload(requested_uris)); @@ -185,9 +185,9 @@ SetupSuccessfulResponse(test_response.SerializeAsString()); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchSucceededProxy()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), requested_uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(requested_uris); WaitForResponse(); ASSERT_NO_FATAL_FAILURE(VerifyRequestPayload(requested_uris)); @@ -216,9 +216,9 @@ SetupSuccessfulResponse(empty_test_response.SerializeAsString()); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchSucceededProxy()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), requested_uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(requested_uris); WaitForResponse(); ASSERT_NO_FATAL_FAILURE(VerifyRequestPayload(requested_uris)); @@ -247,9 +247,9 @@ SetupSuccessfulResponse(test_response.SerializeAsString()); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchSucceededProxy()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), requested_uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(requested_uris); WaitForResponse(); ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate)); @@ -275,9 +275,9 @@ SetupSuccessfulResponse(test_response.SerializeAsString()); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchSucceededProxy()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), requested_uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(requested_uris); WaitForResponse(); ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate)); @@ -307,9 +307,9 @@ SetupSuccessfulResponse(test_response.SerializeAsString()); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchSucceededProxy()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), requested_uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(requested_uris); WaitForResponse(); ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&mock_delegate)); @@ -331,9 +331,9 @@ SetupSuccessfulResponse(kMalformedResponse); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnMalformedResponse()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(uris); WaitForResponse(); } @@ -355,9 +355,9 @@ SetupSuccessfulResponse(test_response.SerializeAsString()); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnMalformedResponse()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(uris); WaitForResponse(); } @@ -368,9 +368,9 @@ SetupServerErrorResponse(); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchFailed()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(uris); WaitForResponse(); } @@ -381,9 +381,9 @@ SetupNetworkErrorResponse(); MockAffiliationFetcherDelegate mock_delegate; EXPECT_CALL(mock_delegate, OnFetchFailed()); - std::unique_ptr<AffiliationFetcher> fetcher(AffiliationFetcher::Create( - test_shared_loader_factory(), uris, &mock_delegate)); - fetcher->StartRequest(); + std::unique_ptr<AffiliationFetcher> fetcher( + AffiliationFetcher::Create(test_shared_loader_factory(), &mock_delegate)); + fetcher->StartRequest(uris); WaitForResponse(); }
diff --git a/components/password_manager/core/browser/android_affiliation/fake_affiliation_api.cc b/components/password_manager/core/browser/android_affiliation/fake_affiliation_api.cc index 672f55f6..1f07ed3 100644 --- a/components/password_manager/core/browser/android_affiliation/fake_affiliation_api.cc +++ b/components/password_manager/core/browser/android_affiliation/fake_affiliation_api.cc
@@ -33,7 +33,7 @@ std::vector<FacetURI> ScopedFakeAffiliationAPI::GetNextRequestedFacets() { if (fake_fetcher_factory_.has_pending_fetchers()) - return fake_fetcher_factory_.PeekNextFetcher()->requested_facet_uris(); + return fake_fetcher_factory_.PeekNextFetcher()->GetRequestedFacetURIs(); return std::vector<FacetURI>(); } @@ -46,7 +46,7 @@ new AffiliationFetcherDelegate::Result); for (const auto& preset_equivalence_class : preset_equivalence_relation_) { bool had_intersection_with_request = false; - for (const auto& requested_facet_uri : fetcher->requested_facet_uris()) { + for (const auto& requested_facet_uri : fetcher->GetRequestedFacetURIs()) { if (std::any_of(preset_equivalence_class.begin(), preset_equivalence_class.end(), [&requested_facet_uri](const Facet& facet) {
diff --git a/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.cc b/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.cc index c723cf17..09eff4a 100644 --- a/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.cc +++ b/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.cc
@@ -11,9 +11,8 @@ password_manager::FakeAffiliationFetcher::FakeAffiliationFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_ids, AffiliationFetcherDelegate* delegate) - : AffiliationFetcher(std::move(url_loader_factory), facet_ids, delegate) {} + : AffiliationFetcher(std::move(url_loader_factory), delegate) {} password_manager::FakeAffiliationFetcher::~FakeAffiliationFetcher() = default; @@ -50,10 +49,9 @@ AffiliationFetcher* ScopedFakeAffiliationFetcherFactory::CreateInstance( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_ids, AffiliationFetcherDelegate* delegate) { - FakeAffiliationFetcher* fetcher = new FakeAffiliationFetcher( - std::move(url_loader_factory), facet_ids, delegate); + FakeAffiliationFetcher* fetcher = + new FakeAffiliationFetcher(std::move(url_loader_factory), delegate); pending_fetchers_.push(fetcher); return fetcher; }
diff --git a/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.h b/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.h index 100de78..9343d833 100644 --- a/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.h +++ b/components/password_manager/core/browser/android_affiliation/fake_affiliation_fetcher.h
@@ -21,9 +21,8 @@ public: FakeAffiliationFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_ids, AffiliationFetcherDelegate* delegate); - ~FakeAffiliationFetcher(); + ~FakeAffiliationFetcher() override; // Simulates successful completion of the request with |fake_result|. Note // that the consumer may choose to destroy |this| from within this call. @@ -66,7 +65,6 @@ // AffiliationFetcherFactory: AffiliationFetcher* CreateInstance( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_ids, AffiliationFetcherDelegate* delegate) override; private:
diff --git a/components/password_manager/core/browser/android_affiliation/mock_affiliation_fetcher.cc b/components/password_manager/core/browser/android_affiliation/mock_affiliation_fetcher.cc new file mode 100644 index 0000000..a56cf81 --- /dev/null +++ b/components/password_manager/core/browser/android_affiliation/mock_affiliation_fetcher.cc
@@ -0,0 +1,13 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/android_affiliation/mock_affiliation_fetcher.h" + +namespace password_manager { + +MockAffiliationFetcher::MockAffiliationFetcher() = default; + +MockAffiliationFetcher::~MockAffiliationFetcher() = default; + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/android_affiliation/mock_affiliation_fetcher.h b/components/password_manager/core/browser/android_affiliation/mock_affiliation_fetcher.h new file mode 100644 index 0000000..75b8334 --- /dev/null +++ b/components/password_manager/core/browser/android_affiliation/mock_affiliation_fetcher.h
@@ -0,0 +1,29 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_MOCK_AFFILIATION_FETCHER_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_MOCK_AFFILIATION_FETCHER_H_ + +#include <string> + +#include "components/password_manager/core/browser/android_affiliation/affiliation_fetcher_interface.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace password_manager { + +class MockAffiliationFetcher : public AffiliationFetcherInterface { + public: + MockAffiliationFetcher(); + ~MockAffiliationFetcher() override; + + MOCK_METHOD(void, StartRequest, (const std::vector<FacetURI>&), (override)); + MOCK_METHOD(std::vector<FacetURI>&, + GetRequestedFacetURIs, + (), + (const, override)); +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_MOCK_AFFILIATION_FETCHER_H_
diff --git a/components/password_manager/core/browser/android_affiliation/test_affiliation_fetcher_factory.h b/components/password_manager/core/browser/android_affiliation/test_affiliation_fetcher_factory.h index 8b43a20..e2de713 100644 --- a/components/password_manager/core/browser/android_affiliation/test_affiliation_fetcher_factory.h +++ b/components/password_manager/core/browser/android_affiliation/test_affiliation_fetcher_factory.h
@@ -13,7 +13,6 @@ namespace password_manager { -class FacetURI; class AffiliationFetcherDelegate; // Interface for a factory to be used by AffiliationFetcher::Create() in tests @@ -27,7 +26,6 @@ // to the |delegate| on the same thread that creates the instance. virtual AffiliationFetcher* CreateInstance( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - const std::vector<FacetURI>& facet_ids, AffiliationFetcherDelegate* delegate) = 0; protected:
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn index a7a89b65e4..6db3d80 100644 --- a/components/payments/content/android/BUILD.gn +++ b/components/payments/content/android/BUILD.gn
@@ -78,6 +78,7 @@ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] sources = [ "java/src/org/chromium/components/payments/Address.java", + "java/src/org/chromium/components/payments/BrowserPaymentRequest.java", "java/src/org/chromium/components/payments/CanMakePaymentQuery.java", "java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java", "java/src/org/chromium/components/payments/CurrencyFormatter.java",
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java b/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java new file mode 100644 index 0000000..fafcf4c8 --- /dev/null +++ b/components/payments/content/android/java/src/org/chromium/components/payments/BrowserPaymentRequest.java
@@ -0,0 +1,85 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.payments; + +import org.chromium.mojo.system.MojoException; +import org.chromium.payments.mojom.PaymentDetails; +import org.chromium.payments.mojom.PaymentMethodData; +import org.chromium.payments.mojom.PaymentOptions; +import org.chromium.payments.mojom.PaymentValidationErrors; + +/** + * The browser part of the PaymentRequest implementation. The browser here can be either the + * Android Chrome browser or the WebLayer "browser". + */ +public interface BrowserPaymentRequest { + /** + * The browser part of the {@link PaymentRequest#init} implementation. + * @param methodData The supported methods specified by the merchant. + * @param details The payment details specified by the merchant. + * @param options The payment options specified by the merchant. + * @param googlePayBridgeEligible True when the renderer process deems the current request + * eligible for the skip-to-GPay experimental flow. It is ultimately up to the browser + * process to determine whether to trigger it + */ + void init(PaymentMethodData[] methodData, PaymentDetails details, PaymentOptions options, + boolean googlePayBridgeEligible); + + /** + * The browser part of the {@link PaymentRequest#show} implementation. + * @param isUserGesture Whether this method is triggered from a user gesture. + * @param waitForUpdatedDetails Whether to wait for updated details. It's true when merchant + * passed in a promise into PaymentRequest.show(), so Chrome should disregard the + * initial payment details and show a spinner until the promise resolves with the + * correct payment details. + */ + void show(boolean isUserGesture, boolean waitForUpdatedDetails); + + /** + * The browser part of the {@link PaymentRequest#updateWith} implementation. + * @param details The details that the merchant provides to update the payment request. + */ + void updateWith(PaymentDetails details); + + /** The browser part of the {@link PaymentRequest#onPaymentDetailsNotUpdated} implementation. */ + void onPaymentDetailsNotUpdated(); + + /** The browser part of the {@link PaymentRequest#abort} implementation. */ + void abort(); + + /** The browser part of the {@link PaymentRequest#complete} implementation. */ + void complete(int result); + + /** + * The browser part of the {@link PaymentRequest#retry} implementation. + * @param errors The merchant-defined error message strings, which are used to indicate to the + * end-user that something is wrong with the data of the payment response. + */ + void retry(PaymentValidationErrors errors); + + /** + * The browser part of the {@link PaymentRequest#hasEnrolledInstrument} implementation. + * @param perMethodQuota Whether to query with per-method quota. + */ + void hasEnrolledInstrument(boolean perMethodQuota); + + /** The browser part of the {@link PaymentRequest#canMakePayment} implementation. */ + void canMakePayment(); + + /** The browser part of the {@link PaymentRequest#close} implementation. */ + void close(); + + /** + * The browser part of the {@link PaymentRequest#onConnectionError} implementation. + * @param e The detail of the error. + */ + void onConnectionError(MojoException e); + + /** @return The JourneyLogger of PaymentRequestImpl. */ + JourneyLogger getJourneyLogger(); + + /** Delegate to the same method of PaymentRequestImpl. */ + void disconnectFromClientWithDebugMessage(String debugMessage); +}
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java b/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java index c667c3ca..0b7fb674 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java
@@ -10,6 +10,7 @@ import org.chromium.components.autofill.EditableOption; import org.chromium.mojo.system.MojoException; import org.chromium.payments.mojom.PaymentDetails; +import org.chromium.payments.mojom.PaymentItem; import org.chromium.payments.mojom.PaymentMethodData; import org.chromium.payments.mojom.PaymentOptions; import org.chromium.payments.mojom.PaymentRequest; @@ -25,45 +26,22 @@ * org.chromium.chrome.browser.payments.PaymentRequestImpl. */ public class ComponentPaymentRequestImpl implements PaymentRequest { - private final ComponentPaymentRequestDelegate mDelegate; private static NativeObserverForTest sNativeObserverForTest; + private final BrowserPaymentRequestFactory mBrowserPaymentRequestFactory; + private BrowserPaymentRequest mBrowserPaymentRequest; private PaymentRequestClient mClient; private PaymentRequestLifecycleObserver mPaymentRequestLifecycleObserver; - /** - * The delegate of {@link ComponentPaymentRequestImpl}. - */ - public interface ComponentPaymentRequestDelegate { - // The implementation of the same methods in {@link PaymentRequest). - void init(PaymentMethodData[] methodData, PaymentDetails details, PaymentOptions options, - boolean googlePayBridgeEligible); - void show(boolean isUserGesture, boolean waitForUpdatedDetails); - void updateWith(PaymentDetails details); - void onPaymentDetailsNotUpdated(); - void abort(); - void complete(int result); - void retry(PaymentValidationErrors errors); - void hasEnrolledInstrument(boolean perMethodQuota); - void canMakePayment(); - void close(); - void onConnectionError(MojoException e); - + /** The factory that creates an instance of {@link BrowserPaymentRequest}. */ + public interface BrowserPaymentRequestFactory { /** - * Set a weak reference to the client of this delegate. - * @param componentPaymentRequestImpl The client of this delegate. + * Create an instance of {@link BrowserPaymentRequest}, and have it working together with an + * instance of {@link ComponentPaymentRequestImpl}. + * @param componentPaymentRequestImpl The ComponentPaymentRequestImpl to work together with + * the BrowserPaymentRequest instance. */ - void setComponentPaymentRequestImpl( + BrowserPaymentRequest createBrowserPaymentRequest( ComponentPaymentRequestImpl componentPaymentRequestImpl); - - /** - * @return The JourneyLogger of PaymentRequestImpl. - */ - JourneyLogger getJourneyLogger(); - - /** - * Delegate to the same method of PaymentRequestImpl. - */ - void disconnectFromClientWithDebugMessage(String debugMessage); } /** @@ -78,8 +56,7 @@ void onCanMakePaymentReturned(); void onHasEnrolledInstrumentCalled(); void onHasEnrolledInstrumentReturned(); - void onAppListReady(@Nullable List<EditableOption> paymentApps, - org.chromium.payments.mojom.PaymentItem total); + void onAppListReady(@Nullable List<EditableOption> paymentApps, PaymentItem total); void onNotSupportedError(); void onConnectionTerminated(); void onAbortCalled(); @@ -89,11 +66,11 @@ /** * Build an instance of the PaymentRequest implementation. - * @param delegate A delegate of the instance. + * @param browserPaymentRequestFactory The factory that generates an instance of + * BrowserPaymentRequest to work with this ComponentPaymentRequestImpl instance. */ - public ComponentPaymentRequestImpl(ComponentPaymentRequestDelegate delegate) { - mDelegate = delegate; - mDelegate.setComponentPaymentRequestImpl(this); + public ComponentPaymentRequestImpl(BrowserPaymentRequestFactory browserPaymentRequestFactory) { + mBrowserPaymentRequestFactory = browserPaymentRequestFactory; } /** @@ -115,75 +92,76 @@ @Override public void init(PaymentRequestClient client, PaymentMethodData[] methodData, PaymentDetails details, PaymentOptions options, boolean googlePayBridgeEligible) { + mBrowserPaymentRequest = mBrowserPaymentRequestFactory.createBrowserPaymentRequest(this); + assert mBrowserPaymentRequest != null; if (mClient != null) { - mDelegate.getJourneyLogger().setAborted( - org.chromium.components.payments.AbortReason.INVALID_DATA_FROM_RENDERER); - mDelegate.disconnectFromClientWithDebugMessage( - org.chromium.components.payments.ErrorStrings.ATTEMPTED_INITIALIZATION_TWICE); + mBrowserPaymentRequest.getJourneyLogger().setAborted( + AbortReason.INVALID_DATA_FROM_RENDERER); + mBrowserPaymentRequest.disconnectFromClientWithDebugMessage( + ErrorStrings.ATTEMPTED_INITIALIZATION_TWICE); return; } if (client == null) { - mDelegate.getJourneyLogger().setAborted( - org.chromium.components.payments.AbortReason.INVALID_DATA_FROM_RENDERER); - mDelegate.disconnectFromClientWithDebugMessage( - org.chromium.components.payments.ErrorStrings.INVALID_STATE); + mBrowserPaymentRequest.getJourneyLogger().setAborted( + AbortReason.INVALID_DATA_FROM_RENDERER); + mBrowserPaymentRequest.disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_STATE); return; } mClient = client; - mDelegate.init(methodData, details, options, googlePayBridgeEligible); + mBrowserPaymentRequest.init(methodData, details, options, googlePayBridgeEligible); } @Override public void show(boolean isUserGesture, boolean waitForUpdatedDetails) { - mDelegate.show(isUserGesture, waitForUpdatedDetails); + mBrowserPaymentRequest.show(isUserGesture, waitForUpdatedDetails); } @Override public void updateWith(PaymentDetails details) { - mDelegate.updateWith(details); + mBrowserPaymentRequest.updateWith(details); } @Override public void onPaymentDetailsNotUpdated() { - mDelegate.onPaymentDetailsNotUpdated(); + mBrowserPaymentRequest.onPaymentDetailsNotUpdated(); } @Override public void abort() { - mDelegate.abort(); + mBrowserPaymentRequest.abort(); } @Override public void complete(int result) { - mDelegate.complete(result); + mBrowserPaymentRequest.complete(result); } @Override public void retry(PaymentValidationErrors errors) { - mDelegate.retry(errors); + mBrowserPaymentRequest.retry(errors); } @Override public void canMakePayment() { - mDelegate.canMakePayment(); + mBrowserPaymentRequest.canMakePayment(); } @Override public void hasEnrolledInstrument(boolean perMethodQuota) { - mDelegate.hasEnrolledInstrument(perMethodQuota); + mBrowserPaymentRequest.hasEnrolledInstrument(perMethodQuota); } @Override public void close() { - mDelegate.close(); + mBrowserPaymentRequest.close(); } @Override public void onConnectionError(MojoException e) { - mDelegate.onConnectionError(e); + mBrowserPaymentRequest.onConnectionError(e); } /**
diff --git a/components/permissions/contexts/geolocation_permission_context.cc b/components/permissions/contexts/geolocation_permission_context.cc index b62512c..6890e7f 100644 --- a/components/permissions/contexts/geolocation_permission_context.cc +++ b/components/permissions/contexts/geolocation_permission_context.cc
@@ -5,7 +5,7 @@ #include "components/permissions/contexts/geolocation_permission_context.h" #include "base/bind.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/permissions/permission_request_id.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/device_service.h" @@ -52,12 +52,12 @@ const PermissionRequestID& id, const GURL& requesting_frame, bool allowed) { - content_settings::TabSpecificContentSettings* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings* content_settings = + content_settings::PageSpecificContentSettings::GetForFrame( id.render_process_id(), id.render_frame_id()); // WebContents might not exist (extensions) or no longer exist. In which case, - // TabSpecificContentSettings will be null. + // PageSpecificContentSettings will be null. if (content_settings) content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(), allowed);
diff --git a/components/permissions/contexts/geolocation_permission_context_unittest.cc b/components/permissions/contexts/geolocation_permission_context_unittest.cc index 5c4fbd1..76dc457 100644 --- a/components/permissions/contexts/geolocation_permission_context_unittest.cc +++ b/components/permissions/contexts/geolocation_permission_context_unittest.cc
@@ -28,8 +28,8 @@ #include "base/time/clock.h" #include "build/build_config.h" #include "components/content_settings/browser/content_settings_usages_state.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" -#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h" +#include "components/content_settings/browser/page_specific_content_settings.h" +#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/permissions/features.h" #include "components/permissions/permission_context_base.h" @@ -253,7 +253,7 @@ const GURL& requesting_frame, ContentSetting expected_content_setting) { auto* content_settings = - content_settings::TabSpecificContentSettings::GetForFrame( + content_settings::PageSpecificContentSettings::GetForFrame( web_contents()->GetMainFrame()); const ContentSettingsUsagesState::StateMap& state_map = @@ -269,10 +269,10 @@ void GeolocationPermissionContextTests::SetUp() { RenderViewHostTestHarness::SetUp(); - content_settings::TabSpecificContentSettings::CreateForWebContents( + content_settings::PageSpecificContentSettings::CreateForWebContents( web_contents(), std::make_unique< - content_settings::TestTabSpecificContentSettingsDelegate>( + content_settings::TestPageSpecificContentSettingsDelegate>( /*prefs=*/nullptr, PermissionsClient::Get()->GetSettingsMap(browser_context())));
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto index 4b22f20..a0045b6 100644 --- a/components/policy/proto/chrome_device_policy.proto +++ b/components/policy/proto/chrome_device_policy.proto
@@ -320,16 +320,19 @@ // Types of channel downgrade behavior. enum ChannelDowngradeBehavior { + // Channel downgrade behavior unspecified. Default is + // WAIT_FOR_VERSION_CATCH_UP. + CHANNEL_DOWNGRADE_BEHAVIOR_UNSPECIFIED = 0; // On a channel downgrade, e.g. beta to stable, wait for the device's // version to become available on the new channel. No updates happen until // then. This is the default. - WAIT_FOR_VERSION_CATCH_UP = 0; + WAIT_FOR_VERSION_CATCH_UP = 1; // Roll back and reset the device on a channel downgrade. This does a full // powerwash and tries to preserve wifi and enrollment. - ROLLBACK = 1; + ROLLBACK = 2; // Allow the user to decide whether to wait or roll back and reset on a // user-initiated channel downgrade. - ALLOW_USER_TO_CONFIGURE = 2; + ALLOW_USER_TO_CONFIGURE = 3; } // Specifies what should happen if the device channel is downgraded.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 69f868b..1a4ef7a 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -9353,22 +9353,22 @@ 'type': 'int-enum', 'schema': { 'type': 'integer', - 'enum': [0, 1, 2], + 'enum': [1, 2, 3], }, 'items': [ { 'name': 'WaitForVersionCatchUp', - 'value': 0, + 'value': 1, 'caption': '''Wait for the target channel to catch up on channel downgrade''', }, { 'name': 'Rollback', - 'value': 1, + 'value': 2, 'caption': '''Roll back and reset the device on channel downgrade, try to preserve enrollment''', }, { 'name': 'AllowUserToConfigure', - 'value': 2, + 'value': 3, 'caption': '''User decides on channel downgrade behavior''', }, ], @@ -9377,7 +9377,7 @@ 'features': { 'dynamic_refresh': True, }, - 'example_value': 0, + 'example_value': 1, 'id': 757, 'caption': '''Channel downgrade behavior''', 'tags': [],
diff --git a/components/safe_browsing/core/realtime/url_lookup_service.cc b/components/safe_browsing/core/realtime/url_lookup_service.cc index 7fc36ca..4e4edce1 100644 --- a/components/safe_browsing/core/realtime/url_lookup_service.cc +++ b/components/safe_browsing/core/realtime/url_lookup_service.cc
@@ -145,9 +145,9 @@ })"); } -std::string RealTimeUrlLookupService::GetDMTokenString() const { +base::Optional<std::string> RealTimeUrlLookupService::GetDMTokenString() const { // DM token should only be set for enterprise requests. - return ""; + return base::nullopt; } std::string RealTimeUrlLookupService::GetMetricSuffix() const {
diff --git a/components/safe_browsing/core/realtime/url_lookup_service.h b/components/safe_browsing/core/realtime/url_lookup_service.h index fab556ea..11d62f7 100644 --- a/components/safe_browsing/core/realtime/url_lookup_service.h +++ b/components/safe_browsing/core/realtime/url_lookup_service.h
@@ -79,7 +79,7 @@ void GetAccessToken(const GURL& url, RTLookupRequestCallback request_callback, RTLookupResponseCallback response_callback) override; - std::string GetDMTokenString() const override; + base::Optional<std::string> GetDMTokenString() const override; std::string GetMetricSuffix() const override; // Called when the access token is obtained from |token_fetcher_|.
diff --git a/components/safe_browsing/core/realtime/url_lookup_service_base.cc b/components/safe_browsing/core/realtime/url_lookup_service_base.cc index 8d4cdf8..fc7cda17 100644 --- a/components/safe_browsing/core/realtime/url_lookup_service_base.cc +++ b/components/safe_browsing/core/realtime/url_lookup_service_base.cc
@@ -413,7 +413,10 @@ auto request = std::make_unique<RTLookupRequest>(); request->set_url(SanitizeURL(url).spec()); request->set_lookup_type(RTLookupRequest::NAVIGATION); - request->set_dm_token(GetDMTokenString()); + base::Optional<std::string> dm_token_string = GetDMTokenString(); + if (dm_token_string.has_value()) { + request->set_dm_token(dm_token_string.value()); + } ChromeUserPopulation* user_population = request->mutable_population(); user_population->set_user_population(
diff --git a/components/safe_browsing/core/realtime/url_lookup_service_base.h b/components/safe_browsing/core/realtime/url_lookup_service_base.h index 048dee0b..29fa016 100644 --- a/components/safe_browsing/core/realtime/url_lookup_service_base.h +++ b/components/safe_browsing/core/realtime/url_lookup_service_base.h
@@ -137,7 +137,7 @@ RTLookupResponseCallback response_callback) = 0; // Gets a dm token string to be set in a request proto. - virtual std::string GetDMTokenString() const = 0; + virtual base::Optional<std::string> GetDMTokenString() const = 0; // Suffix for logging metrics. virtual std::string GetMetricSuffix() const = 0;
diff --git a/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc b/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc index 9e62834a..ffb482a 100644 --- a/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc +++ b/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc
@@ -602,6 +602,7 @@ url, base::BindOnce( [](std::unique_ptr<RTLookupRequest> request, std::string token) { + EXPECT_FALSE(request->has_dm_token()); // Check token is attached. EXPECT_EQ("access_token_string", token); }),
diff --git a/components/test/data/payments/payment_handler.js b/components/test/data/payments/payment_handler.js index ac926dc..df468477 100644 --- a/components/test/data/payments/payment_handler.js +++ b/components/test/data/payments/payment_handler.js
@@ -4,19 +4,27 @@ * found in the LICENSE file. */ -const methodName = window.location.origin + '/pay'; -const swSrcUrl = 'payment_handler_sw.js'; +const DEFAULT_METHOD_NAME = window.location.origin + '/pay'; +const SW_SRC_URL = 'payment_handler_sw.js'; -/** Installs the payment handler. */ -async function install() { // eslint-disable-line no-unused-vars +let methodName = DEFAULT_METHOD_NAME; +var request; + +/** Installs the payment handler. + * @param {string} method - The payment method that this service worker + * supports. + * @return {Promise<string>} - 'success' or error message on failure. + */ +async function install(method=DEFAULT_METHOD_NAME) { // eslint-disable-line no-unused-vars, max-len try { + methodName = method; let registration = - await navigator.serviceWorker.getRegistration(swSrcUrl); + await navigator.serviceWorker.getRegistration(SW_SRC_URL); if (registration) { return 'The payment handler is already installed.'; } - await navigator.serviceWorker.register(swSrcUrl); + await navigator.serviceWorker.register(SW_SRC_URL); registration = await navigator.serviceWorker.ready; if (!registration.paymentManager) { return 'PaymentManager API not found.'; @@ -24,7 +32,7 @@ await registration.paymentManager.instruments.set('instrument-id', { name: 'Instrument Name', - method: methodName, + method, }); return 'success'; } catch (e) { @@ -33,15 +41,33 @@ } /** + * Uninstalls the payment handler. + * @return {Promise<string>} - 'success' or error message on failure. + */ +async function uninstall() { // eslint-disable-line no-unused-vars + try { + let registration = + await navigator.serviceWorker.getRegistration(SW_SRC_URL); + if (!registration) { + return 'The Payment handler has not been installed yet.'; + } + await registration.unregister(); + return 'success'; + } catch (e) { + return e.toString(); + } +} + +/** * Delegates handling of the provided options to the payment handler. * @param {Array<string>} delegations The list of payment options to delegate. - * @return {string} The 'success' or error message. + * @return {Promise<string>} - 'success' or error message on failure. */ async function enableDelegations(delegations) { // eslint-disable-line no-unused-vars, max-len try { await navigator.serviceWorker.ready; let registration = - await navigator.serviceWorker.getRegistration(swSrcUrl); + await navigator.serviceWorker.getRegistration(SW_SRC_URL); if (!registration) { return 'The payment handler is not installed.'; } @@ -61,6 +87,7 @@ /** * Launches the payment handler. + * @return {Promise<string>} - 'success' or error message on failure. */ async function launch() { // eslint-disable-line no-unused-vars try { @@ -81,7 +108,7 @@ */ function launchWithoutWaitForResponse() { // eslint-disable-line no-unused-vars try { - const request = new PaymentRequest([{supportedMethods: methodName}], { + request = new PaymentRequest([{supportedMethods: methodName}], { total: {label: 'Total', amount: {currency: 'USD', value: '0.01'}}, }); request.show(); @@ -91,6 +118,19 @@ } } +/** + * Aborts the on-going payment request. + * @return {Promise<string>} - 'success' or error message on failure. + */ +async function abort() { // eslint-disable-line no-unused-vars + try { + await request.abort(); + return 'success'; + } catch (e) { + return e.toString(); + } +} + var paymentOptions = null; /**
diff --git a/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java b/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java index 980f8ea..aa6e6c0 100644 --- a/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java +++ b/components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java
@@ -49,7 +49,6 @@ private static byte[] sExpectedSignature; private static byte[] sCommentSignedPublicKeyBytes; private static PublicKey sCommentSignedPublicKey; - private static boolean sDisableValidation; private static boolean sOverrideValidationForTesting; /** @@ -178,8 +177,7 @@ */ @SuppressLint("PackageManagerGetSignatures") public static boolean isValidWebApk(Context context, String webappPackageName) { - if ((sExpectedSignature == null || sCommentSignedPublicKeyBytes == null) - && !sDisableValidation) { + if (sExpectedSignature == null || sCommentSignedPublicKeyBytes == null) { Log.wtf(TAG, "WebApk validation failure - expected signature not set." + "missing call to WebApkValidator.initWithBrowserHostSignature"); @@ -199,7 +197,7 @@ if (isNotWebApkQuick(packageInfo)) { return false; } - if (sDisableValidation || sOverrideValidationForTesting) { + if (sOverrideValidationForTesting) { if (DEBUG) { Log.d(TAG, "Ok! Looks like a WebApk (has start url) and validation is disabled."); } @@ -417,14 +415,6 @@ } /** - * Disables all validation performed by this class. This should only be called when some other - * means of validating WebApks is already present and otherwise should never be called. - */ - public static void disableValidationUnsafe() { - sDisableValidation = true; - } - - /** * Lazy evaluate the creation of the Public Key as the KeyFactories may not yet be initialized. * @return The decoded PublicKey or null */
diff --git a/components/webrtc/media_stream_devices_controller.h b/components/webrtc/media_stream_devices_controller.h index 0c6cc67f..73d035a 100644 --- a/components/webrtc/media_stream_devices_controller.h +++ b/components/webrtc/media_stream_devices_controller.h
@@ -86,11 +86,6 @@ // Runs |callback_| with the current audio/video permission settings. void RunCallback(bool blocked_by_feature_policy); - // Called when the permission has been set to update the - // TabSpecificContentSettings. - void UpdateTabSpecificContentSettings(ContentSetting audio_setting, - ContentSetting video_setting) const; - // Returns the content settings for the given content type and request. ContentSetting GetContentSetting( ContentSettingsType content_type,
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc index d62c622..35b8f41 100644 --- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -545,6 +545,22 @@ } IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, + AccessibilityEventsAriaHiddenDescendants) { + RunEventTest(FILE_PATH_LITERAL("aria-hidden-descendants.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, + AccessibilityEventsAriaHiddenDescendantsAlreadyIgnored) { + RunEventTest( + FILE_PATH_LITERAL("aria-hidden-descendants-already-ignored.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, + AccessibilityEventsCSSDisplayDescendants) { + RunEventTest(FILE_PATH_LITERAL("css-display-descendants.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, AccessibilityEventsCSSFlexTextUpdate) { RunEventTest(FILE_PATH_LITERAL("css-flex-text-update.html")); } @@ -555,6 +571,11 @@ } IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, + AccessibilityEventsCSSVisibilityDescendants) { + RunEventTest(FILE_PATH_LITERAL("css-visibility-descendants.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, AccessibilityEventsCSSCollapse) { RunEventTest(FILE_PATH_LITERAL("css-visibility-collapse.html")); }
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h index e13d028..36e3e53b 100644 --- a/content/browser/bad_message.h +++ b/content/browser/bad_message.h
@@ -256,6 +256,7 @@ INPUT_ROUTER_INVALID_EVENT_SOURCE = 228, RFH_INACTIVE_CHECK_FROM_SPECULATIVE_RFH = 229, RFH_SUBFRAME_CAPTURE_ON_MAIN_FRAME = 230, + RFH_CSP_ATTRIBUTE = 231, // Please add new elements here. The naming convention is abbreviated class // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/browsing_data/clear_site_data_handler.cc b/content/browser/browsing_data/clear_site_data_handler.cc index 7c717e1..9924493 100644 --- a/content/browser/browsing_data/clear_site_data_handler.cc +++ b/content/browser/browsing_data/clear_site_data_handler.cc
@@ -182,7 +182,7 @@ // modification to cookies. Clear-Site-Data applies this restriction to other // data types as well. // TODO(msramek): Consider showing a blocked icon via - // TabSpecificContentSettings and reporting the action in the "Blocked" + // PageSpecificContentSettings and reporting the action in the "Blocked" // section of the cookies dialog in OIB. if (load_flags_ & net::LOAD_DO_NOT_SAVE_COOKIES) { delegate_->AddMessage(
diff --git a/content/browser/frame_host/ancestor_throttle.cc b/content/browser/frame_host/ancestor_throttle.cc index 99910c1..7ba6dbc4 100644 --- a/content/browser/frame_host/ancestor_throttle.cc +++ b/content/browser/frame_host/ancestor_throttle.cc
@@ -145,6 +145,49 @@ AncestorThrottle::~AncestorThrottle() {} +NavigationThrottle::ThrottleCheckResult AncestorThrottle::WillStartRequest() { + if (!base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE)) + return NavigationThrottle::PROCEED; + + NavigationRequest* request = NavigationRequest::From(navigation_handle()); + if (request->IsInMainFrame()) + return NavigationThrottle::PROCEED; + + // TODO(antoniosartori): Probably we should have taken a snapshot of the 'csp' + // attribute at the beginning of the navigation and not now, since the + // beforeunload handlers might have modified it in the meantime. + std::vector<network::mojom::ContentSecurityPolicyPtr> frame_csp; + frame_csp.emplace_back( + request->frame_tree_node()->csp_attribute() + ? request->frame_tree_node()->csp_attribute()->Clone() + : nullptr); + const network::mojom::ContentSecurityPolicy* parent_required_csp = + request->frame_tree_node()->parent()->required_csp(); + + std::string error_message; + if (!network::IsValidRequiredCSPAttr(frame_csp, parent_required_csp, + error_message)) { + if (frame_csp[0]) { + navigation_handle()->GetParentFrame()->AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kError, + base::StringPrintf("The frame 'csp' attribute ('%s') is invalid and " + "will be discarded: %s", + frame_csp[0]->header->header_value.c_str(), + error_message.c_str())); + } + if (parent_required_csp) + request->SetRequiredCSP(parent_required_csp->Clone()); + // TODO(antoniosartori): Consider instead blocking the navigation here, + // since this seems to be insecure + // (cf. https://github.com/w3c/webappsec-cspee/pull/11). + } else { + // If |frame_csp| is valid then it is not null. + request->SetRequiredCSP(std::move(frame_csp[0])); + } + + return NavigationThrottle::PROCEED; +} + NavigationThrottle::ThrottleCheckResult AncestorThrottle::WillRedirectRequest() { // During a redirect, we don't know which RenderFrameHost we'll end up in, @@ -395,7 +438,8 @@ if (!base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE)) return CheckResult::PROCEED; - if (NavigationRequest::From(navigation_handle())->IsInMainFrame()) { + NavigationRequest* request = NavigationRequest::From(navigation_handle()); + if (request->IsInMainFrame()) { // We enforce CSPEE only for frames, not for portals. return CheckResult::PROCEED; } @@ -403,19 +447,16 @@ RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>( navigation_handle()->GetRenderFrameHost()); - const std::string& required_csp = - frame->frame_tree_node()->frame_owner_properties().required_csp; - - if (required_csp.empty()) + if (!request->required_csp()) return CheckResult::PROCEED; const network::mojom::AllowCSPFromHeaderValuePtr& allow_csp_from = - NavigationRequest::From(navigation_handle()) - ->response() - ->parsed_headers->allow_csp_from; + request->response()->parsed_headers->allow_csp_from; if (AllowsBlanketEnforcementOfRequiredCSP( frame->GetParent()->GetLastCommittedOrigin(), navigation_handle()->GetURL(), allow_csp_from)) { + // Enforce the required csps on the frame by passing them down to blink + request->ForceCSPForResponse(request->required_csp()->header->header_value); return CheckResult::PROCEED; } @@ -433,9 +474,7 @@ // TODO(antoniosartori): This is temporary, since the check in this function // is incomplete and will require iterations in several CLs. For now, let's // allow anything that has no "allow-csp-from" header. - if (!NavigationRequest::From(navigation_handle()) - ->GetResponseHeaders() - ->HasHeader("allow-csp-from")) { + if (!allow_csp_from) { return CheckResult::PROCEED; } @@ -447,7 +486,8 @@ "frame neither accepts that policy using the Allow-CSP-From header " "nor delivers a Content Security Policy which is at least as strong " "as that one.", - sanitized_blocked_url.c_str(), required_csp.c_str())); + sanitized_blocked_url.c_str(), + request->required_csp()->header->header_value.c_str())); return CheckResult::BLOCK; }
diff --git a/content/browser/frame_host/ancestor_throttle.h b/content/browser/frame_host/ancestor_throttle.h index 5122ece..7c92f0f 100644 --- a/content/browser/frame_host/ancestor_throttle.h +++ b/content/browser/frame_host/ancestor_throttle.h
@@ -45,6 +45,7 @@ ~AncestorThrottle() override; + NavigationThrottle::ThrottleCheckResult WillStartRequest() override; NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override; NavigationThrottle::ThrottleCheckResult WillProcessResponse() override; const char* GetNameForLogging() override;
diff --git a/content/browser/frame_host/ancestor_throttle_unittest.cc b/content/browser/frame_host/ancestor_throttle_unittest.cc index 5bfab420..a62a7ea 100644 --- a/content/browser/frame_host/ancestor_throttle_unittest.cc +++ b/content/browser/frame_host/ancestor_throttle_unittest.cc
@@ -7,10 +7,14 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/ref_counted.h" +#include "base/test/scoped_feature_list.h" +#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_renderer_host.h" +#include "content/test/navigation_simulator_impl.h" +#include "content/test/test_navigation_url_loader.h" #include "net/http/http_response_headers.h" #include "services/network/public/cpp/content_security_policy/content_security_policy.h" #include "services/network/public/cpp/features.h" @@ -41,6 +45,17 @@ return headers; } +network::mojom::ContentSecurityPolicyPtr ParsePolicy( + const std::string& policy) { + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders("HTTP/1.1 200 OK")); + headers->SetHeader("Content-Security-Policy", policy); + std::vector<network::mojom::ContentSecurityPolicyPtr> policies; + network::AddContentSecurityPolicyFromHeaders( + *headers, GURL("https://example.com/"), &policies); + return std::move(policies[0]); +} + } // namespace // AncestorThrottleTest @@ -132,8 +147,8 @@ } TEST_F(AncestorThrottleTest, AllowsBlanketEnforcementOfRequiredCSP) { - if (!base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE)) - return; + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(network::features::kOutOfBlinkCSPEE); struct TestCase { const char* name; @@ -250,4 +265,155 @@ } } +class AncestorThrottleNavigationTest + : public content::RenderViewHostTestHarness {}; + +TEST_F(AncestorThrottleNavigationTest, + WillStartRequestAddsSecRequiredCSPHeader) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(network::features::kOutOfBlinkCSPEE); + + // Perform an initial navigation to set up everything. + NavigateAndCommit(GURL("https://test.com")); + + // Create a frame tree with different 'csp' attributes according to the + // following graph: + // + // FRAME NAME | 'csp' attribute + // ------------------------------|------------------------------------- + // main_frame | (none) + // ├─child_with_csp | script-src 'none' + // │ ├─grandchild_same_csp | script-src 'none' + // │ ├─grandchild_no_csp | (none) + // │ │ └─grandgrandchild | (none) + // │ ├─grandchild_invalid_csp | report-to group + // │ └─grandchild_invalid_csp2 | script-src 'none'; invalid-directive + // └─sibling | (none) + // + // Test that the required CSP of every frame is computed/inherited correctly + // and that the Sec-Required-CSP header is set. + + auto* main_frame = static_cast<TestRenderFrameHost*>(main_rfh()); + + auto* child_with_csp = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(main_frame) + ->AppendChild("child_frame")); + child_with_csp->frame_tree_node()->set_csp_attribute( + ParsePolicy("script-src 'none'")); + + auto* grandchild_same_csp = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(child_with_csp) + ->AppendChild("grandchild_frame")); + grandchild_same_csp->frame_tree_node()->set_csp_attribute( + ParsePolicy("script-src 'none'")); + + auto* grandchild_no_csp = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(child_with_csp) + ->AppendChild("grandchild_frame")); + + auto* grandgrandchild = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(grandchild_no_csp) + ->AppendChild("grandgrandchild_frame")); + + auto* grandchild_invalid_csp = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(child_with_csp) + ->AppendChild("grandchild_frame")); + grandchild_invalid_csp->frame_tree_node()->set_csp_attribute( + ParsePolicy("report-to group")); + + auto* grandchild_invalid_csp2 = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(child_with_csp) + ->AppendChild("grandchild_frame")); + grandchild_invalid_csp2->frame_tree_node()->set_csp_attribute( + ParsePolicy("script-src 'none'; invalid-directive")); + + auto* sibling = static_cast<TestRenderFrameHost*>( + content::RenderFrameHostTester::For(main_frame) + ->AppendChild("sibling_frame")); + + struct TestCase { + const char* name; + TestRenderFrameHost* frame; + const char* expected_header; + } cases[] = { + { + "Main frame does not set header", + main_frame, + nullptr, + }, + { + "Frame with 'csp' attribute sets correct header", + child_with_csp, + "script-src 'none'", + }, + { + "Child with same 'csp' attribute as parent frame sets correct header", + grandchild_same_csp, + "script-src 'none'", + }, + { + "Child without 'csp' attribute inherits from parent", + grandchild_no_csp, + "script-src 'none'", + }, + { + "Grandchild without 'csp' attribute inherits from grandparent" + "header", + grandgrandchild, + "script-src 'none'", + }, + { + "Child with invalid 'csp' attribute inherits from parent", + grandchild_invalid_csp, + "script-src 'none'", + }, + { + "Child with invalid 'csp' attribute inherits from parent 2", + grandchild_invalid_csp2, + "script-src 'none'", + }, + { + "Frame without 'csp' attribute does not set header", + sibling, + nullptr, + }, + }; + + for (auto test : cases) { + SCOPED_TRACE(test.name); + std::unique_ptr<NavigationSimulator> simulator = + content::NavigationSimulator::CreateRendererInitiated( + GURL("https://www.foo.com/"), test.frame); + simulator->Start(); + NavigationRequest* request = + NavigationRequest::From(simulator->GetNavigationHandle()); + std::string header_value; + bool found = request->GetRequestHeaders().GetHeader("sec-required-csp", + &header_value); + if (test.expected_header) { + EXPECT_TRUE(found); + EXPECT_EQ(test.expected_header, header_value); + } else { + EXPECT_FALSE(found); + } + + // Complete the navigation and store the required CSP in the + // RenderFrameHostImpl so that the next tests can rely on this. + // TODO(antoniosartori): Update the NavigationSimulatorImpl so that this is + // done automatically on commit. + TestNavigationURLLoader* url_loader = + static_cast<TestNavigationURLLoader*>(request->loader_for_testing()); + auto response = network::mojom::URLResponseHead::New(); + response->headers = + base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK"); + response->parsed_headers = network::mojom::ParsedHeaders::New(); + response->parsed_headers->allow_csp_from = + network::mojom::AllowCSPFromHeaderValue::NewAllowStar(true); + url_loader->CallOnResponseStarted(std::move(response)); + auto* new_required_csp = request->required_csp(); + if (new_required_csp) + test.frame->required_csp_ = new_required_csp->Clone(); + } +} + } // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h index 54fd7c1..05c9871 100644 --- a/content/browser/frame_host/frame_tree_node.h +++ b/content/browser/frame_host/frame_tree_node.h
@@ -248,6 +248,15 @@ frame_owner_properties_ = frame_owner_properties; } + const network::mojom::ContentSecurityPolicy* csp_attribute() { + return csp_attribute_.get(); + } + + void set_csp_attribute( + network::mojom::ContentSecurityPolicyPtr parsed_csp_attribute) { + csp_attribute_ = std::move(parsed_csp_attribute); + } + bool HasSameOrigin(const FrameTreeNode& node) const { return replication_state_.origin.IsSameOriginWith( node.replication_state_.origin); @@ -514,6 +523,9 @@ // Note that dynamic updates only take effect on the next frame navigation. blink::mojom::FrameOwnerProperties frame_owner_properties_; + // Contains the current parsed value of the 'csp' attribute of this frame. + network::mojom::ContentSecurityPolicyPtr csp_attribute_; + // Owns an ongoing NavigationRequest until it is ready to commit. It will then // be reset and a RenderFrameHost will be responsible for the navigation. std::unique_ptr<NavigationRequest> navigation_request_;
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index c7e2973..2899140 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -3332,7 +3332,8 @@ false /* origin_isolated */, std::vector< network::mojom::WebClientHintsType>() /* enabled_client_hints */, - false /* is_cross_browsing_instance */); + false /* is_cross_browsing_instance */, + std::vector<std::string>() /* forced_content_security_policies */); #if defined(OS_ANDROID) if (ValidateDataURLAsString(params.data_url_as_string)) { commit_params->data_url_as_string = params.data_url_as_string->data();
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index 0df3b800..f346d5a 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -833,7 +833,8 @@ false /* origin_isolated */, std::vector< network::mojom::WebClientHintsType>() /* enabled_client_hints */, - false /* is_cross_browsing_instance */); + false /* is_cross_browsing_instance */, + std::vector<std::string>() /* forced_content_security_policies */); #if defined(OS_ANDROID) if (NavigationControllerImpl::ValidateDataURLAsString(GetDataURLAsString())) { commit_params->data_url_as_string = GetDataURLAsString()->data();
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 9830bd1..b836c4a 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -937,7 +937,8 @@ false /* origin_isolated */, std::vector< network::mojom::WebClientHintsType>() /* enabled_client_hints */, - false /* is_cross_browsing_instance */); + false /* is_cross_browsing_instance */, + std::vector<std::string>() /* forced_content_security_policies */); // CreateRendererInitiated() should only be triggered when the navigation is // initiated by a frame in the same process. @@ -1027,10 +1028,9 @@ std::vector<std::string>() /* force_enabled_origin_trials */, false /* origin_isolated */, std::vector< - network::mojom::WebClientHintsType>() /* enabled_client_hints - */ - , - false /* is_cross_browsing_instance */ + network::mojom::WebClientHintsType>() /* enabled_client_hints */, + false /* is_cross_browsing_instance */, + std::vector<std::string>() /* forced_content_security_policies */ ); mojom::BeginNavigationParamsPtr begin_params = mojom::BeginNavigationParams::New(); @@ -1693,6 +1693,21 @@ return std::move(client_security_state_); } +void NavigationRequest::SetRequiredCSP( + network::mojom::ContentSecurityPolicyPtr csp) { + DCHECK(!required_csp_); + required_csp_ = std::move(csp); + if (required_csp_) { + const std::string& header_value = required_csp_->header->header_value; + DCHECK(net::HttpUtil::IsValidHeaderValue(header_value)); + SetRequestHeader("Sec-Required-CSP", header_value); + } +} + +network::mojom::ContentSecurityPolicyPtr NavigationRequest::TakeRequiredCSP() { + return std::move(required_csp_); +} + void NavigationRequest::CreateCoepReporter( StoragePartition* storage_partition) { const auto& coep = client_security_state_->cross_origin_embedder_policy; @@ -4732,6 +4747,10 @@ return entry_overrides_ua_; } +void NavigationRequest::ForceCSPForResponse(const std::string& csp) { + commit_params_->forced_content_security_policies.push_back(csp); +} + // static NavigationRequest* NavigationRequest::From(NavigationHandle* handle) { return static_cast<NavigationRequest*>(handle);
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index bc60e642..c0691276 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -45,6 +45,7 @@ #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/cpp/origin_policy.h" #include "services/network/public/mojom/blocked_by_response_reason.mojom-shared.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h" #include "third_party/blink/public/common/loader/previews_state.h" @@ -350,6 +351,8 @@ // The NavigationRequest can be deleted while BeginNavigation() is called. void BeginNavigation(); + void ForceCSPForResponse(const std::string& csp); + const mojom::CommonNavigationParams& common_params() const { return *common_params_; } @@ -638,6 +641,12 @@ bool ua_change_requires_reload() const { return ua_change_requires_reload_; } + const network::mojom::ContentSecurityPolicy* required_csp() { + return required_csp_.get(); + } + void SetRequiredCSP(network::mojom::ContentSecurityPolicyPtr csp); + network::mojom::ContentSecurityPolicyPtr TakeRequiredCSP(); + CrossOriginEmbedderPolicyReporter* coep_reporter() { return coep_reporter_.get(); } @@ -1399,6 +1408,10 @@ // at the network request level. network::mojom::ClientSecurityStatePtr client_security_state_; + // Holds the required CSP for this navigation. This will be moved into + // the RenderFrameHost at DidCommitNavigation time. + network::mojom::ContentSecurityPolicyPtr required_csp_; + std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter_; std::unique_ptr<CrossOriginOpenerPolicyReporter> coop_reporter_;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 4e10c1cf..c53a217 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -4540,6 +4540,17 @@ opener_frame_token.value_or(base::UnguessableToken()), GetSiteInstance()); } +void RenderFrameHostImpl::DidChangeCSPAttribute( + const base::UnguessableToken& child_frame_token, + network::mojom::ContentSecurityPolicyPtr parsed_csp_attribute) { + auto* child = + FindAndVerifyChild(child_frame_token, bad_message::RFH_CSP_ATTRIBUTE); + if (!child) + return; + + child->frame_tree_node()->set_csp_attribute(std::move(parsed_csp_attribute)); +} + void RenderFrameHostImpl::DidChangeFramePolicy( const base::UnguessableToken& child_frame_token, const blink::FramePolicy& frame_policy) { @@ -8222,6 +8233,9 @@ } } + network::mojom::ContentSecurityPolicyPtr required_csp = + navigation_request->TakeRequiredCSP(); + // TODO(arthursonzogni, altimin): By taking ownership and deleting the // NavigationRequest, this line triggers the DidFinishNavigation event. There // are several document's associated state assigned below when a new document @@ -8251,6 +8265,10 @@ coep_reporter_ = std::move(coep_reporter); coop_reporter_ = std::move(coop_reporter); + // Store the required CSP (it will be used by the AncestorThrottle if + // this frame embeds a subframe when that subframe navigates). + required_csp_ = std::move(required_csp); + if (coep_reporter_) { mojo::PendingRemote<blink::mojom::ReportingObserver> remote; mojo::PendingReceiver<blink::mojom::ReportingObserver> receiver = @@ -8263,7 +8281,6 @@ base::BindOnce(&RenderFrameHostImpl::BindReportingObserver, weak_ptr_factory_.GetWeakPtr(), std::move(receiver))); } - } RecordCrossOriginIsolationMetrics(this);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 4cd841d..a2995be1 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1452,6 +1452,10 @@ return last_committed_client_security_state_; } + const network::mojom::ContentSecurityPolicy* required_csp() { + return required_csp_.get(); + } + // This function mimics DidCommitProvisionalLoad for navigations served from // the back-forward cache. void DidCommitBackForwardCacheNavigation( @@ -1616,6 +1620,9 @@ blink::mojom::FrameOwnerPropertiesPtr frame_owner_properties) override; void DidChangeOpener( const base::Optional<base::UnguessableToken>& opener_frame) override; + void DidChangeCSPAttribute( + const base::UnguessableToken& child_frame_token, + network::mojom::ContentSecurityPolicyPtr parsed_csp_attribute) override; void DidChangeFramePolicy(const base::UnguessableToken& child_frame_token, const blink::FramePolicy& frame_policy) override; void CapturePaintPreviewOfSubframe( @@ -1890,6 +1897,8 @@ AttemptDuplicateRenderWidgetHost); FRIEND_TEST_ALL_PREFIXES(RenderDocumentHostUserDataTest, CheckInPendingDeletionState); + FRIEND_TEST_ALL_PREFIXES(AncestorThrottleNavigationTest, + WillStartRequestAddsSecRequiredCSPHeader); class DroppedInterfaceRequestLogger; @@ -3134,6 +3143,11 @@ // RenderFrameHost. bool is_outer_delegate_frame_ = false; + // The browsing context's required CSP as defined by + // https://w3c.github.io/webappsec-cspee/#required-csp, + // stored when the frame commits the navigation. + network::mojom::ContentSecurityPolicyPtr required_csp_; + // NOTE: This must be the last member. base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_{this};
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 0ba74f2..2aecfd92 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -113,6 +113,10 @@ #include "content/browser/host_zoom_map_impl.h" #endif +#if defined(USE_OZONE) +#include "ui/base/ui_base_features.h" +#endif + using base::TimeDelta; using blink::WebConsoleMessage; @@ -141,6 +145,20 @@ } #endif // OS_WIN +#if defined(USE_OZONE) || defined(USE_X11) +bool IsSelectionBufferAvailable() { +#if defined(USE_OZONE) + if (features::IsUsingOzonePlatform()) + return ui::Clipboard::GetForCurrentThread()->IsSelectionBufferAvailable(); +#endif +#if defined(USE_X11) + return true; +#else + return false; +#endif +} +#endif // defined(USE_OZONE) || defined(USE_X11) + } // namespace // static @@ -218,6 +236,9 @@ // TODO(crbug.com/1066605): Consider exposing this as a FIDL parameter. prefs->focus_ring_color = SK_AlphaTRANSPARENT; #endif +#if defined(USE_OZONE) || defined(USE_X11) + prefs->selection_clipboard_buffer_available = IsSelectionBufferAvailable(); +#endif } RenderViewHostImpl::RenderViewHostImpl(
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index cc6dabc4..c313a00 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1211,7 +1211,7 @@ // Linux window managers like to handle raise-on-click themselves. If we // raise-on-click manually, this may override user settings that prevent // focus-stealing. -#if !defined(USE_X11) +#if !defined(OS_LINUX) // It is possible for the web-contents to be destroyed while it is being // activated. Use a weak-ptr to track whether that happened or not. // More in https://crbug.com/1040725
diff --git a/content/browser/web_contents/web_contents_view_aura_unittest.cc b/content/browser/web_contents/web_contents_view_aura_unittest.cc index 19e3fe9d..73d9cbd 100644 --- a/content/browser/web_contents/web_contents_view_aura_unittest.cc +++ b/content/browser/web_contents/web_contents_view_aura_unittest.cc
@@ -186,17 +186,11 @@ 0); ui::EventHandler* event_handler = GetView(); event_handler->OnMouseEvent(&mouse_event); -#if defined(USE_X11) - // The web-content is not activated during mouse-press on X11. +#if defined(OS_LINUX) + // The web-content is not activated during mouse-press on Linux. // See comment in WebContentsViewAura::OnMouseEvent() for more details. - // TODO(https://crbug.com/1109695): enable for Ozone/Linux. - if (!features::IsUsingOzonePlatform()) { - EXPECT_NE(web_contents(), nullptr); - } else + EXPECT_NE(web_contents(), nullptr); #endif - { - EXPECT_EQ(web_contents(), nullptr); - } } TEST_F(WebContentsViewAuraTest, OccludeView) { @@ -319,6 +313,7 @@ #if defined(OS_WIN) || defined(USE_X11) TEST_F(WebContentsViewAuraTest, DragDropFilesOriginateFromRenderer) { #if defined(USE_X11) + // TODO(https://crbug.com/1109695): enable for Ozone/Linux. if (features::IsUsingOzonePlatform()) return; #endif
diff --git a/content/common/navigation_params.mojom b/content/common/navigation_params.mojom index e610aad..94509a73 100644 --- a/content/common/navigation_params.mojom +++ b/content/common/navigation_params.mojom
@@ -438,4 +438,10 @@ // Whether this is a cross browsing instance navigation. bool is_cross_browsing_instance = false; + + // A list of additional Content Security Policies to be enforced by blink + // on the document. This is being used by Content Security Policy: Embedded + // Enforcement for enforcing on frames Content Security Policies required by + // their embedders. + array<string> forced_content_security_policies; };
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/OWNERS b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/OWNERS new file mode 100644 index 0000000..5d55ae16 --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/OWNERS
@@ -0,0 +1,3 @@ +file://content/browser/media/OWNERS + +# OS: Android
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/CursorAnchorInfoController.java b/content/public/android/java/src/org/chromium/content/browser/input/CursorAnchorInfoController.java index 67b23035..7b52265 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/CursorAnchorInfoController.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/CursorAnchorInfoController.java
@@ -97,7 +97,6 @@ }); } - @VisibleForTesting public void setInputMethodManagerWrapper(InputMethodManagerWrapper inputMethodManagerWrapper) { mInputMethodManagerWrapper = inputMethodManagerWrapper; }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java index 5cd00b38..559be9a 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
@@ -835,7 +835,6 @@ return true; } - @VisibleForTesting boolean finishComposingText() { if (!isValid()) return false; ImeAdapterImplJni.get().finishComposingText(mNativeImeAdapterAndroid, ImeAdapterImpl.this);
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java b/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java index ae355b7..c38f4995 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java
@@ -99,7 +99,6 @@ containerView.getContext(), handler, containerView, this); } - @VisibleForTesting @Override public void setTriggerDelayedOnCreateInputConnection(boolean trigger) { mTriggerDelayedOnCreateInputConnection = trigger;
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ImeAdapter.java b/content/public/android/java/src/org/chromium/content_public/browser/ImeAdapter.java index 96d70d4..d2a9c94 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/ImeAdapter.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/ImeAdapter.java
@@ -19,7 +19,6 @@ */ public interface ImeAdapter { /** Composition key code sent when user either hit a key or hit a selection. */ - @VisibleForTesting static final int COMPOSITION_KEY_CODE = 229; /**
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 9ab84b4d..1280deb 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -514,6 +514,14 @@ for (const auto& trial : commit_params.force_enabled_origin_trials) web_origin_trials.emplace_back(WebString::FromASCII(trial)); navigation_params->force_enabled_origin_trials = web_origin_trials; + + WebVector<WebString> forced_content_security_policies; + forced_content_security_policies.reserve( + commit_params.forced_content_security_policies.size()); + for (const auto& csp : commit_params.forced_content_security_policies) + forced_content_security_policies.emplace_back(WebString::FromASCII(csp)); + navigation_params->forced_content_security_policies = + forced_content_security_policies; } mojom::CommonNavigationParamsPtr MakeCommonNavigationParams(
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index b34393f..c468b81 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1663,6 +1663,11 @@ GetWebView()->GetSettings()->SetCaretBrowsingEnabled( renderer_preferences_.caret_browsing_enabled); } + +#if defined(USE_X11) || defined(USE_OZONE) + GetWebView()->GetSettings()->SetSelectionClipboardBufferAvailable( + renderer_preferences_.selection_clipboard_buffer_available); +#endif // defined(USE_X11) || defined(USE_OZONE) } void RenderViewImpl::OnMoveOrResizeStarted() {
diff --git a/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored-expected-win.txt b/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored-expected-win.txt new file mode 100644 index 0000000..770bdfc --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored-expected-win.txt
@@ -0,0 +1 @@ +EVENT_OBJECT_HIDE on <div#heading-root.a> role=ROLE_SYSTEM_GROUPING name="Heading" INVISIBLE level=2
diff --git a/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored.html b/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored.html new file mode 100644 index 0000000..47a7b4e --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored.html
@@ -0,0 +1,27 @@ +<!-- +@WIN-DENY:IA2_EVENT_TEXT_INSERTED* +@WIN-DENY:IA2_EVENT_TEXT_REMOVED* +@WIN-DENY:EVENT_OBJECT_REORDER* +--> +<html> +<body> +<!-- Hide events only need to occur on the root of what's shown/hidden, + not for each descendant, with some descendants already ignored. --> +<div role="toolbar"> + <div id="heading-root" role="heading" aria-label="Heading" class="a"> + <div> <!-- already ignored--> + <div> <!-- already ignored --> + <div id="heading-child"> + <div id="heading-grandchild"></div> + </div> + </div> + </div> + </div> +</div> +<script> + function go() { + document.querySelector('.a').setAttribute("aria-hidden", "true"); + } +</script> +</body> +</html>
diff --git a/content/test/data/accessibility/event/aria-hidden-descendants-expected-win.txt b/content/test/data/accessibility/event/aria-hidden-descendants-expected-win.txt new file mode 100644 index 0000000..4ae2446b0 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-descendants-expected-win.txt
@@ -0,0 +1,3 @@ +EVENT_OBJECT_HIDE on <div#heading-root.a> role=ROLE_SYSTEM_GROUPING name="Heading" INVISIBLE level=2 +EVENT_OBJECT_REORDER on <div> role=ROLE_SYSTEM_TOOLBAR IA2_STATE_HORIZONTAL +EVENT_OBJECT_SHOW on <div#banner-root.b> role=ROLE_SYSTEM_GROUPING name="Banner"
diff --git a/content/test/data/accessibility/event/aria-hidden-descendants.html b/content/test/data/accessibility/event/aria-hidden-descendants.html new file mode 100644 index 0000000..4a33575 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-descendants.html
@@ -0,0 +1,28 @@ +<!-- +@WIN-DENY:IA2_EVENT_TEXT_INSERTED* +@WIN-DENY:IA2_EVENT_TEXT_REMOVED* +--> +<html> +<body> +<!-- Show/hide events only need to occur on the root of what's shown/hidden, + not for each descendant --> +<div role="toolbar"> + <div id="heading-root" role="heading" aria-label="Heading" class="a"> + <div id="heading-child"> + <div id="heading-grandchild"></div> + </div> + </div> + <div id="banner-root" role="banner" aria-label="Banner" aria-hidden="true" class="b"> + <div id="banner-child"> + <div id="banner-grandchild"></div> + </div> + </div> +</div> +<script> + function go() { + document.querySelector('.a').setAttribute("aria-hidden", "true"); + document.querySelector('.b').removeAttribute("aria-hidden"); + } +</script> +</body> +</html>
diff --git a/content/test/data/accessibility/event/css-display-descendants-expected-win.txt b/content/test/data/accessibility/event/css-display-descendants-expected-win.txt new file mode 100644 index 0000000..ef42547 --- /dev/null +++ b/content/test/data/accessibility/event/css-display-descendants-expected-win.txt
@@ -0,0 +1,4 @@ +EVENT_OBJECT_HIDE on <div#heading-root.a> role=ROLE_SYSTEM_GROUPING name="Heading" level=2 +EVENT_OBJECT_REORDER on <div#banner-child> role=ROLE_SYSTEM_GROUPING +EVENT_OBJECT_REORDER on <div> role=ROLE_SYSTEM_TOOLBAR IA2_STATE_HORIZONTAL +EVENT_OBJECT_SHOW on <div#banner-root.b> role=ROLE_SYSTEM_GROUPING name="Banner"
diff --git a/content/test/data/accessibility/event/css-display-descendants.html b/content/test/data/accessibility/event/css-display-descendants.html new file mode 100644 index 0000000..add55ee --- /dev/null +++ b/content/test/data/accessibility/event/css-display-descendants.html
@@ -0,0 +1,35 @@ +<!-- +@WIN-DENY:IA2_EVENT_TEXT_INSERTED* +@WIN-DENY:IA2_EVENT_TEXT_REMOVED* +--> +<html> +<head> +<style> + .a { display: block; } + .b { display: none; } + body.flip .a { display: none; } + body.flip .b { display: block; } +</style> +</head> +<body> +<!-- Show/hide events only need to occur on the root of what's shown/hidden, + not for each descendant --> +<div role="toolbar"> + <div id="heading-root" role="heading" aria-label="Heading" class="a"> + <div id="heading-child"> + <div id="heading-grandchild"></div> + </div> + </div> + <div id="banner-root" role="banner" aria-label="Banner" class="b"> + <div id="banner-child"> + <div id="banner-grandchild"></div> + </div> + </div> +</div> +<script> + function go() { + document.body.className = 'flip'; + } +</script> +</body> +</html>
diff --git a/content/test/data/accessibility/event/css-visibility-descendants-expected-win.txt b/content/test/data/accessibility/event/css-visibility-descendants-expected-win.txt new file mode 100644 index 0000000..4ae2446b0 --- /dev/null +++ b/content/test/data/accessibility/event/css-visibility-descendants-expected-win.txt
@@ -0,0 +1,3 @@ +EVENT_OBJECT_HIDE on <div#heading-root.a> role=ROLE_SYSTEM_GROUPING name="Heading" INVISIBLE level=2 +EVENT_OBJECT_REORDER on <div> role=ROLE_SYSTEM_TOOLBAR IA2_STATE_HORIZONTAL +EVENT_OBJECT_SHOW on <div#banner-root.b> role=ROLE_SYSTEM_GROUPING name="Banner"
diff --git a/content/test/data/accessibility/event/css-visibility-descendants.html b/content/test/data/accessibility/event/css-visibility-descendants.html new file mode 100644 index 0000000..0aafc051 --- /dev/null +++ b/content/test/data/accessibility/event/css-visibility-descendants.html
@@ -0,0 +1,35 @@ +<!-- +@WIN-DENY:IA2_EVENT_TEXT_INSERTED* +@WIN-DENY:IA2_EVENT_TEXT_REMOVED* +--> +<html> +<head> +<style> + .a { visibility: visible; } + .b { visibility: hidden; } + body.flip .a { visibility: hidden; } + body.flip .b { visibility: visible; } +</style> +</head> +<body> +<!-- Show/hide events only need to occur on the root of what's shown/hidden, + not for each descendant --> +<div role="toolbar"> + <div id="heading-root" role="heading" aria-label="Heading" class="a"> + <div id="heading-child"> + <div id="heading-grandchild"></div> + </div> + </div> + <div id="banner-root" role="banner" aria-label="Banner" class="b"> + <div id="banner-child"> + <div id="banner-grandchild"></div> + </div> + </div> +</div> +<script> + function go() { + document.body.className = 'flip'; + } +</script> +</body> +</html>
diff --git a/content/test/test_navigation_url_loader.cc b/content/test/test_navigation_url_loader.cc index cb93b0f..e902ca3 100644 --- a/content/test/test_navigation_url_loader.cc +++ b/content/test/test_navigation_url_loader.cc
@@ -72,7 +72,8 @@ void TestNavigationURLLoader::CallOnResponseStarted( network::mojom::URLResponseHeadPtr response_head) { - response_head->parsed_headers = network::mojom::ParsedHeaders::New(); + if (!response_head->parsed_headers) + response_head->parsed_headers = network::mojom::ParsedHeaders::New(); // Create a bidirectionnal communication pipe between a URLLoader and a // URLLoaderClient. It will be closed at the end of this function. The sole // purpose of this is not to violate some DCHECKs when the navigation commits.
diff --git a/headless/lib/browser/headless_clipboard.cc b/headless/lib/browser/headless_clipboard.cc index 44667f3..603f28d 100644 --- a/headless/lib/browser/headless_clipboard.cc +++ b/headless/lib/browser/headless_clipboard.cc
@@ -176,6 +176,12 @@ *result = it->second; } +#if defined(USE_OZONE) +bool HeadlessClipboard::IsSelectionBufferAvailable() const { + return false; +} +#endif // defined(USE_OZONE) + // |data_src| is not used. It's only passed to be consistent with other // platforms. void HeadlessClipboard::WritePortableRepresentations(
diff --git a/headless/lib/browser/headless_clipboard.h b/headless/lib/browser/headless_clipboard.h index 67a40dd3..20bbf7bc 100644 --- a/headless/lib/browser/headless_clipboard.h +++ b/headless/lib/browser/headless_clipboard.h
@@ -67,6 +67,9 @@ void ReadData(const ui::ClipboardFormatType& format, const ui::ClipboardDataEndpoint* data_dst, std::string* result) const override; +#if defined(USE_OZONE) + bool IsSelectionBufferAvailable() const override; +#endif // defined(USE_OZONE) void WritePortableRepresentations( ui::ClipboardBuffer buffer, const ObjectMap& objects,
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 751773d..cb6d579 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -357,12 +357,12 @@ <message name="IDS_IOS_AUTOFILL_SET_UP_SCREENLOCK_CONTENT" desc="Message informing the user that in order to use the password, a screen lock needs to be set up on the device. This is shown as an alert message after the user tries to view or copy the password from a settings page. [CHAR_LIMIT=100]"> To use passwords, you must first set a passcode on your device. </message> - <message name="IDS_IOS_COPY_ACTION_TITLE" desc="Title of the action used to copy the selected piece of content to the clipboard. Targeted content type includes URL or image. [iOS only]"> - Copy - </message> <message name="IDS_IOS_DELETE_ACTION_TITLE" desc="Title of the action used to delete a selected item. Item types include, for example, a Bookmark or an History Entry. [iOS only]"> Delete </message> + <message name="IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE" desc="Title of the action used to open an URL in a new Incognito tab. [iOS only]"> + Open in Incognito + </message> <message name="IDS_IOS_BADGE_INCOGNITO_HINT" desc="Button displayed when the user is in Incognito mode. [iOS only]"> Current Webpage is on Incognito </message> @@ -616,7 +616,7 @@ Open </message> <message name="IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW" desc="The iOS menu item for opening a link in a new window. [iOS only]"> - Open In New Window + Open in New Window </message> <message name="IDS_IOS_CONTENT_CONTEXT_OPENIMAGE" desc="The name of the Open Image command in the content area context menu"> Open Image
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW.png.sha1 index 6b4f6835..6492618 100644 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW.png.sha1 +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW.png.sha1
@@ -1 +1 @@ -2589d145f8e666dad0b925a24d010fd5bb7a342b \ No newline at end of file +b7f2e1d1ccbf5bb66cf754f620214caa77b38df9 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COPY_ACTION_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COPY_ACTION_TITLE.png.sha1 deleted file mode 100644 index 244445a..0000000 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_COPY_ACTION_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9caa7694a2ef308a353a2ab234f4f1ba44920f86 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE.png.sha1 new file mode 100644 index 0000000..6492618 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE.png.sha1
@@ -0,0 +1 @@ +b7f2e1d1ccbf5bb66cf754f620214caa77b38df9 \ No newline at end of file
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index c3742fc..3a8f5118 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -554,9 +554,6 @@ {"page-info-refactoring", flag_descriptions::kPageInfoRefactoringName, flag_descriptions::kPageInfoRefactoringDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kPageInfoRefactoring)}, - {"contained-browser-bvc", flag_descriptions::kContainedBVCName, - flag_descriptions::kContainedBVCDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(kContainedBVC)}, {"ssl-committed-interstitials", flag_descriptions::kSSLCommittedInterstitialsName, flag_descriptions::kSSLCommittedInterstitialsDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 0dfb506..dc867c02 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -165,11 +165,6 @@ const char kConfirmInfobarMessagesUIDescription[] = "When enabled Confirm Infobars use the new Messages UI."; -const char kContainedBVCName[] = "Contained Browser ViewController"; -const char kContainedBVCDescription[] = - "When enabled, the BrowserViewController is contained by the TabGrid " - "instead of being presented"; - const char kCrashRestoreInfobarMessagesUIName[] = "Crash Restore Infobars Messages UI"; const char kCrashRestoreInfobarMessagesUIDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index ebadd3a..1d1b418 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -130,11 +130,6 @@ extern const char kConfirmInfobarMessagesUIName[]; extern const char kConfirmInfobarMessagesUIDescription[]; -// Title and description for the flag that makes the Browser being contained by -// the TabGrid instead of being presented. -extern const char kContainedBVCName[]; -extern const char kContainedBVCDescription[]; - // Title and description for the flag that enables Messages UI on // Crash Restore Infobars. extern const char kCrashRestoreInfobarMessagesUIName[];
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index 48fa0fb..e8b7f58c 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -178,7 +178,7 @@ NTPTabOpeningPostOpeningAction NTPActionAfterTabSwitcherDismissal; // TabSwitcher object -- the tab grid. -@property(nonatomic, strong) id<TabSwitcher> tabSwitcher; +@property(nonatomic, strong, readonly) id<TabSwitcher> tabSwitcher; // The main coordinator, lazily created the first time it is accessed. Manages // the main view controller. This property should not be accessed before the @@ -270,6 +270,10 @@ self.signinCoordinator.isSettingsViewPresented; } +- (id<TabSwitcher>)tabSwitcher { + return self.mainCoordinator; +} + #pragma mark - SceneStateObserver - (void)sceneState:(SceneState*)sceneState @@ -584,9 +588,8 @@ // Lazy init of mainCoordinator. [self.mainCoordinator start]; - self.tabSwitcher = self.mainCoordinator.tabSwitcher; // Call -restoreInternalState so that the grid shows the correct panel. - [_tabSwitcher + [self.tabSwitcher restoreInternalStateWithMainBrowser:self.mainInterface.browser otrBrowser:self.incognitoInterface.browser activeBrowser:self.currentInterface.browser];
diff --git a/ios/chrome/browser/ui/menu/BUILD.gn b/ios/chrome/browser/ui/menu/BUILD.gn index b1549bb..2d86946 100644 --- a/ios/chrome/browser/ui/menu/BUILD.gn +++ b/ios/chrome/browser/ui/menu/BUILD.gn
@@ -12,6 +12,7 @@ ] configs += [ "//build/config/compiler:enable_arc" ] deps = [ + "resources:copy_link_url", "//base", "//ios/chrome/app/strings", "//ios/chrome/browser/ui/commands", @@ -30,6 +31,7 @@ sources = [ "action_factory_unittest.mm" ] deps = [ ":menu", + "resources:copy_link_url", "//base", "//base/test:test_support", "//ios/chrome/app/strings",
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm index 370d3ac..3d334c9 100644 --- a/ios/chrome/browser/ui/menu/action_factory.mm +++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -59,12 +59,13 @@ } - (UIAction*)actionToCopyURL:(const GURL)URL { - return [self actionWithTitle:l10n_util::GetNSString(IDS_IOS_COPY_ACTION_TITLE) - image:[UIImage systemImageNamed:@"doc.on.doc"] - type:MenuActionType::Copy - block:^{ - StoreURLInPasteboard(URL); - }]; + return + [self actionWithTitle:l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_COPY) + image:[UIImage imageNamed:@"copy_link_url"] + type:MenuActionType::Copy + block:^{ + StoreURLInPasteboard(URL); + }]; } - (UIAction*)actionToDeleteWithBlock:(ProceduralBlock)block { @@ -113,12 +114,11 @@ } - (UIAction*)actionToOpenInNewIncognitoTabWithBlock:(ProceduralBlock)block { - return - [self actionWithTitle:l10n_util::GetNSString( - IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB) - image:nil - type:MenuActionType::OpenInNewIncognitoTab - block:block]; + return [self actionWithTitle:l10n_util::GetNSString( + IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE) + image:nil + type:MenuActionType::OpenInNewIncognitoTab + block:block]; } - (UIAction*)actionToOpenInNewWindowWithURL:(const GURL)URL
diff --git a/ios/chrome/browser/ui/menu/action_factory_unittest.mm b/ios/chrome/browser/ui/menu/action_factory_unittest.mm index 2a19dc0a..74b01fd 100644 --- a/ios/chrome/browser/ui/menu/action_factory_unittest.mm +++ b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
@@ -96,8 +96,9 @@ [[ActionFactory alloc] initWithBrowser:test_browser_.get() scenario:kTestMenuScenario]; - UIImage* expectedImage = [UIImage systemImageNamed:@"doc.on.doc"]; - NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_COPY_ACTION_TITLE); + UIImage* expectedImage = [UIImage imageNamed:@"copy_link_url"]; + NSString* expectedTitle = + l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_COPY); GURL testURL = GURL("https://example.com"); @@ -162,7 +163,7 @@ GURL testURL = GURL("https://example.com"); NSString* expectedTitle = - l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB); + l10n_util::GetNSString(IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE); UIAction* actionWithURL = [factory actionToOpenInNewIncognitoTabWithURL:testURL completion:nil];
diff --git a/ios/chrome/browser/ui/menu/resources/BUILD.gn b/ios/chrome/browser/ui/menu/resources/BUILD.gn new file mode 100644 index 0000000..fc0ae5e --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/BUILD.gn
@@ -0,0 +1,13 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ios/asset_catalog.gni") + +imageset("copy_link_url") { + sources = [ + "copy_link_url.imageset/Contents.json", + "copy_link_url.imageset/copy_link_url@2x.png", + "copy_link_url.imageset/copy_link_url@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/Contents.json new file mode 100644 index 0000000..280deeec --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "copy_link_url@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "copy_link_url@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/copy_link_url@2x.png b/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/copy_link_url@2x.png new file mode 100644 index 0000000..9771a14 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/copy_link_url@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/copy_link_url@3x.png b/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/copy_link_url@3x.png new file mode 100644 index 0000000..69e9af0 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/copy_link_url.imageset/copy_link_url@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm index e3895a4a..6f6e05e 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
@@ -42,6 +42,11 @@ } // namespace +#if defined(__IPHONE_14_0) +@interface OmniboxViewController (Scribble) <UIScribbleInteractionDelegate> +@end +#endif // defined(__IPHONE14_0) + @interface OmniboxViewController () <OmniboxTextFieldDelegate> { // Weak, acts as a delegate OmniboxTextChangeDelegate* _textChangeDelegate; @@ -122,6 +127,13 @@ SetA11yLabelAndUiAutomationName(self.textField, IDS_ACCNAME_LOCATION, @"Address"); + +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + if (@available(iOS 14, *)) { + [self.textField + addInteraction:[[UIScribbleInteraction alloc] initWithDelegate:self]]; + } +#endif // defined(__IPHONE_14_0) } - (void)viewDidLoad { @@ -227,6 +239,17 @@ return self.view.textField; } +- (void)prepareOmniboxForScribble { + [self.textField exitPreEditState]; + [self.textField setText:[[NSAttributedString alloc] initWithString:@""] + userTextLength:0]; + self.textField.placeholder = nil; +} + +- (void)cleanupOmniboxAfterScribble { + self.textField.placeholder = l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT); +} + #pragma mark - OmniboxTextFieldDelegate - (BOOL)textField:(UITextField*)textField @@ -588,4 +611,29 @@ })); } +#pragma mark - UIScribbleInteractionDelegate + +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + +- (void)scribbleInteractionWillBeginWriting:(UIScribbleInteraction*)interaction + API_AVAILABLE(ios(14.0)) { + if (self.textField.isPreEditing) { + [self.textField exitPreEditState]; + [self.textField setText:[[NSAttributedString alloc] initWithString:@""] + userTextLength:0]; + } + + [self.textField clearAutocompleteText]; +} + +- (void)scribbleInteractionDidFinishWriting:(UIScribbleInteraction*)interaction + API_AVAILABLE(ios(14.0)) { + [self cleanupOmniboxAfterScribble]; + + // Dismiss any inline autocomplete. The user expectation is to not have it. + [self.textField clearAutocompleteText]; +} + +#endif // defined(__IPHONE_14_0) + @end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm index 05ca688b..321ff7c6a 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -421,6 +421,8 @@ - (UIContextMenuConfiguration*)contextMenuConfigurationForItem: (id<ReadingListListItem>)item API_AVAILABLE(ios(13.0)) { + __weak id<ReadingListListItemAccessibilityDelegate> accessibilityDelegate = + self.tableViewController; __weak __typeof(self) weakSelf = self; UIContextMenuActionProvider actionProvider = @@ -468,6 +470,10 @@ [menuElements addObject:[actionFactory actionToCopyURL:item.entryURL]]; + [menuElements addObject:[actionFactory actionToDeleteWithBlock:^{ + [accessibilityDelegate deleteItem:item]; + }]]; + return [UIMenu menuWithTitle:@"" children:menuElements]; };
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h b/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h index 4833e07..050c497 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h +++ b/ios/chrome/browser/ui/reading_list/reading_list_list_item_accessibility_delegate.h
@@ -19,6 +19,7 @@ - (void)openItemOffline:(id<ReadingListListItem>)item; - (void)markItemRead:(id<ReadingListListItem>)item; - (void)markItemUnread:(id<ReadingListListItem>)item; +- (void)deleteItem:(id<ReadingListListItem>)item; @end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm index 8e8b019..da91a67 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -441,6 +441,16 @@ } } +- (void)deleteItem:(id<ReadingListListItem>)item { + TableViewItem<ReadingListListItem>* tableViewItem = + base::mac::ObjCCastStrict<TableViewItem<ReadingListListItem>>(item); + if ([self.tableViewModel hasItem:tableViewItem]) { + NSIndexPath* indexPath = + [self.tableViewModel indexPathForItem:tableViewItem]; + [self deleteItemsAtIndexPaths:@[ indexPath ]]; + } +} + #pragma mark - ReadingListToolbarButtonCommands - (void)enterReadingListEditMode {
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index d2d41e2..efddfb3 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -181,9 +181,6 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - if (!base::FeatureList::IsEnabled(kContainedBVC)) { - self.preventUpdates = NO; - } if (!self.preventUpdates) { // The table view might get stale while hidden, so we need to forcibly // refresh it here. @@ -193,9 +190,6 @@ } - (void)viewWillDisappear:(BOOL)animated { - if (!base::FeatureList::IsEnabled(kContainedBVC)) { - self.preventUpdates = YES; - } [super viewWillDisappear:animated]; } @@ -223,7 +217,7 @@ _preventUpdates = preventUpdates; - if (preventUpdates || !base::FeatureList::IsEnabled(kContainedBVC)) + if (preventUpdates) return; [self loadModel]; [self.tableView reloadData];
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn index ead7b36b..42582503 100644 --- a/ios/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -6,8 +6,6 @@ source_set("tab_grid") { sources = [ - "tab_grid_adaptor.h", - "tab_grid_adaptor.mm", "tab_grid_coordinator.h", "tab_grid_coordinator.mm", "tab_grid_mediator.h", @@ -67,8 +65,6 @@ source_set("tab_grid_ui") { sources = [ - "legacy_tab_grid_transition_handler.h", - "legacy_tab_grid_transition_handler.mm", "tab_grid_bottom_toolbar.h", "tab_grid_bottom_toolbar.mm", "tab_grid_empty_state_view.h",
diff --git a/ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.h b/ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.h deleted file mode 100644 index d13fdfa..0000000 --- a/ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_LEGACY_TAB_GRID_TRANSITION_HANDLER_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_LEGACY_TAB_GRID_TRANSITION_HANDLER_H_ - -#import <UIKit/UIKit.h> - -@protocol GridTransitionAnimationLayoutProviding; - -@interface LegacyTabGridTransitionHandler - : NSObject <UIViewControllerTransitioningDelegate> - -@property(nonatomic, weak) id<GridTransitionAnimationLayoutProviding> provider; - -@end - -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_LEGACY_TAB_GRID_TRANSITION_HANDLER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.mm b/ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.mm deleted file mode 100644 index 2e242dc..0000000 --- a/ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.mm +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.h" - -#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation_layout_providing.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation LegacyTabGridTransitionHandler - -#pragma mark - UIViewControllerTransitioningDelegate - -- (id<UIViewControllerAnimatedTransitioning>) - animationControllerForPresentedController:(UIViewController*)presented - presentingController:(UIViewController*)presenting - sourceController:(UIViewController*)source { - if (!UIAccessibilityIsReduceMotionEnabled() && - self.provider.selectedCellVisible) { - return [[LegacyGridToVisibleTabAnimator alloc] - initWithAnimationLayoutProvider:self.provider]; - } - ReducedMotionAnimator* simpleAnimator = [[ReducedMotionAnimator alloc] init]; - simpleAnimator.presenting = YES; - return simpleAnimator; -} - -- (id<UIViewControllerAnimatedTransitioning>) - animationControllerForDismissedController:(UIViewController*)dismissed { - if (!UIAccessibilityIsReduceMotionEnabled()) { - return [[LegacyTabToGridAnimator alloc] - initWithAnimationLayoutProvider:self.provider]; - } - ReducedMotionAnimator* simpleAnimator = [[ReducedMotionAnimator alloc] init]; - simpleAnimator.presenting = NO; - return simpleAnimator; -} - -@end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h deleted file mode 100644 index 6e051df..0000000 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_ADAPTOR_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_ADAPTOR_H_ - -#import <Foundation/Foundation.h> - -#import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h" -#import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" -#import "ios/chrome/browser/ui/tab_grid/tab_switcher.h" - -@class TabGridViewController; - -// An opaque adaptor for the TabSwitcher protocol into the TabGrid. -// Consuming objects should be passed instances of this object as an -// id<TabSwitcher>. -// All of the methods and properties on this class are internal API fot the -// tab grid, and external code shouldn't depend on them. -@interface TabGridAdaptor : NSObject<TabSwitcher> -@property(nonatomic, weak) TabGridViewController* tabGridViewController; -// The mediator for the incognito grid. -@property(nonatomic, weak) TabGridMediator* incognitoMediator; -@end - -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_ADAPTOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm deleted file mode 100644 index 13bc471..0000000 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h" - -#include "base/check.h" -#import "ios/chrome/browser/main/browser.h" -#include "ios/chrome/browser/main/browser.h" -#import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h" -#import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" -#import "ios/chrome/browser/url_loading/url_loading_params.h" -#import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h" -#import "ios/chrome/browser/web_state_list/web_state_list.h" -#import "ios/web/public/navigation/navigation_manager.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation TabGridAdaptor -// TabSwitcher properties. -@synthesize delegate = _delegate; - -#pragma mark - TabSwitcher - -- (void)restoreInternalStateWithMainBrowser:(Browser*)mainBrowser - otrBrowser:(Browser*)otrBrowser - activeBrowser:(Browser*)activeBrowser { - // The only action here is to signal to the tab grid which panel should be - // active. - if (activeBrowser == otrBrowser) { - self.tabGridViewController.activePage = TabGridPageIncognitoTabs; - } else { - self.tabGridViewController.activePage = TabGridPageRegularTabs; - } -} - -- (UIViewController*)viewController { - return self.tabGridViewController; -} - -- (void)dismissWithNewTabAnimationToBrowser:(Browser*)browser - withUrlLoadParams:(const UrlLoadParams&)urlLoadParams - atIndex:(int)position { - int tabIndex = std::min(position, browser->GetWebStateList()->count()); - - TabInsertionBrowserAgent::FromBrowser(browser)->InsertWebState( - urlLoadParams.web_params, nil, false, tabIndex, false); - - // Tell the delegate to display the tab. - DCHECK(self.delegate); - [self.delegate tabSwitcher:self - shouldFinishWithBrowser:browser - focusOmnibox:NO]; -} - -- (void)setOtrBrowser:(Browser*)browser { - DCHECK(self.incognitoMediator); - self.incognitoMediator.browser = browser; -} - -@end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h index f00c88e..7f253ee 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h
@@ -9,14 +9,14 @@ #import "base/ios/block_types.h" #import "ios/chrome/browser/chrome_root_coordinator.h" +#import "ios/chrome/browser/ui/tab_grid/tab_switcher.h" @protocol ApplicationCommands; @protocol BrowsingDataCommands; -@protocol TabSwitcher; class Browser; -@interface TabGridCoordinator : ChromeRootCoordinator +@interface TabGridCoordinator : ChromeRootCoordinator <TabSwitcher> - (instancetype)initWithWindow:(UIWindow*)window applicationCommandEndpoint: @@ -27,7 +27,7 @@ - (instancetype)initWithWindow:(UIWindow*)window NS_UNAVAILABLE; -@property(nonatomic, readonly) id<TabSwitcher> tabSwitcher; +@property(nonatomic, weak) id<TabSwitcherDelegate> delegate; @property(nonatomic, assign) Browser* regularBrowser; @property(nonatomic, assign) Browser* incognitoBrowser;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index 6e395fa..c640384 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -21,8 +21,6 @@ #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_presentation_delegate.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h" -#import "ios/chrome/browser/ui/tab_grid/legacy_tab_grid_transition_handler.h" -#import "ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" @@ -30,6 +28,7 @@ #include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" +#import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -41,20 +40,12 @@ RecentTabsPresentationDelegate> // Superclass property specialized for the class that this coordinator uses. @property(nonatomic, weak) TabGridViewController* baseViewController; -// Pointer to the masking view used to prevent the main view controller from -// being shown at launch. -@property(nonatomic, strong) UIView* launchMaskView; // Commad dispatcher used while this coordinator's view controller is active. // (for compatibility with the TabSwitcher protocol). @property(nonatomic, strong) CommandDispatcher* dispatcher; -// Object that internally backs the public TabSwitcher -@property(nonatomic, strong) TabGridAdaptor* adaptor; // Container view controller for the BVC to live in; this class's view // controller will present this. @property(nonatomic, strong) BVCContainerViewController* bvcContainer; -// Transitioning delegate for the view controller. -@property(nonatomic, strong) - LegacyTabGridTransitionHandler* legacyTransitionHandler; // Handler for the transitions between the TabGrid and the Browser. @property(nonatomic, strong) TabGridTransitionHandler* transitionHandler; // Mediator for regular Tabs. @@ -99,10 +90,6 @@ #pragma mark - Public -- (id<TabSwitcher>)tabSwitcher { - return self.adaptor; -} - - (Browser*)regularBrowser { // Ensure browser which is actually used by the mediator is returned, as it // may have been updated. @@ -151,16 +138,9 @@ [[TabGridViewController alloc] init]; baseViewController.handler = HandlerForProtocol(self.dispatcher, ApplicationCommands); - self.legacyTransitionHandler = [[LegacyTabGridTransitionHandler alloc] init]; - self.legacyTransitionHandler.provider = baseViewController; - baseViewController.modalPresentationStyle = UIModalPresentationCustom; - baseViewController.transitioningDelegate = self.legacyTransitionHandler; baseViewController.tabPresentationDelegate = self; _baseViewController = baseViewController; - self.adaptor = [[TabGridAdaptor alloc] init]; - self.adaptor.tabGridViewController = self.baseViewController; - self.regularTabsMediator = [[TabGridMediator alloc] initWithConsumer:baseViewController.regularTabsConsumer]; ChromeBrowserState* regularBrowserState = @@ -177,7 +157,6 @@ self.incognitoTabsMediator = [[TabGridMediator alloc] initWithConsumer:baseViewController.incognitoTabsConsumer]; self.incognitoTabsMediator.browser = _incognitoBrowser; - self.adaptor.incognitoMediator = self.incognitoTabsMediator; baseViewController.regularTabsDelegate = self.regularTabsMediator; baseViewController.incognitoTabsDelegate = self.incognitoTabsMediator; baseViewController.regularTabsDragDropHandler = self.regularTabsMediator; @@ -207,21 +186,7 @@ WindowOpenDisposition::NEW_FOREGROUND_TAB; baseViewController.remoteTabsViewController.presentationDelegate = self; - if (!base::FeatureList::IsEnabled(kContainedBVC)) { - // Insert the launch screen view in front of this view to hide it until - // after launch. This should happen before |baseViewController| is made the - // window's root view controller. - NSBundle* mainBundle = base::mac::FrameworkBundle(); - NSArray* topObjects = [mainBundle loadNibNamed:@"LaunchScreen" - owner:self - options:nil]; - UIViewController* launchScreenController = - base::mac::ObjCCastStrict<UIViewController>([topObjects lastObject]); - self.launchMaskView = launchScreenController.view; - [baseViewController.view addSubview:self.launchMaskView]; - } else { - self.firstPresentation = YES; - } + self.firstPresentation = YES; // TODO(crbug.com/850387) : Currently, consumer calls from the mediator // prematurely loads the view in |RecentTabsTableViewController|. Fix this so @@ -265,10 +230,6 @@ - (UIViewController*)activeViewController { if (self.bvcContainer) { - if (!base::FeatureList::IsEnabled(kContainedBVC)) { - DCHECK_EQ(self.bvcContainer, - self.baseViewController.presentedViewController); - } DCHECK(self.bvcContainer.currentBVC); return self.bvcContainer.currentBVC; } @@ -290,41 +251,30 @@ } - (void)showTabSwitcher:(id<TabSwitcher>)tabSwitcher { - DCHECK(tabSwitcher); DCHECK_EQ([tabSwitcher viewController], self.baseViewController); - // It's also expected that |tabSwitcher| will be |self.tabSwitcher|, but that - // may not be worth a DCHECK? - BOOL animated = !self.animationsDisabledForTesting; // If a BVC is currently being presented, dismiss it. This will trigger any // necessary animations. if (self.bvcContainer) { - if (base::FeatureList::IsEnabled(kContainedBVC)) { - // This is done with a dispatch to make sure that the view isn't added to - // the view hierarchy right away, as it is not the expectations of the - // API. - dispatch_async(dispatch_get_main_queue(), ^{ - [self.baseViewController contentWillAppearAnimated:animated]; - self.baseViewController.childViewControllerForStatusBarStyle = nil; + // This is done with a dispatch to make sure that the view isn't added to + // the view hierarchy right away, as it is not the expectations of the + // API. + dispatch_async(dispatch_get_main_queue(), ^{ + [self.baseViewController contentWillAppearAnimated:animated]; + self.baseViewController.childViewControllerForStatusBarStyle = nil; - self.transitionHandler = [[TabGridTransitionHandler alloc] - initWithLayoutProvider:self.baseViewController]; - self.transitionHandler.animationDisabled = !animated; - [self.transitionHandler - transitionFromBrowser:self.bvcContainer - toTabGrid:self.baseViewController - withCompletion:^{ - self.bvcContainer = nil; - [self.baseViewController contentDidAppear]; - }]; - }); - } else { - self.bvcContainer.transitioningDelegate = self.legacyTransitionHandler; - self.bvcContainer = nil; - [self.baseViewController dismissViewControllerAnimated:animated - completion:nil]; - } + self.transitionHandler = [[TabGridTransitionHandler alloc] + initWithLayoutProvider:self.baseViewController]; + self.transitionHandler.animationDisabled = !animated; + [self.transitionHandler + transitionFromBrowser:self.bvcContainer + toTabGrid:self.baseViewController + withCompletion:^{ + self.bvcContainer = nil; + [self.baseViewController contentDidAppear]; + }]; + }); } // Record when the tab switcher is presented. base::RecordAction(base::UserMetricsAction("MobileTabGridEntered")); @@ -348,12 +298,10 @@ } self.bvcContainer = [[BVCContainerViewController alloc] init]; - self.bvcContainer.modalPresentationStyle = UIModalPresentationFullScreen; self.bvcContainer.currentBVC = viewController; - self.bvcContainer.transitioningDelegate = self.legacyTransitionHandler; BOOL animated = !self.animationsDisabledForTesting; // Never animate the first time. - if (self.launchMaskView || self.firstPresentation) + if (self.firstPresentation) animated = NO; // Extened |completion| to signal the tab switcher delegate @@ -361,43 +309,31 @@ // on top of the tab switcher) transition has completed. // Finally, the launch mask view should be removed. ProceduralBlock extendedCompletion = ^{ - [self.tabSwitcher.delegate - tabSwitcherDismissTransitionDidEnd:self.tabSwitcher]; - if (base::FeatureList::IsEnabled(kContainedBVC)) { - if (!GetFirstResponder()) { - // It is possible to already have a first responder (for example the - // omnibox). In that case, we don't want to mark BVC as first responder. - [self.bvcContainer.currentBVC becomeFirstResponder]; - } + [self.delegate tabSwitcherDismissTransitionDidEnd:self]; + if (!GetFirstResponder()) { + // It is possible to already have a first responder (for example the + // omnibox). In that case, we don't want to mark BVC as first responder. + [self.bvcContainer.currentBVC becomeFirstResponder]; } if (completion) { completion(); } - [self.launchMaskView removeFromSuperview]; - self.launchMaskView = nil; self.firstPresentation = NO; }; - if (base::FeatureList::IsEnabled(kContainedBVC)) { - self.baseViewController.childViewControllerForStatusBarStyle = - self.bvcContainer.currentBVC; + self.baseViewController.childViewControllerForStatusBarStyle = + self.bvcContainer.currentBVC; - [self.adaptor.tabGridViewController contentWillDisappearAnimated:animated]; + [self.baseViewController contentWillDisappearAnimated:animated]; - self.transitionHandler = [[TabGridTransitionHandler alloc] - initWithLayoutProvider:self.baseViewController]; - self.transitionHandler.animationDisabled = !animated; - [self.transitionHandler transitionFromTabGrid:self.baseViewController - toBrowser:self.bvcContainer - withCompletion:^{ - extendedCompletion(); - }]; - - } else { - [self.baseViewController presentViewController:self.bvcContainer - animated:animated - completion:extendedCompletion]; - } + self.transitionHandler = [[TabGridTransitionHandler alloc] + initWithLayoutProvider:self.baseViewController]; + self.transitionHandler.animationDisabled = !animated; + [self.transitionHandler transitionFromTabGrid:self.baseViewController + toBrowser:self.bvcContainer + withCompletion:^{ + extendedCompletion(); + }]; } #pragma mark - TabPresentationDelegate @@ -420,11 +356,11 @@ // Defensively early return instead of continuing. return; } - // Trigger the transition through the TabSwitcher delegate. This will in turn - // call back into this coordinator via the ViewControllerSwapping protocol. - [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher - shouldFinishWithBrowser:activeBrowser - focusOmnibox:focusOmnibox]; + // Trigger the transition through the delegate. This will in turn call back + // into this coordinator via the ViewControllerSwapping protocol. + [self.delegate tabSwitcher:self + shouldFinishWithBrowser:activeBrowser + focusOmnibox:focusOmnibox]; } #pragma mark - RecentTabsPresentationDelegate @@ -448,23 +384,56 @@ } - (void)showActiveRegularTabFromRecentTabs { - [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher - shouldFinishWithBrowser:self.regularBrowser - focusOmnibox:NO]; + [self.delegate tabSwitcher:self + shouldFinishWithBrowser:self.regularBrowser + focusOmnibox:NO]; } #pragma mark - HistoryPresentationDelegate - (void)showActiveRegularTabFromHistory { - [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher - shouldFinishWithBrowser:self.regularBrowser - focusOmnibox:NO]; + [self.delegate tabSwitcher:self + shouldFinishWithBrowser:self.regularBrowser + focusOmnibox:NO]; } - (void)showActiveIncognitoTabFromHistory { - [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher - shouldFinishWithBrowser:self.incognitoBrowser - focusOmnibox:NO]; + [self.delegate tabSwitcher:self + shouldFinishWithBrowser:self.incognitoBrowser + focusOmnibox:NO]; +} + +#pragma mark - TabSwitcher + +- (void)restoreInternalStateWithMainBrowser:(Browser*)mainBrowser + otrBrowser:(Browser*)otrBrowser + activeBrowser:(Browser*)activeBrowser { + // The only action here is to signal to the tab grid which panel should be + // active. + if (activeBrowser == otrBrowser) { + self.baseViewController.activePage = TabGridPageIncognitoTabs; + } else { + self.baseViewController.activePage = TabGridPageRegularTabs; + } +} + +- (void)dismissWithNewTabAnimationToBrowser:(Browser*)browser + withUrlLoadParams:(const UrlLoadParams&)urlLoadParams + atIndex:(int)position { + int tabIndex = std::min(position, browser->GetWebStateList()->count()); + + TabInsertionBrowserAgent::FromBrowser(browser)->InsertWebState( + urlLoadParams.web_params, nil, false, tabIndex, false); + + // Tell the delegate to display the tab. + [self.delegate tabSwitcher:self + shouldFinishWithBrowser:browser + focusOmnibox:NO]; +} + +- (void)setOtrBrowser:(Browser*)browser { + DCHECK(self.incognitoTabsMediator); + self.incognitoTabsMediator.browser = browser; } @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm index ca65276..447b754 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm
@@ -59,7 +59,7 @@ [coordinator_ start]; delegate_ = [[TestTabSwitcherDelegate alloc] init]; - coordinator_.tabSwitcher.delegate = delegate_; + coordinator_.delegate = delegate_; normal_tab_view_controller_ = [[UIViewController alloc] init]; normal_tab_view_controller_.view.frame = CGRectMake(20, 20, 10, 10); @@ -115,11 +115,11 @@ EXPECT_EQ(normal_tab_view_controller_, coordinator_.activeViewController); // Now setting a TabSwitcher will make the switcher active. - [coordinator_ showTabSwitcher:coordinator_.tabSwitcher]; + [coordinator_ showTabSwitcher:coordinator_]; bool tab_switcher_active = base::test::ios::WaitUntilConditionOrTimeout( base::test::ios::kWaitForUIElementTimeout, ^bool { - return [coordinator_.tabSwitcher viewController] == - coordinator_.activeViewController; + return + [coordinator_ viewController] == coordinator_.activeViewController; }); EXPECT_TRUE(tab_switcher_active); } @@ -127,20 +127,19 @@ // Tests that it is possible to set a TabViewController after setting a // TabSwitcher. TEST_F(TabGridCoordinatorTest, TabViewControllerAfterTabSwitcher) { - [coordinator_ showTabSwitcher:coordinator_.tabSwitcher]; - EXPECT_EQ([coordinator_.tabSwitcher viewController], - coordinator_.activeViewController); + [coordinator_ showTabSwitcher:coordinator_]; + EXPECT_EQ([coordinator_ viewController], coordinator_.activeViewController); [coordinator_ showTabViewController:normal_tab_view_controller_ completion:nil]; EXPECT_EQ(normal_tab_view_controller_, coordinator_.activeViewController); // Showing the TabSwitcher again will make it active. - [coordinator_ showTabSwitcher:coordinator_.tabSwitcher]; + [coordinator_ showTabSwitcher:coordinator_]; bool tab_switcher_active = base::test::ios::WaitUntilConditionOrTimeout( base::test::ios::kWaitForUIElementTimeout, ^bool { - return [coordinator_.tabSwitcher viewController] == - coordinator_.activeViewController; + return + [coordinator_ viewController] == coordinator_.activeViewController; }); EXPECT_TRUE(tab_switcher_active); } @@ -158,13 +157,11 @@ // Tests calling showTabSwitcher twice in a row with the same VC. TEST_F(TabGridCoordinatorTest, ShowTabSwitcherTwice) { - [coordinator_ showTabSwitcher:coordinator_.tabSwitcher]; - EXPECT_EQ([coordinator_.tabSwitcher viewController], - coordinator_.activeViewController); + [coordinator_ showTabSwitcher:coordinator_]; + EXPECT_EQ([coordinator_ viewController], coordinator_.activeViewController); - [coordinator_ showTabSwitcher:coordinator_.tabSwitcher]; - EXPECT_EQ([coordinator_.tabSwitcher viewController], - coordinator_.activeViewController); + [coordinator_ showTabSwitcher:coordinator_]; + EXPECT_EQ([coordinator_ viewController], coordinator_.activeViewController); } // Tests calling showTabViewController twice in a row with the same VC. @@ -182,7 +179,7 @@ // handlers are called properly after the new view controller is made active. TEST_F(TabGridCoordinatorTest, CompletionHandlers) { // Setup: show the switcher. - [coordinator_ showTabSwitcher:coordinator_.tabSwitcher]; + [coordinator_ showTabSwitcher:coordinator_]; // Tests that the completion handler is called when showing a tab view // controller. Tests that the delegate 'didEnd' method is also called.
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index 6c8a7e9..cc6af504 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -182,33 +182,12 @@ } } -- (void)viewWillAppear:(BOOL)animated { - if (!base::FeatureList::IsEnabled(kContainedBVC)) { - [self contentWillAppearAnimated:animated]; - } - [super viewWillAppear:animated]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - if (!base::FeatureList::IsEnabled(kContainedBVC)) { - [self contentDidAppear]; - } -} - - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // Modify Incognito and Regular Tabs Insets [self setInsetForGridViews]; } -- (void)viewWillDisappear:(BOOL)animated { - if (!base::FeatureList::IsEnabled(kContainedBVC)) { - [self contentWillDisappearAnimated:animated]; - } - [super viewWillDisappear:animated]; -} - - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>)coordinator { @@ -376,11 +355,9 @@ } [self broadcastIncognitoContentVisibility]; - if (base::FeatureList::IsEnabled(kContainedBVC)) { - [self.incognitoTabsViewController contentWillAppearAnimated:animated]; - [self.regularTabsViewController contentWillAppearAnimated:animated]; - self.remoteTabsViewController.preventUpdates = NO; - } + [self.incognitoTabsViewController contentWillAppearAnimated:animated]; + [self.regularTabsViewController contentWillAppearAnimated:animated]; + self.remoteTabsViewController.preventUpdates = NO; } - (void)contentDidAppear { @@ -404,11 +381,9 @@ } self.viewVisible = NO; - if (base::FeatureList::IsEnabled(kContainedBVC)) { - [self.incognitoTabsViewController contentWillDisappear]; - [self.regularTabsViewController contentWillDisappear]; - self.remoteTabsViewController.preventUpdates = YES; - } + [self.incognitoTabsViewController contentWillDisappear]; + [self.regularTabsViewController contentWillDisappear]; + self.remoteTabsViewController.preventUpdates = YES; } #pragma mark - Public Properties
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn b/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn index f92e86b..719c02b 100644 --- a/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn
@@ -12,12 +12,6 @@ "grid_transition_animation_layout_providing.h", "grid_transition_layout.h", "grid_transition_layout.mm", - "legacy_grid_to_visible_tab_animator.h", - "legacy_grid_to_visible_tab_animator.mm", - "legacy_tab_to_grid_animator.h", - "legacy_tab_to_grid_animator.mm", - "reduced_motion_animator.h", - "reduced_motion_animator.mm", "tab_grid_transition_handler.h", "tab_grid_transition_handler.mm", ]
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.h b/ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.h deleted file mode 100644 index bcc2773..0000000 --- a/ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_LEGACY_GRID_TO_VISIBLE_TAB_ANIMATOR_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_LEGACY_GRID_TO_VISIBLE_TAB_ANIMATOR_H_ - -#import <UIKit/UIKit.h> - -@protocol GridTransitionAnimationLayoutProviding; - -// Animator object for transitioning from a collection view of square-ish items -// (the "grid") into a fullscreen view controller (the "tab"). -@interface LegacyGridToVisibleTabAnimator - : NSObject <UIViewControllerAnimatedTransitioning> - -// Initialize an animator object with |animationLayoutProvider| to provide -// layout information for the transition. -- (instancetype)initWithAnimationLayoutProvider: - (id<GridTransitionAnimationLayoutProviding>)animationLayoutProvider; - -@end - -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_LEGACY_GRID_TO_VISIBLE_TAB_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.mm deleted file mode 100644 index 9ca1ab1..0000000 --- a/ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.mm +++ /dev/null
@@ -1,171 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/tab_grid/transitions/legacy_grid_to_visible_tab_animator.h" - -#include "ios/chrome/browser/crash_report/crash_keys_helper.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation_layout_providing.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h" -#import "ios/chrome/browser/ui/util/layout_guide_names.h" -#import "ios/chrome/browser/ui/util/named_guide.h" -#import "ios/chrome/browser/ui/util/property_animator_group.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface LegacyGridToVisibleTabAnimator () -@property(nonatomic, weak) id<GridTransitionAnimationLayoutProviding> - animationLayoutProvider; -// Animation object for this transition. -@property(nonatomic, strong) GridTransitionAnimation* animation; -// Transition context passed into this object when the animation is started. -@property(nonatomic, weak) id<UIViewControllerContextTransitioning> - transitionContext; -@end - -@implementation LegacyGridToVisibleTabAnimator - -- (instancetype)initWithAnimationLayoutProvider: - (id<GridTransitionAnimationLayoutProviding>)animationLayoutProvider { - if ((self = [super init])) { - _animationLayoutProvider = animationLayoutProvider; - } - return self; -} - -- (NSTimeInterval)transitionDuration: - (id<UIViewControllerContextTransitioning>)transitionContext { - return 0.5; -} - -- (void)animateTransition: - (id<UIViewControllerContextTransitioning>)transitionContext { - // Keep a pointer to the transition context for use in animation delegate - // callbacks. - self.transitionContext = transitionContext; - - // Get views and view controllers for this transition. - UIView* containerView = [transitionContext containerView]; - UIViewController* presentedViewController = [transitionContext - viewControllerForKey:UITransitionContextToViewControllerKey]; - UIView* presentedView = - [transitionContext viewForKey:UITransitionContextToViewKey]; - - // Add the presented view to the container. This isn't just for the - // transition; this is how the presented view controller's view is added to - // the view hierarchy. - [containerView addSubview:presentedView]; - presentedView.frame = - [transitionContext finalFrameForViewController:presentedViewController]; - - // Get the layout of the grid for the transition. - GridTransitionLayout* layout = - [self.animationLayoutProvider transitionLayout]; - - // Ask the state provider for the views to use when inserting the animation. - UIView* animationContainer = - [self.animationLayoutProvider animationViewsContainer]; - - // Find the rect for the animating tab by getting the content area layout - // guide. - // Conceptually this transition is presenting a tab (a BVC). However, - // currently the BVC instances are themselves contanted within a BVCContainer - // view controller. This means that the |presentedView| is not the BVC's - // view; rather it's the view of the view controller that contains the BVC. - // Unfortunatley, the layout guide needed here is attached to the BVC's view, - // which is the first (and only) subview of the BVCContainerViewController's - // view. - // TODO(crbug.com/860234) Clean up this arrangement. - UIView* viewWithNamedGuides = presentedView.subviews[0]; - CGRect finalRect = [NamedGuide guideWithName:kContentAreaGuide - view:viewWithNamedGuides] - .layoutFrame; - - [layout.activeItem populateWithSnapshotsFromView:viewWithNamedGuides - middleRect:finalRect]; - - layout.expandedRect = - [animationContainer convertRect:viewWithNamedGuides.frame - fromView:presentedView]; - - NSTimeInterval duration = [self transitionDuration:transitionContext]; - // Create the animation view and insert it. - self.animation = [[GridTransitionAnimation alloc] - initWithLayout:layout - duration:duration - direction:GridAnimationDirectionExpanding]; - - UIView* bottomViewForAnimations = - [self.animationLayoutProvider animationViewsContainerBottomView]; - [animationContainer insertSubview:self.animation - aboveSubview:bottomViewForAnimations]; - - // Reparent the active cell view so that it can animate above the presenting - // view while the rest of the animation is embedded inside it. - UIView* presentingView = - [transitionContext viewForKey:UITransitionContextFromViewKey]; - [containerView insertSubview:self.animation.activeCell - aboveSubview:presentingView]; - - // Make the presented view alpha-zero; this should happen after all snapshots - // are taken. - presentedView.alpha = 0.0; - - [self.animation.animator addCompletion:^(UIViewAnimatingPosition position) { - BOOL finished = (position == UIViewAnimatingPositionEnd); - [self gridTransitionAnimationDidFinish:finished]; - }]; - - // Run the main animation. - [self.animation.animator startAnimation]; -} - -- (void)gridTransitionAnimationDidFinish:(BOOL)finished { - // Clean up the animation. First the active cell, then the animation itself. - // These views will not be re-used, so there's no need to reparent the - // active cell view. - [self.animation.activeCell removeFromSuperview]; - [self.animation removeFromSuperview]; - // If the transition was cancelled, remove the presented view. - // If not, remove the grid view. - UIView* gridView = - [self.transitionContext viewForKey:UITransitionContextFromViewKey]; - UIView* presentedView = - [self.transitionContext viewForKey:UITransitionContextToViewKey]; - if (self.transitionContext.transitionWasCancelled) { - [presentedView removeFromSuperview]; - } else { - // TODO(crbug.com/850507): Have the tab view animate itself in alongside - // this transition instead of just setting the alpha here. - presentedView.alpha = 1; - [gridView removeFromSuperview]; - } - - // TODO(crbug.com/959774): The logging below is to better understand a crash - // when |-completeTransition| is called. We expect the |toViewController| to - // be BVC. We are testing the assumption below that there should be no - // presentingViewController, presentedViewController, or parentViewController. - UIViewController* toViewController = [self.transitionContext - viewControllerForKey:UITransitionContextToViewControllerKey]; - NSString* toViewControllerName = NSStringFromClass([toViewController class]); - NSString* presentingViewControllerName = - NSStringFromClass([toViewController.presentingViewController class]); - NSString* presentedViewControllerName = - NSStringFromClass([toViewController.presentedViewController class]); - NSString* parentViewControllerName = - NSStringFromClass([toViewController.parentViewController class]); - crash_keys::SetGridToVisibleTabAnimation( - toViewControllerName, presentingViewControllerName, - presentedViewControllerName, parentViewControllerName); - - // Mark the transition as completed. - [self.transitionContext completeTransition:YES]; - - // Remove the crash log since the presentation completed without a crash. - crash_keys::RemoveGridToVisibleTabAnimation(); -} - -@end
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.h b/ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.h deleted file mode 100644 index 826dead2..0000000 --- a/ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_LEGACY_TAB_TO_GRID_ANIMATOR_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_LEGACY_TAB_TO_GRID_ANIMATOR_H_ - -#import <UIKit/UIKit.h> - -@protocol GridTransitionAnimationLayoutProviding; - -// Animator object for transitioning from a fullscreen view controller (the -// "tab") into a collection view of square-ish items (the "grid"). -@interface LegacyTabToGridAnimator - : NSObject <UIViewControllerAnimatedTransitioning> - -// Initialize an animator object with |animationLayoutProvider| to provide -// layout information for the transition. -- (instancetype)initWithAnimationLayoutProvider: - (id<GridTransitionAnimationLayoutProviding>)animationLayoutProvider; - -@end - -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_LEGACY_TAB_TO_GRID_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.mm deleted file mode 100644 index 145d686..0000000 --- a/ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.mm +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/tab_grid/transitions/legacy_tab_to_grid_animator.h" - -#include <ostream> - -#include "base/check_op.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation_layout_providing.h" -#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h" -#import "ios/chrome/browser/ui/util/layout_guide_names.h" -#import "ios/chrome/browser/ui/util/named_guide.h" -#import "ios/chrome/browser/ui/util/property_animator_group.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface LegacyTabToGridAnimator () -@property(nonatomic, weak) id<GridTransitionAnimationLayoutProviding> - animationLayoutProvider; -// Animation object for this transition. -@property(nonatomic, strong) GridTransitionAnimation* animation; -// Transition context passed into this object when the animation is started. -@property(nonatomic, weak) id<UIViewControllerContextTransitioning> - transitionContext; -@end - -@implementation LegacyTabToGridAnimator - -- (instancetype)initWithAnimationLayoutProvider: - (id<GridTransitionAnimationLayoutProviding>)animationLayoutProvider { - if ((self = [super init])) { - _animationLayoutProvider = animationLayoutProvider; - } - return self; -} - -- (NSTimeInterval)transitionDuration: - (id<UIViewControllerContextTransitioning>)transitionContext { - return 0.3; -} - -- (void)animateTransition: - (id<UIViewControllerContextTransitioning>)transitionContext { - // Keep a pointer to the transition context for use in animation delegate - // callbacks. - self.transitionContext = transitionContext; - - // Get views and view controllers for this transition. - UIView* containerView = [transitionContext containerView]; - UIViewController* gridViewController = [transitionContext - viewControllerForKey:UITransitionContextToViewControllerKey]; - UIView* gridView = - [transitionContext viewForKey:UITransitionContextToViewKey]; - UIView* dismissingView = - [transitionContext viewForKey:UITransitionContextFromViewKey]; - - // Find the rect for the animating tab by getting the content area layout - // guide. - // Add the grid view to the container. This isn't just for the transition; - // this is how the grid view controller's view is added to the view - // hierarchy. - [containerView insertSubview:gridView belowSubview:dismissingView]; - gridView.frame = - [transitionContext finalFrameForViewController:gridViewController]; - // Normally this view will layout before it's displayed, but in order to build - // the layout for the animation, |gridView|'s layout needs to be current, so - // force an update here. - [gridView layoutIfNeeded]; - - // Ask the state provider for the views to use when inserting the animation. - UIView* animationContainer = - [self.animationLayoutProvider animationViewsContainer]; - - // Get the layout of the grid for the transition. - GridTransitionLayout* layout = - [self.animationLayoutProvider transitionLayout]; - - // Get the initial rect for the snapshotted content of the active tab. - // Conceptually this transition is dismissing a tab (a BVC). However, - // currently the BVC instances are themselves contanted within a BVCContainer - // view controller. This means that the |dismissingView| is not the BVC's - // view; rather it's the view of the view controller that contains the BVC. - // Unfortunatley, the layout guide needed here is attached to the BVC's view, - // which is the first (and only) subview of the BVCContainerViewController's - // view in most cases. However, crbug.com/1053452 shows that we cannot just - // blindly use the first subview. The for-loop below ensures that a layout - // guide is obtained from the first subview that has it. - // TODO(crbug.com/860234) Clean up this arrangement. - UIView* viewWithNamedGuides = nil; - CGRect initialRect; - for (viewWithNamedGuides in dismissingView.subviews) { - NamedGuide* namedGuide = [NamedGuide guideWithName:kContentAreaGuide - view:viewWithNamedGuides]; - if (namedGuide) { - initialRect = namedGuide.layoutFrame; - break; - } - } - // Prefer to crash here at the root cause, rather than crashing later where - // the reason is more ambiguous. - CHECK_NE(nil, viewWithNamedGuides); - [layout.activeItem populateWithSnapshotsFromView:viewWithNamedGuides - middleRect:initialRect]; - - layout.expandedRect = - [animationContainer convertRect:viewWithNamedGuides.frame - fromView:dismissingView]; - - NSTimeInterval duration = [self transitionDuration:transitionContext]; - // Create the animation view and insert it. - self.animation = [[GridTransitionAnimation alloc] - initWithLayout:layout - duration:duration - direction:GridAnimationDirectionContracting]; - - UIView* bottomViewForAnimations = - [self.animationLayoutProvider animationViewsContainerBottomView]; - [animationContainer insertSubview:self.animation - aboveSubview:bottomViewForAnimations]; - - [self.animation.animator addCompletion:^(UIViewAnimatingPosition position) { - BOOL finished = (position == UIViewAnimatingPositionEnd); - [self gridTransitionAnimationDidFinish:finished]; - }]; - - // TODO(crbug.com/850507): Have the tab view animate itself out alongside this - // transition instead of just zeroing the alpha here. - dismissingView.alpha = 0; - - // Run the main animation. - [self.animation.animator startAnimation]; -} - -- (void)gridTransitionAnimationDidFinish:(BOOL)finished { - // Clean up the animation - [self.animation removeFromSuperview]; - // If the transition was cancelled, restore the dismissing view and - // remove the grid view. - // If not, remove the dismissing view. - UIView* gridView = - [self.transitionContext viewForKey:UITransitionContextToViewKey]; - UIView* dismissingView = - [self.transitionContext viewForKey:UITransitionContextFromViewKey]; - if (self.transitionContext.transitionWasCancelled) { - dismissingView.alpha = 1.0; - [gridView removeFromSuperview]; - } else { - [dismissingView removeFromSuperview]; - } - // Mark the transition as completed. - [self.transitionContext completeTransition:YES]; -} - -@end
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.h b/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.h deleted file mode 100644 index ab04454..0000000 --- a/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_REDUCED_MOTION_ANIMATOR_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_REDUCED_MOTION_ANIMATOR_H_ - -#import <UIKit/UIKit.h> - -// Animator object used when a simpler transition is needed. -@interface ReducedMotionAnimator - : NSObject<UIViewControllerAnimatedTransitioning> - -// YES if the animation presents a tab; NO if it dismisses it. -@property(nonatomic, assign) BOOL presenting; - -@end - -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_REDUCED_MOTION_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.mm deleted file mode 100644 index 77e6dfba..0000000 --- a/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.mm +++ /dev/null
@@ -1,108 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.h" - -#include "ios/chrome/browser/ui/util/ui_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation ReducedMotionAnimator - -@synthesize presenting = _presenting; - -- (NSTimeInterval)transitionDuration: - (id<UIViewControllerContextTransitioning>)transitionContext { - return 0.25; -} - -- (void)animateTransition: - (id<UIViewControllerContextTransitioning>)transitionContext { - // Get views and view controllers for this transition. - UIView* containerView = [transitionContext containerView]; - - UIViewController* appearingViewController = [transitionContext - viewControllerForKey:UITransitionContextToViewControllerKey]; - // The disappearing view, already in the view hierarchy. - UIView* disappearingView = - [transitionContext viewForKey:UITransitionContextFromViewKey]; - // The appearing view, not yet in the view hierarchy. - UIView* appearingView = - [transitionContext viewForKey:UITransitionContextToViewKey]; - - // Add the tab view to the container view with the correct size. - appearingView.frame = - [transitionContext finalFrameForViewController:appearingViewController]; - // If presenting, the appearing view does in front of the disappearing view. - // If dismissing, the disappearing view stays in front. - if (self.presenting) { - [containerView addSubview:appearingView]; - } else { - [containerView insertSubview:appearingView belowSubview:disappearingView]; - } - - // The animation here creates a simple quick zoom effect -- the tab view - // fades in/out as it expands/contracts. The zoom is not large (80% to 100%) - // and is centered on the view's final center position, so it's not directly - // connected to any tab grid positions. - UIView* animatingView; - CGFloat finalAnimatingViewAlpha; - CGAffineTransform finalAnimatingViewTransform; - CGFloat finalAnimatingCornerRadius; - - if (self.presenting) { - // If presenting, the appearing view (the tab view) animates in from 0% - // opacity, 75% scale transform, and a 13px corner radius - animatingView = appearingView; - finalAnimatingViewAlpha = animatingView.alpha; - animatingView.alpha = 0; - finalAnimatingViewTransform = animatingView.transform; - animatingView.transform = - CGAffineTransformScale(finalAnimatingViewTransform, 0.75, 0.75); - finalAnimatingCornerRadius = DeviceCornerRadius(); - animatingView.layer.cornerRadius = 26.0; - } else { - // If dismissing, the disappearing view (the tab view) animates out - // to 0% opacity, 75% scale, and 13px corner radius. - animatingView = disappearingView; - finalAnimatingViewAlpha = 0; - finalAnimatingViewTransform = - CGAffineTransformScale(animatingView.transform, 0.75, 0.75); - animatingView.layer.cornerRadius = DeviceCornerRadius(); - finalAnimatingCornerRadius = 26.0; - } - - // Set clipsToBounds on the animating view so its corner radius will look - // right. - BOOL oldClipsToBounds = animatingView.clipsToBounds; - animatingView.clipsToBounds = YES; - - // Animate the animating view to final properties, then clean up by removing - // the disappearing view. - [UIView animateWithDuration:[self transitionDuration:transitionContext] - delay:0.0 - options:UIViewAnimationOptionCurveEaseOut - animations:^{ - animatingView.alpha = finalAnimatingViewAlpha; - animatingView.transform = finalAnimatingViewTransform; - animatingView.layer.cornerRadius = finalAnimatingCornerRadius; - } - completion:^(BOOL finished) { - // Restore clipping state. - animatingView.clipsToBounds = oldClipsToBounds; - // If the transition was cancelled, remove the disappearing view. - // If not, remove the appearing view. - if (transitionContext.transitionWasCancelled) { - [appearingView removeFromSuperview]; - } else { - [disappearingView removeFromSuperview]; - } - // Mark the transition as completed. - [transitionContext completeTransition:YES]; - }]; -} - -@end
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc index 4163a2f1..e3f80c0e 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.cc +++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -28,9 +28,6 @@ const base::Feature kForceUnstackedTabstrip{"ForceUnstackedTabstrip", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kContainedBVC{"ContainedBVC", - base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kTestFeature{"TestFeature", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h index e7f7f25..68f801e 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.h +++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -29,10 +29,6 @@ // Feature flag to always force an unstacked tabstrip. extern const base::Feature kForceUnstackedTabstrip; -// Feature flag to have the Browser contained by the TabGrid instead of being -// presented. -extern const base::Feature kContainedBVC; - // Test-only: Feature flag used to verify that EG2 can trigger flags. Must be // always disabled by default, because it is used to verify that enabling // features in tests works.
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h index 905b5485..de3f185 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h +++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
@@ -154,30 +154,40 @@ // Returns YES if |identity| is valid and if the service has it in its list of // identitites. virtual bool IsValidIdentity(ChromeIdentity* identity) const; + virtual bool IsValidIdentityTemporary(ChromeIdentity* identity) const; // Returns the chrome identity having the email equal to |email| or |nil| if // no matching identity is found. virtual ChromeIdentity* GetIdentityWithEmail(const std::string& email) const; + virtual ChromeIdentity* GetIdentityWithEmailTemporary( + const std::string& email) const; // Returns the chrome identity having the gaia ID equal to |gaia_id| or |nil| // if no matching identity is found. virtual ChromeIdentity* GetIdentityWithGaiaID( const std::string& gaia_id) const; + virtual ChromeIdentity* GetIdentityWithGaiaIDTemporary( + const std::string& gaia_id) const; // Returns the canonicalized emails for all identities. virtual std::vector<std::string> GetCanonicalizeEmailsForAllIdentities() const; + virtual std::vector<std::string> + GetCanonicalizeEmailsForAllIdentitiesTemporary() const; // Returns true if there is at least one identity. virtual bool HasIdentities() const; + virtual bool HasIdentitiesTemporary() const; // Returns all ChromeIdentity objects in an array. virtual NSArray* GetAllIdentities() const; + virtual NSArray* GetAllIdentitiesTemporary() const; // Returns all ChromeIdentity objects sorted by the ordering used in the // account manager, which is typically based on the keychain ordering of // accounts. virtual NSArray* GetAllIdentitiesSortedForDisplay() const; + virtual NSArray* GetAllIdentitiesSortedForDisplayTemporary() const; // Forgets the given identity on the device. This method logs the user out. // It is asynchronous because it needs to contact the server to revoke the
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm index f0ffb74c..cdcb2b8 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm +++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
@@ -62,33 +62,66 @@ } bool ChromeIdentityService::IsValidIdentity(ChromeIdentity* identity) const { + return IsValidIdentityTemporary(identity); +} + +bool ChromeIdentityService::IsValidIdentityTemporary( + ChromeIdentity* identity) const { return false; } ChromeIdentity* ChromeIdentityService::GetIdentityWithEmail( const std::string& email) const { + return GetIdentityWithEmailTemporary(email); +} + +ChromeIdentity* ChromeIdentityService::GetIdentityWithEmailTemporary( + const std::string& email) const { return nil; } ChromeIdentity* ChromeIdentityService::GetIdentityWithGaiaID( const std::string& gaia_id) const { + return GetIdentityWithGaiaIDTemporary(gaia_id); +} + +ChromeIdentity* ChromeIdentityService::GetIdentityWithGaiaIDTemporary( + const std::string& gaia_id) const { return nil; } std::vector<std::string> ChromeIdentityService::GetCanonicalizeEmailsForAllIdentities() const { + return GetCanonicalizeEmailsForAllIdentitiesTemporary(); +} + +std::vector<std::string> +ChromeIdentityService::GetCanonicalizeEmailsForAllIdentitiesTemporary() const { return std::vector<std::string>(); } bool ChromeIdentityService::HasIdentities() const { + return HasIdentitiesTemporary(); +} + +bool ChromeIdentityService::HasIdentitiesTemporary() const { return false; } NSArray* ChromeIdentityService::GetAllIdentities() const { + return GetAllIdentitiesTemporary(); +} + +NSArray* ChromeIdentityService::GetAllIdentitiesTemporary() const { return nil; } NSArray* ChromeIdentityService::GetAllIdentitiesSortedForDisplay() const { + return GetAllIdentitiesSortedForDisplayTemporary(); +} + +NSArray* ChromeIdentityService::GetAllIdentitiesSortedForDisplayTemporary() + const { return nil; }
diff --git a/media/audio/audio_input_unittest.cc b/media/audio/audio_input_unittest.cc index 5a38c8d6..f603729 100644 --- a/media/audio/audio_input_unittest.cc +++ b/media/audio/audio_input_unittest.cc
@@ -75,12 +75,6 @@ audio_manager_(AudioManager::CreateForTesting( std::make_unique<TestAudioThread>())), audio_input_stream_(nullptr) { -#if defined(OS_LINUX) - // Due to problems with PulseAudio failing to start, use a fake audio - // stream. https://crbug.com/1047655#c70 - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kDisableAudioOutput); -#endif base::RunLoop().RunUntilIdle(); }
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc index 533de6c..0624621 100644 --- a/media/audio/audio_manager_unittest.cc +++ b/media/audio/audio_manager_unittest.cc
@@ -335,12 +335,6 @@ protected: AudioManagerTest() { -#if defined(OS_LINUX) - // Due to problems with PulseAudio failing to start, use a fake audio - // stream. https://crbug.com/1047655#c70 - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kDisableAudioOutput); -#endif CreateAudioManagerForTesting(); } ~AudioManagerTest() override { audio_manager_->Shutdown(); }
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java index c67f6165..480c0ff 100644 --- a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java +++ b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java
@@ -553,7 +553,7 @@ case HWEncoder.MediatekH264: return BitrateAdjuster.Type.FRAMERATE_ADJUSTMENT; } - return -1; + throw new IllegalArgumentException("Invalid HWEncoder decoder parameter."); } /**
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn index 7df70b3..28aa4b7 100644 --- a/media/cast/BUILD.gn +++ b/media/cast/BUILD.gn
@@ -408,6 +408,7 @@ "//build/win:default_exe_manifest", "//media:test_support", "//net", + "//ui/base:features", "//ui/gfx/geometry", ]
diff --git a/media/cast/DEPS b/media/cast/DEPS index d1cb7e6..19af2a19 100644 --- a/media/cast/DEPS +++ b/media/cast/DEPS
@@ -4,5 +4,6 @@ "+net", "+third_party/libyuv", "+third_party/zlib", + "+ui/base", "+ui/gfx", ]
diff --git a/media/cast/test/receiver.cc b/media/cast/test/receiver.cc index d357fb0..7254c096 100644 --- a/media/cast/test/receiver.cc +++ b/media/cast/test/receiver.cc
@@ -49,6 +49,7 @@ #include "media/cast/test/utility/input_builder.h" #include "media/cast/test/utility/standalone_cast_environment.h" #include "net/base/ip_address.h" +#include "ui/base/ui_base_features.h" #if defined(USE_X11) #include "media/cast/test/linux_output_window.h" @@ -424,7 +425,8 @@ if (!video_playout_queue_.empty()) { const scoped_refptr<VideoFrame> video_frame = PopOneVideoFrame(false); #if defined(USE_X11) - render_.RenderFrame(*video_frame); + if (!features::IsUsingOzonePlatform()) + render_.RenderFrame(*video_frame); #endif // defined(USE_X11) } ScheduleVideoPlayout(); @@ -595,7 +597,8 @@ int window_width = 0; int window_height = 0; #if defined(USE_X11) - media::cast::GetWindowSize(&window_width, &window_height); + if (!features::IsUsingOzonePlatform()) + media::cast::GetWindowSize(&window_width, &window_height); #endif // defined(USE_X11) media::cast::NaivePlayer player(cast_environment, local_end_point,
diff --git a/media/gpu/test/video_test_environment.cc b/media/gpu/test/video_test_environment.cc index 18733d7..1feb8cd5 100644 --- a/media/gpu/test/video_test_environment.cc +++ b/media/gpu/test/video_test_environment.cc
@@ -17,6 +17,7 @@ #endif #if defined(USE_OZONE) +#include "ui/base/ui_base_features.h" #include "ui/ozone/public/ozone_platform.h" #endif @@ -58,12 +59,14 @@ #if defined(USE_OZONE) // Initialize Ozone. This is necessary to gain access to the GPU for hardware // video decode acceleration. - LOG(WARNING) << "Initializing Ozone Platform...\n" - "If this hangs indefinitely please call 'stop ui' first!"; - ui::OzonePlatform::InitParams params; - params.single_process = true; - ui::OzonePlatform::InitializeForUI(params); - ui::OzonePlatform::InitializeForGPU(params); + if (features::IsUsingOzonePlatform()) { + LOG(WARNING) << "Initializing Ozone Platform...\n" + "If this hangs indefinitely please call 'stop ui' first!"; + ui::OzonePlatform::InitParams params; + params.single_process = true; + ui::OzonePlatform::InitializeForUI(params); + ui::OzonePlatform::InitializeForGPU(params); + } #endif }
diff --git a/media/gpu/vaapi/BUILD.gn b/media/gpu/vaapi/BUILD.gn index 1f3a775..5ec2c41 100644 --- a/media/gpu/vaapi/BUILD.gn +++ b/media/gpu/vaapi/BUILD.gn
@@ -166,6 +166,7 @@ deps = [ ":libva_stubs", "//third_party/libyuv", + "//ui/base:features", "//ui/gfx:memory_buffer", "//ui/gl", ]
diff --git a/media/gpu/vaapi/vaapi_picture_factory.cc b/media/gpu/vaapi/vaapi_picture_factory.cc index ea01697..46d4ceee 100644 --- a/media/gpu/vaapi/vaapi_picture_factory.cc +++ b/media/gpu/vaapi/vaapi_picture_factory.cc
@@ -6,6 +6,7 @@ #include "media/gpu/vaapi/vaapi_wrapper.h" #include "media/video/picture.h" +#include "ui/base/ui_base_features.h" #include "ui/gl/gl_bindings.h" #if defined(USE_X11) @@ -20,23 +21,18 @@ namespace media { -namespace { - -const struct { - gl::GLImplementation gl_impl; - VaapiPictureFactory::VaapiImplementation va_impl; -} kVaapiImplementationPairs[] = {{gl::kGLImplementationEGLGLES2, - VaapiPictureFactory::kVaapiImplementationDrm} +VaapiPictureFactory::VaapiPictureFactory() { + vaapi_impl_pairs_.insert( + std::make_pair(gl::kGLImplementationEGLGLES2, + VaapiPictureFactory::kVaapiImplementationDrm)); #if defined(USE_X11) - , - {gl::kGLImplementationDesktopGL, - VaapiPictureFactory::kVaapiImplementationX11} -#endif // USE_X11 -}; - -} // namespace - -VaapiPictureFactory::VaapiPictureFactory() = default; + if (!features::IsUsingOzonePlatform()) { + vaapi_impl_pairs_.insert( + std::make_pair(gl::kGLImplementationDesktopGL, + VaapiPictureFactory::kVaapiImplementationX11)); + } +#endif +} VaapiPictureFactory::~VaapiPictureFactory() = default; @@ -60,56 +56,23 @@ ? picture_buffer.service_texture_ids()[0] : 0; - std::unique_ptr<VaapiPicture> picture; - // Select DRM(egl) / TFP(glx) at runtime with --use-gl=egl / --use-gl=desktop - switch (GetVaapiImplementation(gl::GetGLImplementation())) { + #if defined(USE_OZONE) - // We can be called without GL initialized, which is valid if we use Ozone. - case kVaapiImplementationNone: - FALLTHROUGH; - case kVaapiImplementationDrm: - picture.reset(new VaapiPictureNativePixmapOzone( - std::move(vaapi_wrapper), make_context_current_cb, bind_image_cb, - picture_buffer.id(), picture_buffer.size(), visible_size, - service_texture_id, client_texture_id, - picture_buffer.texture_target())); - break; -#elif defined(USE_EGL) - case kVaapiImplementationDrm: - picture.reset(new VaapiPictureNativePixmapEgl( - std::move(vaapi_wrapper), make_context_current_cb, bind_image_cb, - picture_buffer.id(), picture_buffer.size(), visible_size, - service_texture_id, client_texture_id, - picture_buffer.texture_target())); - break; + if (features::IsUsingOzonePlatform()) + return CreateVaapiPictureNativeForOzone( + vaapi_wrapper, make_context_current_cb, bind_image_cb, picture_buffer, + visible_size, client_texture_id, service_texture_id); #endif - -#if defined(USE_X11) - case kVaapiImplementationX11: - picture.reset(new VaapiTFPPicture( - std::move(vaapi_wrapper), make_context_current_cb, bind_image_cb, - picture_buffer.id(), picture_buffer.size(), visible_size, - service_texture_id, client_texture_id, - picture_buffer.texture_target())); - break; -#endif // USE_X11 - - default: - NOTREACHED(); - return nullptr; - } - - return picture; + return CreateVaapiPictureNative(vaapi_wrapper, make_context_current_cb, + bind_image_cb, picture_buffer, visible_size, + client_texture_id, service_texture_id); } VaapiPictureFactory::VaapiImplementation VaapiPictureFactory::GetVaapiImplementation(gl::GLImplementation gl_impl) { - for (const auto& implementation_pair : kVaapiImplementationPairs) { - if (gl_impl == implementation_pair.gl_impl) - return implementation_pair.va_impl; - } - + if (base::Contains(vaapi_impl_pairs_, gl_impl)) + return vaapi_impl_pairs_[gl_impl]; return kVaapiImplementationNone; } @@ -129,4 +92,73 @@ #endif } +#if defined(USE_OZONE) +std::unique_ptr<VaapiPicture> +VaapiPictureFactory::CreateVaapiPictureNativeForOzone( + scoped_refptr<VaapiWrapper> vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb, + const PictureBuffer& picture_buffer, + const gfx::Size& visible_size, + uint32_t client_texture_id, + uint32_t service_texture_id) { + DCHECK(features::IsUsingOzonePlatform()); + switch (GetVaapiImplementation(gl::GetGLImplementation())) { + // We can be called without GL initialized, which is valid if we use Ozone. + case kVaapiImplementationNone: + FALLTHROUGH; + case kVaapiImplementationDrm: + return std::make_unique<VaapiPictureNativePixmapOzone>( + std::move(vaapi_wrapper), make_context_current_cb, bind_image_cb, + picture_buffer.id(), picture_buffer.size(), visible_size, + service_texture_id, client_texture_id, + picture_buffer.texture_target()); + break; + + default: + NOTREACHED(); + return nullptr; + } + + return nullptr; +} +#endif // USE_OZONE + +std::unique_ptr<VaapiPicture> VaapiPictureFactory::CreateVaapiPictureNative( + scoped_refptr<VaapiWrapper> vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb, + const PictureBuffer& picture_buffer, + const gfx::Size& visible_size, + uint32_t client_texture_id, + uint32_t service_texture_id) { + switch (GetVaapiImplementation(gl::GetGLImplementation())) { +#if defined(USE_EGL) + case kVaapiImplementationDrm: + return std::make_unique<VaapiPictureNativePixmapEgl>( + std::move(vaapi_wrapper), make_context_current_cb, bind_image_cb, + picture_buffer.id(), picture_buffer.size(), visible_size, + service_texture_id, client_texture_id, + picture_buffer.texture_target()); +#endif // USE_EGL + +#if defined(USE_X11) + case kVaapiImplementationX11: + DCHECK(!features::IsUsingOzonePlatform()); + return std::make_unique<VaapiTFPPicture>( + std::move(vaapi_wrapper), make_context_current_cb, bind_image_cb, + picture_buffer.id(), picture_buffer.size(), visible_size, + service_texture_id, client_texture_id, + picture_buffer.texture_target()); + break; +#endif // USE_X11 + + default: + NOTREACHED(); + return nullptr; + } + + return nullptr; +} + } // namespace media
diff --git a/media/gpu/vaapi/vaapi_picture_factory.h b/media/gpu/vaapi/vaapi_picture_factory.h index 09edc66..08372fc 100644 --- a/media/gpu/vaapi/vaapi_picture_factory.h +++ b/media/gpu/vaapi/vaapi_picture_factory.h
@@ -51,6 +51,29 @@ // the format decoded frames in VASurfaces are converted into. gfx::BufferFormat GetBufferFormat(); +#if defined(USE_OZONE) + std::unique_ptr<VaapiPicture> CreateVaapiPictureNativeForOzone( + scoped_refptr<VaapiWrapper> vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb, + const PictureBuffer& picture_buffer, + const gfx::Size& visible_size, + uint32_t client_texture_id, + uint32_t service_texture_id); +#endif + + std::unique_ptr<VaapiPicture> CreateVaapiPictureNative( + scoped_refptr<VaapiWrapper> vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb, + const PictureBuffer& picture_buffer, + const gfx::Size& visible_size, + uint32_t client_texture_id, + uint32_t service_texture_id); + + std::map<gl::GLImplementation, VaapiPictureFactory::VaapiImplementation> + vaapi_impl_pairs_; + private: DISALLOW_COPY_AND_ASSIGN(VaapiPictureFactory); };
diff --git a/media/gpu/vaapi/vaapi_picture_tfp.cc b/media/gpu/vaapi/vaapi_picture_tfp.cc index b42620d..37b821c 100644 --- a/media/gpu/vaapi/vaapi_picture_tfp.cc +++ b/media/gpu/vaapi/vaapi_picture_tfp.cc
@@ -6,6 +6,7 @@ #include "media/gpu/vaapi/va_surface.h" #include "media/gpu/vaapi/vaapi_wrapper.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/x/x11_types.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_image_glx.h" @@ -35,6 +36,7 @@ x_display_(gfx::GetXDisplay()), x_pixmap_(0) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!features::IsUsingOzonePlatform()); DCHECK(texture_id); DCHECK(client_texture_id); }
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc index 12daaefd..1eb262e 100644 --- a/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc +++ b/media/gpu/vaapi/vaapi_video_decode_accelerator_unittest.cc
@@ -15,6 +15,7 @@ #include "media/gpu/vaapi/vaapi_wrapper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/ui_base_features.h" using base::test::RunClosure; using ::testing::_; @@ -405,9 +406,11 @@ gl::kGLImplementationEGLGLES2)); #if defined(USE_X11) - EXPECT_EQ(VaapiPictureFactory::kVaapiImplementationX11, - mock_vaapi_picture_factory_->GetVaapiImplementation( - gl::kGLImplementationDesktopGL)); + if (!features::IsUsingOzonePlatform()) { + EXPECT_EQ(VaapiPictureFactory::kVaapiImplementationX11, + mock_vaapi_picture_factory_->GetVaapiImplementation( + gl::kGLImplementationDesktopGL)); + } #endif }
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc index 040296d..34257d7f 100644 --- a/media/gpu/vaapi/vaapi_wrapper.cc +++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -37,6 +37,7 @@ #include "base/system/sys_info.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "ui/base/ui_base_features.h" #include "media/base/media_switches.h" #include "media/base/video_frame.h" @@ -380,13 +381,13 @@ bool VADisplayState::Initialize() { base::AutoLock auto_lock(va_lock_); - if (!IsVaInitialized() || + bool libraries_initialized = IsVaInitialized() && IsVa_drmInitialized(); #if defined(USE_X11) - !IsVa_x11Initialized() || + if (!features::IsUsingOzonePlatform()) + libraries_initialized = libraries_initialized && IsVa_x11Initialized(); #endif - !IsVa_drmInitialized()) { + if (!libraries_initialized) return false; - } // Manual refcounting to ensure the rest of the method is called only once. if (refcount_++ > 0) @@ -409,7 +410,8 @@ break; case gl::kGLImplementationDesktopGL: #if defined(USE_X11) - va_display_ = vaGetDisplay(gfx::GetXDisplay()); + if (!features::IsUsingOzonePlatform()) + va_display_ = vaGetDisplay(gfx::GetXDisplay()); #else LOG(WARNING) << "VAAPI video acceleration not available without " "DesktopGL (GLX)."; @@ -418,9 +420,11 @@ // Cannot infer platform from GL, try all available displays case gl::kGLImplementationNone: #if defined(USE_X11) - va_display_ = vaGetDisplay(gfx::GetXDisplay()); - if (vaDisplayIsValid(va_display_)) - break; + if (!features::IsUsingOzonePlatform()) { + va_display_ = vaGetDisplay(gfx::GetXDisplay()); + if (vaDisplayIsValid(va_display_)) + break; + } #endif // USE_X11 va_display_ = vaGetDisplayDRM(drm_fd_.get()); break; @@ -1770,6 +1774,7 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, Pixmap x_pixmap, gfx::Size dest_size) { + DCHECK(!features::IsUsingOzonePlatform()); base::AutoLock auto_lock(*va_lock_); VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); @@ -2143,7 +2148,8 @@ paths[kModuleVa].push_back(std::string("libva.so.") + va_suffix); paths[kModuleVa_drm].push_back(std::string("libva-drm.so.") + va_suffix); #if defined(USE_X11) - paths[kModuleVa_x11].push_back(std::string("libva-x11.so.") + va_suffix); + if (!features::IsUsingOzonePlatform()) + paths[kModuleVa_x11].push_back(std::string("libva-x11.so.") + va_suffix); #endif // InitializeStubs dlopen() VA-API libraries
diff --git a/net/cookies/README.md b/net/cookies/README.md index 3f6384d..c4baf8e 100644 --- a/net/cookies/README.md +++ b/net/cookies/README.md
@@ -386,14 +386,14 @@ The `CookieAccessObserver`s forward the notifications to `WebContents`, which then notifies its `WebContentsObserver`s. One such `WebContentsObserver` that cares about this information is - `TabSpecificContentSettings`, which displays information about allowed and + `PageSpecificContentSettings`, which displays information about allowed and blocked cookies in UI surfaces (see next item). * [`CookiesTreeModel`](/chrome/browser/browsing_data/cookies_tree_model.h) Stores cookie information for use in settings UI (the Page Info Bubble and various `chrome://settings` pages). Populated with info from - `TabSpecificContentSettings`. + `PageSpecificContentSettings`. * [`CookieJar`](/third_party/blink/renderer/core/loader/cookie_jar.h)
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc index ab194e2b..222158c 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_android.cc
@@ -112,6 +112,10 @@ case __NR_openat: case __NR_pwrite64: case __NR_rt_sigtimedwait: + // sched_setaffinity() is required for an experiment to schedule all + // Chromium threads onto LITTLE cores (crbug.com/1111789). Should be removed + // or reconsidered once the experiment is complete. + case __NR_sched_setaffinity: case __NR_sched_getparam: case __NR_sched_getscheduler: case __NR_sched_setscheduler:
diff --git a/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java b/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java index c3651e74..ebdfcc7 100644 --- a/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java +++ b/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
@@ -6,8 +6,6 @@ import android.location.Location; -import androidx.annotation.VisibleForTesting; - import org.chromium.base.Log; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; @@ -23,7 +21,6 @@ * content/browser/geolocation/location_api_adapter_android.h. * Based on android.webkit.GeolocationService.java */ -@VisibleForTesting public class LocationProviderAdapter { private static final String TAG = "LocationProvider";
diff --git a/services/network/public/cpp/content_security_policy/content_security_policy.cc b/services/network/public/cpp/content_security_policy/content_security_policy.cc index a879e5d..914a787 100644 --- a/services/network/public/cpp/content_security_policy/content_security_policy.cc +++ b/services/network/public/cpp/content_security_policy/content_security_policy.cc
@@ -949,6 +949,9 @@ const mojom::ContentSecurityPolicy* context, std::string& error_message) { DCHECK(policy.size() == 1); + if (!policy[0]) + return false; + if (!policy[0]->parsing_errors.empty()) { error_message = "Parsing the csp attribute into a Content-Security-Policy returned one "
diff --git a/services/network/public/cpp/content_security_policy/csp_source.cc b/services/network/public/cpp/content_security_policy/csp_source.cc index 1bb0c8d..983b8a5 100644 --- a/services/network/public/cpp/content_security_policy/csp_source.cc +++ b/services/network/public/cpp/content_security_policy/csp_source.cc
@@ -48,6 +48,17 @@ }; enum class SchemeMatchingResult { NotMatching, MatchingUpgrade, MatchingExact }; +SchemeMatchingResult MatchScheme(const std::string& scheme_a, + const std::string& scheme_b) { + if (scheme_a == scheme_b) + return SchemeMatchingResult::MatchingExact; + if ((scheme_a == url::kHttpScheme && scheme_b == url::kHttpsScheme) || + (scheme_a == url::kWsScheme && scheme_b == url::kWssScheme)) { + return SchemeMatchingResult::MatchingUpgrade; + } + return SchemeMatchingResult::NotMatching; +} + SchemeMatchingResult SourceAllowScheme(const mojom::CSPSourcePtr& source, const GURL& url, CSPContext* context) { @@ -60,19 +71,11 @@ const std::string& allowed_scheme = source->scheme.empty() ? context->self_source()->scheme : source->scheme; - if (url.SchemeIs(allowed_scheme)) - return SchemeMatchingResult::MatchingExact; - - // Implicitly allow using a more secure version of a protocol when the - // non-secure one is allowed. - if ((allowed_scheme == url::kHttpScheme && url.SchemeIs(url::kHttpsScheme)) || - (allowed_scheme == url::kWsScheme && url.SchemeIs(url::kWssScheme))) { - return SchemeMatchingResult::MatchingUpgrade; - } - return SchemeMatchingResult::NotMatching; + return MatchScheme(allowed_scheme, url.scheme()); } -bool SourceAllowHost(const mojom::CSPSourcePtr& source, const GURL& url) { +bool SourceAllowHost(const mojom::CSPSourcePtr& source, + const std::string& host) { if (source->is_host_wildcard) { if (source->host.empty()) return true; @@ -80,66 +83,86 @@ // The renderer version of this function counts how many times it happens. // It might be useful to do it outside of blink too. // See third_party/blink/renderer/core/frame/csp/csp_source.cc - return base::EndsWith(url.host(), '.' + source->host, + return base::EndsWith(host, '.' + source->host, base::CompareCase::INSENSITIVE_ASCII); } else { - return base::EqualsCaseInsensitiveASCII(url.host(), source->host); + return base::EqualsCaseInsensitiveASCII(host, source->host); } } -PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source, - const GURL& url) { - int url_port = url.EffectiveIntPort(); +bool SourceAllowHost(const mojom::CSPSourcePtr& source, const GURL& url) { + return SourceAllowHost(source, url.host()); +} +PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source, + int port, + const std::string& scheme) { if (source->is_port_wildcard) return PortMatchingResult::MatchingWildcard; - if (source->port == url_port) { + if (source->port == port) { if (source->port == url::PORT_UNSPECIFIED) return PortMatchingResult::MatchingWildcard; return PortMatchingResult::MatchingExact; } if (source->port == url::PORT_UNSPECIFIED) { - if (DefaultPortForScheme(url.scheme()) == url_port) { + if (DefaultPortForScheme(scheme) == port) return PortMatchingResult::MatchingWildcard; - } - return PortMatchingResult::NotMatching; + } + + if (port == url::PORT_UNSPECIFIED) { + if (source->port == DefaultPortForScheme(scheme)) + return PortMatchingResult::MatchingWildcard; } int source_port = source->port; if (source_port == url::PORT_UNSPECIFIED) source_port = DefaultPortForScheme(source->scheme); - if (source_port == 80 && url_port == 443) + if (port == url::PORT_UNSPECIFIED) + port = DefaultPortForScheme(scheme); + + if (source_port == 80 && port == 443) return PortMatchingResult::MatchingUpgrade; return PortMatchingResult::NotMatching; } +PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source, + const GURL& url) { + return SourceAllowPort(source, url.EffectiveIntPort(), url.scheme()); +} + +bool SourceAllowPath(const mojom::CSPSourcePtr& source, + const std::string& path) { + std::string path_decoded; + if (!DecodePath(path, &path_decoded)) { + // TODO(arthursonzogni): try to figure out if that could happen and how to + // handle it. + return false; + } + + if (source->path.empty() || (source->path == "/" && path_decoded.empty())) + return true; + + // If the path represents a directory. + if (base::EndsWith(source->path, "/", base::CompareCase::SENSITIVE)) { + return base::StartsWith(path_decoded, source->path, + base::CompareCase::SENSITIVE); + } + + // The path represents a file. + return source->path == path_decoded; +} + bool SourceAllowPath(const mojom::CSPSourcePtr& source, const GURL& url, bool has_followed_redirect) { if (has_followed_redirect) return true; - if (source->path.empty()) - return true; - - std::string url_path; - if (!DecodePath(url.path(), &url_path)) { - // TODO(arthursonzogni): try to figure out if that could happen and how to - // handle it. - return false; - } - - // If the path represents a directory. - if (base::EndsWith(source->path, "/", base::CompareCase::SENSITIVE)) - return base::StartsWith(url_path, source->path, - base::CompareCase::SENSITIVE); - - // The path represents a file. - return source->path == url_path; + return SourceAllowPath(source, url.path()); } bool requiresUpgrade(const PortMatchingResult result) { @@ -181,6 +204,42 @@ SourceAllowPath(source, url, has_followed_redirect); } +// Check whether |source_a| subsumes |source_b|. +bool CSPSourceSubsumes(const mojom::CSPSourcePtr& source_a, + const mojom::CSPSourcePtr& source_b) { + // If the original source expressions didn't have a scheme, we should have + // filled that already with origin's scheme. + DCHECK(!source_a->scheme.empty()); + DCHECK(!source_b->scheme.empty()); + + if (MatchScheme(source_a->scheme, source_b->scheme) == + SchemeMatchingResult::NotMatching) { + return false; + } + + if (IsSchemeOnly(source_a)) + return true; + if (IsSchemeOnly(source_b)) + return false; + + if (!SourceAllowHost(source_a, (source_b->is_host_wildcard ? "*." : "") + + source_b->host)) { + return false; + } + + if (source_b->is_port_wildcard && !source_a->is_port_wildcard) + return false; + PortMatchingResult port_matching = + SourceAllowPort(source_a, source_b->port, source_b->scheme); + if (port_matching == PortMatchingResult::NotMatching) + return false; + + if (!SourceAllowPath(source_a, source_b->path)) + return false; + + return true; +} + std::string ToString(const mojom::CSPSourcePtr& source) { // scheme if (IsSchemeOnly(source))
diff --git a/services/network/public/cpp/content_security_policy/csp_source.h b/services/network/public/cpp/content_security_policy/csp_source.h index 902aed3e..d0e6c05f 100644 --- a/services/network/public/cpp/content_security_policy/csp_source.h +++ b/services/network/public/cpp/content_security_policy/csp_source.h
@@ -22,6 +22,12 @@ CSPContext* context, bool has_followed_redirect = false); +// Check if |source_a| subsumes |source_b| according to +// https://w3c.github.io/webappsec-cspee/#subsume-source-expressions +COMPONENT_EXPORT(NETWORK_CPP) +bool CSPSourceSubsumes(const mojom::CSPSourcePtr& source_a, + const mojom::CSPSourcePtr& source_b); + // Serialize the CSPSource |source| as a string. This is used for reporting // violations. COMPONENT_EXPORT(NETWORK_CPP)
diff --git a/services/network/public/cpp/content_security_policy/csp_source_unittest.cc b/services/network/public/cpp/content_security_policy/csp_source_unittest.cc index 8d34dac..0ff85ab 100644 --- a/services/network/public/cpp/content_security_policy/csp_source_unittest.cc +++ b/services/network/public/cpp/content_security_policy/csp_source_unittest.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "services/network/public/cpp/content_security_policy/csp_source.h" +#include "net/http/http_response_headers.h" +#include "services/network/public/cpp/content_security_policy/content_security_policy.h" #include "services/network/public/cpp/content_security_policy/csp_context.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/origin.h" @@ -20,6 +22,17 @@ return CheckCSPSource(source, url, context, is_redirect); } +network::mojom::CSPSourcePtr CSPSource(const std::string& raw) { + scoped_refptr<net::HttpResponseHeaders> headers( + new net::HttpResponseHeaders("HTTP/1.1 200 OK")); + headers->SetHeader("Content-Security-Policy", "script-src " + raw); + std::vector<mojom::ContentSecurityPolicyPtr> policies; + AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"), + &policies); + return std::move( + policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]->sources[0]); +} + } // namespace TEST(CSPSourceTest, BasicMatching) { @@ -310,6 +323,184 @@ EXPECT_FALSE(Allow(source, GURL("http://a.com:9000/foo/"), &context, false)); } +TEST(CSPSourceTest, DoesNotSubsume) { + struct TestCase { + const char* a; + const char* b; + } cases[] = { + // In the following test cases, neither |a| subsumes |b| nor |b| subsumes + // |a|. + // Different hosts. + {"http://example.com", "http://another.com"}, + // Different schemes (wss -> http). + {"wss://example.com", "http://example.com"}, + // Different schemes (wss -> about). + {"wss://example.com/", "about://example.com/"}, + // Different schemes (wss -> about). + {"http://example.com/", "about://example.com/"}, + // Different paths. + {"http://example.com/1.html", "http://example.com/2.html"}, + // Different ports. + {"http://example.com:443/", "http://example.com:800/"}, + }; + for (const auto& test : cases) { + auto a = CSPSource(test.a); + auto b = CSPSource(test.b); + + EXPECT_FALSE(CSPSourceSubsumes(a, b)) + << test.a << " should not subsume " << test.b; + EXPECT_FALSE(CSPSourceSubsumes(b, a)) + << test.b << " should not subsume " << test.a; + } +} + +TEST(CSPSourceTest, Subsumes) { + struct TestCase { + const char* a; + const char* b; + bool expected_a_subsumes_b; + bool expected_b_subsumes_a; + } cases[] = { + // Equal signals. + {"http://a.org/", "http://a.org/", true, true}, + {"https://a.org/", "https://a.org/", true, true}, + {"https://a.org/page.html", "https://a.org/page.html", true, true}, + {"http://a.org:70", "http://a.org:70", true, true}, + {"https://a.org:70", "https://a.org:70", true, true}, + {"https://a.org/page.html", "https://a.org/page.html", true, true}, + {"http://a.org:70/page.html", "http://a.org:70/page.html", true, true}, + {"https://a.org:70/page.html", "https://a.org:70/page.html", true, true}, + {"http://a.org/", "http://a.org", true, true}, + {"http://a.org:80", "http://a.org:80", true, true}, + {"http://a.org:80", "https://a.org:443", true, false}, + {"http://a.org", "https://a.org:443", true, false}, + {"http://a.org:80", "https://a.org", true, false}, + // One stronger signal in the first CSPSource. + {"http://a.org/", "https://a.org/", true, false}, + {"http://a.org/page.html", "http://a.org/", false, true}, + {"http://a.org:80/page.html", "http://a.org:80/", false, true}, + {"http://a.org:80", "http://a.org/", true, true}, + {"http://a.org:700", "http://a.org/", false, false}, + // Two stronger signals in the first CSPSource. + {"https://a.org/page.html", "http://a.org/", false, true}, + {"https://a.org:80", "http://a.org/", false, false}, + {"http://a.org:80/page.html", "http://a.org/", false, true}, + // Three stronger signals in the first CSPSource. + {"https://a.org:70/page.html", "http://a.org/", false, false}, + // Mixed signals. + {"https://a.org/", "http://a.org/page.html", false, false}, + {"https://a.org", "http://a.org:70/", false, false}, + {"http://a.org/page.html", "http://a.org:70/", false, false}, + }; + + for (const auto& test : cases) { + auto a = CSPSource(test.a); + auto b = CSPSource(test.b); + + EXPECT_EQ(CSPSourceSubsumes(a, b), test.expected_a_subsumes_b) + << test.a << " subsumes " << test.b << " should return " + << test.expected_a_subsumes_b; + EXPECT_EQ(CSPSourceSubsumes(b, a), test.expected_b_subsumes_a) + << test.b << " subsumes " << test.a << " should return " + << test.expected_b_subsumes_a; + + a->is_host_wildcard = true; + EXPECT_FALSE(CSPSourceSubsumes(b, a)) + << test.b << " should not subsume " << ToString(a); + + // If also |b| has a wildcard host, then the result should be the expected + // one. + b->is_host_wildcard = true; + EXPECT_EQ(CSPSourceSubsumes(b, a), test.expected_b_subsumes_a) + << ToString(b) << " subsumes " << ToString(a) << " should return " + << test.expected_b_subsumes_a; + } +} + +TEST(CSPSourceTest, HostWildcardSubsumes) { + const char* a = "http://*.example.org"; + const char* b = "http://www.example.org"; + const char* c = "http://example.org"; + const char* d = "https://*.example.org"; + + auto source_a = CSPSource(a); + auto source_b = CSPSource(b); + auto source_c = CSPSource(c); + auto source_d = CSPSource(d); + + // *.example.com subsumes www.example.com. + EXPECT_TRUE(CSPSourceSubsumes(source_a, source_b)) + << a << " should subsume " << b; + EXPECT_FALSE(CSPSourceSubsumes(source_b, source_a)) + << b << " should not subsume " << a; + + // *.example.com and example.com have no relations. + EXPECT_FALSE(CSPSourceSubsumes(source_a, source_c)) + << a << " should not subsume " << c; + EXPECT_FALSE(CSPSourceSubsumes(source_c, source_a)) + << c << " should not subsume " << a; + + // https://*.example.com and http://www.example.com have no relations. + EXPECT_FALSE(CSPSourceSubsumes(source_d, source_b)) + << d << " should not subsume " << b; + EXPECT_FALSE(CSPSourceSubsumes(source_b, source_d)) + << b << " should not subsume " << d; +} + +TEST(CSPSourceTest, PortWildcardSubsumes) { + const char* a = "http://example.org:*"; + const char* b = "http://example.org"; + const char* c = "https://example.org:*"; + + auto source_a = CSPSource(a); + auto source_b = CSPSource(b); + auto source_c = CSPSource(c); + + EXPECT_TRUE(CSPSourceSubsumes(source_a, source_b)) + << a << " should subsume " << b; + EXPECT_FALSE(CSPSourceSubsumes(source_b, source_a)) + << b << " should not subsume " << a; + + // https://example.com:* and http://example.com have no relations. + EXPECT_FALSE(CSPSourceSubsumes(source_b, source_c)) + << b << " should not subsume " << c; + EXPECT_FALSE(CSPSourceSubsumes(source_c, source_b)) + << c << " should not subsume " << b; +} + +TEST(CSPSourceTest, SchemesOnlySubsumes) { + struct TestCase { + const char* a; + const char* b; + bool expected; + } cases[] = { + // HTTP. + {"http:", "http:", true}, + {"http:", "https:", true}, + {"https:", "http:", false}, + {"https:", "https:", true}, + // WSS. + {"ws:", "ws:", true}, + {"ws:", "wss:", true}, + {"wss:", "ws:", false}, + {"wss:", "wss:", true}, + // Unequal. + {"ws:", "http:", false}, + {"http:", "ws:", false}, + {"http:", "about:", false}, + {"wss:", "https:", false}, + {"https:", "wss:", false}, + }; + + for (const auto& test : cases) { + auto source_a = CSPSource(test.a); + auto source_b = CSPSource(test.b); + EXPECT_EQ(CSPSourceSubsumes(source_a, source_b), test.expected) + << test.a << " subsumes " << test.b << " should return " + << test.expected; + } +} + TEST(CSPSourceTest, ToString) { { auto source = network::mojom::CSPSource::New(
diff --git a/testing/scripts/run_wpt_tests.py b/testing/scripts/run_wpt_tests.py index b777ba1..7efdcd1 100755 --- a/testing/scripts/run_wpt_tests.py +++ b/testing/scripts/run_wpt_tests.py
@@ -43,6 +43,7 @@ "--binary-arg=--enable-experimental-web-platform-features", "--binary-arg=--enable-blink-features=MojoJS,MojoJSTest", "--webdriver-binary=../../out/Release/chromedriver", + "--webdriver-arg=--enable-chrome-logs", "--headless", "--no-capture-stdio", "--no-manifest-download",
diff --git a/testing/scripts/wpt_common.py b/testing/scripts/wpt_common.py index bbe53e56..de1b7e7 100644 --- a/testing/scripts/wpt_common.py +++ b/testing/scripts/wpt_common.py
@@ -106,6 +106,7 @@ log_artifact = root_node["artifacts"].pop("log", None) if log_artifact: artifact_subpath = self._write_log_artifact( + test_failures.FILENAME_SUFFIX_ACTUAL, results_dir, path_so_far, log_artifact) root_node["artifacts"]["actual_text"] = [artifact_subpath] @@ -117,6 +118,13 @@ for screenshot_key, path in screenshot_paths_dict.items(): root_node["artifacts"][screenshot_key] = [path] + crashlog_artifact = root_node["artifacts"].pop("wpt_crash_log", + None) + if crashlog_artifact: + artifact_subpath = self._write_log_artifact( + test_failures.FILENAME_SUFFIX_CRASH_LOG, + results_dir, path_so_far, crashlog_artifact) + return # We're not at a leaf node, continue traversing the trie. @@ -128,13 +136,15 @@ self._process_test_leaves(results_dir, delim, root_node[key], new_path) - def _write_log_artifact(self, results_dir, test_name, log_artifact): + def _write_log_artifact(self, suffix, results_dir, test_name, log_artifact): """Writes a log artifact to disk. - The log artifact contains all the output of a test. It gets written to - the -actual.txt file for the test. + A log artifact contains some form of output for a test. It is written to + a txt file with a suffix generated from the log type. Args: + suffix: str suffix of the artifact to write, e.g. + test_failures.FILENAME_SUFFIX_ACTUAL results_dir: str path to the directory that results live in test_name: str name of the test that this artifact is for log_artifact: list of strings, the log entries for this test from @@ -146,9 +156,7 @@ """ log_artifact_sub_path = ( os.path.join("layout-test-results", - self.port.output_filename( - test_name, test_failures.FILENAME_SUFFIX_ACTUAL, - ".txt")) + self.port.output_filename(test_name, suffix, ".txt")) ) log_artifact_full_path = os.path.join(results_dir, log_artifact_sub_path)
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 6063dab..41a924d 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3578,6 +3578,24 @@ ] } ], + "IOSRequestDesktopByDefault": [ + { + "platforms": [ + "ios" + ], + "experiments": [ + { + "name": "DesktopEverywhere", + "enable_features": [ + "UseDefaultUserAgentInWebClient" + ], + "disable_features": [ + "MobileGoogleSRP" + ] + } + ] + } + ], "IOSSSLCommittedInterstitials": [ { "platforms": [ @@ -7217,9 +7235,9 @@ ], "experiments": [ { - "name": "Emabled5_v1", + "name": "Enabled3_v1", "params": { - "limit": "5" + "limit": "3" }, "enable_features": [ "ThrottleInstallingServiceWorker"
diff --git a/third_party/blink/common/feature_policy/policy_value.cc b/third_party/blink/common/feature_policy/policy_value.cc index 6be24bb..7bcf38e 100644 --- a/third_party/blink/common/feature_policy/policy_value.cc +++ b/third_party/blink/common/feature_policy/policy_value.cc
@@ -72,28 +72,6 @@ return *this; } -// static -PolicyValue PolicyValue::Combine(const PolicyValue& lhs, - const PolicyValue& rhs) { - PolicyValue result = lhs; - result.Combine(rhs); - return result; -} - -void PolicyValue::Combine(const PolicyValue& rhs) { - DCHECK_EQ(type_, rhs.Type()); - switch (type_) { - case mojom::PolicyValueType::kBool: - SetBoolValue(bool_value_ && rhs.BoolValue()); - break; - case mojom::PolicyValueType::kDecDouble: - SetDoubleValue(std::min(double_value_, rhs.DoubleValue()), type_); - break; - default: - NOTREACHED(); - } -} - bool operator==(const PolicyValue& lhs, const PolicyValue& rhs) { if (lhs.Type() != rhs.Type()) return false;
diff --git a/third_party/blink/public/common/feature_policy/policy_value.h b/third_party/blink/public/common/feature_policy/policy_value.h index ba96d1b9..bcb49c9 100644 --- a/third_party/blink/public/common/feature_policy/policy_value.h +++ b/third_party/blink/public/common/feature_policy/policy_value.h
@@ -48,10 +48,6 @@ // Operater overrides PolicyValue& operator=(const PolicyValue& rhs); - // Combine a new PolicyValue to self, by taking the stricter value of the two. - void Combine(const PolicyValue& value); - // Combine two PolicyValue_s together by taking the stricter value of the two. - static PolicyValue Combine(const PolicyValue& lhs, const PolicyValue& rhs); void SetToMax(); void SetToMin();
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 11fdd68..4abca4d 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -4,6 +4,7 @@ import("//mojo/public/tools/bindings/mojom.gni") import("//third_party/blink/public/public_features.gni") +import("//ui/ozone/ozone.gni") if (is_android) { import("//build/config/android/config.gni") @@ -257,8 +258,12 @@ ] } + enabled_features = [] if (is_linux || is_chromeos) { - enabled_features = [ "renderer_pref_system_font_family_name" ] + enabled_features += [ "renderer_pref_system_font_family_name" ] + } + if (use_x11 || use_ozone) { + enabled_features += [ "is_selection_clipboard_buffer_possible" ] } shared_cpp_typemaps = [
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index 6816b218..d3ea704 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -417,6 +417,12 @@ mojo_base.mojom.UnguessableToken child_frame_token, blink.mojom.FramePolicy frame_policy); + // Notifies the browser that the frame changed the 'csp' attribute + // of one of its child frames. + DidChangeCSPAttribute( + mojo_base.mojom.UnguessableToken child_frame_token, + network.mojom.ContentSecurityPolicy? parsed_csp_attribute); + // Sent by the renderer to request a paint preview of a subframe. |clip_rect| // is the size of the frame in it's parent. |guid| is an an identifier for // all the capture work (regardless of the process captures are happening in)
diff --git a/third_party/blink/public/mojom/payments/payment_request.mojom b/third_party/blink/public/mojom/payments/payment_request.mojom index 54cb03cc..4abac44c 100644 --- a/third_party/blink/public/mojom/payments/payment_request.mojom +++ b/third_party/blink/public/mojom/payments/payment_request.mojom
@@ -218,10 +218,17 @@ [EnableIf=is_android] bool google_pay_bridge_eligible); // Shows the user interface with the payment details. + // |is_user_gesture|: Whether the show is triggered from a user gesture. + // |wait_for_updated_details|: It's true when merchant passed in a promise + // into PaymentRequest.show(), so Chrome should disregard the initial payment + // details and show a spinner until the promise resolves with the correct + // payment details. Show(bool is_user_gesture, bool wait_for_updated_details); // Updates the payment details in response to new shipping address or shipping // option. + // |details|: The details that the merchant provides to update the payment + // request. UpdateWith(PaymentDetails details); // Called when the merchant received a new shipping address or shipping
diff --git a/third_party/blink/public/mojom/renderer_preferences.mojom b/third_party/blink/public/mojom/renderer_preferences.mojom index ee5a09d..f580532 100644 --- a/third_party/blink/public/mojom/renderer_preferences.mojom +++ b/third_party/blink/public/mojom/renderer_preferences.mojom
@@ -154,4 +154,9 @@ // The width of the arrow bitmap on a horizontal scroll bar in dips. [EnableIf=is_win] int32 arrow_bitmap_width_horizontal_scroll_bar_in_dips = 0; + + // Whether the selection clipboard buffer is available. Linux environments + // may support this. + [EnableIf=is_selection_clipboard_buffer_possible] + bool selection_clipboard_buffer_available = false; };
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h index 27539d30..0df09c1b 100644 --- a/third_party/blink/public/web/web_navigation_params.h +++ b/third_party/blink/public/web/web_navigation_params.h
@@ -401,6 +401,9 @@ // Whether the navigation is cross browsing context group (browsing instance). bool is_cross_browsing_context_group_navigation = false; + + // A list of additional content security policies to be enforced by blink. + WebVector<WebString> forced_content_security_policies; }; } // namespace blink
diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h index ada5a91..b01fc0f1 100644 --- a/third_party/blink/public/web/web_settings.h +++ b/third_party/blink/public/web/web_settings.h
@@ -298,6 +298,7 @@ virtual void SetNavigationControls(NavigationControls) = 0; virtual void SetAriaModalPrunesAXTree(bool) = 0; virtual void SetUseAXMenuList(bool) = 0; + virtual void SetSelectionClipboardBufferAvailable(bool) = 0; protected: ~WebSettings() = default;
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc index 8fd94fb..ceecbc795 100644 --- a/third_party/blink/renderer/core/animation/animation.cc +++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -171,13 +171,12 @@ AtomicString GetCSSTransitionCSSPropertyName(const Animation* animation) { CSSPropertyID property_id = - To<CSSTransition>(animation)->TransitionCSSProperty().PropertyID(); + To<CSSTransition>(animation)->TransitionCSSPropertyName().Id(); if (property_id == CSSPropertyID::kVariable || property_id == CSSPropertyID::kInvalid) return AtomicString(); return To<CSSTransition>(animation) - ->TransitionCSSProperty() - .GetCSSPropertyName() + ->TransitionCSSPropertyName() .ToAtomicString(); } } // namespace @@ -943,7 +942,9 @@ // * animation does not have either a pending play task or a pending pause // task, // then idle. - if (!CurrentTimeInternal() && !start_time_ && !PendingInternal()) + // https://github.com/w3c/csswg-drafts/issues/5400 + if (!CurrentTimeInternal() && (!start_time_ || !timeline_) && + !PendingInternal()) return kIdle; // 2. Either of the following conditions are true: @@ -1937,16 +1938,15 @@ playback_rate_); } - double result = + AnimationTimeDelta result = playback_rate_ > 0 - ? content_->TimeToForwardsEffectChange().InSecondsF() / playback_rate_ - : content_->TimeToReverseEffectChange().InSecondsF() / - -playback_rate_; + ? content_->TimeToForwardsEffectChange() / playback_rate_ + : content_->TimeToReverseEffectChange() / -playback_rate_; return !HasActiveAnimationsOnCompositor() && content_->GetPhase() == Timing::kPhaseActive ? AnimationTimeDelta() - : AnimationTimeDelta::FromSecondsD(result); + : result; } void Animation::cancel() {
diff --git a/third_party/blink/renderer/core/animation/animation_time_delta.h b/third_party/blink/renderer/core/animation/animation_time_delta.h index 7984ceb..0f0c00b 100644 --- a/third_party/blink/renderer/core/animation/animation_time_delta.h +++ b/third_party/blink/renderer/core/animation/animation_time_delta.h
@@ -80,6 +80,14 @@ AnimationTimeDelta& operator*=(V a) { return *this = (*this * a); } + template <typename T> + AnimationTimeDelta operator/(T a) const { + return AnimationTimeDelta(delta_ / a); + } + template <typename T> + AnimationTimeDelta& operator/=(T a) { + return *this = (*this / a); + } protected: constexpr explicit AnimationTimeDelta(double delta) : delta_(delta) {}
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index becf7ed9..6e30713 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -2120,10 +2120,8 @@ ->Layer() ->GetCompositedLayerMapping(); ASSERT_NE(nullptr, composited_layer_mapping); - const cc::PictureLayer* layer = - composited_layer_mapping->MainGraphicsLayer()->CcLayer(); - ASSERT_NE(nullptr, layer); - EXPECT_FALSE(layer->should_check_backface_visibility()); + const auto& layer = composited_layer_mapping->MainGraphicsLayer()->CcLayer(); + EXPECT_FALSE(layer.should_check_backface_visibility()); // Change the backface visibility, while the compositor animation is // happening. @@ -2132,7 +2130,7 @@ // Make sure the setting made it to both blink and all the way to CC. EXPECT_EQ(transform->GetBackfaceVisibilityForTesting(), TransformPaintPropertyNode::BackfaceVisibility::kHidden); - EXPECT_TRUE(layer->should_check_backface_visibility()) + EXPECT_TRUE(layer.should_check_backface_visibility()) << "Change to hidden did not get propagated to CC"; // Make sure the animation state is initialized in paint properties after // blink pushing new paint properties without animation state change.
diff --git a/third_party/blink/renderer/core/animation/css/css_transition.h b/third_party/blink/renderer/core/animation/css/css_transition.h index b1858af..6097b27 100644 --- a/third_party/blink/renderer/core/animation/css/css_transition.h +++ b/third_party/blink/renderer/core/animation/css/css_transition.h
@@ -29,8 +29,8 @@ uint64_t TransitionGeneration() const { return transition_generation_; } AtomicString transitionProperty() const; - const CSSProperty& TransitionCSSProperty() const { - return transition_property_.GetCSSProperty(); + CSSPropertyName TransitionCSSPropertyName() const { + return transition_property_.GetCSSPropertyName(); } // Animation overrides.
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.cc b/third_party/blink/renderer/core/clipboard/system_clipboard.cc index 4027f9b..1c201d04 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.cc +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -12,11 +12,15 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_drag_data.h" #include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h" #include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h" #include "third_party/blink/renderer/core/clipboard/data_object.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/local_frame_client.h" +#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/platform/graphics/image.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" @@ -37,6 +41,10 @@ frame->GetBrowserInterfaceBroker().GetInterface( clipboard_.BindNewPipeAndPassReceiver( frame->GetTaskRunner(TaskType::kUserInteraction))); +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + is_selection_buffer_available_ = + frame->GetSettings()->GetSelectionClipboardBufferAvailable(); +#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) } bool SystemClipboard::IsSelectionMode() const { @@ -242,14 +250,7 @@ case mojom::ClipboardBuffer::kStandard: return true; case mojom::ClipboardBuffer::kSelection: -#if defined(USE_X11) - return true; -#else - // Chrome OS and non-X11 unix builds do not support - // the X selection clipboard. - // TODO(http://crbug.com/361753): remove the need for this case. - return false; -#endif + return is_selection_buffer_available_; } return true; }
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.h b/third_party/blink/renderer/core/clipboard/system_clipboard.h index 8f4979d..04a769dd 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.h +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -79,10 +79,14 @@ bool IsValidBufferType(mojom::ClipboardBuffer); HeapMojoRemote<mojom::blink::ClipboardHost> clipboard_; - // In X11, |buffer_| may equal ClipboardBuffer::kStandard or kSelection. - // Outside X11, |buffer_| always equals ClipboardBuffer::kStandard. + // In some Linux environments, |buffer_| may equal ClipboardBuffer::kStandard + // or kSelection. In other platforms |buffer_| always equals + // ClipboardBuffer::kStandard. mojom::ClipboardBuffer buffer_ = mojom::ClipboardBuffer::kStandard; + // Whether the selection buffer is available on the underlying platform. + bool is_selection_buffer_available_ = false; + DISALLOW_COPY_AND_ASSIGN(SystemClipboard); };
diff --git a/third_party/blink/renderer/core/editing/compute_layer_selection.cc b/third_party/blink/renderer/core/editing/compute_layer_selection.cc index dfd0ea9..75b582b 100644 --- a/third_party/blink/renderer/core/editing/compute_layer_selection.cc +++ b/third_party/blink/renderer/core/editing/compute_layer_selection.cc
@@ -169,7 +169,7 @@ edge_start_in_layer, layout_object, graphics_layer); bound.edge_end = LocalToInvalidationBackingPoint( edge_end_in_layer, layout_object, graphics_layer); - bound.layer_id = graphics_layer.CcLayer()->id(); + bound.layer_id = graphics_layer.CcLayer().id(); bound.hidden = !IsVisible(layout_object, edge_start_in_layer, edge_end_in_layer); return bound;
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index 234a5c7..dc54a49 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -6223,7 +6223,7 @@ ASSERT_TRUE(layer_owner_node_for_start); EXPECT_EQ(GetExpectedLayerForSelection(layer_owner_node_for_start) ->CcLayer() - ->id(), + .id(), selection.start.layer_id); EXPECT_EQ(start_edge_start_in_layer_x, selection.start.edge_start.x()); @@ -6236,7 +6236,7 @@ ASSERT_TRUE(layer_owner_node_for_end); EXPECT_EQ( - GetExpectedLayerForSelection(layer_owner_node_for_end)->CcLayer()->id(), + GetExpectedLayerForSelection(layer_owner_node_for_end)->CcLayer().id(), selection.end.layer_id); EXPECT_EQ(end_edge_start_in_layer_x, selection.end.edge_start.x());
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.cc b/third_party/blink/renderer/core/exported/web_settings_impl.cc index 3e58fd8..de0a67d0 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.cc +++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc
@@ -788,6 +788,10 @@ settings_->SetUseAXMenuList(enabled); } +void WebSettingsImpl::SetSelectionClipboardBufferAvailable(bool available) { + settings_->SetSelectionClipboardBufferAvailable(available); +} + STATIC_ASSERT_ENUM(WebSettings::ImageAnimationPolicy::kAllowed, kImageAnimationPolicyAllowed); STATIC_ASSERT_ENUM(WebSettings::ImageAnimationPolicy::kAnimateOnce,
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.h b/third_party/blink/renderer/core/exported/web_settings_impl.h index dcd1119..13ed538 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.h +++ b/third_party/blink/renderer/core/exported/web_settings_impl.h
@@ -225,6 +225,7 @@ void SetAriaModalPrunesAXTree(bool) override; void SetUseAXMenuList(bool) override; + void SetSelectionClipboardBufferAvailable(bool) override; bool RenderVSyncNotificationEnabled() const { return render_v_sync_notification_enabled_;
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc index bfc6638..b8b7a5ef 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -1048,12 +1048,13 @@ // StripURLForUseInReport(..) source_url.SetQuery(String()); - // TODO(arthursonzogni): |redirect_status| refers to the redirect status of - // the |blocked_url|. This is unrelated to |source_url|. Why using it in - // this case? This is obviously wrong: + // The |source_url| is the URL of the script that triggered the CSP + // violation. It is the URL pre-redirect. So it is safe to expose it in + // reports without leaking any new informations to the document. See + // https://crrev.com/c/2187792. String source_file = StripURLForUseInReport(delegate->GetSecurityOrigin(), source_url, - redirect_status, effective_type); + RedirectStatus::kNoRedirect, effective_type); init->setSourceFile(source_file); init->setLineNumber(source_location->LineNumber()); @@ -1723,6 +1724,8 @@ // static bool ContentSecurityPolicy::IsValidCSPAttr(const String& attr, const String& context_required_csp) { + DCHECK(!base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE)); + // we don't allow any newline characters in the CSP attributes if (attr.Contains('\n') || attr.Contains('\r')) return false; @@ -1746,9 +1749,6 @@ return true; } - if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE)) - return true; - auto* context_policy = MakeGarbageCollected<ContentSecurityPolicy>(); context_policy->AddPolicyFromHeaderValue(context_required_csp, ContentSecurityPolicyType::kEnforce,
diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc index 4f0f773..3581ff0 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc +++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
@@ -265,7 +265,7 @@ report_endpoints_, use_reporting_api_, header_, header_type_, ContentSecurityPolicy::kEvalViolation, std::unique_ptr<SourceLocation>(), nullptr, - RedirectStatus::kFollowedRedirect, nullptr, content); + RedirectStatus::kNoRedirect, nullptr, content); } bool CSPDirectiveList::CheckEval(SourceListDirective* directive) const { @@ -340,7 +340,7 @@ ContentSecurityPolicy::GetDirectiveName( ContentSecurityPolicy::DirectiveType::kRequireTrustedTypesFor), ContentSecurityPolicy::DirectiveType::kRequireTrustedTypesFor, message, - KURL(), RedirectStatus::kFollowedRedirect, + KURL(), RedirectStatus::kNoRedirect, ContentSecurityPolicy::kTrustedTypesSinkViolation, sample, sample_prefix); return IsReportOnly(); }
diff --git a/third_party/blink/renderer/core/frame/frame_owner.h b/third_party/blink/renderer/core/frame/frame_owner.h index cce810a3..c18dc8a4 100644 --- a/third_party/blink/renderer/core/frame/frame_owner.h +++ b/third_party/blink/renderer/core/frame/frame_owner.h
@@ -79,6 +79,7 @@ protected: virtual void FrameOwnerPropertiesChanged() {} + virtual void CSPAttributeChanged() {} private: virtual void SetIsSwappingFrames(bool) {} @@ -107,6 +108,7 @@ if (frame_owner_) { frame_owner_->SetIsSwappingFrames(false); frame_owner_->FrameOwnerPropertiesChanged(); + frame_owner_->CSPAttributeChanged(); } }
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 8acf297..f1d3ff00 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2803,7 +2803,7 @@ root, [](const GraphicsLayer& layer) { PaintArtifactCompositor::UpdateLayerDebugInfo( - *layer.CcLayer(), + layer.CcLayer(), PaintChunk::Id(layer, DisplayItem::kGraphicsLayerWrapper), layer.GetCompositingReasons(), layer.GetRasterInvalidationTracking());
diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5 index 23989e8..3ea132ac 100644 --- a/third_party/blink/renderer/core/frame/settings.json5 +++ b/third_party/blink/renderer/core/frame/settings.json5
@@ -1099,6 +1099,10 @@ { name: "useAXMenuList", initial: true, + }, + { + name: "selectionClipboardBufferAvailable", + initial: false, type: "bool", }, ],
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 43d129e7..706fb4e1 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -20,6 +20,7 @@ #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" +#include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" @@ -383,6 +384,33 @@ std::move(properties)); } +void HTMLFrameOwnerElement::CSPAttributeChanged() { + if (!base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE)) + return; + + // Don't notify about updates if ContentFrame() is null, for example when + // the subframe hasn't been created yet; or if we are in the middle of + // swapping one frame for another, in which case the final state + // will be propagated at the end of the swapping operation. + if (is_swapping_frames_ || !ContentFrame()) + return; + + String fake_header = + "HTTP/1.1 200 OK\nContent-Security-Policy: " + RequiredCsp(); + network::mojom::blink::ParsedHeadersPtr parsed_headers = + ParseHeaders(fake_header, GetDocument().Url()); + + DCHECK_LE(parsed_headers->content_security_policy.size(), 1u); + + network::mojom::blink::ContentSecurityPolicyPtr csp = + parsed_headers->content_security_policy.IsEmpty() + ? nullptr + : std::move(parsed_headers->content_security_policy[0]); + + GetDocument().GetFrame()->GetLocalFrameHostRemote().DidChangeCSPAttribute( + ContentFrame()->GetFrameToken(), std::move(csp)); +} + void HTMLFrameOwnerElement::AddResourceTiming(const ResourceTimingInfo& info) { // Resource timing info should only be reported if the subframe is attached. DCHECK(ContentFrame() && ContentFrame()->IsLocalFrame()); @@ -548,6 +576,9 @@ if (!child_frame) return false; + // Send 'csp' attribute to the browser. + CSPAttributeChanged(); + WebFrameLoadType child_load_type = WebFrameLoadType::kReplaceCurrentItem; if (!GetDocument().LoadEventFinished() && GetDocument().Loader()->LoadType() ==
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h index 038a9c1..a103ca44 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.h +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -145,6 +145,7 @@ bool replace_current_item); bool IsKeyboardFocusable() const override; void FrameOwnerPropertiesChanged() override; + void CSPAttributeChanged() override; void DisposePluginSoon(WebPluginContainerImpl*);
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 2fdf9bca..3d708f4 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/html/html_iframe_element.h" #include "base/metrics/histogram_macros.h" +#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/web_sandbox_flags.h" #include "services/network/public/mojom/trust_tokens.mojom-blink.h" #include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h" @@ -231,19 +232,35 @@ UpdateContainerPolicy(); } } else if (name == html_names::kCspAttr) { - if (!ContentSecurityPolicy::IsValidCSPAttr( - value.GetString(), GetDocument().RequiredCSP().GetString())) { - required_csp_ = g_null_atom; - GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( - mojom::ConsoleMessageSource::kOther, - mojom::ConsoleMessageLevel::kError, - "'csp' attribute is not a valid policy: " + value)); - return; - } - if (required_csp_ != value) { - required_csp_ = value; - FrameOwnerPropertiesChanged(); - UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute); + if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE)) { + if (value.Contains('\n') || value.Contains('\r') || value.Contains(',')) { + required_csp_ = g_null_atom; + GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kOther, + mojom::blink::ConsoleMessageLevel::kError, + "'csp' attribute is invalid: " + value)); + return; + } + if (required_csp_ != value) { + required_csp_ = value; + CSPAttributeChanged(); + UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute); + } + } else { + if (!ContentSecurityPolicy::IsValidCSPAttr( + value.GetString(), GetDocument().RequiredCSP().GetString())) { + required_csp_ = g_null_atom; + GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kOther, + mojom::blink::ConsoleMessageLevel::kError, + "'csp' attribute is not a valid policy: " + value)); + return; + } + if (required_csp_ != value) { + required_csp_ = value; + FrameOwnerPropertiesChanged(); + UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute); + } } } else if (name == html_names::kAllowAttr) { if (allow_ != value) { @@ -432,7 +449,8 @@ auto* html_doc = DynamicTo<HTMLDocument>(GetDocument()); if (html_doc && insertion_point.IsInDocumentTree()) { html_doc->AddNamedItem(name_); - if (!ContentSecurityPolicy::IsValidCSPAttr( + if (!base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE) && + !ContentSecurityPolicy::IsValidCSPAttr( required_csp_, GetDocument().RequiredCSP().GetString())) { if (!required_csp_.IsEmpty()) { GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
diff --git a/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc b/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc index 1a052a4..917896ec 100644 --- a/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc
@@ -406,30 +406,31 @@ } String InspectorAnimationAgent::CreateCSSId(blink::Animation& animation) { - static const CSSProperty* g_animation_properties[] = { - &GetCSSPropertyAnimationDelay(), - &GetCSSPropertyAnimationDirection(), - &GetCSSPropertyAnimationDuration(), - &GetCSSPropertyAnimationFillMode(), - &GetCSSPropertyAnimationIterationCount(), - &GetCSSPropertyAnimationName(), - &GetCSSPropertyAnimationTimingFunction(), + static CSSPropertyID g_animation_properties[] = { + CSSPropertyID::kAnimationDelay, + CSSPropertyID::kAnimationDirection, + CSSPropertyID::kAnimationDuration, + CSSPropertyID::kAnimationFillMode, + CSSPropertyID::kAnimationIterationCount, + CSSPropertyID::kAnimationName, + CSSPropertyID::kAnimationTimingFunction, }; - static const CSSProperty* g_transition_properties[] = { - &GetCSSPropertyTransitionDelay(), &GetCSSPropertyTransitionDuration(), - &GetCSSPropertyTransitionProperty(), - &GetCSSPropertyTransitionTimingFunction(), + static CSSPropertyID g_transition_properties[] = { + CSSPropertyID::kTransitionDelay, + CSSPropertyID::kTransitionDuration, + CSSPropertyID::kTransitionProperty, + CSSPropertyID::kTransitionTimingFunction, }; auto* effect = To<KeyframeEffect>(animation.effect()); - Vector<const CSSProperty*> css_properties; + Vector<CSSPropertyName> css_property_names; if (IsA<CSSAnimation>(animation)) { - for (const CSSProperty* property : g_animation_properties) - css_properties.push_back(property); + for (CSSPropertyID property : g_animation_properties) + css_property_names.push_back(CSSPropertyName(property)); } else if (auto* css_transition = DynamicTo<CSSTransition>(animation)) { - for (const CSSProperty* property : g_transition_properties) - css_properties.push_back(property); - css_properties.push_back(&css_transition->TransitionCSSProperty()); + for (CSSPropertyID property : g_transition_properties) + css_property_names.push_back(CSSPropertyName(property)); + css_property_names.push_back(css_transition->TransitionCSSPropertyName()); } else { NOTREACHED(); } @@ -442,14 +443,14 @@ ? AnimationType::CSSTransition : AnimationType::CSSAnimation); digestor.UpdateUtf8(animation.id()); - for (const CSSProperty* property : css_properties) { + for (const CSSPropertyName& name : css_property_names) { CSSStyleDeclaration* style = - css_agent_->FindEffectiveDeclaration(*property, styles); + css_agent_->FindEffectiveDeclaration(name, styles); // Ignore inline styles. if (!style || !style->ParentStyleSheet() || !style->parentRule() || style->parentRule()->GetType() != CSSRule::kStyleRule) continue; - digestor.UpdateUtf8(property->GetPropertyNameString()); + digestor.UpdateUtf8(name.ToAtomicString()); digestor.UpdateUtf8(css_agent_->StyleSheetId(style->ParentStyleSheet())); digestor.UpdateUtf8(To<CSSStyleRule>(style->parentRule())->selectorText()); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc index 5a7b7db9..731b51b 100644 --- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -37,6 +37,7 @@ #include "third_party/blink/renderer/core/css/css_import_rule.h" #include "third_party/blink/renderer/core/css/css_keyframe_rule.h" #include "third_party/blink/renderer/core/css/css_media_rule.h" +#include "third_party/blink/renderer/core/css/css_property_name.h" #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/css/css_rule.h" @@ -743,7 +744,7 @@ void InspectorCSSAgent::CompleteEnabled() { instrumenting_agents_->AddInspectorCSSAgent(this); - dom_agent_->SetDOMListener(this); + dom_agent_->AddDOMListener(this); HeapVector<Member<Document>> documents = dom_agent_->Documents(); for (Document* document : documents) { UpdateActiveStyleSheets(document); @@ -774,7 +775,7 @@ Response InspectorCSSAgent::disable() { Reset(); - dom_agent_->SetDOMListener(nullptr); + dom_agent_->RemoveDOMListener(this); instrumenting_agents_->RemoveInspectorCSSAgent(this); enable_completed_ = false; enable_requested_.Set(false); @@ -2320,12 +2321,12 @@ } CSSStyleDeclaration* InspectorCSSAgent::FindEffectiveDeclaration( - const CSSProperty& property_class, + const CSSPropertyName& property_name, const HeapVector<Member<CSSStyleDeclaration>>& styles) { if (!styles.size()) return nullptr; - String longhand = property_class.GetPropertyNameString(); + String longhand = property_name.ToAtomicString(); CSSStyleDeclaration* found_style = nullptr; for (unsigned i = 0; i < styles.size(); ++i) { @@ -2357,16 +2358,13 @@ "Can't edit a node from a non-active document"); } - CSSPropertyID property = - cssPropertyID(element->GetExecutionContext(), property_name); - if (!isValidCSSPropertyID(property)) + base::Optional<CSSPropertyName> css_property_name = + CSSPropertyName::From(element->GetExecutionContext(), property_name); + if (!css_property_name.has_value()) return Response::ServerError("Invalid property name"); - CSSPropertyID property_id = - cssPropertyID(element->GetExecutionContext(), property_name); - const CSSProperty& property_class = CSSProperty::Get(property_id); CSSStyleDeclaration* style = - FindEffectiveDeclaration(property_class, MatchingStyles(element)); + FindEffectiveDeclaration(*css_property_name, MatchingStyles(element)); if (!style) return Response::ServerError("Can't find a style to edit"); @@ -2390,13 +2388,13 @@ return Response::ServerError("Can't find a source to edit"); Vector<StylePropertyShorthand, 4> shorthands; - getMatchingShorthandsForLonghand(property_id, &shorthands); + getMatchingShorthandsForLonghand(css_property_name->Id(), &shorthands); String shorthand = shorthands.size() > 0 ? CSSProperty::Get(shorthands[0].id()).GetPropertyNameString() : String(); - String longhand = property_class.GetPropertyNameString(); + String longhand = css_property_name->ToAtomicString(); int found_index = -1; Vector<CSSPropertySourceData>& properties = source_data->property_data;
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.h b/third_party/blink/renderer/core/inspector/inspector_css_agent.h index eaf2c0f..0de4ab3 100644 --- a/third_party/blink/renderer/core/inspector/inspector_css_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.h
@@ -50,6 +50,7 @@ class RecalculateStyle; } // namespace probe +class CSSPropertyName; class CSSRule; class CSSStyleRule; class CSSStyleSheet; @@ -233,7 +234,7 @@ CSSRule*); CSSStyleDeclaration* FindEffectiveDeclaration( - const CSSProperty&, + const CSSPropertyName&, const HeapVector<Member<CSSStyleDeclaration>>& styles); HeapVector<Member<CSSStyleDeclaration>> MatchingStyles(Element*);
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc index f8798c4..f0a7244 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -231,7 +231,6 @@ : isolate_(isolate), inspected_frames_(inspected_frames), v8_session_(v8_session), - dom_listener_(nullptr), document_node_to_id_map_(MakeGarbageCollected<NodeToIdMap>()), last_node_id_(1), suppress_attribute_modified_event_(false), @@ -256,8 +255,32 @@ return result; } -void InspectorDOMAgent::SetDOMListener(DOMListener* listener) { - dom_listener_ = listener; +void InspectorDOMAgent::AddDOMListener(DOMListener* listener) { + dom_listeners_.insert(listener); +} + +void InspectorDOMAgent::RemoveDOMListener(DOMListener* listener) { + dom_listeners_.erase(listener); +} + +void InspectorDOMAgent::NotifyDidAddDocument(Document* document) { + for (DOMListener* listener : dom_listeners_) + listener->DidAddDocument(document); +} + +void InspectorDOMAgent::NotifyDidRemoveDocument(Document* document) { + for (DOMListener* listener : dom_listeners_) + listener->DidRemoveDocument(document); +} + +void InspectorDOMAgent::NotifyWillRemoveDOMNode(Node* node) { + for (DOMListener* listener : dom_listeners_) + listener->WillRemoveDOMNode(node); +} + +void InspectorDOMAgent::NotifyDidModifyDOMAttr(Element* element) { + for (DOMListener* listener : dom_listeners_) + listener->DidModifyDOMAttr(element); } void InspectorDOMAgent::SetDocument(Document* doc) { @@ -304,8 +327,8 @@ id_to_node_.erase(id); id_to_nodes_map_.erase(id); - if (IsA<Document>(node) && dom_listener_) - dom_listener_->DidRemoveDocument(To<Document>(node)); + if (IsA<Document>(node)) + NotifyDidRemoveDocument(To<Document>(node)); if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) { Document* content_document = frame_owner->contentDocument(); @@ -331,8 +354,7 @@ } } - if (dom_listener_) - dom_listener_->WillRemoveDOMNode(node); + NotifyWillRemoveDOMNode(node); document_node_to_id_map_->erase(node); bool children_requested = children_requested_.Contains(id); @@ -1859,8 +1881,7 @@ void InspectorDOMAgent::DidCommitLoad(LocalFrame*, DocumentLoader* loader) { Document* document = loader->GetFrame()->GetDocument(); - if (dom_listener_) - dom_listener_->DidAddDocument(document); + NotifyDidAddDocument(document); LocalFrame* inspected_frame = inspected_frames_->Root(); if (loader->GetFrame() != inspected_frame) { @@ -1948,8 +1969,7 @@ if (!id) return; - if (dom_listener_) - dom_listener_->DidModifyDOMAttr(element); + NotifyDidModifyDOMAttr(element); GetFrontend()->attributeModified(id, name.ToString(), value); } @@ -1961,8 +1981,7 @@ if (!id) return; - if (dom_listener_) - dom_listener_->DidModifyDOMAttr(element); + NotifyDidModifyDOMAttr(element); GetFrontend()->attributeRemoved(id, name.ToString()); } @@ -1977,8 +1996,7 @@ if (!id) continue; - if (dom_listener_) - dom_listener_->DidModifyDOMAttr(element); + NotifyDidModifyDOMAttr(element); node_ids->emplace_back(id); } GetFrontend()->inlineStyleInvalidated(std::move(node_ids)); @@ -2374,7 +2392,7 @@ } void InspectorDOMAgent::Trace(Visitor* visitor) const { - visitor->Trace(dom_listener_); + visitor->Trace(dom_listeners_); visitor->Trace(inspected_frames_); visitor->Trace(document_node_to_id_map_); visitor->Trace(dangling_node_to_id_maps_);
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.h b/third_party/blink/renderer/core/inspector/inspector_dom_agent.h index 06c6b4bf..c36df12 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.h
@@ -278,7 +278,8 @@ Node* NodeForId(int node_id); int BoundNodeId(Node*); - void SetDOMListener(DOMListener*); + void AddDOMListener(DOMListener*); + void RemoveDOMListener(DOMListener*); int PushNodePathToFrontend(Node*); protocol::Response NodeForRemoteObjectId(const String& remote_object_id, Node*&); @@ -317,6 +318,11 @@ // For idempotence, call enable(). void EnableAndReset(); + void NotifyDidAddDocument(Document*); + void NotifyDidRemoveDocument(Document*); + void NotifyWillRemoveDOMNode(Node*); + void NotifyDidModifyDOMAttr(Element*); + // Node-related methods. typedef HeapHashMap<Member<Node>, int> NodeToIdMap; int Bind(Node*, NodeToIdMap*); @@ -367,7 +373,7 @@ v8::Isolate* isolate_; Member<InspectedFrames> inspected_frames_; v8_inspector::V8InspectorSession* v8_session_; - Member<DOMListener> dom_listener_; + HeapHashSet<Member<DOMListener>> dom_listeners_; Member<NodeToIdMap> document_node_to_id_map_; // Owns node mappings for dangling nodes. HeapVector<Member<NodeToIdMap>> dangling_node_to_id_maps_;
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc index a130efe..664a49d 100644 --- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -389,6 +389,7 @@ visitor->Trace(dom_agent_); visitor->Trace(inspect_tool_); visitor->Trace(hinge_); + visitor->Trace(document_to_ax_context_); InspectorBaseAgent::Trace(visitor); } @@ -421,9 +422,26 @@ } backend_node_id_to_inspect_ = 0; SetNeedsUnbufferedInput(true); + dom_agent_->AddDOMListener(this); + for (Document* document : dom_agent_->Documents()) + DidAddDocument(document); + return Response::Success(); } +void InspectorOverlayAgent::DidAddDocument(Document* document) { + auto context = std::make_unique<AXContext>(*document); + document_to_ax_context_.Set(document, std::move(context)); +} + +void InspectorOverlayAgent::DidRemoveDocument(Document* document) { + document_to_ax_context_.erase(document); +} + +void InspectorOverlayAgent::WillRemoveDOMNode(Node* node) {} + +void InspectorOverlayAgent::DidModifyDOMAttr(Element* element) {} + Response InspectorOverlayAgent::disable() { enabled_.Clear(); setShowAdHighlights(false); @@ -450,6 +468,8 @@ frame_resource_name_ = 0; PickTheRightTool(); SetNeedsUnbufferedInput(false); + dom_agent_->RemoveDOMListener(this); + document_to_ax_context_.clear(); return Response::Success(); } @@ -855,7 +875,7 @@ frame_overlay_->GetDelegate()) ->GetLayer(); } - return layer == frame_overlay_->GetGraphicsLayer()->CcLayer(); + return layer == &frame_overlay_->GetGraphicsLayer()->CcLayer(); } LocalFrame* InspectorOverlayAgent::GetFrame() const {
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h index d8fff418..be4973a 100644 --- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
@@ -35,9 +35,12 @@ #include "base/memory/scoped_refptr.h" #include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/platform/web_input_event_result.h" +#include "third_party/blink/renderer/core/accessibility/ax_context.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" #include "third_party/blink/renderer/core/inspector/inspector_base_agent.h" +#include "third_party/blink/renderer/core/inspector/inspector_dom_agent.h" #include "third_party/blink/renderer/core/inspector/inspector_highlight.h" #include "third_party/blink/renderer/core/inspector/inspector_overlay_host.h" #include "third_party/blink/renderer/core/inspector/protocol/Overlay.h" @@ -126,6 +129,7 @@ class CORE_EXPORT InspectorOverlayAgent final : public InspectorBaseAgent<protocol::Overlay::Metainfo>, + public InspectorDOMAgent::DOMListener, public InspectorOverlayHost::Delegate { public: static std::unique_ptr<InspectorGridHighlightConfig> ToGridHighlightConfig( @@ -233,6 +237,12 @@ // InspectorOverlayHost::Delegate implementation. void Dispatch(const String& message) override; + // InspectorDOMAgent::DOMListener implementation + void DidAddDocument(Document*) override; + void DidRemoveDocument(Document*) override; + void WillRemoveDOMNode(Node*) override; + void DidModifyDOMAttr(Element*) override; + bool IsEmpty(); LocalFrame* OverlayMainFrame(); @@ -272,6 +282,10 @@ std::unique_ptr<FrameOverlay> frame_overlay_; Member<InspectTool> inspect_tool_; Member<Hinge> hinge_; + // The agent needs to keep AXContext because it enables caching of + // a11y attributes shown in the inspector overlay. + HeapHashMap<Member<Document>, std::unique_ptr<AXContext>> + document_to_ax_context_; bool swallow_next_mouse_up_; DOMNodeId backend_node_id_to_inspect_; InspectorAgentState::Boolean enabled_;
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 4bb4e61..69f427e 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -1067,7 +1067,7 @@ LocalToPageQuad(*layout_object, clip_rect, &quad); CreateQuad(value.get(), "clip", quad); SetGeneratingNodeInfo(value.get(), layout_object, "nodeId"); - int graphics_layer_id = graphics_layer ? graphics_layer->CcLayer()->id() : 0; + int graphics_layer_id = graphics_layer ? graphics_layer->CcLayer().id() : 0; value->SetInteger("layerId", graphics_layer_id); SetCallStack(value.get()); return value;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index b9b4ead3..a035565f 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -991,6 +991,12 @@ navigation_params->origin_policy, last_origin_window_csp_.Release(), commit_reason); + for (auto& csp : navigation_params->forced_content_security_policies) { + content_security_policy->AddPolicyFromHeaderValue( + csp, network::mojom::ContentSecurityPolicyType::kEnforce, + network::mojom::ContentSecurityPolicySource::kHTTP); + } + base::Optional<Document::UnloadEventTiming> unload_timing; FrameSwapScope frame_swap_scope(frame_owner); { @@ -1547,7 +1553,8 @@ const FetchClientSettingsObject* fetch_client_settings_object, LocalDOMWindow* window_for_logging, mojom::RequestContextFrameType frame_type) const { - if (!RequiredCSP().IsEmpty()) { + if (!base::FeatureList::IsEnabled(network::features::kOutOfBlinkCSPEE) && + !RequiredCSP().IsEmpty()) { DCHECK( ContentSecurityPolicy::IsValidCSPAttr(RequiredCSP().GetString(), "")); resource_request.SetHttpHeaderField(http_names::kSecRequiredCSP,
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index 8302e1f..c66e94d 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -254,7 +254,7 @@ owner = &GetLayoutObject().GetDocument(); } if (owner) { - graphics_layer->CcLayer()->SetFrameElementId( + graphics_layer->CcLayer().SetFrameElementId( CompositorElementIdFromUniqueObjectId( DOMNodeIds::IdForNode(owner), CompositorElementIdNamespace::kDOMNodeId)); @@ -301,7 +301,7 @@ // Determine whether the external texture layer covers the whole graphics // layer. This may not be the case if there are box decorations or // shadows. - if (layer && layer->bounds() == graphics_layer_->CcLayer()->bounds()) { + if (layer && layer->bounds() == graphics_layer_->CcLayer().bounds()) { // Determine whether the rendering context's external texture layer is // opaque. if (!context->CreationAttributes().alpha) { @@ -361,11 +361,11 @@ bool transformed_rasterization_allowed = !(owning_layer_.GetCompositingReasons() & CompositingReason::kComboTransformedRasterizationDisallowedReasons); - graphics_layer_->CcLayer()->SetTransformedRasterizationAllowed( + graphics_layer_->CcLayer().SetTransformedRasterizationAllowed( transformed_rasterization_allowed); if (non_scrolling_squashing_layer_) { non_scrolling_squashing_layer_->CcLayer() - ->SetTransformedRasterizationAllowed(true); + .SetTransformedRasterizationAllowed(true); } } @@ -1085,7 +1085,7 @@ if (scrolling_contents_layer_ && scrollable_area->NeedsShowScrollbarLayers()) { - scrolling_contents_layer_->CcLayer()->ShowScrollbars(); + scrolling_contents_layer_->CcLayer().ShowScrollbars(); scrollable_area->DidShowScrollbarLayers(); } } @@ -1248,7 +1248,7 @@ CompositorElementIdNamespace::kEffectMask); mask_layer_->SetElementId(element_id); if (GetLayoutObject().HasNonInitialBackdropFilter()) - mask_layer_->CcLayer()->SetIsBackdropFilterMask(true); + mask_layer_->CcLayer().SetIsBackdropFilterMask(true); mask_layer_->SetHitTestable(true); layer_changed = true; }
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc index 1e98f165..d1ca418 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -1343,7 +1343,7 @@ target_layer ? target_layer->GraphicsLayerBacking() : nullptr; ASSERT_TRUE(target_graphics_layer); EXPECT_FALSE( - target_graphics_layer->CcLayer()->transformed_rasterization_allowed()); + target_graphics_layer->CcLayer().transformed_rasterization_allowed()); } { LayoutObject* target = GetLayoutObjectByElementId("target2"); @@ -1353,7 +1353,7 @@ target_layer ? target_layer->GraphicsLayerBacking() : nullptr; ASSERT_TRUE(target_graphics_layer); EXPECT_FALSE( - target_graphics_layer->CcLayer()->transformed_rasterization_allowed()); + target_graphics_layer->CcLayer().transformed_rasterization_allowed()); } } @@ -1376,7 +1376,7 @@ target_layer ? target_layer->GraphicsLayerBacking() : nullptr; ASSERT_TRUE(target_graphics_layer); EXPECT_TRUE( - target_graphics_layer->CcLayer()->transformed_rasterization_allowed()); + target_graphics_layer->CcLayer().transformed_rasterization_allowed()); } TEST_F(CompositedLayerMappingTest, @@ -1399,7 +1399,7 @@ target_layer ? target_layer->GraphicsLayerBacking() : nullptr; ASSERT_TRUE(target_graphics_layer); EXPECT_TRUE( - target_graphics_layer->CcLayer()->transformed_rasterization_allowed()); + target_graphics_layer->CcLayer().transformed_rasterization_allowed()); } TEST_F(CompositedLayerMappingTest, @@ -1417,7 +1417,7 @@ target_layer ? target_layer->GraphicsLayerBacking() : nullptr; ASSERT_TRUE(target_graphics_layer); EXPECT_TRUE( - target_graphics_layer->CcLayer()->transformed_rasterization_allowed()); + target_graphics_layer->CcLayer().transformed_rasterization_allowed()); } TEST_F(CompositedLayerMappingTest, @@ -1433,7 +1433,7 @@ target_layer ? target_layer->GraphicsLayerBacking() : nullptr; ASSERT_TRUE(target_graphics_layer); EXPECT_TRUE( - target_graphics_layer->CcLayer()->transformed_rasterization_allowed()); + target_graphics_layer->CcLayer().transformed_rasterization_allowed()); } TEST_F(CompositedLayerMappingTest, ScrollingContainerBoundsChange) { @@ -1676,15 +1676,15 @@ auto* box = ToLayoutBoxModelObject(GetLayoutObjectByElementId("target")); auto* mapping = box->Layer()->GetCompositedLayerMapping(); - const auto* layer = mapping->MainGraphicsLayer()->CcLayer(); + const auto& layer = mapping->MainGraphicsLayer()->CcLayer(); auto expected = gfx::Rect(0, 0, 100, 100); - EXPECT_EQ(layer->touch_action_region().GetAllRegions().bounds(), expected); + EXPECT_EQ(layer.touch_action_region().GetAllRegions().bounds(), expected); EXPECT_TRUE(mapping->MainGraphicsLayer()->PaintsHitTest()); // The only painted content for the main graphics layer is the touch-action // rect which is not sent to cc, so the cc::layer should not draw content. - EXPECT_FALSE(layer->DrawsContent()); + EXPECT_FALSE(layer.DrawsContent()); EXPECT_FALSE(mapping->MainGraphicsLayer()->DrawsContent()); } @@ -1886,10 +1886,10 @@ Element* child = GetDocument().getElementById("child"); PaintLayer* child_paint_layer = ToLayoutBoxModelObject(child->GetLayoutObject())->Layer(); - auto* child_layer = child_paint_layer->GraphicsLayerBacking()->CcLayer(); - EXPECT_TRUE(child_layer->frame_element_id()); + auto& child_layer = child_paint_layer->GraphicsLayerBacking()->CcLayer(); + EXPECT_TRUE(child_layer.frame_element_id()); - EXPECT_EQ(child_layer->frame_element_id(), + EXPECT_EQ(child_layer.frame_element_id(), CompositorElementIdFromUniqueObjectId( DOMNodeIds::IdForNode(&GetDocument()), CompositorElementIdNamespace::kDOMNodeId)); @@ -1901,11 +1901,11 @@ EXPECT_TRUE(subframe); PaintLayer* subframe_paint_layer = ToLayoutBoxModelObject(subframe->GetLayoutObject())->Layer(); - auto* subframe_layer = + auto& subframe_layer = subframe_paint_layer->GraphicsLayerBacking()->CcLayer(); - EXPECT_TRUE(subframe_layer->frame_element_id()); + EXPECT_TRUE(subframe_layer.frame_element_id()); - EXPECT_EQ(subframe_layer->frame_element_id(), + EXPECT_EQ(subframe_layer.frame_element_id(), CompositorElementIdFromUniqueObjectId( DOMNodeIds::IdForNode(subframe->contentDocument()), CompositorElementIdNamespace::kDOMNodeId));
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 b3e9c6c..9a49901 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -1212,21 +1212,22 @@ auto* grouped_mapping = GetElementById("topleft")->GetLayoutBox()->Layer()->GroupedMapping(); - auto* squashed_layer = + ASSERT_TRUE(grouped_mapping); + ASSERT_TRUE(grouped_mapping->NonScrollingSquashingLayer()); + auto& squashing_layer = grouped_mapping->NonScrollingSquashingLayer()->CcLayer(); - ASSERT_NE(nullptr, squashed_layer); // Top left and bottom right are squashed. // This squashed layer should not be opaque, as it is squashing two squares // with some gaps between them. - EXPECT_FALSE(squashed_layer->contents_opaque()); + EXPECT_FALSE(squashing_layer.contents_opaque()); // This shouldn't DCHECK. - squashed_layer->SafeOpaqueBackgroundColor(); + squashing_layer.SafeOpaqueBackgroundColor(); // Because contents_opaque is false, the SafeOpaqueBackgroundColor() getter // will return SK_ColorTRANSPARENT. So we need to grab the actual color, // to make sure it's right. SkColor squashed_bg_color = - squashed_layer->ActualSafeOpaqueBackgroundColorForTesting(); + squashing_layer.ActualSafeOpaqueBackgroundColorForTesting(); // The squashed layer should have a non-transparent safe opaque background // color, that isn't blue. Exactly which color it is depends on heuristics, // but it should be one of the two colors of the elements that created it.
diff --git a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc index bea6453..f8c6758 100644 --- a/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc +++ b/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
@@ -45,7 +45,7 @@ PointAsJSONArray(layer->GetOffsetFromTransformNode())); } - layer->AppendAdditionalInfoAsJSON(flags, *layer->CcLayer(), *json.get()); + layer->AppendAdditionalInfoAsJSON(flags, layer->CcLayer(), *json.get()); return json; }
diff --git a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc index 8a5f1bd3..7803daa8 100644 --- a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc +++ b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
@@ -79,14 +79,13 @@ <div id="target"></div> )HTML"); auto* target = GetDocument().getElementById("target"); - auto* cc_layer = + auto& cc_layer = RuntimeEnabledFeatures::CompositeAfterPaintEnabled() - ? GetDocument() - .View() - ->GetPaintArtifactCompositor() - ->RootLayer() - ->children()[1] - .get() + ? *GetDocument() + .View() + ->GetPaintArtifactCompositor() + ->RootLayer() + ->children()[1] : GetLayoutView().Layer()->GraphicsLayerBacking()->CcLayer(); { @@ -94,20 +93,20 @@ target->setAttribute(html_names::kStyleAttr, "height: 200px"); UpdateAllLifecyclePhasesForTest(); - ASSERT_TRUE(cc_layer->debug_info()); - EXPECT_EQ(1u, cc_layer->debug_info()->invalidations.size()); + ASSERT_TRUE(cc_layer.debug_info()); + EXPECT_EQ(1u, cc_layer.debug_info()->invalidations.size()); target->setAttribute(html_names::kStyleAttr, "height: 200px; width: 200px"); UpdateAllLifecyclePhasesForTest(); - ASSERT_TRUE(cc_layer->debug_info()); - EXPECT_EQ(2u, cc_layer->debug_info()->invalidations.size()); + ASSERT_TRUE(cc_layer.debug_info()); + EXPECT_EQ(2u, cc_layer.debug_info()->invalidations.size()); } target->setAttribute(html_names::kStyleAttr, "height: 300px; width: 300px"); UpdateAllLifecyclePhasesForTest(); - ASSERT_TRUE(cc_layer->debug_info()); + ASSERT_TRUE(cc_layer.debug_info()); // No new invalidations tracked. - EXPECT_EQ(2u, cc_layer->debug_info()->invalidations.size()); + EXPECT_EQ(2u, cc_layer.debug_info()->invalidations.size()); } TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationExpand) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 88eafe7..f3bd433 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -284,7 +284,7 @@ cc::Layer* PaintLayerScrollableArea::LayerForScrolling() const { if (auto* graphics_layer = GraphicsLayerForScrolling()) - return graphics_layer->CcLayer(); + return &graphics_layer->CcLayer(); return nullptr; } @@ -302,7 +302,7 @@ cc::Layer* PaintLayerScrollableArea::LayerForScrollCorner() const { if (auto* graphics_layer = GraphicsLayerForScrollCorner()) - return graphics_layer->CcLayer(); + return &graphics_layer->CcLayer(); return nullptr; }
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc index 56299a0f..b381726 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -188,6 +188,10 @@ void FakeLocalFrameHost::DidChangeOpener( const base::Optional<base::UnguessableToken>& opener_frame) {} +void FakeLocalFrameHost::DidChangeCSPAttribute( + const base::UnguessableToken& child_frame_token, + network::mojom::blink::ContentSecurityPolicyPtr) {} + void FakeLocalFrameHost::DidChangeFramePolicy( const base::UnguessableToken& child_frame_token, const FramePolicy& frame_policy) {}
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/third_party/blink/renderer/core/testing/fake_local_frame_host.h index b174b9e1..a34a906c 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.h +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -118,6 +118,9 @@ mojom::blink::FrameOwnerPropertiesPtr frame_owner_properties) override; void DidChangeOpener( const base::Optional<base::UnguessableToken>& opener_frame) override; + void DidChangeCSPAttribute(const base::UnguessableToken& child_frame_token, + network::mojom::blink::ContentSecurityPolicyPtr + parsed_csp_attribute) override; void DidChangeFramePolicy(const base::UnguessableToken& child_frame_token, const FramePolicy& frame_policy) override; void CapturePaintPreviewOfSubframe(
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.cc b/third_party/blink/renderer/modules/native_io/native_io_file.cc index c26d6076..5943495 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_file.cc +++ b/third_party/blink/renderer/modules/native_io/native_io_file.cc
@@ -231,6 +231,38 @@ return resolver->Promise(); } +ScriptPromise NativeIOFile::flush(ScriptState* script_state, + ExceptionState& exception_state) { + // This implementation of flush attempts to physically store the data it has + // written on disk. This behaviour might change in the future in order to + // support more performant but less reliable persistency guarantees. + if (io_pending_) { + exception_state.ThrowDOMException( + DOMExceptionCode::kInvalidStateError, + "Another I/O operation is in progress on the same file"); + return ScriptPromise(); + } + if (closed_) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "The file was already closed"); + return ScriptPromise(); + } + io_pending_ = true; + + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); + // CrossThreadUnretained() is safe here because the NativeIOFile::FileState + // instance is owned by this NativeIOFile, which is also passed to the task + // via WrapCrossThreadPersistent. Therefore, the FileState instance is + // guaranteed to remain alive during the task's execution. + worker_pool::PostTask( + FROM_HERE, {base::MayBlock(), base::ThreadPool()}, + CrossThreadBindOnce(&DoFlush, WrapCrossThreadPersistent(this), + WrapCrossThreadPersistent(resolver), + CrossThreadUnretained(file_state_.get()), + resolver_task_runner_)); + return resolver->Promise(); +} + void NativeIOFile::Trace(Visitor* visitor) const { ScriptWrappable::Trace(visitor); visitor->Trace(queued_close_resolver_); @@ -462,6 +494,49 @@ resolver->Resolve(written_bytes); } +// static +void NativeIOFile::DoFlush( + CrossThreadPersistent<NativeIOFile> native_io_file, + CrossThreadPersistent<ScriptPromiseResolver> resolver, + NativeIOFile::FileState* file_state, + scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) { + DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread"; + bool success = false; + { + WTF::MutexLocker mutex_locker(file_state->mutex); + DCHECK(file_state->file.IsValid()) + << "file I/O operation queued after file closed"; + success = file_state->file.Flush(); + } + + PostCrossThreadTask( + *resolver_task_runner, FROM_HERE, + CrossThreadBindOnce(&NativeIOFile::DidFlush, std::move(native_io_file), + std::move(resolver), success)); +} + +void NativeIOFile::DidFlush( + CrossThreadPersistent<ScriptPromiseResolver> resolver, + bool success) { + ScriptState* script_state = resolver->GetScriptState(); + if (!script_state->ContextIsValid()) + return; + ScriptState::Scope scope(script_state); + + DCHECK(io_pending_) << "I/O operation performed without io_pending_ set"; + io_pending_ = false; + + DispatchQueuedClose(); + + if (!success) { + resolver->Reject(V8ThrowDOMException::CreateOrEmpty( + script_state->GetIsolate(), DOMExceptionCode::kOperationError, + "flush() failed")); + return; + } + resolver->Resolve(); +} + void NativeIOFile::CloseBackingFile() { closed_ = true; file_state_->mutex.lock();
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.h b/third_party/blink/renderer/modules/native_io/native_io_file.h index d91a8aa..7a47e2a 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_file.h +++ b/third_party/blink/renderer/modules/native_io/native_io_file.h
@@ -56,6 +56,7 @@ MaybeShared<DOMArrayBufferView> buffer, uint64_t file_offset, ExceptionState&); + ScriptPromise flush(ScriptState*, ExceptionState&); // GarbageCollected void Trace(Visitor* visitor) const override; @@ -124,6 +125,16 @@ int written_bytes, base::File::Error write_error); + // Performs the file I/O part of flush(). + static void DoFlush( + CrossThreadPersistent<NativeIOFile> native_io_file, + CrossThreadPersistent<ScriptPromiseResolver> resolver, + NativeIOFile::FileState* file_state, + scoped_refptr<base::SequencedTaskRunner> file_task_runner); + // Performs the post file-I/O part of flush(), on the main thread. + void DidFlush(CrossThreadPersistent<ScriptPromiseResolver> resolver, + bool success); + // Kicks off closing the file from the main thread. void CloseBackingFile();
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.idl b/third_party/blink/renderer/modules/native_io/native_io_file.idl index 65594a2..38dba604 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_file.idl +++ b/third_party/blink/renderer/modules/native_io/native_io_file.idl
@@ -23,4 +23,7 @@ CallWith=ScriptState, RaisesException ] Promise<unsigned long long> write([AllowShared] ArrayBufferView buffer, unsigned long long file_offset); + [ + CallWith=ScriptState, RaisesException + ] Promise<void> flush(); };
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_sync.cc b/third_party/blink/renderer/modules/native_io/native_io_file_sync.cc index 6cf4151..f06f36a8 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_file_sync.cc +++ b/third_party/blink/renderer/modules/native_io/native_io_file_sync.cc
@@ -105,6 +105,22 @@ return base::as_unsigned(written_bytes); } +void NativeIOFileSync::flush(ExceptionState& exception_state) { + // This implementation of flush attempts to physically store the data it has + // written on disk. This behaviour might change in the future. + if (!backing_file_.IsValid()) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "The file was already closed"); + return; + } + bool success = backing_file_.Flush(); + if (!success) { + exception_state.ThrowDOMException(DOMExceptionCode::kOperationError, + "flush() failed"); + } + return; +} + void NativeIOFileSync::Trace(Visitor* visitor) const { visitor->Trace(backend_file_); ScriptWrappable::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_sync.h b/third_party/blink/renderer/modules/native_io/native_io_file_sync.h index d9f02f2..8f4567f 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_file_sync.h +++ b/third_party/blink/renderer/modules/native_io/native_io_file_sync.h
@@ -45,6 +45,7 @@ uint64_t write(MaybeShared<DOMArrayBufferView> buffer, uint64_t file_offset, ExceptionState&); + void flush(ExceptionState&); // GarbageCollected void Trace(Visitor* visitor) const override;
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_sync.idl b/third_party/blink/renderer/modules/native_io/native_io_file_sync.idl index 4be4baf..f4378bc7 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_file_sync.idl +++ b/third_party/blink/renderer/modules/native_io/native_io_file_sync.idl
@@ -23,4 +23,7 @@ RaisesException ] unsigned long long write([AllowShared] ArrayBufferView buffer, unsigned long long file_offset); + [ + RaisesException + ] void flush(); };
diff --git a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc index d5eb163..361d113 100644 --- a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc +++ b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc
@@ -87,9 +87,7 @@ static bool VerifyCustomHandlerURL(const LocalDOMWindow& window, const String& user_url, ExceptionState& exception_state) { - String new_url = user_url; - new_url.Remove(user_url.Find(kToken), base::size(kToken) - 1); - KURL full_url = window.CompleteURL(new_url); + KURL full_url = window.CompleteURL(user_url); KURL base_url = window.BaseURL(); String error_message;
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm index cf25ba02..aafddac 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm +++ b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac.mm
@@ -32,6 +32,8 @@ #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> #import <math.h> + +#include "base/bit_cast.h" #include "base/mac/foundation_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" @@ -59,16 +61,15 @@ 0x3fe3d70a40000000, // NSFontWeightBlack }; if (font_weight <= 50 || font_weight >= 950) - return ns_font_weights[3]; + return bit_cast<CGFloat>(ns_font_weights[3]); size_t select_weight = roundf(font_weight / 100) - 1; DCHECK_GE(select_weight, 0ul); DCHECK_LE(select_weight, base::size(ns_font_weights)); - CGFloat* return_weight = - reinterpret_cast<CGFloat*>(&ns_font_weights[select_weight]); - return *return_weight; + return bit_cast<CGFloat>(ns_font_weights[select_weight]); } -} + +} // namespace namespace blink {
diff --git a/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc b/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc index 2adb8011..a356a43 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.cc
@@ -25,48 +25,48 @@ } // namespace // Create a JSON version of the specified |layer|. -std::unique_ptr<JSONObject> CCLayerAsJSON(const cc::Layer* layer, +std::unique_ptr<JSONObject> CCLayerAsJSON(const cc::Layer& layer, LayerTreeFlags flags) { auto json = std::make_unique<JSONObject>(); if (flags & kLayerTreeIncludesDebugInfo) { - json->SetString("this", PointerAsString(layer)); - json->SetInteger("ccLayerId", layer->id()); + json->SetString("this", PointerAsString(&layer)); + json->SetInteger("ccLayerId", layer.id()); } - json->SetString("name", String(layer->DebugName().c_str())); + json->SetString("name", String(layer.DebugName().c_str())); - if (layer->offset_to_transform_parent() != gfx::Vector2dF()) { + if (layer.offset_to_transform_parent() != gfx::Vector2dF()) { json->SetArray( "position", - PointAsJSONArray(FloatPoint(layer->offset_to_transform_parent()))); + PointAsJSONArray(FloatPoint(layer.offset_to_transform_parent()))); } // This is testing against gfx::Size(), *not* whether the size is empty. - if (layer->bounds() != gfx::Size()) - json->SetArray("bounds", SizeAsJSONArray(IntSize(layer->bounds()))); + if (layer.bounds() != gfx::Size()) + json->SetArray("bounds", SizeAsJSONArray(IntSize(layer.bounds()))); - if (layer->contents_opaque()) + if (layer.contents_opaque()) json->SetBoolean("contentsOpaque", true); - else if (layer->contents_opaque_for_text()) + else if (layer.contents_opaque_for_text()) json->SetBoolean("contentsOpaqueForText", true); - if (!layer->DrawsContent()) + if (!layer.DrawsContent()) json->SetBoolean("drawsContent", false); - if (layer->should_check_backface_visibility()) + if (layer.should_check_backface_visibility()) json->SetString("backfaceVisibility", "hidden"); - if (Color(layer->background_color()).Alpha()) { + if (Color(layer.background_color()).Alpha()) { json->SetString("backgroundColor", - Color(layer->background_color()).NameForLayoutTreeAsText()); + Color(layer.background_color()).NameForLayoutTreeAsText()); } if (flags & (kLayerTreeIncludesDebugInfo | kLayerTreeIncludesCompositingReasons)) { - if (layer->debug_info()) { + if (layer.debug_info()) { auto compositing_reasons_json = std::make_unique<JSONArray>(); - for (const char* name : layer->debug_info()->compositing_reasons) + for (const char* name : layer.debug_info()->compositing_reasons) compositing_reasons_json->PushString(name); json->SetArray("compositingReasons", std::move(compositing_reasons_json)); } @@ -138,7 +138,7 @@ layer.DebugName() == "Scrolling Contents Layer")) return; - auto layer_json = CCLayerAsJSON(&layer, flags_); + auto layer_json = CCLayerAsJSON(layer, flags_); if (json_client) { json_client->AppendAdditionalInfoAsJSON(flags_, layer, *(layer_json.get())); }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h b/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h index 4be8eed2..aaa88b5d 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h +++ b/third_party/blink/renderer/platform/graphics/compositing/layers_as_json.h
@@ -67,7 +67,7 @@ }; PLATFORM_EXPORT std::unique_ptr<JSONObject> CCLayerAsJSON( - const cc::Layer* layer, + const cc::Layer& layer, LayerTreeFlags flags); } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index 59c328ef..562a1c8d 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -118,7 +118,7 @@ if (display_item.IsGraphicsLayerWrapper()) { const GraphicsLayerDisplayItem& graphics_layer_display_item = static_cast<const GraphicsLayerDisplayItem&>(display_item); - layer = graphics_layer_display_item.GetGraphicsLayer().CcLayer(); + layer = &graphics_layer_display_item.GetGraphicsLayer().CcLayer(); json_client = &graphics_layer_display_item.GetGraphicsLayer(); } else { DCHECK(display_item.IsForeignLayer()); @@ -176,7 +176,7 @@ DCHECK(RuntimeEnabledFeatures::CompositeSVGEnabled()); return nullptr; } - layer = graphics_layer.CcLayer(); + layer = &graphics_layer.CcLayer(); layer_offset = FloatPoint(graphics_layer_display_item.GetGraphicsLayer() .GetOffsetFromTransformNode()); } else { @@ -363,7 +363,7 @@ } void PaintArtifactCompositor::UpdateTouchActionRects( - cc::Layer* layer, + cc::Layer& layer, const gfx::Vector2dF& layer_offset, const PropertyTreeState& layer_state, const PaintChunkSubset& paint_chunks) { @@ -386,11 +386,11 @@ (gfx::Rect)EnclosingIntRect(rect.Rect())); } } - layer->SetTouchActionRegion(std::move(touch_action_in_layer_space)); + layer.SetTouchActionRegion(std::move(touch_action_in_layer_space)); } void PaintArtifactCompositor::UpdateNonFastScrollableRegions( - cc::Layer* layer, + cc::Layer& layer, const gfx::Vector2dF& layer_offset, const PropertyTreeState& layer_state, const PaintChunkSubset& paint_chunks, @@ -410,7 +410,7 @@ if (const auto* scroll_translation = hit_test_data->scroll_translation) { const auto& scroll_node = *scroll_translation->ScrollNode(); auto scroll_element_id = scroll_node.GetCompositorElementId(); - if (layer->element_id() == scroll_element_id) + if (layer.element_id() == scroll_element_id) continue; // Ensure the cc scroll node to prepare for possible descendant nodes // referenced by later composited layers. This can't be done by ensuring @@ -436,7 +436,7 @@ non_fast_scrollable_regions_in_layer_space.Union( EnclosingIntRect(rect.Rect())); } - layer->SetNonFastScrollableRegion(non_fast_scrollable_regions_in_layer_space); + layer.SetNonFastScrollableRegion(non_fast_scrollable_regions_in_layer_space); } bool PaintArtifactCompositor::HasComposited( @@ -1310,10 +1310,10 @@ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { auto paint_chunks = paint_artifact->GetPaintChunkSubset( pending_layer.paint_chunk_indices); - UpdateTouchActionRects(layer.get(), layer->offset_to_transform_parent(), + UpdateTouchActionRects(*layer, layer->offset_to_transform_parent(), property_state, paint_chunks); UpdateNonFastScrollableRegions( - layer.get(), layer->offset_to_transform_parent(), property_state, + *layer, layer->offset_to_transform_parent(), property_state, paint_chunks, &property_tree_manager); }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h index 2b5fb9a..cd528b3 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -184,7 +184,7 @@ // Update the cc::Layer's touch action region from the touch action rects of // the paint chunks. - static void UpdateTouchActionRects(cc::Layer*, + static void UpdateTouchActionRects(cc::Layer&, const gfx::Vector2dF& layer_offset, const PropertyTreeState& layer_state, const PaintChunkSubset& paint_chunks); @@ -192,7 +192,7 @@ // Update the cc::Layer's non-fast scrollable region from the non-fast regions // in the paint chunks. static void UpdateNonFastScrollableRegions( - cc::Layer*, + cc::Layer&, const gfx::Vector2dF& layer_offset, const PropertyTreeState& layer_state, const PaintChunkSubset& paint_chunks,
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc index 9c3a4814..d5ac3c1 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -87,14 +87,14 @@ client.VerifyNotPainting(); #endif layer_ = cc::PictureLayer::Create(this); - CcLayer()->SetIsDrawable(draws_content_ && contents_visible_); - CcLayer()->SetHitTestable(hit_testable_); + layer_->SetIsDrawable(draws_content_ && contents_visible_); + layer_->SetHitTestable(hit_testable_); UpdateTrackingRasterInvalidations(); } GraphicsLayer::~GraphicsLayer() { - CcLayer()->ClearClient(); + CcLayer().ClearClient(); contents_layer_ = nullptr; #if DCHECK_IS_ON() @@ -313,7 +313,7 @@ GetPaintController().AppendDebugDrawingAfterCommit(std::move(record), layer_state_->state); // Ensure the compositor will raster the under-invalidation overlay. - CcLayer()->SetNeedsDisplay(); + CcLayer().SetNeedsDisplay(); } } } @@ -325,7 +325,7 @@ void GraphicsLayer::UpdateSafeOpaqueBackgroundColor() { if (!DrawsContent()) return; - CcLayer()->SetSafeOpaqueBackgroundColor( + CcLayer().SetSafeOpaqueBackgroundColor( GetPaintController().GetPaintArtifact().SafeOpaqueBackgroundColor( GetPaintController().GetPaintArtifact().PaintChunks())); } @@ -403,12 +403,12 @@ // shouldn't receive the drawsContent flag, so it is only given // contentsVisible. - CcLayer()->SetIsDrawable(draws_content_ && contents_visible_); + CcLayer().SetIsDrawable(draws_content_ && contents_visible_); if (contents_layer_) contents_layer_->SetIsDrawable(contents_visible_); if (draws_content_) - CcLayer()->SetNeedsDisplay(); + CcLayer().SetNeedsDisplay(); } void GraphicsLayer::UpdateContentsLayerBounds() { @@ -504,18 +504,18 @@ } const gfx::Size& GraphicsLayer::Size() const { - return CcLayer()->bounds(); + return CcLayer().bounds(); } void GraphicsLayer::SetSize(const gfx::Size& size) { DCHECK(size.width() >= 0 && size.height() >= 0); - if (size == CcLayer()->bounds()) + if (size == CcLayer().bounds()) return; Invalidate(PaintInvalidationReason::kIncremental); // as DisplayItemClient. - CcLayer()->SetBounds(size); + CcLayer().SetBounds(size); // Note that we don't resize m_contentsLayer. It's up the caller to do that. } @@ -547,32 +547,32 @@ } RGBA32 GraphicsLayer::BackgroundColor() const { - return CcLayer()->background_color(); + return CcLayer().background_color(); } void GraphicsLayer::SetBackgroundColor(RGBA32 color) { - CcLayer()->SetBackgroundColor(color); + CcLayer().SetBackgroundColor(color); } bool GraphicsLayer::ContentsOpaque() const { - return CcLayer()->contents_opaque(); + return CcLayer().contents_opaque(); } void GraphicsLayer::SetContentsOpaque(bool opaque) { - CcLayer()->SetContentsOpaque(opaque); + CcLayer().SetContentsOpaque(opaque); if (contents_layer_ && !prevent_contents_opaque_changes_) contents_layer_->SetContentsOpaque(opaque); } void GraphicsLayer::SetContentsOpaqueForText(bool opaque) { - CcLayer()->SetContentsOpaqueForText(opaque); + CcLayer().SetContentsOpaqueForText(opaque); } void GraphicsLayer::SetHitTestable(bool should_hit_test) { if (hit_testable_ == should_hit_test) return; hit_testable_ = should_hit_test; - CcLayer()->SetHitTestable(should_hit_test); + CcLayer().SetHitTestable(should_hit_test); } void GraphicsLayer::SetContentsNeedsDisplay() { @@ -587,7 +587,7 @@ if (!PaintsContentOrHitTest()) return; - CcLayer()->SetNeedsDisplay(); + CcLayer().SetNeedsDisplay(); // Invalidate the paint controller if it exists, but don't bother creating one // if not. @@ -603,7 +603,7 @@ void GraphicsLayer::SetNeedsDisplayInRect(const IntRect& rect) { DCHECK(PaintsContentOrHitTest()); - CcLayer()->SetNeedsDisplayRect(rect); + CcLayer().SetNeedsDisplayRect(rect); } void GraphicsLayer::SetContentsRect(const IntRect& rect) { @@ -615,10 +615,6 @@ client_.GraphicsLayersDidChange(); } -cc::PictureLayer* GraphicsLayer::CcLayer() const { - return layer_.get(); -} - void GraphicsLayer::SetPaintingPhase(GraphicsLayerPaintingPhase phase) { if (painting_phase_ == phase) return; @@ -634,8 +630,7 @@ } void GraphicsLayer::SetElementId(const CompositorElementId& id) { - if (cc::Layer* layer = CcLayer()) - layer->SetElementId(id); + CcLayer().SetElementId(id); } sk_sp<PaintRecord> GraphicsLayer::CapturePaintRecord() const { @@ -674,8 +669,7 @@ std::make_unique<LayerState>(LayerState{layer_state, layer_offset}); } - if (auto* layer = CcLayer()) - layer->SetSubtreePropertyChanged(); + CcLayer().SetSubtreePropertyChanged(); client_.GraphicsLayersDidChange(); }
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h index b039fc05..6725517 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.h +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -173,7 +173,7 @@ const IntRect& ContentsRect() const { return contents_rect_; } // For hosting this GraphicsLayer in a native layer hierarchy. - cc::PictureLayer* CcLayer() const; + cc::PictureLayer& CcLayer() const { return *layer_; } void UpdateTrackingRasterInvalidations(); void ResetTrackedRasterInvalidations();
diff --git a/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc index 9f5e9538..eb71a06 100644 --- a/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc +++ b/third_party/blink/renderer/platform/graphics/paint/graphics_layer_display_item.cc
@@ -39,7 +39,7 @@ #if DCHECK_IS_ON() void GraphicsLayerDisplayItem::PropertiesAsJSON(JSONObject& json) const { DisplayItem::PropertiesAsJSON(json); - json.SetInteger("layer", graphics_layer_.CcLayer()->id()); + json.SetInteger("layer", graphics_layer_.CcLayer().id()); FloatPoint offset(graphics_layer_.GetOffsetFromTransformNode()); json.SetDouble("offset_x", offset.X()); json.SetDouble("offset_y", offset.Y()); @@ -53,7 +53,7 @@ // extraneous layers are still attached. In future we will disable all // those layer hierarchy code so we won't need this line. DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); - graphics_layer.CcLayer()->RemoveAllChildren(); + graphics_layer.CcLayer().RemoveAllChildren(); PaintController& paint_controller = context.GetPaintController();
diff --git a/third_party/blink/renderer/platform/network/http_parsers.cc b/third_party/blink/renderer/platform/network/http_parsers.cc index d3235e2..af9d9ff 100644 --- a/third_party/blink/renderer/platform/network/http_parsers.cc +++ b/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -102,25 +102,34 @@ String::FromUTF8(header->header_value), header->type, header->source); } +WTF::HashMap<blink::CSPDirectiveName, blink::CSPSourceListPtr> ConvertToBlink( + base::flat_map<CSPDirectiveName, CSPSourceListPtr> directives) { + WTF::HashMap<blink::CSPDirectiveName, blink::CSPSourceListPtr> out; + + for (auto& list : directives) { + out.insert(ConvertToBlink(list.first), + ConvertToBlink(std::move(list.second))); + } + + return out; +} + +WTF::Vector<WTF::String> ConvertToBlink(std::vector<std::string> in) { + WTF::Vector<WTF::String> out; + for (auto& el : in) + out.push_back(String::FromUTF8(el)); + return out; +} + blink::ContentSecurityPolicyPtr ConvertToBlink( ContentSecurityPolicyPtr policy_in) { - auto policy = blink::ContentSecurityPolicy::New(); - - policy->header = ConvertToBlink(std::move(policy_in->header)); - policy->use_reporting_api = policy_in->use_reporting_api; - - for (auto& list : policy_in->directives) { - policy->directives.insert(ConvertToBlink(list.first), - ConvertToBlink(std::move(list.second))); - } - policy->upgrade_insecure_requests = policy_in->upgrade_insecure_requests; - policy->sandbox = policy_in->sandbox; - policy->treat_as_public_address = policy_in->treat_as_public_address; - - for (auto& endpoint : policy_in->report_endpoints) - policy->report_endpoints.push_back(String::FromUTF8(endpoint)); - - return policy; + return blink::ContentSecurityPolicy::New( + ConvertToBlink(std::move(policy_in->directives)), + policy_in->upgrade_insecure_requests, policy_in->treat_as_public_address, + policy_in->sandbox, ConvertToBlink(std::move(policy_in->header)), + policy_in->use_reporting_api, + ConvertToBlink(std::move(policy_in->report_endpoints)), + ConvertToBlink(std::move(policy_in->parsing_errors))); } WTF::Vector<blink::ContentSecurityPolicyPtr> ConvertToBlink(
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc index 5460712..5b01605 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -308,28 +308,6 @@ return webrtc::kVideoCodecGeneric; } -// Populates struct webrtc::RTPFragmentationHeader for H264 codec. -// Each entry specifies the offset and length (excluding start code) of a NALU. -// Returns true if successful. -bool GetRTPFragmentationHeaderH264(webrtc::RTPFragmentationHeader* header, - const uint8_t* data, - uint32_t length) { - std::vector<media::H264NALU> nalu_vector; - if (!media::H264Parser::ParseNALUs(data, length, &nalu_vector)) { - // H264Parser::ParseNALUs() has logged the errors already. - return false; - } - - // TODO(zijiehe): Find a right place to share the following logic between - // //content and //remoting. - header->VerifyAndAllocateFragmentationHeader(nalu_vector.size()); - for (size_t i = 0; i < nalu_vector.size(); ++i) { - header->fragmentationOffset[i] = nalu_vector[i].data - data; - header->fragmentationLength[i] = static_cast<size_t>(nalu_vector[i].size); - } - return true; -} - void RecordInitEncodeUMA(int32_t init_retval, media::VideoCodecProfile profile) { UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", @@ -1292,31 +1270,7 @@ if (!encoded_image_callback_) return; - webrtc::RTPFragmentationHeader header; - memset(&header, 0, sizeof(header)); - switch (video_codec_type_) { - case webrtc::kVideoCodecVP8: - case webrtc::kVideoCodecVP9: - // Generate a header describing a single fragment. - header.VerifyAndAllocateFragmentationHeader(1); - header.fragmentationOffset[0] = 0; - header.fragmentationLength[0] = image.size(); - break; - case webrtc::kVideoCodecH264: - if (!GetRTPFragmentationHeaderH264(&header, image.data(), image.size())) { - DLOG(ERROR) << "Failed to get RTP fragmentation header for H264"; - NotifyError( - (media::VideoEncodeAccelerator::Error)WEBRTC_VIDEO_CODEC_ERROR); - return; - } - break; - default: - NOTREACHED() << "Invalid video codec type"; - return; - } - - const auto result = - encoded_image_callback_->OnEncodedImage(image, &info, &header); + const auto result = encoded_image_callback_->OnEncodedImage(image, &info); if (result.error != webrtc::EncodedImageCallback::Result::OK) { DVLOG(2) << "ReturnEncodedImage(): webrtc::EncodedImageCallback::Result.error = "
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc index 052b6b3..edeaaed4 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc
@@ -42,18 +42,15 @@ public: using EncodedCallback = base::OnceCallback<void( const webrtc::EncodedImage& encoded_image, - const webrtc::CodecSpecificInfo* codec_specific_info, - const webrtc::RTPFragmentationHeader* fragmentation)>; + const webrtc::CodecSpecificInfo* codec_specific_info)>; EncodedImageCallbackWrapper(EncodedCallback encoded_callback) : encoded_callback_(std::move(encoded_callback)) {} Result OnEncodedImage( const webrtc::EncodedImage& encoded_image, - const webrtc::CodecSpecificInfo* codec_specific_info, - const webrtc::RTPFragmentationHeader* fragmentation) override { - std::move(encoded_callback_) - .Run(encoded_image, codec_specific_info, fragmentation); + const webrtc::CodecSpecificInfo* codec_specific_info) override { + std::move(encoded_callback_).Run(encoded_image, codec_specific_info); return Result(Result::OK); } @@ -261,8 +258,7 @@ void VerifyTimestamp(uint32_t rtp_timestamp, int64_t capture_time_ms, const webrtc::EncodedImage& encoded_image, - const webrtc::CodecSpecificInfo* codec_specific_info, - const webrtc::RTPFragmentationHeader* fragmentation) { + const webrtc::CodecSpecificInfo* codec_specific_info) { DVLOG(3) << __func__; EXPECT_EQ(rtp_timestamp, encoded_image.Timestamp()); EXPECT_EQ(capture_time_ms, encoded_image.capture_time_ms_);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index b0406abf..ac27142 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -1479,28 +1479,6 @@ NOTREACHED(); } - if (main_thread_only().prioritize_compositing_after_input) { - new_policy.compositor_priority() = - base::sequence_manager::TaskQueue::QueuePriority::kVeryHighPriority; - } else if (scheduling_settings_ - .prioritize_compositing_and_loading_during_early_loading && - current_use_case() == UseCase::kEarlyLoading) { - new_policy.compositor_priority() = - base::sequence_manager::TaskQueue::QueuePriority::kHighPriority; - new_policy.should_prioritize_loading_with_compositing() = true; - } else { - base::Optional<TaskQueue::QueuePriority> computed_compositor_priority = - ComputeCompositorPriorityFromUseCase(); - if (computed_compositor_priority) { - new_policy.compositor_priority() = computed_compositor_priority.value(); - } else if (main_thread_only() - .compositor_priority_experiments.IsExperimentActive()) { - new_policy.compositor_priority() = - main_thread_only() - .compositor_priority_experiments.GetCompositorPriority(); - } - } - // TODO(skyostil): Add an idle state for foreground tabs too. if (main_thread_only().renderer_hidden) new_policy.rail_mode() = RAILMode::kIdle; @@ -1520,8 +1498,16 @@ new_policy.timer_queue_policy().use_virtual_time = true; } + if (scheduling_settings_ + .prioritize_compositing_and_loading_during_early_loading && + current_use_case() == UseCase::kEarlyLoading) { + new_policy.should_prioritize_loading_with_compositing() = true; + } + new_policy.should_disable_throttling() = main_thread_only().use_virtual_time; + new_policy.compositor_priority() = ComputeCompositorPriority(); + new_policy.find_in_page_priority() = find_in_page_budget_pool_controller_->CurrentTaskPriority(); @@ -2725,13 +2711,41 @@ } main_thread_only().prioritize_compositing_after_input = prioritize_compositing_after_input; - UpdatePolicy(); + UpdateCompositorPolicy(); } void MainThreadSchedulerImpl:: OnCompositorPriorityExperimentUpdateCompositorPriority() { - if (!ComputeCompositorPriorityFromUseCase()) - UpdatePolicy(); + UpdateCompositorPolicy(); +} + +TaskQueue::QueuePriority MainThreadSchedulerImpl::ComputeCompositorPriority() + const { + if (main_thread_only().prioritize_compositing_after_input) { + return TaskQueue::QueuePriority::kVeryHighPriority; + } else if (scheduling_settings_ + .prioritize_compositing_and_loading_during_early_loading && + current_use_case() == UseCase::kEarlyLoading) { + return TaskQueue::QueuePriority::kHighPriority; + } else { + base::Optional<TaskQueue::QueuePriority> computed_compositor_priority = + ComputeCompositorPriorityFromUseCase(); + if (computed_compositor_priority) { + return computed_compositor_priority.value(); + } else if (main_thread_only() + .compositor_priority_experiments.IsExperimentActive()) { + return main_thread_only() + .compositor_priority_experiments.GetCompositorPriority(); + } + } + return TaskQueue::QueuePriority::kNormalPriority; +} + +void MainThreadSchedulerImpl::UpdateCompositorPolicy() { + main_thread_only().current_policy.compositor_priority() = + ComputeCompositorPriority(); + CompositorTaskQueue()->SetQueuePriority( + ComputePriority(CompositorTaskQueue().get())); } base::Optional<TaskQueue::QueuePriority>
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h index fbe13ad2..01fec36 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -772,6 +772,14 @@ // trigger a priority update. bool ShouldUpdateTaskQueuePriorities(Policy new_policy) const; + // Computes compositor priority based on various experiments and + // the use case. Defaults to kNormalPriority. + TaskQueue::QueuePriority ComputeCompositorPriority() const; + + // Used to update the compositor policy on the main thread when there is a + // change in the compositor priority. + void UpdateCompositorPolicy(); + // Computes the priority for compositing based on the current use case. // Returns nullopt if the use case does not need to set the priority. base::Optional<TaskQueue::QueuePriority>
diff --git a/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc b/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc index 09f8a12c..06c5baf 100644 --- a/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc +++ b/third_party/blink/renderer/platform/testing/viewport_layers_setup.cc
@@ -23,9 +23,9 @@ graphics_layer_->SetDrawsContent(true); graphics_layer_->SetHitTestable(true); root_layer_->AddChild(graphics_layer_.get()); - graphics_layer_->CcLayer()->SetScrollable(root_layer_->CcLayer()->bounds()); + graphics_layer_->CcLayer().SetScrollable(root_layer_->CcLayer().bounds()); layer_tree_ = std::make_unique<LayerTreeHostEmbedder>(); - layer_tree_->layer_tree_host()->SetRootLayer(root_layer_->CcLayer()); + layer_tree_->layer_tree_host()->SetRootLayer(&root_layer_->CcLayer()); layer_tree_->layer_tree_host()->SetViewportRectAndScale( gfx::Rect(1, 1), /*device_scale_factor=*/1.f,
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index f092222..211db6e 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2727,9 +2727,6 @@ crbug.com/626703 [ Linux ] external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-5.html [ Failure ] crbug.com/626703 [ Mac ] external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-5.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-5.html [ Failure ] -crbug.com/626703 [ Linux ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-5.html [ Failure ] -crbug.com/626703 [ Mac ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-5.html [ Failure ] -crbug.com/626703 [ Win ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-5.html [ Failure ] crbug.com/626703 [ Linux ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-1.html [ Failure ] crbug.com/626703 [ Mac ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-1.html [ Failure ] crbug.com/626703 [ Win ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-1.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-createImageBitmap-e_srgb.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-createImageBitmap-e_srgb.html index 4bb4475..fd9a5e96d 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-createImageBitmap-e_srgb.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-createImageBitmap-e_srgb.html
@@ -285,31 +285,33 @@ // HTMLImageElement - Opaque sRGB // File formats: AVIF, Bitmap, GIF, ICO, JPEG, PNG, WEBP -promise_test(function() { - return Promise.all(['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].map( - ext => new Promise((resolve,reject) => { +['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].forEach(ext => { + promise_test(function() { + return new Promise((resolve,reject) => { var image = new Image(); image.onload = function() { resolve(image); } image.src = 'resources/pattern-srgb.' + ext; - }).then(testImageBitmapOpaque))); -}, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLImageElement (AVIF, \ -BMP, GIF, ICO, JPG, PNG, WEBP) with resize.'); + }).then(testImageBitmapOpaque); + }, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLImageElement (' + ext + + ') with resize.'); +}); // HTMLImageElement - Transparent sRGB // File formats: AVIF, Bitmap, ICO, PNG, WEBP -promise_test(function() { - return Promise.all(['avif', 'bmp', 'ico', 'png', 'webp'].map( - ext => new Promise((resolve,reject) => { +['avif', 'bmp', 'ico', 'png', 'webp'].forEach(ext => { + promise_test(function() { + return new Promise((resolve,reject) => { var image = new Image(); image.onload = function() { resolve(image); } image.src = 'resources/pattern-srgb-transparent.' + ext; - }).then(testImageBitmapFromTransparentImage))); -}, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLImageElement \ -(AVIF, BMP, ICO, PNG, WEBP) with resize.'); + }).then(testImageBitmapFromTransparentImage); + }, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLImageElement (' + ext + + ') with resize.'); +}); //////////////////////////////////////////////////////////////////////////////// @@ -370,9 +372,9 @@ // Blob from file - Opaque sRGB // File formats: AVIF, Bitmap, GIF, ICO, JPEG, PNG, WEBP -promise_test(function() { - return Promise.all(['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].map( - ext => new Promise((resolve, reject) => { +['avif', 'bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].forEach(ext => { + promise_test(function() { + return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.open("GET", 'resources/pattern-srgb.' + ext); xhr.responseType = 'blob'; @@ -380,15 +382,15 @@ xhr.onload = function() { resolve(xhr.response); }; - }).then(testImageBitmapOpaque))); -}, 'createImageBitmap in e-sRGB from an opaque sRGB Blob (AVIF, BMP, GIF, ICO, \ -JPG, PNG, WEBP) with resize.'); + }).then(testImageBitmapOpaque); + }, 'createImageBitmap in e-sRGB from an opaque sRGB Blob (' + ext + ') with resize.'); +}); // Blob form file - Transparent sRGB // File formats: AVIF, Bitmap, ICO, PNG, WEBP -promise_test(function() { - return Promise.all(['avif', 'bmp', 'ico', 'png', 'webp'].map( - ext => new Promise((resolve, reject) => { +['avif', 'bmp', 'ico', 'png', 'webp'].forEach(ext => { + promise_test(function() { + return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest(); xhr.open("GET", 'resources/pattern-srgb-transparent.' + ext); xhr.responseType = 'blob'; @@ -396,9 +398,9 @@ xhr.onload = function() { resolve(xhr.response); }; - }).then(testImageBitmapFromTransparentImage))); -}, 'createImageBitmap in e-sRGB from a transparent sRGB Blob (AVIF, BMP, ICO, \ -PNG, WEBP) with resize.'); + }).then(testImageBitmapFromTransparentImage); + }, 'createImageBitmap in e-sRGB from a transparent sRGB Blob (' + ext + ') with resize.'); +}); // Color managed blob from canvas function testCreateImageBitmapFromColorManagedBlob(pixelFormat, isTransparent) {
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html b/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html index d8e064d..f4dca7d6 100644 --- a/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html +++ b/third_party/blink/web_tests/external/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html
@@ -24,6 +24,10 @@ [ '%s', 'foo/%s', + `%s${location.href}`, + location.href.replace(location.protocol, + `${location.protocol[0]}%s${location.protocol.substring(1)}`), + location.href.replace(location.protocol, `${location.protocol}%s`), location.href + '/%s', location.href + '#%s', location.href + '?foo=%s', @@ -45,6 +49,10 @@ [ '', '%S', + 'http://%s.com', + 'http://%s.example.com', + location.href.replace(location.hostname, `%s${location.hostname}`), + location.href.replace(location.port, `%s${location.port}`), location.href + '', location.href + '/%', location.href + '/%a', @@ -64,8 +72,6 @@ }); [ - 'http://%s.com', - 'http://%s.example.com', 'http://example.com/%s', 'https://example.com/%s', 'http://foobar.example.com/%s',
diff --git a/third_party/blink/web_tests/external/wpt/native-io/close_async.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/native-io/close_async.tentative.https.any.js index a2b692e..0338cda 100644 --- a/third_party/blink/web_tests/external/wpt/native-io/close_async.tentative.https.any.js +++ b/third_party/blink/web_tests/external/wpt/native-io/close_async.tentative.https.any.js
@@ -95,3 +95,18 @@ await promise_rejects_dom(testCase, 'InvalidStateError', file.getLength()); assert_equals(await closePromise, undefined); }, 'NativeIOFile.getLength fails immediately after calling NativeIOFile.close'); + +promise_test(async testCase => { + const file = await createFile(testCase, 'file_name'); + assert_equals(await file.close(), undefined); + + await promise_rejects_dom(testCase, 'InvalidStateError', file.flush()); +}, 'NativeIOFile.flush fails after NativeIOFile.close settles'); + +promise_test(async testCase => { + const file = await createFile(testCase, 'file_name'); + const closePromise = file.close(); + + await promise_rejects_dom(testCase, 'InvalidStateError', file.flush()); + assert_equals(await closePromise, undefined); +}, 'NativeIOFile.flush fails immediately after calling NativeIOFile.close');
diff --git a/third_party/blink/web_tests/external/wpt/native-io/close_sync.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/native-io/close_sync.tentative.https.any.js index b5fb288..834265f 100644 --- a/third_party/blink/web_tests/external/wpt/native-io/close_sync.tentative.https.any.js +++ b/third_party/blink/web_tests/external/wpt/native-io/close_sync.tentative.https.any.js
@@ -49,3 +49,10 @@ assert_throws_dom('InvalidStateError', () => file.getLength()); }, 'NativeIOFileSync.getLength fails after NativeIOFileSync.close'); + +test(testCase => { + const file = createFileSync(testCase, 'file_name'); + assert_equals(undefined, file.close()); + + assert_throws_dom('InvalidStateError', () => file.flush()); +}, 'NativeIOFileSync.flush fails after NativeIOFileSync.close');
diff --git a/third_party/blink/web_tests/external/wpt/native-io/concurrent_io/concurrent_io_flush_async.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/native-io/concurrent_io/concurrent_io_flush_async.tentative.https.any.js new file mode 100644 index 0000000..7436b86 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/native-io/concurrent_io/concurrent_io_flush_async.tentative.https.any.js
@@ -0,0 +1,32 @@ +// META: title=NativeIO API: Concurrent io while flush is resolving. +// META: global=window,worker +// META: script=operation_helpers.js +// META: script=../resources/support.js + + +'use strict'; + +// See documentation in operation_helpers.js + +for (let op of kOperations) { + promise_test(async testCase => { + const file = await createFile(testCase, 'flush_file'); + + const res = op.prepare(); + + const flushPromise = file.flush(); + op.assertRejection(testCase, file, res); + + await flushPromise; + + const readSharedArrayBuffer = new SharedArrayBuffer(4); + const readBytes = new Uint8Array(readSharedArrayBuffer); + assert_equals(await file.read(readBytes, 0), 4, + `NativeIOFile.read() should not fail after a rejected ` + + `${op.name}() during flush()`); + assert_array_equals(readBytes, [64, 65, 66, 67], + `Rejecting ${op.name}() during flush() should not ` + + `change the file.`); + op.assertUnchanged(res); + }, `${op.name}() rejects while flush() is resolving.`); +};
diff --git a/third_party/blink/web_tests/external/wpt/native-io/concurrent_io/operation_helpers.js b/third_party/blink/web_tests/external/wpt/native-io/concurrent_io/operation_helpers.js index 71cbc29efa..76804ca 100644 --- a/third_party/blink/web_tests/external/wpt/native-io/concurrent_io/operation_helpers.js +++ b/third_party/blink/web_tests/external/wpt/native-io/concurrent_io/operation_helpers.js
@@ -64,4 +64,15 @@ assertUnchanged: () => {}, }; kOperations.push(kOpGetLength); + + const kOpFlush = { + name: 'flush', + prepare: () => {}, + assertRejection: async (testCase, file) => { + await promise_rejects_dom(testCase, 'InvalidStateError', + file.flush()); + }, + assertUnchanged: () => {}, + }; + kOperations.push(kOpFlush); })();
diff --git a/third_party/blink/web_tests/external/wpt/native-io/flush_async_basic.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/native-io/flush_async_basic.tentative.https.any.js new file mode 100644 index 0000000..2036d22 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/native-io/flush_async_basic.tentative.https.any.js
@@ -0,0 +1,30 @@ +// META: title=Synchronous NativeIO API: Flushed data is read back. +// META: global=window,worker +// META: script=resources/support.js + +'use strict'; + +promise_test(async testCase => { + const file = await nativeIO.open('test_file'); + testCase.add_cleanup(async () => { + await file.close(); + await nativeIO.delete('test_file'); + }); + + const size = 1024; + const longarray = createLargeArray(size, /*seed = */ 103); + const writeSharedArrayBuffer = new SharedArrayBuffer(size); + const writtenBytes = new Uint8Array(writeSharedArrayBuffer); + writtenBytes.set(longarray); + const writeCount = await file.write(writtenBytes, 0); + assert_equals( + writeCount, size, + 'NativeIOFile.write() should resolve with the number of bytes written'); + + await file.flush(); + const readBytes = await readIoFile(file); + + assert_array_equals(readBytes, writtenBytes, + 'the bytes read should match the bytes written'); +}, 'NativeIOFile.read returns bytes written by NativeIOFile.write' + + ' after NativeIOFile.flush');
diff --git a/third_party/blink/web_tests/external/wpt/native-io/flush_sync_basic.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/native-io/flush_sync_basic.tentative.https.any.js new file mode 100644 index 0000000..c5a1268e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/native-io/flush_sync_basic.tentative.https.any.js
@@ -0,0 +1,28 @@ +// META: title=Synchronous NativeIO API: Flushed data is read back. +// META: global=dedicatedworker +// META: script=resources/support.js + +'use strict'; + +test(testCase => { + const file = nativeIO.openSync('test_file'); + testCase.add_cleanup(() => { + file.close(); + nativeIO.deleteSync('test_file'); + }); + + const size = 1024; + const longarray = createLargeArray(size, /*seed = */ 107); + const writtenBytes = Uint8Array.from(longarray); + const writeCount = file.write(writtenBytes, 0); + assert_equals( + writeCount, size, + 'NativeIOFile.write() should resolve with the number of bytes written'); + + file.flush(); + const readBytes = readIoFileSync(file); + + assert_array_equals(readBytes, writtenBytes, + 'the bytes read should match the bytes written'); +}, 'NativeIOFileSync.read returns bytes written by NativeIOFileSync.write' + + ' after NativeIOFileSync.flush');
diff --git a/third_party/blink/web_tests/external/wpt/native-io/resources/support.js b/third_party/blink/web_tests/external/wpt/native-io/resources/support.js index 90bb912..bf7cf5a 100644 --- a/third_party/blink/web_tests/external/wpt/native-io/resources/support.js +++ b/third_party/blink/web_tests/external/wpt/native-io/resources/support.js
@@ -24,3 +24,56 @@ return file; } + +// Returns a handle to a newly created file that holds some data. +// +// The file will be closed and deleted when the test ends. +function createFileSync(testCase, fileName) { + const file = nativeIO.openSync(fileName); + testCase.add_cleanup(() => { + file.close(); + nativeIO.deleteSync(fileName); + }); + + const writtenBytes = Uint8Array.from([64, 65, 66, 67]); + const writeCount = file.write(writtenBytes, 0); + assert_equals(writeCount, 4); + + return file; +} + +// Returns an Uint8Array with pseudorandom data. +// +// The PRNG should be sufficient to defeat compression schemes, but it is not +// cryptographically strong. +function createLargeArray(size, seed) { + const buffer = new Uint8Array(size); + + // 32-bit xorshift - the seed can't be zero + let state = 1000 + seed; + + for (let i = 0; i < size; ++i) { + state ^= state << 13; + state ^= state >> 17; + state ^= state << 5; + buffer[i] = state & 0xff; + } + + return buffer; +} + +// Attempts to read the entire file into a buffer. +async function readIoFile(file) { + const length = await file.getLength(); + const readBuffer = new Uint8Array(new SharedArrayBuffer(length)); + await file.read(readBuffer, 0); + return readBuffer; +} + +// Attempts to read the entire file into a buffer. +function readIoFileSync(file) { + const length = file.getLength(); + const readBuffer = new Uint8Array(length); + file.read(readBuffer, 0); + return readBuffer; +}
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_mouse-on-object.html b/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_mouse-on-object.html index fa0e97f..78edfbd 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_mouse-on-object.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_mouse-on-object.html
@@ -1,9 +1,9 @@ <!DOCTYPE HTML> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-vendor.js"></script> -<script src="/resources/testdriver-actions.js"></script> +<script type="text/javascript" src="/resources/testharness.js"></script> +<script type="text/javascript" src="/resources/testharnessreport.js"></script> +<script type="text/javascript" src="/resources/testdriver.js"></script> +<script type="text/javascript" src="/resources/testdriver-vendor.js"></script> +<script type="text/javascript" src="/resources/testdriver-actions.js"></script> <script type="text/javascript" src="../pointerevent_support.js"></script> <style> @@ -11,61 +11,101 @@ width: 50px; height: 50px; padding: 50px; + background-color: lightblue; + border:1px solid black; +} +div { + display: block; } </style> <h1>Verifies that mouse activities on an object fire pointerevents. It expected to get pointerup when the pointerdown happened on the object for compatibility with flash objects.</h1> -<object id="obj"></object> -<button id="done"></button> +<p> + To test that when clicking inside the blue rectangle all compat mouse events are correct: + <ul> + <li> Click once in the blue rectangle + <li> Click the Done button + </ul> +</p> +<p> + To test that when dragging mouse outside all compat mouse events are correct: + <ul> + <li> Press left mouse button in the blue rectangle + <li> Drag the mouse cursor out of the blue rectangle + <li> Release the left mouse button + <li> Click the Done button + </ul> +</p> +<!-- draggable is set to false because there is a difference between auto draggable value in different browsers --> +<object id="obj" draggable="false"></object> +<button id="done">Done</button> <div id="log"></div> - <script> var target = document.getElementById("obj"); var done = document.getElementById("done"); + var rect = target.getBoundingClientRect(); -var done_clicked = false; +var done_clicked = 0; var receivedEvents = []; +var previous_done_clicked = 0; + ["mousedown", "mouseup", "mousemove", "pointerdown", "pointerup", "pointermove"].forEach(function(eventName) { target.addEventListener(eventName, function(event) { + // This will clear receivedEvents once another test starts + if(previous_done_clicked !== done_clicked){ + previous_done_clicked = done_clicked; + receivedEvents = []; + } receivedEvents.push(event.type); }); }); -document.getElementById('done').addEventListener('click', (e) => done_clicked = true); +document.getElementById('done').addEventListener('click', (e) => done_clicked++); -promise_test(async() => { - done_clicked = false; - receivedEvents = []; +// Need to prevent the default behaviour for firefox +target.addEventListener("dragstart", (e)=>e.preventDefault()); - await new test_driver.Actions() - .pointerMove(Math.ceil(rect.left+5), Math.ceil(rect.top+5)) - .pointerDown() - .pointerUp() - .send() - .then(() => clickInTarget("mouse", done)); - await resolveWhen(() => done_clicked); +if(window.promise_test){ + promise_test(async() => { + receivedEvents = []; - assert_array_equals(receivedEvents, ["pointermove", "mousemove", "pointerdown", "mousedown", "pointerup", "mouseup"], - "Click on object should result in the correct sequence of events"); -}, "Normal click event sequence within object"); + await new test_driver.Actions() + .pointerMove(Math.ceil(rect.left+5), Math.ceil(rect.top+5)) + .pointerDown() + .pointerUp() + .send() + .then(() => clickInTarget("mouse", done)); + await resolveWhen(() => done_clicked === 1); -promise_test(async() => { - done_clicked = false; - receivedEvents = []; + assert_array_equals(receivedEvents.filter(isPointerEvent), ["pointermove", "pointerdown", "pointerup"], + "Click on object should result in the correct sequence of pointer events"); + assert_array_equals(receivedEvents.filter(isMouseEvent), ["mousemove", "mousedown", "mouseup"], + "Click on object should result in the correct sequence of mouse events"); + assert_true(arePointerEventsBeforeCompatMouseEvents(receivedEvents), + "Click on object should result in the correct sequence of events: " + receivedEvents); + }, "Normal click event sequence within object"); - await new test_driver.Actions() - .pointerMove(Math.ceil(rect.left+5), Math.ceil(rect.top+5)) - .pointerDown() - .pointerMove(Math.ceil(rect.left-5), Math.ceil(rect.top-5)) - .pointerUp() - .send() - .then(() => clickInTarget("mouse", done)); - await resolveWhen(() => done_clicked); + promise_test(async() => { + receivedEvents = []; - assert_array_equals(receivedEvents, ["pointermove", "mousemove", "pointerdown", "mousedown", "pointermove", "mousemove", "pointerup", "mouseup"], - "Drag from object should result in the correct sequence of events"); + await new test_driver.Actions() + .pointerMove(Math.ceil(rect.left+5), Math.ceil(rect.top+5)) + .pointerDown() + .pointerMove(Math.ceil(rect.left-5), Math.ceil(rect.top-5)) + .pointerUp() + .send() + .then(() => clickInTarget("mouse", done)); + await resolveWhen(() => done_clicked === 2); -}, "Click and drag outside of object event sequence"); + assert_array_equals(receivedEvents.filter(isPointerEvent), ["pointermove", "pointerdown", "pointermove", "pointerup"], + "Drag from object should result in the correct sequence of pointer events"); + assert_array_equals(receivedEvents.filter(isMouseEvent), ["mousemove", "mousedown", "mousemove", "mouseup"], + "Drag from object should result in the correct sequence of mouse events"); + assert_true(arePointerEventsBeforeCompatMouseEvents(receivedEvents), + "Drag from object should result in the correct sequence of events: " + receivedEvents); + + }, "Click and drag outside of object event sequence"); +} </script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js index 7f291d7..6cbc8d6 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_support.js
@@ -402,3 +402,54 @@ } return resolveWhen(next); } + +function isPointerEvent(eventName){ + return All_Pointer_Events.includes(eventName); +} + +function isMouseEvent(eventName){ + return ["mousedown", "mouseup", "mousemove", "mouseover", + "mouseenter", "mouseout", "mouseleave", + "click", "contextmenu", "dblclick" + ].includes(eventName); +} + +function arePointerAndMouseEventCompatible(pointerEventName, mouseEventName){ + // e.g. compatible pointer-mouse events: pointerup - mouseup etc + return pointerEventName.startsWith("pointer") && + mouseEventName.startsWith("mouse") && + pointerEventName.substring(7) === mouseEventName.substring(5); +} + +// events is a list of events fired at a target +// checks to see if each pointer event has a corresponding mouse event in the event array +// and the two events are in the proper order (pointer event is first) +// see https://www.w3.org/TR/pointerevents3/#mapping-for-devices-that-support-hover +function arePointerEventsBeforeCompatMouseEvents(events){ + // checks to see if the pointer event is compatible with the mouse event + // and the pointer event happens before the mouse event + function arePointerAndMouseEventInProperOrder(pointerEventIndex, mouseEventIndex, events){ + return (pointerEventIndex < mouseEventIndex && isPointerEvent(events[pointerEventIndex]) && isMouseEvent(events[mouseEventIndex]) + && arePointerAndMouseEventCompatible(events[pointerEventIndex], events[mouseEventIndex])); + } + + let currentPointerEventIndex = events.findIndex((event)=>isPointerEvent(event)); + let currentMouseEventIndex = events.findIndex((event)=>isMouseEvent(event)); + + while(1){ + if(currentMouseEventIndex < 0 && currentPointerEventIndex < 0) + return true; + if(currentMouseEventIndex < 0 || currentPointerEventIndex < 0) + return false; + if(!arePointerAndMouseEventInProperOrder(currentPointerEventIndex, currentMouseEventIndex, events)) + return false; + + let pointerIdx = events.slice(currentPointerEventIndex+1).findIndex(isPointerEvent); + let mouseIdx = events.slice(currentMouseEventIndex+1).findIndex(isMouseEvent); + + currentPointerEventIndex = (pointerIdx < 0)?pointerIdx:(currentPointerEventIndex+1+pointerIdx); + currentMouseEventIndex = (mouseIdx < 0)?mouseIdx:(currentMouseEventIndex+1+mouseIdx); + } + + return true; +}
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py index 445063d..0c2fc40 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
@@ -38,6 +38,9 @@ # List of tests that have failing subtests. self.tests_with_subtest_fails = set() + # Browser log for the current test under execution. + self.test_log = [] + def _append_test_message(self, test, subtest, status, expected, message): """ Appends the message data for a test. @@ -90,6 +93,9 @@ self._append_artifact(cur_dict, "wpt_subtest_failure", "true") if wpt_actual != actual: self._append_artifact(cur_dict, "wpt_actual_status", wpt_actual) + if wpt_actual == 'CRASH': + for line in self.test_log: + self._append_artifact(cur_dict, "wpt_crash_log", line) for message in messages: self._append_artifact(cur_dict, "log", message) @@ -129,13 +135,9 @@ return "SKIP" if status == "EXTERNAL-TIMEOUT": return "TIMEOUT" - if status in ("ERROR", "CRASH", "PRECONDITION_FAILED"): - # CRASH in WPT means a browser crash, which Chromium treats as a - # test failure. + if status in ("ERROR", "PRECONDITION_FAILED"): return "FAIL" if status == "INTERNAL-ERROR": - # CRASH in Chromium refers to an error in the test runner not the - # browser. return "CRASH" # Any other status just gets returned as-is. return status @@ -218,6 +220,9 @@ # Update the count of how many tests ran with each status. self.num_failures_by_status[actual_status] += 1 + # New test, new browser logs. + self.test_log = [] + def suite_end(self, data): # Create the final result dictionary final_result = { @@ -230,3 +235,7 @@ "tests": self.tests } return json.dumps(final_result) + + def process_output(self, data): + if 'command' in data and 'chromedriver' in data['command']: + self.test_log.append(data['data'])
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py index efff5f0..59f39c1e 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
@@ -570,3 +570,56 @@ "foo.html: DATA1", "foo-ref.html: DATA2", ] + + +def test_process_output_crashing_test(capfd): + """Test that chromedriver logs are preserved for crashing tests""" + + # Set up the handler. + output = StringIO() + logger = structuredlog.StructuredLogger("test_a") + logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter())) + + logger.suite_start(["t1", "t2", "t3"], run_info={}, time=123) + + logger.test_start("t1") + logger.process_output(100, "This message should be recorded", "/some/path/to/chromedriver --some-flag") + logger.process_output(101, "This message should not be recorded", "/some/other/process --another-flag") + logger.process_output(100, "This message should also be recorded", "/some/path/to/chromedriver --some-flag") + logger.test_end("t1", status="CRASH", expected="CRASH") + + logger.test_start("t2") + logger.process_output(100, "Another message for the second test", "/some/path/to/chromedriver --some-flag") + logger.test_end("t2", status="CRASH", expected="PASS") + + logger.test_start("t3") + logger.process_output(100, "This test fails", "/some/path/to/chromedriver --some-flag") + logger.process_output(100, "But the output should not be captured", "/some/path/to/chromedriver --some-flag") + logger.process_output(100, "Because it does not crash", "/some/path/to/chromedriver --some-flag") + logger.test_end("t3", status="FAIL", expected="PASS") + + logger.suite_end() + + # check nothing got output to stdout/stderr + # (note that mozlog outputs exceptions during handling to stderr!) + captured = capfd.readouterr() + assert captured.out == "" + assert captured.err == "" + + # check the actual output of the formatter + output.seek(0) + output_json = json.load(output) + + test_obj = output_json["tests"]["t1"] + assert test_obj["artifacts"]["wpt_crash_log"] == [ + "This message should be recorded", + "This message should also be recorded" + ] + + test_obj = output_json["tests"]["t2"] + assert test_obj["artifacts"]["wpt_crash_log"] == [ + "Another message for the second test" + ] + + test_obj = output_json["tests"]["t3"] + assert "wpt_crash_log" not in test_obj["artifacts"]
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-source-file-path.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-source-file-path.tentative.html index 61adb29..6e87c25a 100644 --- a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-source-file-path.tentative.html +++ b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-source-file-path.tentative.html
@@ -38,7 +38,7 @@ promise_test(async t => { let future_violation = futureViolation(); - assert_throws_js(TypeError, () => { + assert_throws_js(TypeError, _ => { document.getElementById("to-be-modified").innerHTML = "'test'"; }); let violation = await future_violation; @@ -64,9 +64,7 @@ let future_violation = futureViolation(); assert_throws_js(TypeError, () => setInnerHtml(toBeModified, "'test'")); let violation = await future_violation; - // TODO(https://crbug.com/1113163): Consider exposing the full path of the - // cross-origin script here instead of just its origin. - assert_equals(violation.sourceFile, script_origin); + assert_equals(violation.sourceFile, script_src); }, "cross-origin script") // TODO(arthursonzogni): Check what happens with redirects. Do we report the
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html index 7e98ef42..dd861750 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html +++ b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/setting-the-timeline-of-an-animation.html
@@ -60,7 +60,7 @@ new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.startTime = document.timeline.currentTime; - assert_equals(animation.playState, 'running'); + assert_equals(animation.playState, 'idle'); animation.timeline = document.timeline; @@ -73,7 +73,7 @@ new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC), null); animation.startTime = document.timeline.currentTime - 200 * MS_PER_SEC; - assert_equals(animation.playState, 'running'); + assert_equals(animation.playState, 'idle'); animation.timeline = document.timeline;
diff --git a/third_party/blink/web_tests/http/tests/reporting-observer/reporting-observer-worker.html b/third_party/blink/web_tests/http/tests/reporting-observer/reporting-observer-worker.html deleted file mode 100644 index 51dcb15..0000000 --- a/third_party/blink/web_tests/http/tests/reporting-observer/reporting-observer-worker.html +++ /dev/null
@@ -1,74 +0,0 @@ -<!doctype html> -<html> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/serviceworker/resources/test-helpers.js"></script> -<script> - const WORKER_URL - = new URL('resources/deprecation-worker.js', location).href; - function checkReport(report) { - assert_equals(report.type, 'deprecation'); - assert_equals(report.url, WORKER_URL); - assert_equals(typeof report.body.id, 'string'); - assert_equals(typeof report.body.anticipatedRemoval, 'string'); - assert_equals(typeof report.body.message, 'string'); - assert_equals(report.body.sourceFile, WORKER_URL); - assert_equals(typeof report.body.lineNumber, 'number'); - assert_equals(typeof report.body.columnNumber, 'number'); - } - - promise_test(async (test) => { - const worker = new Worker(WORKER_URL); - test.add_cleanup(() => worker.terminate()); - - const mc = new MessageChannel(); - worker.postMessage(mc.port2, [mc.port2]); - test.add_cleanup(() => mc.port1.close()); - - const reports = (await new Promise(r => { - mc.port1.onmessage = r; - })).data; - - assert_equals(reports.length, 1); - checkReport(reports[0]); - }, 'Deprecation reports on DedicatedWorker'); - - promise_test(async (test) => { - const worker = new SharedWorker(WORKER_URL); - - const mc = new MessageChannel(); - worker.port.start(); - worker.port.postMessage(mc.port2, [mc.port2]); - test.add_cleanup(() => mc.port1.close()); - - const reports = (await new Promise(r => { - mc.port1.onmessage = r; - })).data; - - assert_equals(reports.length, 1); - checkReport(reports[0]); - }, 'Deprecation reports on SharedWorker'); - - promise_test(async (test) => { - const SCOPE = new URL('resources/empty.html', location).pathname; - const reg = await service_worker_unregister_and_register(test, WORKER_URL, SCOPE); - await wait_for_state(test, reg.installing, 'activated'); - test.add_cleanup(() => reg.unregister()); - - const frame = await with_iframe(SCOPE); - - const mc = new MessageChannel(); - const worker = frame.contentWindow.navigator.serviceWorker.controller; - worker.postMessage(mc.port2, [mc.port2]); - test.add_cleanup(() => mc.port1.close()); - - const reports = (await new Promise(r => { - mc.port1.onmessage = r; - })).data; - - assert_equals(reports.length, 1); - checkReport(reports[0]); - }, 'Deprecation reports on ServiceWorker'); -</script> - -</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/reporting-observer/resources/deprecation-worker.js b/third_party/blink/web_tests/http/tests/reporting-observer/resources/deprecation-worker.js deleted file mode 100644 index 7a9b2191..0000000 --- a/third_party/blink/web_tests/http/tests/reporting-observer/resources/deprecation-worker.js +++ /dev/null
@@ -1,21 +0,0 @@ -function run(port) { - const observer = new ReportingObserver((reports) => { - port.postMessage(reports.map(report => report.toJSON())); - }); - observer.observe(); - - try { - // This API is deprecated. This throws an exception because of a bad - // argument, but we don't care. - Atomics.wake(); - } catch (e) { - } -} - -// For DedicatedWorker and ServiceWorker -self.addEventListener('message', (e) => run(e.data)); - -// For SharedWorker -self.addEventListener('connect', (e) => { - e.ports[0].onmessage = (ev) => run(ev.data); -});
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 344d7a3..89a34803 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -922,6 +922,7 @@ attribute @@toStringTag method close method constructor + method flush method getLength method read method write
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt index 5c5d76a..28bee53e 100644 --- a/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt +++ b/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value-expected.txt
@@ -3,6 +3,7 @@ { padding-top: 55px; margin-top: 33px !important; + --x: foo; } Dumping matched rules: *#inspected* { regular @@ -28,6 +29,7 @@ { padding-top: 55px; margin-top: 33px !important; + --x: foo; } *#inspected* { regular margin-left: 10px !important; @@ -51,6 +53,7 @@ { padding-top: 55px; margin-top: 33px !important; + --x: foo; } *#inspected* { regular margin-left: 10px !important; @@ -74,6 +77,7 @@ { padding-top: 55px; margin-top: 33px !important; + --x: foo; } *#inspected* { regular margin-left: 101px !important; @@ -97,6 +101,7 @@ { padding-top: 101px; margin-top: 33px !important; + --x: foo; } *#inspected* { regular margin-left: 10px !important; @@ -120,6 +125,7 @@ { padding-top: 55px; margin-top: 101px !important; + --x: foo; } *#inspected* { regular margin-left: 10px !important; @@ -143,6 +149,7 @@ { padding-top: 55px; margin-top: 33px !important; + --x: foo; margin-bottom: 101px; } *#inspected* { regular @@ -176,3 +183,27 @@ padding-right: 101px; } +Running test: testChangeCustomProperty +{ + padding-top: 55px; + margin-top: 33px !important; + --x: bar; +} +*#inspected* { regular + margin-left: 10px !important; +} +*#inspected* { regular + padding: 10px 20px 30px 40px; + padding-top: 50px; + padding-right: 20px; + padding-bottom: 30px; + padding-left: 40px; +} +@media (min-width: 1px) + *#inspected* { regular + padding-left: 5px; + margin-left: 20px; + padding-left: 10px; + margin-top: 15px !important; + } +
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value.js b/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value.js index 35e51be..70c6860d 100644 --- a/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value.js +++ b/third_party/blink/web_tests/inspector-protocol/css/css-set-effective-property-value.js
@@ -1,7 +1,7 @@ (async function(testRunner) { var {page, session, dp} = await testRunner.startHTML(` <link rel='stylesheet' href='${testRunner.url('resources/set-active-property-value.css')}'/> -<div id='inspected' style='padding-top: 55px; margin-top: 33px !important;'></div> +<div id='inspected' style='padding-top: 55px; margin-top: 33px !important; --x:foo'></div> <div id='append-test' style='padding-left: 10px'/> `, 'The test verifies functionality of protocol method CSS.setEffectivePropertyValueForNode.'); @@ -55,7 +55,12 @@ testRunner.log('Resulting styles'); await dp.CSS.setEffectivePropertyValueForNode({nodeId, propertyName: 'padding-right', value : '101px'}); await cssHelper.loadAndDumpInlineAndMatchingRules(documentNodeId, '#append-test', true /* omitLog */); + }, + + async function testChangeCustomProperty() { + await updateProperty('--x', 'bar'); } + ]); });
diff --git a/third_party/blink/web_tests/virtual/out-of-blink-cspee/external/wpt/content-security-policy/embedded-enforcement/allow_csp_from-header-expected.txt b/third_party/blink/web_tests/virtual/out-of-blink-cspee/external/wpt/content-security-policy/embedded-enforcement/allow_csp_from-header-expected.txt index 11afaac..54921ea 100644 --- a/third_party/blink/web_tests/virtual/out-of-blink-cspee/external/wpt/content-security-policy/embedded-enforcement/allow_csp_from-header-expected.txt +++ b/third_party/blink/web_tests/virtual/out-of-blink-cspee/external/wpt/content-security-policy/embedded-enforcement/allow_csp_from-header-expected.txt
@@ -8,7 +8,7 @@ PASS Cross origin iframe with correct Allow-CSP-From header is allowed. PASS Iframe with improper Allow-CSP-From header gets blocked. PASS Allow-CSP-From header with a star value allows cross origin frame. -FAIL Star Allow-CSP-From header enforces EmbeddingCSP. assert_equals: expected (string) "inline" but got (undefined) undefined -FAIL Allow-CSP-From header enforces EmbeddingCSP. assert_equals: expected (string) "inline" but got (undefined) undefined +PASS Star Allow-CSP-From header enforces EmbeddingCSP. +PASS Allow-CSP-From header enforces EmbeddingCSP. Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/virtual/out-of-blink-cspee/external/wpt/content-security-policy/embedded-enforcement/required-csp-header-cascade-expected.txt b/third_party/blink/web_tests/virtual/out-of-blink-cspee/external/wpt/content-security-policy/embedded-enforcement/required-csp-header-cascade-expected.txt deleted file mode 100644 index 454abe66..0000000 --- a/third_party/blink/web_tests/virtual/out-of-blink-cspee/external/wpt/content-security-policy/embedded-enforcement/required-csp-header-cascade-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -This is a testharness.js-based test. -PASS Test same origin: Test same policy for both iframes -PASS Test same origin: Test more restrictive policy on second iframe -FAIL Test same origin: Test less restrictive policy on second iframe assert_unreached: Child iframes have unexpected csp:"script-src 'unsafe-inline';" Reached unreachable code -PASS Test same origin: Test no policy on second iframe -PASS Test same origin: Test no policy on first iframe -PASS Test same origin: Test invalid policy on first iframe (bad directive) -PASS Test same origin: Test invalid policy on first iframe (report directive) -PASS Test same origin: Test invalid policy on second iframe (bad directive) -PASS Test same origin: Test invalid policy on second iframe (report directive) -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 5b1d11b..3789acd4 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -882,6 +882,7 @@ [Worker] attribute @@toStringTag [Worker] method close [Worker] method constructor +[Worker] method flush [Worker] method getLength [Worker] method read [Worker] method write @@ -889,6 +890,7 @@ [Worker] attribute @@toStringTag [Worker] method close [Worker] method constructor +[Worker] method flush [Worker] method getLength [Worker] method read [Worker] method write
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 3b1b26a4..414350d7 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5439,6 +5439,7 @@ attribute @@toStringTag method close method constructor + method flush method getLength method read method write
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index 3a63e8f..e7bc30e7 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -849,6 +849,7 @@ [Worker] attribute @@toStringTag [Worker] method close [Worker] method constructor +[Worker] method flush [Worker] method getLength [Worker] method read [Worker] method write
diff --git a/tools/binary_size/libsupersize/path_util.py b/tools/binary_size/libsupersize/path_util.py index 7712d54..bf123b4e 100644 --- a/tools/binary_size/libsupersize/path_util.py +++ b/tools/binary_size/libsupersize/path_util.py
@@ -6,7 +6,6 @@ import abc import distutils.spawn -import json import logging import os @@ -135,11 +134,11 @@ def _LoadBuildVars(output_directory): - build_vars_path = os.path.join(output_directory, 'build_vars.json') + build_vars_path = os.path.join(output_directory, 'build_vars.txt') if os.path.exists(build_vars_path): with open(build_vars_path) as f: - return json.load(f) - return {} + return dict(l.rstrip().split('=', 1) for l in f if '=' in l) + return dict() def GetSrcRootFromOutputDirectory(output_directory):
diff --git a/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.json b/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.json deleted file mode 100644 index 53e11e8e4..0000000 --- a/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.json +++ /dev/null
@@ -1,4 +0,0 @@ -{ - "android_sdk_root": "../../../mock_sdk", - "android_tool_prefix": "../../../mock_toolchain/" -}
diff --git a/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.txt b/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.txt new file mode 100644 index 0000000..ab47517 --- /dev/null +++ b/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/build_vars.txt
@@ -0,0 +1,2 @@ +android_sdk_root=../../../mock_sdk +android_tool_prefix=../../../mock_toolchain/
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 3a8cbff..5d31da5 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -6244,6 +6244,7 @@ <int value="228" label="INPUT_ROUTER_INVALID_EVENT_SOURCE"/> <int value="229" label="RFH_INACTIVE_CHECK_FROM_SPECULATIVE_RFH"/> <int value="230" label="RFH_SUBFRAME_CAPTURE_ON_MAIN_FRAME"/> + <int value="231" label="RFH_CSP_ATTRIBUTE"/> </enum> <enum name="BadMessageReasonExtensions"> @@ -16010,6 +16011,44 @@ <int value="2" label="Platform dual-screen support used"/> </enum> +<enum name="DevtoolsExperiments"> + <int value="0" label="applyCustomStylesheet"/> + <int value="1" label="captureNodeCreationStacks"/> + <int value="2" label="sourcesPrettyPrint"/> + <int value="3" label="backgroundServices"/> + <int value="4" label="backgroundServicesNotifications"/> + <int value="5" label="backgroundServicesPaymentHandler"/> + <int value="6" label="backgroundServicesPushMessaging"/> + <int value="7" label="blackboxJSFramesOnTimeline"/> + <int value="8" label="cssOverview"/> + <int value="9" label="emptySourceMapAutoStepping"/> + <int value="10" label="inputEventsOnTimelineOverview"/> + <int value="11" label="liveHeapProfile"/> + <int value="12" label="nativeHeapProfiler"/> + <int value="13" label="protocolMonitor"/> + <int value="14" label="issuesPane"/> + <int value="15" label="developerResourcesView"/> + <int value="16" label="recordCoverageWithPerformanceTracing"/> + <int value="17" label="samplingHeapProfilerTimeline"/> + <int value="18" label="showOptionToNotTreatGlobalObjectsAsRoots"/> + <int value="19" label="sourceDiff"/> + <int value="20" label="sourceOrderViewer"/> + <int value="21" label="spotlight"/> + <int value="22" label="webauthnPane"/> + <int value="23" label="customKeyboardShortcuts"/> + <int value="24" label="timelineEventInitiators"/> + <int value="25" label="timelineFlowEvents"/> + <int value="26" label="timelineInvalidationTracking"/> + <int value="27" label="timelineShowAllEvents"/> + <int value="28" label="timelineV8RuntimeCallStats"/> + <int value="29" label="timelineWebGL"/> + <int value="30" label="timelineReplayEvent"/> + <int value="31" label="wasmDWARFDebugging"/> + <int value="32" label="dualScreenSupport"/> + <int value="33" label="cssGridFeatures"/> + <int value="34" label="movableTabs"/> +</enum> + <enum name="DevtoolsGridSettingChanged"> <int value="0" label="showGridBorder.none"/> <int value="1" label="showGridBorder.dashed"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 64e76214..e5bda54 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -39468,6 +39468,36 @@ </summary> </histogram> +<histogram name="DevTools.ExperimentDisabled" enum="DevtoolsExperiments" + expires_after="2021-07-31"> + <owner>yangguo@chromium.org</owner> + <owner>brgoddar@microsoft.com</owner> + <owner>shanejc@microsoft.com</owner> + <summary> + Fired when a devtools experiment is disabled from the experiments tab. + </summary> +</histogram> + +<histogram name="DevTools.ExperimentEnabled" enum="DevtoolsExperiments" + expires_after="2021-07-31"> + <owner>yangguo@chromium.org</owner> + <owner>brgoddar@microsoft.com</owner> + <owner>shanejc@microsoft.com</owner> + <summary> + Fired when a devtools experiment is enabled from the experiments tab. + </summary> +</histogram> + +<histogram name="DevTools.ExperimentEnabledAtLaunch" enum="DevtoolsExperiments" + expires_after="2021-07-31"> + <owner>yangguo@chromium.org</owner> + <owner>brgoddar@microsoft.com</owner> + <owner>shanejc@microsoft.com</owner> + <summary> + Fires for each experiment that is enabled at the time of Devtools Launch. + </summary> +</histogram> + <histogram name="DevTools.GridSettingChanged" enum="DevtoolsGridSettingChanged" expires_after="M87"> <obsolete> @@ -135542,6 +135572,17 @@ </summary> </histogram> +<histogram name="Power.CpuAffinityExperiments.ProcessAffinityUpdateSuccess" + enum="BooleanSuccess" expires_after="2021-08-05"> + <owner>eseckler@chromium.org</owner> + <owner>skyostil@chromium.org</owner> + <summary> + For clients enrolled in CPU affinity restriction experiments (e.g. + restricting execution to little cores only), records whether the CPU + affinity for a process could be succcessfully set. + </summary> +</histogram> + <histogram name="Power.CpuTimeSecondsPerCoreTypeAndFrequency" units="50 MHz" expires_after="2021-06-26"> <owner>eseckler@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 0082debd..27dde277 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@ { "trace_processor_shell": { "win": { - "hash": "4109a0936495f455a113241d44034b723778ee66", - "remote_path": "perfetto_binaries/trace_processor_shell/win/a4cba6578f09d606d32fe32bb0a0c6283ea6d198/trace_processor_shell.exe" + "hash": "9632b44419444a74efa0e5241589bf4235e4853b", + "remote_path": "perfetto_binaries/trace_processor_shell/win/01e0ccdc9b8b4697a343b8ef49f53fd489d79a41/trace_processor_shell.exe" }, "mac": { "hash": "803679e20216dc532ebe9e915e84107065c4c79c", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/a4cba6578f09d606d32fe32bb0a0c6283ea6d198/trace_processor_shell" + "remote_path": "perfetto_binaries/trace_processor_shell/mac/577cc158d1e2a9fc4b69c1e503f5d49f388dd856/trace_processor_shell" }, "linux": { - "hash": "4bdc7c11640334a0bddbe287525847074cf4b576", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/a4cba6578f09d606d32fe32bb0a0c6283ea6d198/trace_processor_shell" + "hash": "283e0325abb12d3cea2c5a23acbdc39cfc6dd13f", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/01e0ccdc9b8b4697a343b8ef49f53fd489d79a41/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/win/IdleWakeups/idle_wakeups.cpp b/tools/win/IdleWakeups/idle_wakeups.cpp index 03a0332..bbb579b 100644 --- a/tools/win/IdleWakeups/idle_wakeups.cpp +++ b/tools/win/IdleWakeups/idle_wakeups.cpp
@@ -54,7 +54,19 @@ } } -// This class holds the app state and constains a number of utilities for +// Count newly created processes: those in |processes| but not +// |previous_processes|. +size_t GetNumProcessesCreated(const ProcessDataMap& previous_processes, + const ProcessDataMap& processes) { + size_t num_processes_created = 0; + for (auto& process : processes) { + if (previous_processes.find(process.first) == previous_processes.end()) + num_processes_created++; + } + return num_processes_created; +} + +// This class holds the app state and contains a number of utilities for // collecting and diffing snapshots of data, handling processes, etc. class IdleWakeups { public: @@ -279,11 +291,15 @@ system_information_sampler.TakeSnapshot(); the_app.OpenProcesses(*previous_snapshot); + const size_t initial_number_of_processes = + previous_snapshot->processes.size(); + size_t final_number_of_processes = initial_number_of_processes; ULONG cumulative_idle_wakeups_per_sec = 0; double cumulative_cpu_usage = 0.0; ULONGLONG cumulative_working_set = 0; double cumulative_energy = 0.0; + size_t cumulative_processes_created = 0; ResultVector results; @@ -300,6 +316,10 @@ std::unique_ptr<ProcessDataSnapshot> snapshot = system_information_sampler.TakeSnapshot(); size_t number_of_processes = snapshot->processes.size(); + final_number_of_processes = number_of_processes; + + cumulative_processes_created += GetNumProcessesCreated( + previous_snapshot->processes, snapshot->processes); Result result = the_app.DiffSnapshots(*previous_snapshot, *snapshot); previous_snapshot = std::move(snapshot); @@ -345,5 +365,10 @@ median_result.idle_wakeups_per_sec, median_result.cpu_usage, '%', median_result.working_set / 1024.0, median_result.power); + printf("\nProcesses created: %zu\n", cumulative_processes_created); + printf("Processes destroyed: %zu\n", initial_number_of_processes + + cumulative_processes_created - + final_number_of_processes); + return 0; }
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc index da9314d4..f57aa0b0 100644 --- a/ui/accessibility/ax_event_generator.cc +++ b/ui/accessibility/ax_event_generator.cc
@@ -47,6 +47,19 @@ } } +// If a node toggled its ignored state, don't also fire children-changed because +// platforms likely will do that in response to ignored-changed. +// Suppress name- and description-changed because those can be emitted as a side +// effect of calculating alternative text values for a newly-displayed object. +// Ditto for text attributes such as foreground and background colors. +void RemoveEventsDueToIgnoredChanged( + std::set<AXEventGenerator::EventParams>* node_events) { + RemoveEvent(node_events, AXEventGenerator::Event::CHILDREN_CHANGED); + RemoveEvent(node_events, AXEventGenerator::Event::DESCRIPTION_CHANGED); + RemoveEvent(node_events, AXEventGenerator::Event::NAME_CHANGED); + RemoveEvent(node_events, AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED); +} + } // namespace AXEventGenerator::EventParams::EventParams( @@ -665,7 +678,51 @@ data.relative_bounds.bounds.height(); } +void AXEventGenerator::TrimEventsDueToAncestorIgnoredChanged( + AXNode* node, + std::map<AXNode*, bool>& ancestor_ignored_changed_map) { + DCHECK(node); + + // Recursively compute and cache ancestor ignored changed results in + // |ancestor_ignored_changed_map|, if |node|'s ancestors have become ignored + // and the ancestor's ignored changed results have not been cached. + if (node->parent() && + !base::Contains(ancestor_ignored_changed_map, node->parent())) { + TrimEventsDueToAncestorIgnoredChanged(node->parent(), + ancestor_ignored_changed_map); + } + + // If an ancestor of |node| changed to ignored state, update the corresponding + // entry in the map for |node| based on the ancestor result (i.e. if an + // ancestor changed to ignored state, set the entry in the map to true for the + // current node). If |node|'s state changed to ignored as well, we want to + // remove its IGNORED_CHANGED event. + const auto& map_iter = ancestor_ignored_changed_map.find(node->parent()); + const auto& events_iter = tree_events_.find(node); + if (map_iter != ancestor_ignored_changed_map.end() && map_iter->second) { + ancestor_ignored_changed_map.insert(std::make_pair(node, true)); + if (node->IsIgnored() && events_iter != tree_events_.end()) { + RemoveEvent(&(events_iter->second), Event::IGNORED_CHANGED); + RemoveEventsDueToIgnoredChanged(&(events_iter->second)); + } + return; + } + + // If ignored changed results are not cached, calculate the corresponding + // entry for |node| in the map using the ignored states and events of |node|. + if (events_iter != tree_events_.end() && + HasEvent(events_iter->second, Event::IGNORED_CHANGED) && + node->IsIgnored()) { + ancestor_ignored_changed_map.insert(std::make_pair(node, true)); + return; + } + + ancestor_ignored_changed_map.insert(std::make_pair(node, false)); +} + void AXEventGenerator::PostprocessEvents() { + std::map<AXNode*, bool> ancestor_ignored_changed_map; + auto iter = tree_events_.begin(); while (iter != tree_events_.end()) { AXNode* node = iter->first; @@ -678,17 +735,13 @@ RemoveEvent(&node_events, Event::LIVE_REGION_CHANGED); } - // If a node toggled its ignored state, don't also fire children-changed - // because platforms likely will do that in response to ignored-changed. - // Suppress name- and description-changed because those can be emitted - // as a side effect of calculating alternative text values for a newly- - // displayed object. Ditto for text attributes such as foreground and - // background colors. if (HasEvent(node_events, Event::IGNORED_CHANGED)) { - RemoveEvent(&node_events, Event::CHILDREN_CHANGED); - RemoveEvent(&node_events, Event::DESCRIPTION_CHANGED); - RemoveEvent(&node_events, Event::NAME_CHANGED); - RemoveEvent(&node_events, Event::TEXT_ATTRIBUTE_CHANGED); + // If a node toggled its ignored state from show to hide, we only want to + // fire IGNORED_CHANGED event on the top most ancestor where this ignored + // state change takes place and suppress all the descendants's + // IGNORED_CHANGED events. + TrimEventsDueToAncestorIgnoredChanged(node, ancestor_ignored_changed_map); + RemoveEventsDueToIgnoredChanged(&node_events); } // When the selected option in an expanded select element changes, the
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h index 2755932f..b068624 100644 --- a/ui/accessibility/ax_event_generator.h +++ b/ui/accessibility/ax_event_generator.h
@@ -235,6 +235,18 @@ void FireActiveDescendantEvents(); void FireRelationSourceEvents(AXTree* tree, AXNode* target_node); bool ShouldFireLoadEvents(AXNode* node); + // Remove excessive events for a tree update containing node. + // We remove certain events on a node when it changes to IGNORED state and one + // of the node's ancestor has also changed to IGNORED in the same tree update. + // |ancestor_has_ignored_map| contains if a node's ancestor has changed to + // IGNORED state. + // Map's key is: an ax node. + // Map's value is: + // - True if an ancestor of node changed to IGNORED state. + // - False if no ancestor of node changed to IGNORED state. + void TrimEventsDueToAncestorIgnoredChanged( + AXNode* node, + std::map<AXNode*, bool>& ancestor_has_ignored_map); void PostprocessEvents(); static void GetRestrictionStates(ax::mojom::Restriction restriction, bool* is_enabled,
diff --git a/ui/accessibility/ax_event_generator_unittest.cc b/ui/accessibility/ax_event_generator_unittest.cc index 3f9eb022f..611ce33 100644 --- a/ui/accessibility/ax_event_generator_unittest.cc +++ b/ui/accessibility/ax_event_generator_unittest.cc
@@ -1152,6 +1152,459 @@ HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 2))); } +TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly1) { + // BEFORE + // 1 (IGN) + // / \ + // 2 3 (IGN) + // AFTER + // 1 (IGN) + // / \ + // 2 (IGN) 3 + // IGNORED_CHANGED expected on #2, #3 + + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(3); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea; + initial_state.nodes[0].AddState(ax::mojom::State::kIgnored); + initial_state.nodes[0].child_ids = {2, 3}; + + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kStaticText; + + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kStaticText; + initial_state.nodes[2].AddState(ax::mojom::State::kIgnored); + + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes[1].AddState(ax::mojom::State::kIgnored); + update.nodes[2].RemoveState(ax::mojom::State::kIgnored); + ASSERT_TRUE(tree.Unserialize(update)); + EXPECT_THAT(event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 2), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 3), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 3))); +} + +TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly2) { + // BEFORE + // 1 + // | + // 2 + // / \ + // 3 4 (IGN) + // AFTER + // 1 + // | + // 2 ___ + // / \ + // 3 (IGN) 4 + // IGNORED_CHANGED expected on #3, #4 + + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(4); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea; + initial_state.nodes[0].child_ids = {2}; + + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kGroup; + initial_state.nodes[1].child_ids = {3, 4}; + + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kStaticText; + + initial_state.nodes[3].id = 4; + initial_state.nodes[3].role = ax::mojom::Role::kStaticText; + initial_state.nodes[3].AddState(ax::mojom::State::kIgnored); + + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes[2].AddState(ax::mojom::State::kIgnored); + update.nodes[3].RemoveState(ax::mojom::State::kIgnored); + ASSERT_TRUE(tree.Unserialize(update)); + EXPECT_THAT(event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 2), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 3), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 4), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 4))); +} + +TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly3) { + // BEFORE + // 1 + // | + // 2 ___ + // / \ + // 3 (IGN) 4 + // AFTER + // 1 (IGN) + // | + // 2 + // / \ + // 3 4 (IGN) + // IGNORED_CHANGED expected on #1, #3 + + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(4); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea; + initial_state.nodes[0].child_ids = {2}; + + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kGroup; + initial_state.nodes[1].child_ids = {3, 4}; + + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kStaticText; + initial_state.nodes[2].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[3].id = 4; + initial_state.nodes[3].role = ax::mojom::Role::kStaticText; + + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes[0].AddState(ax::mojom::State::kIgnored); + update.nodes[2].RemoveState(ax::mojom::State::kIgnored); + update.nodes[3].AddState(ax::mojom::State::kIgnored); + ASSERT_TRUE(tree.Unserialize(update)); + EXPECT_THAT(event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 2), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 1), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 3), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 3))); +} + +TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly4) { + // BEFORE + // 1 (IGN) + // | + // 2 + // | + // 3 (IGN) + // | + // 4 (IGN) + // | + // ____ 5 _____ + // / | \ + // 6 (IGN) 7 (IGN) 8 + // AFTER + // 1 (IGN) + // | + // 2 + // | + // 3 (IGN) + // | + // 4 (IGN) + // | + // ____ 5 _____ + // / | \ + // 6 7 8 (IGN) + + // IGNORED_CHANGED expected on #6, #7, #8 + + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(8); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea; + initial_state.nodes[0].child_ids = {2}; + + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kGroup; + initial_state.nodes[1].child_ids = {3}; + + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kGroup; + initial_state.nodes[2].child_ids = {4}; + initial_state.nodes[2].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[3].id = 4; + initial_state.nodes[3].role = ax::mojom::Role::kGroup; + initial_state.nodes[3].child_ids = {5}; + initial_state.nodes[3].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[4].id = 5; + initial_state.nodes[4].role = ax::mojom::Role::kGroup; + initial_state.nodes[4].child_ids = {6, 7, 8}; + + initial_state.nodes[5].id = 6; + initial_state.nodes[5].role = ax::mojom::Role::kStaticText; + initial_state.nodes[5].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[6].id = 7; + initial_state.nodes[6].role = ax::mojom::Role::kStaticText; + initial_state.nodes[6].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[7].id = 8; + initial_state.nodes[7].role = ax::mojom::Role::kStaticText; + + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes[5].RemoveState(ax::mojom::State::kIgnored); + update.nodes[6].RemoveState(ax::mojom::State::kIgnored); + update.nodes[7].AddState(ax::mojom::State::kIgnored); + ASSERT_TRUE(tree.Unserialize(update)); + EXPECT_THAT(event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 5), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 6), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 7), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 6), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 7), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 8))); +} + +TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly5) { + // BEFORE + // 1 + // | + // 2 + // | + // 3 (IGN) + // | + // 4 (IGN) + // | + // ____ 5 _____ + // / | \ + // 6 (IGN) 7 8 + // AFTER + // 1 (IGN) + // | + // 2 + // | + // 3 (IGN) + // | + // 4 (IGN) + // | + // ____ 5 _____ + // / | \ + // 6 7 (IGN) 8 (IGN) + + // IGNORED_CHANGED expected on #1, #6 + + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(8); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea; + initial_state.nodes[0].child_ids = {2}; + + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kGroup; + initial_state.nodes[1].child_ids = {3}; + + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kGroup; + initial_state.nodes[2].child_ids = {4}; + initial_state.nodes[2].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[3].id = 4; + initial_state.nodes[3].role = ax::mojom::Role::kGroup; + initial_state.nodes[3].child_ids = {5}; + initial_state.nodes[3].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[4].id = 5; + initial_state.nodes[4].role = ax::mojom::Role::kGroup; + initial_state.nodes[4].child_ids = {6, 7, 8}; + + initial_state.nodes[5].id = 6; + initial_state.nodes[5].role = ax::mojom::Role::kStaticText; + initial_state.nodes[5].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[6].id = 7; + initial_state.nodes[6].role = ax::mojom::Role::kStaticText; + + initial_state.nodes[7].id = 8; + initial_state.nodes[7].role = ax::mojom::Role::kStaticText; + + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes[0].AddState(ax::mojom::State::kIgnored); + update.nodes[5].RemoveState(ax::mojom::State::kIgnored); + update.nodes[6].AddState(ax::mojom::State::kIgnored); + update.nodes[7].AddState(ax::mojom::State::kIgnored); + ASSERT_TRUE(tree.Unserialize(update)); + EXPECT_THAT(event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 5), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 6), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 1), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 6))); +} + +TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly6) { + // BEFORE + // 1 (IGN) + // | + // 2 + // | + // 3 + // | + // 4 + // | + // ____ 5 _____ + // / | \ + // 6 (IGN) 7 (IGN) 8 + // AFTER + // 1 + // | + // 2 + // | + // 3 + // | + // 4 + // | + // ____ 5 _____ + // / | \ + // 6 7 8 (IGN) + + // IGNORED_CHANGED expected on #1, #6, #7, #8 + + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(8); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea; + initial_state.nodes[0].child_ids = {2}; + initial_state.nodes[0].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kGroup; + initial_state.nodes[1].child_ids = {3}; + + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kGroup; + initial_state.nodes[2].child_ids = {4}; + + initial_state.nodes[3].id = 4; + initial_state.nodes[3].role = ax::mojom::Role::kGroup; + initial_state.nodes[3].child_ids = {5}; + + initial_state.nodes[4].id = 5; + initial_state.nodes[4].role = ax::mojom::Role::kGroup; + initial_state.nodes[4].child_ids = {6, 7, 8}; + + initial_state.nodes[5].id = 6; + initial_state.nodes[5].role = ax::mojom::Role::kStaticText; + initial_state.nodes[5].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[6].id = 7; + initial_state.nodes[6].role = ax::mojom::Role::kStaticText; + initial_state.nodes[6].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[7].id = 8; + initial_state.nodes[7].role = ax::mojom::Role::kStaticText; + + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes[0].RemoveState(ax::mojom::State::kIgnored); + update.nodes[5].RemoveState(ax::mojom::State::kIgnored); + update.nodes[6].RemoveState(ax::mojom::State::kIgnored); + update.nodes[7].AddState(ax::mojom::State::kIgnored); + ASSERT_TRUE(tree.Unserialize(update)); + EXPECT_THAT(event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 5), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 1), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 6), + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 7), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 1), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 6), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 7), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 8))); +} + +TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly7) { + // BEFORE + // 1 (IGN) + // | + // 2 (IGN) + // | + // 3 + // | + // __ 4 ___ + // / \ + // 5 (IGN) 6 (IGN) + // AFTER + // 1 + // | + // 2 + // | + // 3 (IGN) + // | + // __ 4 (IGN) + // / \ + // 5 (IGN) 6 (IGN) + + // IGNORED_CHANGED expected on #1, #2, #3 + + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(6); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea; + initial_state.nodes[0].child_ids = {2}; + initial_state.nodes[0].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kGroup; + initial_state.nodes[1].child_ids = {3}; + initial_state.nodes[1].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kGroup; + initial_state.nodes[2].child_ids = {4}; + + initial_state.nodes[3].id = 4; + initial_state.nodes[3].role = ax::mojom::Role::kGroup; + initial_state.nodes[3].child_ids = {5, 6}; + + initial_state.nodes[4].id = 5; + initial_state.nodes[4].role = ax::mojom::Role::kStaticText; + initial_state.nodes[4].AddState(ax::mojom::State::kIgnored); + + initial_state.nodes[5].id = 6; + initial_state.nodes[5].role = ax::mojom::Role::kStaticText; + initial_state.nodes[5].AddState(ax::mojom::State::kIgnored); + + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes[0].RemoveState(ax::mojom::State::kIgnored); + update.nodes[1].RemoveState(ax::mojom::State::kIgnored); + update.nodes[2].AddState(ax::mojom::State::kIgnored); + update.nodes[3].AddState(ax::mojom::State::kIgnored); + ASSERT_TRUE(tree.Unserialize(update)); + EXPECT_THAT(event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::SUBTREE_CREATED, 1), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 1), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 2), + HasEventAtNode(AXEventGenerator::Event::IGNORED_CHANGED, 3))); +} + TEST(AXEventGeneratorTest, ActiveDescendantChangeOnDescendant) { AXTreeUpdate initial_state; initial_state.root_id = 1;
diff --git a/ui/android/java/src/org/chromium/ui/DropdownPopupWindowInterface.java b/ui/android/java/src/org/chromium/ui/DropdownPopupWindowInterface.java index 83e89fba..60ba7d5 100644 --- a/ui/android/java/src/org/chromium/ui/DropdownPopupWindowInterface.java +++ b/ui/android/java/src/org/chromium/ui/DropdownPopupWindowInterface.java
@@ -10,12 +10,9 @@ import android.widget.ListView; import android.widget.PopupWindow; -import androidx.annotation.VisibleForTesting; - /** * The interface for dropdown popup window. */ -@VisibleForTesting public interface DropdownPopupWindowInterface { /** * Sets the adapter that provides the data and the views to represent the data
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java index 96e78c26..0c589c4 100644 --- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java +++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
@@ -258,7 +258,6 @@ /** * Set the delegate that will handle android permissions requests. */ - @VisibleForTesting public void setAndroidPermissionDelegate(AndroidPermissionDelegate delegate) { mPermissionDelegate = delegate; } @@ -731,7 +730,6 @@ return mApplicationBottomInsetProvider; } - @VisibleForTesting public void setKeyboardDelegate(KeyboardVisibilityDelegate keyboardDelegate) { mKeyboardVisibilityDelegate = keyboardDelegate; // TODO(fhorschig): Remove - every caller should use the window to get the delegate.
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h index 2cc065a2..62004e65 100644 --- a/ui/base/clipboard/clipboard.h +++ b/ui/base/clipboard/clipboard.h
@@ -227,6 +227,12 @@ // Resets the clipboard last modified time to Time::Time(). virtual void ClearLastModifiedTime(); +#if defined(USE_OZONE) + // Returns whether the selection buffer is available. This is true for some + // Linux platforms. + virtual bool IsSelectionBufferAvailable() const = 0; +#endif // defined(USE_OZONE) + protected: // PortableFormat designates the type of data to be stored in the clipboard. // This designation is shared across all OSes. The system-specific designation
diff --git a/ui/base/clipboard/clipboard_non_backed.cc b/ui/base/clipboard/clipboard_non_backed.cc index 680deff..211e952864e 100644 --- a/ui/base/clipboard/clipboard_non_backed.cc +++ b/ui/base/clipboard/clipboard_non_backed.cc
@@ -585,6 +585,10 @@ clipboard_internal_->ReadData(format.GetName(), result); } +bool ClipboardNonBacked::IsSelectionBufferAvailable() const { + return false; +} + void ClipboardNonBacked::WritePortableRepresentations( ClipboardBuffer buffer, const ObjectMap& objects,
diff --git a/ui/base/clipboard/clipboard_non_backed.h b/ui/base/clipboard/clipboard_non_backed.h index da427a4..77dff2cd 100644 --- a/ui/base/clipboard/clipboard_non_backed.h +++ b/ui/base/clipboard/clipboard_non_backed.h
@@ -86,6 +86,7 @@ void ReadData(const ClipboardFormatType& format, const ClipboardDataEndpoint* data_dst, std::string* result) const override; + bool IsSelectionBufferAvailable() const override; void WritePortableRepresentations( ClipboardBuffer buffer, const ObjectMap& objects,
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc index 93db5c9a..4db9efa6 100644 --- a/ui/base/clipboard/clipboard_ozone.cc +++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -77,6 +77,7 @@ bool IsSelectionOwner(ClipboardBuffer buffer) override { return false; } void SetSequenceNumberUpdateCb( PlatformClipboard::SequenceNumberUpdateCb cb) override {} + bool IsSelectionBufferAvailable() const override { return false; } }; } // namespace @@ -101,6 +102,10 @@ ~AsyncClipboardOzone() = default; + bool IsSelectionBufferAvailable() const { + return platform_clipboard_->IsSelectionBufferAvailable(); + } + base::span<uint8_t> ReadClipboardDataAndWait(ClipboardBuffer buffer, const std::string& mime_type) { // We can use a fastpath if we are the owner of the selection. @@ -299,7 +304,7 @@ base::RepeatingTimer abort_timer_; // Provides communication to a system clipboard under ozone level. - PlatformClipboard* platform_clipboard_ = nullptr; + PlatformClipboard* const platform_clipboard_ = nullptr; base::flat_map<ClipboardBuffer, uint64_t> clipboard_sequence_number_; @@ -513,6 +518,10 @@ result->assign(clipboard_data.begin(), clipboard_data.end()); } +bool ClipboardOzone::IsSelectionBufferAvailable() const { + return async_clipboard_ozone_->IsSelectionBufferAvailable(); +} + // TODO(crbug.com/1103194): |data_src| should be supported void ClipboardOzone::WritePortableRepresentations( ClipboardBuffer buffer,
diff --git a/ui/base/clipboard/clipboard_ozone.h b/ui/base/clipboard/clipboard_ozone.h index 65b3ac19..c254b02 100644 --- a/ui/base/clipboard/clipboard_ozone.h +++ b/ui/base/clipboard/clipboard_ozone.h
@@ -66,6 +66,7 @@ void ReadData(const ClipboardFormatType& format, const ClipboardDataEndpoint* data_dst, std::string* result) const override; + bool IsSelectionBufferAvailable() const override; void WritePortableRepresentations( ClipboardBuffer buffer, const ObjectMap& objects,
diff --git a/ui/base/clipboard/test/test_clipboard.cc b/ui/base/clipboard/test/test_clipboard.cc index 93a37e5..5935c38 100644 --- a/ui/base/clipboard/test/test_clipboard.cc +++ b/ui/base/clipboard/test/test_clipboard.cc
@@ -239,6 +239,12 @@ last_modified_time_ = base::Time(); } +#if defined(USE_OZONE) +bool TestClipboard::IsSelectionBufferAvailable() const { + return false; +} +#endif // defined(USE_OZONE) + void TestClipboard::WritePortableRepresentations( ClipboardBuffer buffer, const ObjectMap& objects,
diff --git a/ui/base/clipboard/test/test_clipboard.h b/ui/base/clipboard/test/test_clipboard.h index 83324202..44f77a57 100644 --- a/ui/base/clipboard/test/test_clipboard.h +++ b/ui/base/clipboard/test/test_clipboard.h
@@ -78,6 +78,9 @@ std::string* result) const override; base::Time GetLastModifiedTime() const override; void ClearLastModifiedTime() override; +#if defined(USE_OZONE) + bool IsSelectionBufferAvailable() const override; +#endif // defined(USE_OZONE) void WritePortableRepresentations( ClipboardBuffer buffer, const ObjectMap& objects,
diff --git a/ui/base/mojom/clipboard_blink_mojom_traits.h b/ui/base/mojom/clipboard_blink_mojom_traits.h index e993d50..b49dd29 100644 --- a/ui/base/mojom/clipboard_blink_mojom_traits.h +++ b/ui/base/mojom/clipboard_blink_mojom_traits.h
@@ -26,12 +26,8 @@ *out = ui::ClipboardBuffer::kCopyPaste; return true; case blink::mojom::ClipboardBuffer::kSelection: -#if defined(USE_X11) *out = ui::ClipboardBuffer::kSelection; return true; -#else - return false; -#endif } return false; }
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn index e71fb2cd..219d6a8f 100644 --- a/ui/compositor/BUILD.gn +++ b/ui/compositor/BUILD.gn
@@ -208,14 +208,26 @@ } if (use_ozone) { - sources += [ "test/test_compositor_host_ozone.cc" ] + sources += [ + "test/test_compositor_host_ozone.cc", + "test/test_compositor_host_ozone.h", + ] deps += [ "//ui/ozone", "//ui/platform_window", ] - } else if (use_x11) { - sources += [ "test/test_compositor_host_x11.cc" ] + } + + if (use_x11) { + sources += [ + "test/test_compositor_host_x11.cc", + "test/test_compositor_host_x11.h", + ] + } + + if (is_linux) { + sources += [ "test/test_compositor_host_linux.cc" ] } }
diff --git a/ui/compositor/test/test_compositor_host_linux.cc b/ui/compositor/test/test_compositor_host_linux.cc new file mode 100644 index 0000000..7dd512d --- /dev/null +++ b/ui/compositor/test/test_compositor_host_linux.cc
@@ -0,0 +1,35 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/compositor/test/test_compositor_host.h" + +#include "base/notreached.h" + +#if defined(USE_OZONE) +#include "ui/base/ui_base_features.h" +#include "ui/compositor/test/test_compositor_host_ozone.h" +#endif + +#if defined(USE_X11) +#include "ui/compositor/test/test_compositor_host_x11.h" +#endif + +namespace ui { + +// static +TestCompositorHost* TestCompositorHost::Create( + const gfx::Rect& bounds, + ui::ContextFactory* context_factory) { +#if defined(USE_OZONE) + if (features::IsUsingOzonePlatform()) + return new TestCompositorHostOzone(bounds, context_factory); +#endif +#if defined(USE_X11) + return new TestCompositorHostX11(bounds, context_factory); +#endif + NOTREACHED(); + return nullptr; +} + +} // namespace ui
diff --git a/ui/compositor/test/test_compositor_host_ozone.cc b/ui/compositor/test/test_compositor_host_ozone.cc index 50b77ca7..7a6179d 100644 --- a/ui/compositor/test/test_compositor_host_ozone.cc +++ b/ui/compositor/test/test_compositor_host_ozone.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/compositor/test/test_compositor_host.h" +#include "ui/compositor/test/test_compositor_host_ozone.h" #include <memory> @@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "build/build_config.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "ui/compositor/compositor.h" #include "ui/gfx/geometry/rect.h" @@ -24,11 +25,10 @@ namespace ui { -namespace { - // Stub implementation of PlatformWindowDelegate that stores the // AcceleratedWidget. -class StubPlatformWindowDelegate : public PlatformWindowDelegate { +class TestCompositorHostOzone::StubPlatformWindowDelegate + : public PlatformWindowDelegate { public: StubPlatformWindowDelegate() {} ~StubPlatformWindowDelegate() override {} @@ -59,26 +59,6 @@ DISALLOW_COPY_AND_ASSIGN(StubPlatformWindowDelegate); }; -class TestCompositorHostOzone : public TestCompositorHost { - public: - TestCompositorHostOzone(const gfx::Rect& bounds, - ui::ContextFactory* context_factory); - ~TestCompositorHostOzone() override; - - private: - // Overridden from TestCompositorHost: - void Show() override; - ui::Compositor* GetCompositor() override; - - gfx::Rect bounds_; - ui::Compositor compositor_; - std::unique_ptr<PlatformWindow> window_; - StubPlatformWindowDelegate window_delegate_; - viz::ParentLocalSurfaceIdAllocator allocator_; - - DISALLOW_COPY_AND_ASSIGN(TestCompositorHostOzone); -}; - TestCompositorHostOzone::TestCompositorHostOzone( const gfx::Rect& bounds, ui::ContextFactory* context_factory) @@ -86,7 +66,8 @@ compositor_(context_factory->AllocateFrameSinkId(), context_factory, base::ThreadTaskRunnerHandle::Get(), - false /* enable_pixel_canvas */) {} + false /* enable_pixel_canvas */), + window_delegate_(std::make_unique<StubPlatformWindowDelegate>()) {} TestCompositorHostOzone::~TestCompositorHostOzone() { // |window_| should be destroyed earlier than |window_delegate_| as it refers @@ -99,12 +80,12 @@ properties.bounds = bounds_; // Create a PlatformWindow to get the AcceleratedWidget backing it. window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow( - &window_delegate_, std::move(properties)); + window_delegate_.get(), std::move(properties)); window_->Show(); - DCHECK_NE(window_delegate_.widget(), gfx::kNullAcceleratedWidget); + DCHECK_NE(window_delegate_->widget(), gfx::kNullAcceleratedWidget); allocator_.GenerateId(); - compositor_.SetAcceleratedWidget(window_delegate_.widget()); + compositor_.SetAcceleratedWidget(window_delegate_->widget()); compositor_.SetScaleAndSize(1.0f, bounds_.size(), allocator_.GetCurrentLocalSurfaceIdAllocation()); compositor_.SetVisible(true); @@ -114,13 +95,16 @@ return &compositor_; } -} // namespace - +// To avoid multiple definitions when use_x11 && use_ozone is true, disable this +// factory method for OS_LINUX as Linux has a factory method that decides what +// screen to use based on IsUsingOzonePlatform feature flag. +#if !defined(OS_LINUX) // static TestCompositorHost* TestCompositorHost::Create( const gfx::Rect& bounds, ui::ContextFactory* context_factory) { return new TestCompositorHostOzone(bounds, context_factory); } +#endif } // namespace ui
diff --git a/ui/compositor/test/test_compositor_host_ozone.h b/ui/compositor/test/test_compositor_host_ozone.h new file mode 100644 index 0000000..7b764f20 --- /dev/null +++ b/ui/compositor/test/test_compositor_host_ozone.h
@@ -0,0 +1,44 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_COMPOSITOR_TEST_TEST_COMPOSITOR_HOST_OZONE_H_ +#define UI_COMPOSITOR_TEST_TEST_COMPOSITOR_HOST_OZONE_H_ + +#include "ui/compositor/test/test_compositor_host.h" + +#include <memory> + +#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "ui/compositor/compositor.h" +#include "ui/gfx/geometry/rect.h" + +namespace ui { + +class PlatformWindow; + +class TestCompositorHostOzone : public TestCompositorHost { + public: + TestCompositorHostOzone(const gfx::Rect& bounds, + ui::ContextFactory* context_factory); + TestCompositorHostOzone(const TestCompositorHostOzone&) = delete; + TestCompositorHostOzone& operator=(const TestCompositorHostOzone&) = delete; + ~TestCompositorHostOzone() override; + + private: + class StubPlatformWindowDelegate; + + // Overridden from TestCompositorHost: + void Show() override; + ui::Compositor* GetCompositor() override; + + gfx::Rect bounds_; + ui::Compositor compositor_; + std::unique_ptr<PlatformWindow> window_; + std::unique_ptr<StubPlatformWindowDelegate> window_delegate_; + viz::ParentLocalSurfaceIdAllocator allocator_; +}; + +} // namespace ui + +#endif // UI_COMPOSITOR_TEST_TEST_COMPOSITOR_HOST_OZONE_H_
diff --git a/ui/compositor/test/test_compositor_host_x11.cc b/ui/compositor/test/test_compositor_host_x11.cc index 1f866da..cff7ee7 100644 --- a/ui/compositor/test/test_compositor_host_x11.cc +++ b/ui/compositor/test/test_compositor_host_x11.cc
@@ -2,50 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/compositor/test/test_compositor_host.h" - -#include <memory> +#include "ui/compositor/test/test_compositor_host_x11.h" #include "base/bind.h" #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" -#include "ui/compositor/compositor.h" #include "ui/events/x/x11_window_event_manager.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/x/x11.h" -#include "ui/gfx/x/x11_types.h" namespace ui { -class TestCompositorHostX11 : public TestCompositorHost { - public: - TestCompositorHostX11(const gfx::Rect& bounds, - ui::ContextFactory* context_factory); - ~TestCompositorHostX11() override; - - private: - // Overridden from TestCompositorHost: - void Show() override; - ui::Compositor* GetCompositor() override; - - gfx::Rect bounds_; - - ui::ContextFactory* context_factory_; - - ui::Compositor compositor_; - - x11::Window window_; - - std::unique_ptr<XScopedEventSelector> window_events_; - viz::ParentLocalSurfaceIdAllocator allocator_; - - DISALLOW_COPY_AND_ASSIGN(TestCompositorHostX11); -}; - TestCompositorHostX11::TestCompositorHostX11( const gfx::Rect& bounds, ui::ContextFactory* context_factory) @@ -88,11 +55,4 @@ return &compositor_; } -// static -TestCompositorHost* TestCompositorHost::Create( - const gfx::Rect& bounds, - ui::ContextFactory* context_factory) { - return new TestCompositorHostX11(bounds, context_factory); -} - } // namespace ui
diff --git a/ui/compositor/test/test_compositor_host_x11.h b/ui/compositor/test/test_compositor_host_x11.h new file mode 100644 index 0000000..4e10912 --- /dev/null +++ b/ui/compositor/test/test_compositor_host_x11.h
@@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_COMPOSITOR_TEST_TEST_COMPOSITOR_HOST_X11_H_ +#define UI_COMPOSITOR_TEST_TEST_COMPOSITOR_HOST_X11_H_ + +#include <memory> + +#include "base/time/time.h" +#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "ui/compositor/compositor.h" +#include "ui/compositor/test/test_compositor_host.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/x/x11.h" +#include "ui/gfx/x/x11_types.h" + +namespace ui { + +class XScopedEventSelector; + +class TestCompositorHostX11 : public TestCompositorHost { + public: + TestCompositorHostX11(const gfx::Rect& bounds, + ui::ContextFactory* context_factory); + TestCompositorHostX11(const TestCompositorHostX11&) = delete; + TestCompositorHostX11& operator=(const TestCompositorHostX11&) = delete; + ~TestCompositorHostX11() override; + + private: + // Overridden from TestCompositorHost: + void Show() override; + ui::Compositor* GetCompositor() override; + + gfx::Rect bounds_; + + ui::ContextFactory* context_factory_; + + ui::Compositor compositor_; + + x11::Window window_; + + std::unique_ptr<XScopedEventSelector> window_events_; + viz::ParentLocalSurfaceIdAllocator allocator_; +}; + +} // namespace ui + +#endif // UI_COMPOSITOR_TEST_TEST_COMPOSITOR_HOST_X11_H_
diff --git a/ui/display/manager/display_configurator.cc b/ui/display/manager/display_configurator.cc index 7f7c2bbc..53dc139 100644 --- a/ui/display/manager/display_configurator.cc +++ b/ui/display/manager/display_configurator.cc
@@ -44,31 +44,14 @@ const DisplayMode* mirror_mode = nullptr; }; -// This is used for calling either SetColorMatrix() or SetGammaCorrection() -// depending on the given |color_correction_closure| which is run synchronously. -// If |reset_color_space_on_success| is true and running -// |color_correction_closure| returns true, then the color space of the display -// with |display_id| will be reset. -bool RunColorCorrectionClosureSync( +// Returns whether |display_id| can be found in |display_list|, +bool IsDisplayIdInDisplayStateList( int64_t display_id, - const DisplayConfigurator::DisplayStateList& cached_displays, - bool reset_color_space_on_success, - base::OnceCallback<bool(void)> color_correction_closure) { - for (DisplaySnapshot* display : cached_displays) { - if (display->display_id() != display_id) - continue; - - const bool success = std::move(color_correction_closure).Run(); - - // Nullify the |display|s ColorSpace to avoid correcting colors twice, if - // we have successfully configured something. - if (success && reset_color_space_on_success) - display->reset_color_space(); - - return success; - } - - return false; + const DisplayConfigurator::DisplayStateList& display_list) { + return std::find_if(display_list.begin(), display_list.end(), + [display_id](DisplaySnapshot* display) { + return display->display_id() == display_id; + }) != display_list.end(); } // Returns true if a platform native |mode| is equal to a |managed_mode|. @@ -761,25 +744,19 @@ bool DisplayConfigurator::SetColorMatrix( int64_t display_id, const std::vector<float>& color_matrix) { - return RunColorCorrectionClosureSync( - display_id, cached_displays_, - !color_matrix.empty() /* reset_color_space_on_success */, - base::BindOnce(&NativeDisplayDelegate::SetColorMatrix, - base::Unretained(native_display_delegate_.get()), - display_id, color_matrix)); + if (!IsDisplayIdInDisplayStateList(display_id, cached_displays_)) + return false; + return native_display_delegate_->SetColorMatrix(display_id, color_matrix); } bool DisplayConfigurator::SetGammaCorrection( int64_t display_id, const std::vector<GammaRampRGBEntry>& degamma_lut, const std::vector<GammaRampRGBEntry>& gamma_lut) { - const bool reset_color_space_on_success = - !degamma_lut.empty() || !gamma_lut.empty(); - return RunColorCorrectionClosureSync( - display_id, cached_displays_, reset_color_space_on_success, - base::BindOnce(&NativeDisplayDelegate::SetGammaCorrection, - base::Unretained(native_display_delegate_.get()), - display_id, degamma_lut, gamma_lut)); + if (!IsDisplayIdInDisplayStateList(display_id, cached_displays_)) + return false; + return native_display_delegate_->SetGammaCorrection(display_id, degamma_lut, + gamma_lut); } void DisplayConfigurator::SetPrivacyScreen(int64_t display_id, bool enabled) {
diff --git a/ui/display/types/display_snapshot.h b/ui/display/types/display_snapshot.h index 22c567a..fc552e50 100644 --- a/ui/display/types/display_snapshot.h +++ b/ui/display/types/display_snapshot.h
@@ -71,7 +71,6 @@ return color_correction_in_linear_space_; } const gfx::ColorSpace& color_space() const { return color_space_; } - void reset_color_space() { color_space_ = gfx::ColorSpace(); } uint32_t bits_per_channel() const { return bits_per_channel_; } const std::string& display_name() const { return display_name_; } const base::FilePath& sys_path() const { return sys_path_; } @@ -122,7 +121,7 @@ // instead of gamma compressed one. const bool color_correction_in_linear_space_; - gfx::ColorSpace color_space_; + const gfx::ColorSpace color_space_; uint32_t bits_per_channel_;
diff --git a/ui/ozone/platform/wayland/common/wayland_util.cc b/ui/ozone/platform/wayland/common/wayland_util.cc index 19d33ef4..3b0b882 100644 --- a/ui/ozone/platform/wayland/common/wayland_util.cc +++ b/ui/ozone/platform/wayland/common/wayland_util.cc
@@ -172,4 +172,16 @@ return wayland_surface->root_window(); } +gfx::Rect TranslateWindowBoundsToParentDIP(ui::WaylandWindow* window, + ui::WaylandWindow* parent_window) { + DCHECK(window); + DCHECK(parent_window); + DCHECK_EQ(window->buffer_scale(), parent_window->buffer_scale()); + DCHECK_EQ(window->ui_scale(), parent_window->ui_scale()); + return gfx::ScaleToRoundedRect( + wl::TranslateBoundsToParentCoordinates(window->GetBounds(), + parent_window->GetBounds()), + 1.0 / window->buffer_scale()); +} + } // namespace wl
diff --git a/ui/ozone/platform/wayland/common/wayland_util.h b/ui/ozone/platform/wayland/common/wayland_util.h index 918f4c6..582a3c7 100644 --- a/ui/ozone/platform/wayland/common/wayland_util.h +++ b/ui/ozone/platform/wayland/common/wayland_util.h
@@ -66,6 +66,13 @@ // Returns the root WaylandWindow for the given wl_surface. ui::WaylandWindow* RootWindowFromWlSurface(wl_surface* surface); +// Returns bounds of the given window, adjusted to its subsurface. We need to +// adjust bounds because WaylandWindow::GetBounds() returns absolute bounds in +// pixels, but wl_subsurface works with bounds relative to the parent surface +// and in DIP. +gfx::Rect TranslateWindowBoundsToParentDIP(ui::WaylandWindow* window, + ui::WaylandWindow* parent_window); + } // namespace wl #endif // UI_OZONE_PLATFORM_WAYLAND_COMMON_WAYLAND_UTIL_H_
diff --git a/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc b/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc index e1859d75..c5e31fd5 100644 --- a/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_auxiliary_window.cc
@@ -12,21 +12,6 @@ namespace ui { -namespace { - -gfx::Rect AdjustSubsurfaceBounds(const gfx::Rect& bounds_px, - const gfx::Rect& parent_bounds_px, - float ui_scale, - int32_t buffer_scale) { - const auto parent_bounds_dip = - gfx::ScaleToRoundedRect(parent_bounds_px, 1.0 / ui_scale); - auto new_bounds_dip = - wl::TranslateBoundsToParentCoordinates(bounds_px, parent_bounds_dip); - return gfx::ScaleToRoundedRect(new_bounds_dip, ui_scale / buffer_scale); -} - -} // namespace - WaylandAuxiliaryWindow::WaylandAuxiliaryWindow(PlatformWindowDelegate* delegate, WaylandConnection* connection) : WaylandWindow(delegate, connection) {} @@ -63,11 +48,10 @@ if (old_bounds == bounds || !parent_window()) return; - // Translate location from screen to surface coordinates. - auto bounds_px = AdjustSubsurfaceBounds( - GetBounds(), parent_window()->GetBounds(), ui_scale(), buffer_scale()); - wl_subsurface_set_position(subsurface_.get(), bounds_px.x() / buffer_scale(), - bounds_px.y() / buffer_scale()); + auto subsurface_bounds_dip = + wl::TranslateWindowBoundsToParentDIP(this, parent_window()); + wl_subsurface_set_position(subsurface_.get(), subsurface_bounds_dip.x(), + subsurface_bounds_dip.y()); root_surface()->Commit(); connection()->ScheduleFlush(); } @@ -99,16 +83,13 @@ subsurface_ = root_surface()->CreateSubsurface(parent->root_surface()); - // Chromium positions tooltip windows in screen coordinates, but Wayland - // requires them to be in local surface coordinates a.k.a relative to parent - // window. - auto bounds_px = AdjustSubsurfaceBounds(GetBounds(), parent->GetBounds(), - ui_scale(), buffer_scale()); + auto subsurface_bounds_dip = + wl::TranslateWindowBoundsToParentDIP(this, parent); DCHECK(subsurface_); // Convert position to DIP. - wl_subsurface_set_position(subsurface_.get(), bounds_px.x() / buffer_scale(), - bounds_px.y() / buffer_scale()); + wl_subsurface_set_position(subsurface_.get(), subsurface_bounds_dip.x(), + subsurface_bounds_dip.y()); wl_subsurface_set_desync(subsurface_.get()); parent->root_surface()->Commit(); connection()->ScheduleFlush();
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/ui/ozone/platform/wayland/host/wayland_clipboard.cc index cd99fdd..7e1cdf1a 100644 --- a/ui/ozone/platform/wayland/host/wayland_clipboard.cc +++ b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
@@ -185,6 +185,10 @@ std::move(callback).Run(mime_types); } +bool WaylandClipboard::IsSelectionBufferAvailable() const { + return (connection_->primary_selection_device_manager() != nullptr); +} + void WaylandClipboard::SetData(PlatformClipboard::Data contents, const std::string& mime_type) { if (!data_map_)
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard.h b/ui/ozone/platform/wayland/host/wayland_clipboard.h index c8b724d..515c85c 100644 --- a/ui/ozone/platform/wayland/host/wayland_clipboard.h +++ b/ui/ozone/platform/wayland/host/wayland_clipboard.h
@@ -53,6 +53,7 @@ bool IsSelectionOwner(ClipboardBuffer buffer) override; void SetSequenceNumberUpdateCb( PlatformClipboard::SequenceNumberUpdateCb cb) override; + bool IsSelectionBufferAvailable() const override; // TODO(nickdiego): Get rid of these methods once DataDevice implementations // are decoupled from WaylandClipboard.
diff --git a/ui/ozone/platform/wayland/host/wayland_popup.cc b/ui/ozone/platform/wayland/host/wayland_popup.cc index ec7e27e..f1f7c8d 100644 --- a/ui/ozone/platform/wayland/host/wayland_popup.cc +++ b/ui/ozone/platform/wayland/host/wayland_popup.cc
@@ -24,10 +24,12 @@ DCHECK(parent_window() && !shell_popup_); - auto bounds_px = AdjustPopupWindowPosition(); + auto subsurface_bounds_dip = + wl::TranslateWindowBoundsToParentDIP(this, parent_window()); ShellObjectFactory factory; - shell_popup_ = factory.CreateShellPopupWrapper(connection(), this, bounds_px); + shell_popup_ = factory.CreateShellPopupWrapper(connection(), this, + subsurface_bounds_dip); if (!shell_popup_) { LOG(ERROR) << "Failed to create Wayland shell popup"; return false; @@ -143,20 +145,4 @@ return true; } -gfx::Rect WaylandPopup::AdjustPopupWindowPosition() { - auto* top_level_parent = GetRootParentWindow(); - DCHECK(top_level_parent); - DCHECK(buffer_scale() == top_level_parent->buffer_scale()); - DCHECK(ui_scale() == top_level_parent->ui_scale()); - - // Chromium positions windows in screen coordinates, but Wayland requires them - // to be in local surface coordinates a.k.a relative to parent window. - const gfx::Rect parent_bounds_dip = - gfx::ScaleToRoundedRect(parent_window()->GetBounds(), 1.0 / ui_scale()); - gfx::Rect new_bounds_dip = wl::TranslateBoundsToParentCoordinates( - gfx::ScaleToRoundedRect(GetBounds(), 1.0 / ui_scale()), - parent_bounds_dip); - return gfx::ScaleToRoundedRect(new_bounds_dip, ui_scale() / buffer_scale()); -} - } // namespace ui
diff --git a/ui/ozone/platform/x11/x11_clipboard_ozone.cc b/ui/ozone/platform/x11/x11_clipboard_ozone.cc index e23c83b..c913289 100644 --- a/ui/ozone/platform/x11/x11_clipboard_ozone.cc +++ b/ui/ozone/platform/x11/x11_clipboard_ozone.cc
@@ -398,4 +398,8 @@ update_sequence_cb_ = std::move(cb); } +bool X11ClipboardOzone::IsSelectionBufferAvailable() const { + return true; +} + } // namespace ui
diff --git a/ui/ozone/platform/x11/x11_clipboard_ozone.h b/ui/ozone/platform/x11/x11_clipboard_ozone.h index 478205c..a8c0c96 100644 --- a/ui/ozone/platform/x11/x11_clipboard_ozone.h +++ b/ui/ozone/platform/x11/x11_clipboard_ozone.h
@@ -49,6 +49,7 @@ bool IsSelectionOwner(ClipboardBuffer buffer) override; void SetSequenceNumberUpdateCb( PlatformClipboard::SequenceNumberUpdateCb cb) override; + bool IsSelectionBufferAvailable() const override; private: struct SelectionState;
diff --git a/ui/ozone/public/platform_clipboard.h b/ui/ozone/public/platform_clipboard.h index 7390222..941e2377 100644 --- a/ui/ozone/public/platform_clipboard.h +++ b/ui/ozone/public/platform_clipboard.h
@@ -90,6 +90,9 @@ // See comment above SequenceNumberUpdateCb. Can be called once. virtual void SetSequenceNumberUpdateCb(SequenceNumberUpdateCb cb) = 0; + + // Returns whether the kSelection buffer is available. + virtual bool IsSelectionBufferAvailable() const = 0; }; } // namespace ui
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn index 8805b11..c9ab2ff 100644 --- a/weblayer/BUILD.gn +++ b/weblayer/BUILD.gn
@@ -214,6 +214,8 @@ "browser/no_state_prefetch/prerender_processor_impl_delegate_impl.h", "browser/page_load_metrics_initialize.cc", "browser/page_load_metrics_initialize.h", + "browser/page_specific_content_settings_delegate.cc", + "browser/page_specific_content_settings_delegate.h", "browser/password_manager_driver_factory.cc", "browser/password_manager_driver_factory.h", "browser/permissions/geolocation_permission_context_delegate.cc", @@ -248,8 +250,6 @@ "browser/system_network_context_manager.h", "browser/tab_impl.cc", "browser/tab_impl.h", - "browser/tab_specific_content_settings_delegate.cc", - "browser/tab_specific_content_settings_delegate.h", "browser/translate_accept_languages_factory.cc", "browser/translate_accept_languages_factory.h", "browser/translate_client_impl.cc",
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc index c73a95e..47928a3 100644 --- a/weblayer/browser/content_browser_client_impl.cc +++ b/weblayer/browser/content_browser_client_impl.cc
@@ -76,13 +76,13 @@ #include "weblayer/browser/i18n_util.h" #include "weblayer/browser/navigation_controller_impl.h" #include "weblayer/browser/navigation_error_navigation_throttle.h" +#include "weblayer/browser/page_specific_content_settings_delegate.h" #include "weblayer/browser/password_manager_driver_factory.h" #include "weblayer/browser/popup_navigation_delegate_impl.h" #include "weblayer/browser/profile_impl.h" #include "weblayer/browser/signin_url_loader_throttle.h" #include "weblayer/browser/system_network_context_manager.h" #include "weblayer/browser/tab_impl.h" -#include "weblayer/browser/tab_specific_content_settings_delegate.h" #include "weblayer/browser/user_agent.h" #include "weblayer/browser/web_contents_view_delegate_impl.h" #include "weblayer/browser/weblayer_browser_interface_binders.h" @@ -692,7 +692,7 @@ /*can_persist_data*/ true, /*force_to_support_secure_codecs*/ false)); #endif - TabSpecificContentSettingsDelegate::UpdateRendererContentSettingRules(host); + PageSpecificContentSettingsDelegate::UpdateRendererContentSettingRules(host); } scoped_refptr<content::QuotaPermissionContext>
diff --git a/weblayer/browser/tab_specific_content_settings_delegate.cc b/weblayer/browser/page_specific_content_settings_delegate.cc similarity index 67% rename from weblayer/browser/tab_specific_content_settings_delegate.cc rename to weblayer/browser/page_specific_content_settings_delegate.cc index 9db88a2..e07b644a 100644 --- a/weblayer/browser/tab_specific_content_settings_delegate.cc +++ b/weblayer/browser/page_specific_content_settings_delegate.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "weblayer/browser/tab_specific_content_settings_delegate.h" +#include "weblayer/browser/page_specific_content_settings_delegate.h" #include "base/bind_helpers.h" #include "components/content_settings/core/common/content_settings.h" @@ -25,15 +25,15 @@ } // namespace -TabSpecificContentSettingsDelegate::TabSpecificContentSettingsDelegate( +PageSpecificContentSettingsDelegate::PageSpecificContentSettingsDelegate( content::WebContents* web_contents) : web_contents_(web_contents) {} -TabSpecificContentSettingsDelegate::~TabSpecificContentSettingsDelegate() = +PageSpecificContentSettingsDelegate::~PageSpecificContentSettingsDelegate() = default; // static -void TabSpecificContentSettingsDelegate::UpdateRendererContentSettingRules( +void PageSpecificContentSettingsDelegate::UpdateRendererContentSettingRules( content::RenderProcessHost* process) { RendererContentSettingRules rules; GetRendererContentSettingRules( @@ -43,25 +43,25 @@ weblayer::SetContentSettingRules(process, rules); } -void TabSpecificContentSettingsDelegate::UpdateLocationBar() {} +void PageSpecificContentSettingsDelegate::UpdateLocationBar() {} -void TabSpecificContentSettingsDelegate::SetContentSettingRules( +void PageSpecificContentSettingsDelegate::SetContentSettingRules( content::RenderProcessHost* process, const RendererContentSettingRules& rules) { weblayer::SetContentSettingRules(process, rules); } -PrefService* TabSpecificContentSettingsDelegate::GetPrefs() { +PrefService* PageSpecificContentSettingsDelegate::GetPrefs() { return static_cast<BrowserContextImpl*>(web_contents_->GetBrowserContext()) ->pref_service(); } -HostContentSettingsMap* TabSpecificContentSettingsDelegate::GetSettingsMap() { +HostContentSettingsMap* PageSpecificContentSettingsDelegate::GetSettingsMap() { return HostContentSettingsMapFactory::GetForBrowserContext( web_contents_->GetBrowserContext()); } -ContentSetting TabSpecificContentSettingsDelegate::GetEmbargoSetting( +ContentSetting PageSpecificContentSettingsDelegate::GetEmbargoSetting( const GURL& request_origin, ContentSettingsType permission) { return PermissionDecisionAutoBlockerFactory::GetForBrowserContext( @@ -71,33 +71,33 @@ } std::vector<storage::FileSystemType> -TabSpecificContentSettingsDelegate::GetAdditionalFileSystemTypes() { +PageSpecificContentSettingsDelegate::GetAdditionalFileSystemTypes() { return {}; } browsing_data::CookieHelper::IsDeletionDisabledCallback -TabSpecificContentSettingsDelegate::GetIsDeletionDisabledCallback() { +PageSpecificContentSettingsDelegate::GetIsDeletionDisabledCallback() { return base::NullCallback(); } -bool TabSpecificContentSettingsDelegate::IsMicrophoneCameraStateChanged( - content_settings::TabSpecificContentSettings::MicrophoneCameraState +bool PageSpecificContentSettingsDelegate::IsMicrophoneCameraStateChanged( + content_settings::PageSpecificContentSettings::MicrophoneCameraState microphone_camera_state, const std::string& media_stream_selected_audio_device, const std::string& media_stream_selected_video_device) { return false; } -content_settings::TabSpecificContentSettings::MicrophoneCameraState -TabSpecificContentSettingsDelegate::GetMicrophoneCameraState() { - return content_settings::TabSpecificContentSettings:: +content_settings::PageSpecificContentSettings::MicrophoneCameraState +PageSpecificContentSettingsDelegate::GetMicrophoneCameraState() { + return content_settings::PageSpecificContentSettings:: MICROPHONE_CAMERA_NOT_ACCESSED; } -void TabSpecificContentSettingsDelegate::OnContentBlocked( +void PageSpecificContentSettingsDelegate::OnContentBlocked( ContentSettingsType type) {} -void TabSpecificContentSettingsDelegate::OnCookieAccessAllowed( +void PageSpecificContentSettingsDelegate::OnCookieAccessAllowed( const net::CookieList& accessed_cookies) {} } // namespace weblayer
diff --git a/weblayer/browser/page_specific_content_settings_delegate.h b/weblayer/browser/page_specific_content_settings_delegate.h new file mode 100644 index 0000000..29dd868 --- /dev/null +++ b/weblayer/browser/page_specific_content_settings_delegate.h
@@ -0,0 +1,55 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ +#define WEBLAYER_BROWSER_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ + +#include "components/content_settings/browser/page_specific_content_settings.h" + +namespace weblayer { + +// Called by PageSpecificContentSettings to handle WebLayer specific logic. +class PageSpecificContentSettingsDelegate + : public content_settings::PageSpecificContentSettings::Delegate { + public: + explicit PageSpecificContentSettingsDelegate( + content::WebContents* web_contents); + ~PageSpecificContentSettingsDelegate() override; + PageSpecificContentSettingsDelegate( + const PageSpecificContentSettingsDelegate&) = delete; + PageSpecificContentSettingsDelegate& operator=( + const PageSpecificContentSettingsDelegate&) = delete; + + static void UpdateRendererContentSettingRules( + content::RenderProcessHost* process); + + private: + // PageSpecificContentSettings::Delegate: + void UpdateLocationBar() override; + void SetContentSettingRules( + content::RenderProcessHost* process, + const RendererContentSettingRules& rules) override; + PrefService* GetPrefs() override; + HostContentSettingsMap* GetSettingsMap() override; + ContentSetting GetEmbargoSetting(const GURL& request_origin, + ContentSettingsType permission) override; + std::vector<storage::FileSystemType> GetAdditionalFileSystemTypes() override; + browsing_data::CookieHelper::IsDeletionDisabledCallback + GetIsDeletionDisabledCallback() override; + bool IsMicrophoneCameraStateChanged( + content_settings::PageSpecificContentSettings::MicrophoneCameraState + microphone_camera_state, + const std::string& media_stream_selected_audio_device, + const std::string& media_stream_selected_video_device) override; + content_settings::PageSpecificContentSettings::MicrophoneCameraState + GetMicrophoneCameraState() override; + void OnContentBlocked(ContentSettingsType type) override; + void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override; + + content::WebContents* web_contents_; +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_PAGE_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
diff --git a/weblayer/browser/tab_impl.cc b/weblayer/browser/tab_impl.cc index 34afe11..535ca4c 100644 --- a/weblayer/browser/tab_impl.cc +++ b/weblayer/browser/tab_impl.cc
@@ -21,7 +21,7 @@ #include "components/blocked_content/popup_opener_tab_helper.h" #include "components/blocked_content/popup_tracker.h" #include "components/captive_portal/core/buildflags.h" -#include "components/content_settings/browser/tab_specific_content_settings.h" +#include "components/content_settings/browser/page_specific_content_settings.h" #include "components/find_in_page/find_tab_helper.h" #include "components/find_in_page/find_types.h" #include "components/js_injection/browser/js_communication_host.h" @@ -63,12 +63,12 @@ #include "weblayer/browser/js_communication/web_message_host_factory_wrapper.h" #include "weblayer/browser/navigation_controller_impl.h" #include "weblayer/browser/page_load_metrics_initialize.h" +#include "weblayer/browser/page_specific_content_settings_delegate.h" #include "weblayer/browser/password_manager_driver_factory.h" #include "weblayer/browser/permissions/permission_manager_factory.h" #include "weblayer/browser/persistence/browser_persister.h" #include "weblayer/browser/popup_navigation_delegate_impl.h" #include "weblayer/browser/profile_impl.h" -#include "weblayer/browser/tab_specific_content_settings_delegate.h" #include "weblayer/browser/translate_client_impl.h" #include "weblayer/browser/weblayer_features.h" #include "weblayer/common/isolated_world_ids.h" @@ -305,9 +305,10 @@ permissions::PermissionRequestManager::CreateForWebContents( web_contents_.get()); - content_settings::TabSpecificContentSettings::CreateForWebContents( - web_contents_.get(), std::make_unique<TabSpecificContentSettingsDelegate>( - web_contents_.get())); + content_settings::PageSpecificContentSettings::CreateForWebContents( + web_contents_.get(), + std::make_unique<PageSpecificContentSettingsDelegate>( + web_contents_.get())); blocked_content::PopupBlockerTabHelper::CreateForWebContents( web_contents_.get()); blocked_content::PopupOpenerTabHelper::CreateForWebContents(
diff --git a/weblayer/browser/tab_specific_content_settings_delegate.h b/weblayer/browser/tab_specific_content_settings_delegate.h deleted file mode 100644 index b987b745..0000000 --- a/weblayer/browser/tab_specific_content_settings_delegate.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef WEBLAYER_BROWSER_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ -#define WEBLAYER_BROWSER_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_ - -#include "components/content_settings/browser/tab_specific_content_settings.h" - -namespace weblayer { - -// Called by TabSpecificContentSettings to handle WebLayer specific logic. -class TabSpecificContentSettingsDelegate - : public content_settings::TabSpecificContentSettings::Delegate { - public: - explicit TabSpecificContentSettingsDelegate( - content::WebContents* web_contents); - ~TabSpecificContentSettingsDelegate() override; - TabSpecificContentSettingsDelegate( - const TabSpecificContentSettingsDelegate&) = delete; - TabSpecificContentSettingsDelegate& operator=( - const TabSpecificContentSettingsDelegate&) = delete; - - static void UpdateRendererContentSettingRules( - content::RenderProcessHost* process); - - private: - // TabSpecificContentSettings::Delegate: - void UpdateLocationBar() override; - void SetContentSettingRules( - content::RenderProcessHost* process, - const RendererContentSettingRules& rules) override; - PrefService* GetPrefs() override; - HostContentSettingsMap* GetSettingsMap() override; - ContentSetting GetEmbargoSetting(const GURL& request_origin, - ContentSettingsType permission) override; - std::vector<storage::FileSystemType> GetAdditionalFileSystemTypes() override; - browsing_data::CookieHelper::IsDeletionDisabledCallback - GetIsDeletionDisabledCallback() override; - bool IsMicrophoneCameraStateChanged( - content_settings::TabSpecificContentSettings::MicrophoneCameraState - microphone_camera_state, - const std::string& media_stream_selected_audio_device, - const std::string& media_stream_selected_video_device) override; - content_settings::TabSpecificContentSettings::MicrophoneCameraState - GetMicrophoneCameraState() override; - void OnContentBlocked(ContentSettingsType type) override; - void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override; - - content::WebContents* web_contents_; -}; - -} // namespace weblayer - -#endif // WEBLAYER_BROWSER_TAB_SPECIFIC_CONTENT_SETTINGS_DELEGATE_H_
diff --git a/weblayer/browser/url_bar/page_info_browsertest.cc b/weblayer/browser/url_bar/page_info_browsertest.cc index dc4ad64..6c59719 100644 --- a/weblayer/browser/url_bar/page_info_browsertest.cc +++ b/weblayer/browser/url_bar/page_info_browsertest.cc
@@ -76,11 +76,11 @@ } IN_PROC_BROWSER_TEST_F(PageInfoBrowserTest, - TabSpecificContentSettingsDelegate) { + PageSpecificContentSettingsDelegate) { std::unique_ptr<PageInfoDelegate> page_info_delegate = page_info::GetPageInfoClient()->CreatePageInfoDelegate(GetWebContents()); ASSERT_TRUE(page_info_delegate); - EXPECT_TRUE(page_info_delegate->GetTabSpecificContentSettingsDelegate()); + EXPECT_TRUE(page_info_delegate->GetPageSpecificContentSettingsDelegate()); } IN_PROC_BROWSER_TEST_F(PageInfoBrowserTest, EmbedderNameSet) {
diff --git a/weblayer/browser/url_bar/page_info_delegate_impl.cc b/weblayer/browser/url_bar/page_info_delegate_impl.cc index f189430f..b9ac734 100644 --- a/weblayer/browser/url_bar/page_info_delegate_impl.cc +++ b/weblayer/browser/url_bar/page_info_delegate_impl.cc
@@ -10,10 +10,10 @@ #include "components/security_state/content/content_utils.h" #include "content/public/browser/browser_context.h" #include "weblayer/browser/host_content_settings_map_factory.h" +#include "weblayer/browser/page_specific_content_settings_delegate.h" #include "weblayer/browser/permissions/permission_decision_auto_blocker_factory.h" #include "weblayer/browser/permissions/permission_manager_factory.h" #include "weblayer/browser/stateful_ssl_host_state_delegate_factory.h" -#include "weblayer/browser/tab_specific_content_settings_delegate.h" #if defined(OS_ANDROID) #include "weblayer/browser/weblayer_impl_android.h" @@ -108,9 +108,9 @@ return *security_state::GetVisibleSecurityState(web_contents_); } -std::unique_ptr<content_settings::TabSpecificContentSettings::Delegate> -PageInfoDelegateImpl::GetTabSpecificContentSettingsDelegate() { - return std::make_unique<TabSpecificContentSettingsDelegate>(web_contents_); +std::unique_ptr<content_settings::PageSpecificContentSettings::Delegate> +PageInfoDelegateImpl::GetPageSpecificContentSettingsDelegate() { + return std::make_unique<PageSpecificContentSettingsDelegate>(web_contents_); } #if defined(OS_ANDROID)
diff --git a/weblayer/browser/url_bar/page_info_delegate_impl.h b/weblayer/browser/url_bar/page_info_delegate_impl.h index 65939b3..e12a4cc45 100644 --- a/weblayer/browser/url_bar/page_info_delegate_impl.h +++ b/weblayer/browser/url_bar/page_info_delegate_impl.h
@@ -43,8 +43,8 @@ override; StatefulSSLHostStateDelegate* GetStatefulSSLHostStateDelegate() override; HostContentSettingsMap* GetContentSettings() override; - std::unique_ptr<content_settings::TabSpecificContentSettings::Delegate> - GetTabSpecificContentSettingsDelegate() override; + std::unique_ptr<content_settings::PageSpecificContentSettings::Delegate> + GetPageSpecificContentSettingsDelegate() override; bool IsContentDisplayedInVrHeadset() override; security_state::SecurityLevel GetSecurityLevel() override; security_state::VisibleSecurityState GetVisibleSecurityState() override;