diff --git a/.gn b/.gn index 1d802d41..1abcb11 100644 --- a/.gn +++ b/.gn
@@ -94,7 +94,6 @@ "//extensions/browser/api/bluetooth_socket:*", # 12 errors "//extensions/browser/api/cast_channel:*", # 3 errors "//extensions/browser/api/cec_private:*", # 4 errors - "//extensions/browser/api/clipboard:*", # 3 errors "//extensions/browser/api/declarative:*", # 20 errors "//extensions/browser/api/declarative_content:*", # 2 errors "//extensions/browser/api/declarative_net_request:*", # 18 errors
diff --git a/DEPS b/DEPS index ceb547c7..be26caae 100644 --- a/DEPS +++ b/DEPS
@@ -199,11 +199,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'd60c919fc866fdb53ea532428a1a8b58b2309dc1', + 'skia_revision': 'db2dad5c644f5a57059ef57483d52090f0e3c0c9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'edfb3b4d60eb7b778b92afc495b0cf11afa7a66a', + 'v8_revision': 'd87c3006482190728da53f87875b2a528dfb7ef3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -211,11 +211,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'd0a38010a14cf01b1a7b32143315108bd3334f46', + 'angle_revision': 'f99ccb082ba59aab0fba2b8d04625bc2364fc01f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '071cf0cff810a95284f8635bbff20d138567fdd8', + 'swiftshader_revision': '937395c1ed5d20af5a5fd999d7e2deddf1b78fe3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # 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 catapult # and whatever else without interference from each other. - 'catapult_revision': 'd9d7213a6c08cd636ae27cea934259f7fa03ee65', + 'catapult_revision': 'e174329bab1589f8df20965fcb9dde4428673a64', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -274,7 +274,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': '61704b4db5d783813e19262bad9ef6e36c8d7ce5', + 'devtools_frontend_revision': 'b43fbe8a06ea52e110218c82644181ed12917400', # 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. @@ -318,7 +318,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '528c36b3cfd0110e56b1158f8f58d833817991e0', + 'quiche_revision': '63bdfe586f8ceddf5e0823b75b1c595cbd380b2e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -893,7 +893,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e856b6bba8266df0634a365b0a51b6097bb01d4b', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '60b433cf0b29e12218abbdf36a8d166fc59e7209', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -961,7 +961,7 @@ Var('chromium_git') + '/external/github.com/google/emoji-segmenter.git' + '@' + Var('emoji_segmenter_revision'), 'src/third_party/libgav1/src': - Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'a9449e612bc251b4271bbe1e3a0d12e9809bf74c', + Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'a5ee0e00923c355ef3aad2b2829365a9fde84430', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1485,7 +1485,7 @@ 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '4191ca1784d8774dbf62d48ab9426c7311a91bc5', - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@725a542f7776a62b8389c8489d7e41885ac115be', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@ffb3b84133b03dfc4b83a8430a418f4fa94308d8', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '6c656df63da5995a932aafd45b32af1974e497d9', @@ -1518,7 +1518,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '3c2fe3888658d82b47ca831d59a2e07579619c2d', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'ec9b281bbc14fe9c3cd2b27241059f52b7eb654a', + Var('webrtc_git') + '/src.git' + '@' + 'cdb3bc3b93dae5237610d0e45bccd900812a0cfe', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1556,7 +1556,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'C_u9-R-I-yQyomb3Y-XIH8Ad3Ya4ZWi2MpPiFTtfHz4C', + 'version': 'SydJmfq0VW7jq5fTDGtIQ-7WoB0vNc-LJAi3Xd4fKvQC', }, ], 'dep_type': 'cipd', @@ -1566,7 +1566,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'FzQDQOcAASIc0LaD9YBjqH2JPm0HbYCE2x0WXw2xpz0C', + 'version': 'mvme2We4n3wONUhzQu6ATl9Ow4Fb4li6ET-Yhv7Ph3EC', }, ], 'dep_type': 'cipd', @@ -1576,7 +1576,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'H_4GgcW8CtnxDnWd7RX17C39CAYzfHUaFR6drL3wWAcC', + 'version': 'oxKWG6EzN6FHwQ-4J6gUYMHuNuHyARpVl4EvirOsXSgC', }, ], 'dep_type': 'cipd', @@ -1590,7 +1590,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7a13b94a1d4c836e869dc10733e068b2573a9aed', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8e33046d8bd53448771287085284e477d29aef1d', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java index 0fd60c6..6870d28c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwMetricsIntegrationTest.java
@@ -6,6 +6,7 @@ import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.MULTI_PROCESS; +import android.os.Build; import android.support.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; @@ -22,6 +23,7 @@ import org.chromium.android_webview.metrics.AwMetricsServiceClient; import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; +import org.chromium.base.compat.ApiHelperForM; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; @@ -167,6 +169,11 @@ // some reason). Assert.assertTrue( "Should have some application_locale", systemProfile.hasApplicationLocale()); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Assert.assertEquals( + ApiHelperForM.isProcess64Bit(), systemProfile.getAppVersion().contains("-64")); + } } @Test
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt index 706879c..8bc05281 100644 --- a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt +++ b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
@@ -62,12 +62,13 @@ # permissions API (crbug.com/490120), presentation API (crbug.com/521319), # share API (crbug.com/765923), custom scheme handlers (crbug.com/589502), -# media session API (crbug.com/925997), and WebXr API (crbug.com/1012899) -# are not supported in webview. +# media session API (crbug.com/925997), Web Serial API (crbug.com/1164036), +# and WebXr API (crbug.com/1012899) are not supported in webview. interface Navigator getter mediaSession # crbug.com/925997 getter permissions # crbug.com/490120 getter presentation # crbug.com/521319 + getter serial # crbug.com/1164036 getter xr # crbug.com/1012899 method registerProtocolHandler # crbug.com/589502 method unregisterProtocolHandler # crbug.com/589502 @@ -172,6 +173,11 @@ interface XRAnchor interface XRAnchorSet +# Web Serial API is not implemented on Android. If Bluetooth Classic support +# were added this could change. https://crbug.com/1164036 +interface Serial : EventTarget +interface SerialPort : EventTarget + [GLOBAL OBJECT] method openDatabase attribute eventSender # test only
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc index a3d3026..d9cca591 100644 --- a/ash/accelerators/accelerator_controller_impl.cc +++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -98,6 +98,7 @@ #include "chromeos/dbus/power/power_manager_client.h" #include "chromeos/ui/vector_icons/vector_icons.h" #include "components/user_manager/user_type.h" +#include "ui/aura/client/aura_constants.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/accelerators/accelerator_manager.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/accelerometer/accelerometer_file_reader.cc b/ash/accelerometer/accelerometer_file_reader.cc index 7c47c13..79feba2f 100644 --- a/ash/accelerometer/accelerometer_file_reader.cc +++ b/ash/accelerometer/accelerometer_file_reader.cc
@@ -20,7 +20,6 @@ #include "base/location.h" #include "base/memory/singleton.h" #include "base/numerics/math_constants.h" -#include "base/observer_list_threadsafe.h" #include "base/sequenced_task_runner.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" @@ -142,8 +141,7 @@ } // namespace -AccelerometerFileReader::AccelerometerFileReader() - : ui_task_runner_(base::SequencedTaskRunnerHandle::Get()) {} +AccelerometerFileReader::AccelerometerFileReader() = default; void AccelerometerFileReader::PrepareAndInitialize() { DCHECK(base::CurrentUIThread::IsSet()); @@ -165,62 +163,11 @@ TryScheduleInitialize(); } -void AccelerometerFileReader::AddObserver( - AccelerometerReader::Observer* observer) { - DCHECK(base::CurrentUIThread::IsSet()); - DCHECK(blocking_task_runner_); - observers_.AddObserver(observer); - - if (initialization_state_ != State::SUCCESS) - return; - - blocking_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&AccelerometerFileReader::ReadSample, this)); -} - -void AccelerometerFileReader::RemoveObserver( - AccelerometerReader::Observer* observer) { - DCHECK(base::CurrentUIThread::IsSet()); - observers_.RemoveObserver(observer); -} - -void AccelerometerFileReader::StartListenToTabletModeController() { - DCHECK(base::CurrentUIThread::IsSet()); - Shell::Get()->tablet_mode_controller()->AddObserver(this); -} - -void AccelerometerFileReader::StopListenToTabletModeController() { - DCHECK(base::CurrentUIThread::IsSet()); - Shell::Get()->tablet_mode_controller()->RemoveObserver(this); -} - -void AccelerometerFileReader::SetEmitEvents(bool emit_events) { - DCHECK(base::CurrentUIThread::IsSet()); - emit_events_ = emit_events; -} - -void AccelerometerFileReader::EnableAccelerometerReading() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (read_refresh_timer_.IsRunning()) - return; - - read_refresh_timer_.Start(FROM_HERE, kDelayBetweenReads, this, - &AccelerometerFileReader::ReadSample); -} - -void AccelerometerFileReader::DisableAccelerometerReading() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!read_refresh_timer_.IsRunning()) - return; - - read_refresh_timer_.Stop(); -} - void AccelerometerFileReader::TriggerRead() { DCHECK(base::CurrentUIThread::IsSet()); switch (initialization_state_) { case State::SUCCESS: - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED) { + if (GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::SUPPORTED) { blocking_task_runner_->PostTask( FROM_HERE, base::BindOnce(&AccelerometerFileReader::EnableAccelerometerReading, @@ -242,7 +189,7 @@ void AccelerometerFileReader::CancelRead() { DCHECK(base::CurrentUIThread::IsSet()); if (initialization_state_ == State::SUCCESS && - ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED) { + GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::SUPPORTED) { blocking_task_runner_->PostTask( FROM_HERE, base::BindOnce(&AccelerometerFileReader::DisableAccelerometerReading, @@ -250,30 +197,6 @@ } } -void AccelerometerFileReader::OnTabletPhysicalStateChanged() { - DCHECK(base::CurrentUIThread::IsSet()); - - // When CrOS EC lid angle driver is not present, accelerometer read is always - // ON and can't be tuned. Thus AccelerometerFileReader no longer listens to - // tablet mode event. - auto* tablet_mode_controller = Shell::Get()->tablet_mode_controller(); - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::NOT_SUPPORTED) { - tablet_mode_controller->RemoveObserver(this); - return; - } - - // Auto rotation is turned on when the device is physically used as a tablet - // (i.e. flipped or detached), regardless of the UI state (i.e. whether tablet - // mode is turned on or off). - const bool is_auto_rotation_on = - tablet_mode_controller->is_in_tablet_physical_state(); - - if (is_auto_rotation_on) - TriggerRead(); - else - CancelRead(); -} - AccelerometerFileReader::InitializationResult::InitializationResult() : initialization_state(State::INITIALIZING), ec_lid_angle_driver_status(ECLidAngleDriverStatus::UNKNOWN) {} @@ -465,9 +388,9 @@ case State::SUCCESS: DCHECK_NE(result.ec_lid_angle_driver_status, ECLidAngleDriverStatus::UNKNOWN); - ec_lid_angle_driver_status_ = result.ec_lid_angle_driver_status; + SetECLidAngleDriverStatus(result.ec_lid_angle_driver_status); - if (ec_lid_angle_driver_status_ == + if (GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::NOT_SUPPORTED) { // If ChromeOS lid angle driver is not present, start accelerometer read // and read is always on. @@ -593,6 +516,20 @@ return true; } +void AccelerometerFileReader::EnableAccelerometerReading() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (read_refresh_timer_.IsRunning()) + return; + + read_refresh_timer_.Start(FROM_HERE, kDelayBetweenReads, this, + &AccelerometerFileReader::ReadSample); +} + +void AccelerometerFileReader::DisableAccelerometerReading() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + read_refresh_timer_.Stop(); +} + void AccelerometerFileReader::ReadSample() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -640,19 +577,8 @@ ui_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&AccelerometerFileReader::NotifyObserversWithUpdate, this, + base::BindOnce(&AccelerometerFileReader::NotifyAccelerometerUpdated, this, update)); } -void AccelerometerFileReader::NotifyObserversWithUpdate( - const AccelerometerUpdate& update) { - DCHECK(base::CurrentUIThread::IsSet()); - - if (!emit_events_) - return; - - for (auto& observer : observers_) - observer.OnAccelerometerUpdated(update); -} - } // namespace ash
diff --git a/ash/accelerometer/accelerometer_file_reader.h b/ash/accelerometer/accelerometer_file_reader.h index 9400055..4f6503e6 100644 --- a/ash/accelerometer/accelerometer_file_reader.h +++ b/ash/accelerometer/accelerometer_file_reader.h
@@ -9,9 +9,7 @@ #include <vector> #include "ash/accelerometer/accelerometer_reader.h" -#include "ash/public/cpp/tablet_mode_observer.h" #include "base/files/file_util.h" -#include "base/observer_list.h" #include "base/sequence_checker.h" #include "base/timer/timer.h" @@ -20,8 +18,7 @@ // Work that runs on a base::TaskRunner. It determines the accelerometer // configuration, and reads the data. Upon a successful read it will notify // all observers. -class AccelerometerFileReader : public AccelerometerProviderInterface, - public TabletModeObserver { +class AccelerometerFileReader : public AccelerometerProviderInterface { public: AccelerometerFileReader(); AccelerometerFileReader(const AccelerometerFileReader&) = delete; @@ -29,24 +26,8 @@ // AccelerometerProviderInterface: void PrepareAndInitialize() override; - void AddObserver(AccelerometerReader::Observer* observer) override; - void RemoveObserver(AccelerometerReader::Observer* observer) override; - void StartListenToTabletModeController() override; - void StopListenToTabletModeController() override; - void SetEmitEvents(bool emit_events) override; - - // Controls accelerometer reading. - void EnableAccelerometerReading(); - void DisableAccelerometerReading(); - - // With ChromeOS EC lid angle driver present, it's triggered when the device - // is physically used as a tablet (even thought its UI might be in clamshell - // mode), cancelled otherwise. - void TriggerRead(); - void CancelRead(); - - // TabletModeObserver: - void OnTabletPhysicalStateChanged() override; + void TriggerRead() override; + void CancelRead() override; private: struct InitializationResult { @@ -97,11 +78,11 @@ ~AccelerometerFileReader() override; - // Post a task to initialize on |task_runner_| and process the result on the - // UI thread. May be called multiple times in the retries. + // Post a task to initialize on |blocking_task_runner_| and process the result + // on the UI thread. May be called multiple times in the retries. void TryScheduleInitialize(); - // Detects the accelerometer configuration in |task_runner_|. + // Detects the accelerometer configuration in |blocking_task_runner_|. // If an accelerometer is available, it triggers reads. // This function MAY be called more than once. // This function contains the actual initialization code to be run by the @@ -130,12 +111,14 @@ bool InitializeLegacyAccelerometers(const base::FilePath& iio_path, const base::FilePath& name); - // Attempts to read the accelerometer data in |task_runner_|. Upon a success, - // converts the raw reading to an AccelerometerUpdate and notifies observers. - void ReadSample(); - void NotifyObserversWithUpdate(const AccelerometerUpdate& update); + // Controls accelerometer reading. + void EnableAccelerometerReading(); + void DisableAccelerometerReading(); - bool emit_events_ = true; + // Attempts to read the accelerometer data in |blocking_task_runner_|. Upon a + // success, converts the raw reading to an AccelerometerUpdate and notifies + // observers. + void ReadSample(); // The time at which initialization re-tries should stop. base::TimeTicks initialization_timeout_; @@ -149,15 +132,9 @@ base::RepeatingTimer read_refresh_timer_ GUARDED_BY_CONTEXT(sequence_checker_); - // The observers to notify of accelerometer updates. - base::ObserverList<AccelerometerReader::Observer>::Unchecked observers_; - // The task runner to use for blocking tasks. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; - // The task runner of the UI thread. - scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/ash/accelerometer/accelerometer_provider_mojo.cc b/ash/accelerometer/accelerometer_provider_mojo.cc index 371fe425..95155bc 100644 --- a/ash/accelerometer/accelerometer_provider_mojo.cc +++ b/ash/accelerometer/accelerometer_provider_mojo.cc
@@ -11,7 +11,6 @@ #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/bind.h" -#include "base/observer_list_threadsafe.h" #include "base/ranges/algorithm.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" @@ -33,89 +32,20 @@ void AccelerometerProviderMojo::PrepareAndInitialize() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // This function should only be called once. - DCHECK(!task_runner_); - task_runner_ = base::SequencedTaskRunnerHandle::Get(); - - task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&AccelerometerProviderMojo::RegisterSensorClient, - base::Unretained(this))); + RegisterSensorClient(); } -void AccelerometerProviderMojo::AddObserver( - AccelerometerReader::Observer* observer) { +void AccelerometerProviderMojo::TriggerRead() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(task_runner_); - - observers_.AddObserver(observer); - - one_time_read_ = true; - - if (accelerometer_read_on_) - return; - - for (auto& accelerometer : accelerometers_) { - if (!accelerometer.second.samples_observer.get()) - continue; - - accelerometer.second.samples_observer->SetEnabled(true); - } + if (GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::SUPPORTED) + EnableAccelerometerReading(); } -void AccelerometerProviderMojo::RemoveObserver( - AccelerometerReader::Observer* observer) { +void AccelerometerProviderMojo::CancelRead() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(task_runner_); - - observers_.RemoveObserver(observer); -} - -void AccelerometerProviderMojo::StartListenToTabletModeController() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - Shell::Get()->tablet_mode_controller()->AddObserver(this); -} - -void AccelerometerProviderMojo::StopListenToTabletModeController() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - Shell::Get()->tablet_mode_controller()->RemoveObserver(this); -} - -void AccelerometerProviderMojo::SetEmitEvents(bool emit_events) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - emit_events_ = emit_events; -} - -void AccelerometerProviderMojo::OnTabletPhysicalStateChanged() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Wait until the existence of the driver is determined. - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::UNKNOWN) { - pending_on_tablet_physical_state_changed_ = true; - return; - } - - // When CrOS EC lid angle driver is not present, accelerometer read is always - // ON and can't be tuned. Thus AccelerometerProviderMojo no longer listens - // to tablet mode event. - auto* tablet_mode_controller = Shell::Get()->tablet_mode_controller(); - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::NOT_SUPPORTED) { - tablet_mode_controller->RemoveObserver(this); - return; - } - - // Auto rotation is turned on when the device is physically used as a tablet - // (i.e. flipped or detached), regardless of the UI state (i.e. whether tablet - // mode is turned on or off). - const bool is_auto_rotation_on = - tablet_mode_controller->is_in_tablet_physical_state(); - - task_runner_->PostNonNestableTask( - FROM_HERE, - is_auto_rotation_on - ? base::BindOnce(&AccelerometerProviderMojo::TriggerRead, this) - : base::BindOnce(&AccelerometerProviderMojo::CancelRead, this)); + if (GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::SUPPORTED) + DisableAccelerometerReading(); } void AccelerometerProviderMojo::SetUpChannel( @@ -127,39 +57,35 @@ return; } - sensor_service_remote_.Bind(std::move(pending_remote), task_runner_); - sensor_service_remote_.set_disconnect_handler( - base::BindOnce(&AccelerometerProviderMojo::OnSensorServiceDisconnect, - base::Unretained(this))); - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::UNKNOWN) { + sensor_service_remote_.Bind(std::move(pending_remote)); + sensor_service_remote_.set_disconnect_handler(base::BindOnce( + &AccelerometerProviderMojo::OnSensorServiceDisconnect, this)); + if (GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::UNKNOWN) { sensor_service_remote_->GetDeviceIds( chromeos::sensors::mojom::DeviceType::ANGL, base::BindOnce(&AccelerometerProviderMojo::GetLidAngleIdsCallback, - base::Unretained(this))); + this)); } sensor_service_remote_->GetDeviceIds( chromeos::sensors::mojom::DeviceType::ACCEL, base::BindOnce(&AccelerometerProviderMojo::GetAccelerometerIdsCallback, - base::Unretained(this))); -} - -void AccelerometerProviderMojo::TriggerRead() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED) - EnableAccelerometerReading(); -} - -void AccelerometerProviderMojo::CancelRead() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED) - DisableAccelerometerReading(); + this)); } State AccelerometerProviderMojo::GetInitializationStateForTesting() const { return initialization_state_; } +bool AccelerometerProviderMojo::ShouldDelayOnTabletPhysicalStateChanged() { + if (GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::UNKNOWN) { + pending_on_tablet_physical_state_changed_ = true; + return true; + } + + return false; +} + AccelerometerProviderMojo::AccelerometerData::AccelerometerData() = default; AccelerometerProviderMojo::AccelerometerData::~AccelerometerData() = default; @@ -171,9 +97,8 @@ chromeos::sensors::SensorHalDispatcher::GetInstance()->RegisterClient( sensor_hal_client_.BindNewPipeAndPassRemote()); - sensor_hal_client_.set_disconnect_handler( - base::BindOnce(&AccelerometerProviderMojo::OnSensorHalClientFailure, - base::Unretained(this))); + sensor_hal_client_.set_disconnect_handler(base::BindOnce( + &AccelerometerProviderMojo::OnSensorHalClientFailure, this)); } void AccelerometerProviderMojo::OnSensorHalClientFailure() { @@ -184,10 +109,9 @@ ResetSensorService(); sensor_hal_client_.reset(); - task_runner_->PostDelayedTask( + ui_task_runner_->PostDelayedTask( FROM_HERE, - base::BindOnce(&AccelerometerProviderMojo::RegisterSensorClient, - base::Unretained(this)), + base::BindOnce(&AccelerometerProviderMojo::RegisterSensorClient, this), kDelayReconnect); } @@ -212,12 +136,12 @@ void AccelerometerProviderMojo::GetLidAngleIdsCallback( const std::vector<int32_t>& lid_angle_ids) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_EQ(ec_lid_angle_driver_status_, ECLidAngleDriverStatus::UNKNOWN); + DCHECK_EQ(GetECLidAngleDriverStatus(), ECLidAngleDriverStatus::UNKNOWN); if (!lid_angle_ids.empty()) { - ec_lid_angle_driver_status_ = ECLidAngleDriverStatus::SUPPORTED; + SetECLidAngleDriverStatus(ECLidAngleDriverStatus::SUPPORTED); } else { - ec_lid_angle_driver_status_ = ECLidAngleDriverStatus::NOT_SUPPORTED; + SetECLidAngleDriverStatus(ECLidAngleDriverStatus::NOT_SUPPORTED); EnableAccelerometerReading(); } @@ -261,8 +185,7 @@ sensor_service_remote_->GetDevice( id, accelerometer.remote.BindNewPipeAndPassReceiver()); accelerometer.remote.set_disconnect_handler(base::BindOnce( - &AccelerometerProviderMojo::OnAccelerometerRemoteDisconnect, - base::Unretained(this), id)); + &AccelerometerProviderMojo::OnAccelerometerRemoteDisconnect, this, id)); std::vector<std::string> attr_names; if (!accelerometer.location.has_value()) @@ -273,8 +196,8 @@ if (!attr_names.empty()) { accelerometer.remote->GetAttributes( attr_names, - base::BindOnce(&AccelerometerProviderMojo::GetAttributesCallback, - base::Unretained(this), id)); + base::BindOnce(&AccelerometerProviderMojo::GetAttributesCallback, this, + id)); } else { // Create the observer directly if the attributes have already been // retrieved. @@ -378,7 +301,7 @@ void AccelerometerProviderMojo::CheckInitialization() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_NE(ec_lid_angle_driver_status_, ECLidAngleDriverStatus::UNKNOWN); + DCHECK_NE(GetECLidAngleDriverStatus(), ECLidAngleDriverStatus::UNKNOWN); if (initialization_state_ != State::INITIALIZING) return; @@ -390,7 +313,7 @@ continue; if (accelerometer.second.location == ACCELEROMETER_SOURCE_SCREEN || - ec_lid_angle_driver_status_ == + GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::NOT_SUPPORTED) { // This ignored accelerometer is essential. FailedToInitialize(); @@ -431,7 +354,7 @@ DCHECK(accelerometer.scale.has_value() && accelerometer.location.has_value()); if (accelerometer.location == ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD && - ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED) { + GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::SUPPORTED) { // Skipping as it's only needed if lid-angle is not supported. // |GetLidAngleIdsCallback| will call this function with this |id| again if // it's found not supported. @@ -442,16 +365,15 @@ std::make_unique<AccelerometerSamplesObserver>( id, std::move(accelerometer.remote), accelerometer.scale.value(), base::BindRepeating( - &AccelerometerProviderMojo::OnSampleUpdatedCallback, - base::Unretained(this))); + &AccelerometerProviderMojo::OnSampleUpdatedCallback, this)); - if (accelerometer_read_on_ || one_time_read_) + if (accelerometer_read_on_) accelerometer.samples_observer->SetEnabled(true); } void AccelerometerProviderMojo::EnableAccelerometerReading() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_NE(ec_lid_angle_driver_status_, ECLidAngleDriverStatus::UNKNOWN); + DCHECK_NE(GetECLidAngleDriverStatus(), ECLidAngleDriverStatus::UNKNOWN); if (accelerometer_read_on_) return; @@ -466,17 +388,12 @@ void AccelerometerProviderMojo::DisableAccelerometerReading() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_EQ(ec_lid_angle_driver_status_, ECLidAngleDriverStatus::SUPPORTED); + DCHECK_EQ(GetECLidAngleDriverStatus(), ECLidAngleDriverStatus::SUPPORTED); if (!accelerometer_read_on_) return; accelerometer_read_on_ = false; - // Allow one more read and let |OnSampleUpdatedCallback| disable the - // observers. - if (one_time_read_) - return; - for (auto& accelerometer : accelerometers_) { if (!accelerometer.second.samples_observer.get()) continue; @@ -495,17 +412,14 @@ DCHECK(accelerometer.location.has_value()); bool need_two_accelerometers = - (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::NOT_SUPPORTED && + (GetECLidAngleDriverStatus() == ECLidAngleDriverStatus::NOT_SUPPORTED && has_accelerometer_base_); - if (!one_time_read_ && !accelerometer_read_on_) { + if (!accelerometer_read_on_) { // This sample is not needed. return; } - if (!emit_events_) - return; - update_.Set(accelerometers_[iio_device_id].location.value(), sample[0], sample[1], sample[2]); @@ -516,22 +430,8 @@ return; } - for (auto& observer : observers_) - observer.OnAccelerometerUpdated(update_); - + NotifyAccelerometerUpdated(update_); update_.Reset(); - - one_time_read_ = false; - if (accelerometer_read_on_) - return; - - // This was a one time read. Disable observers. - for (auto& accelerometer : accelerometers_) { - if (!accelerometer.second.samples_observer.get()) - continue; - - accelerometer.second.samples_observer->SetEnabled(false); - } } void AccelerometerProviderMojo::FailedToInitialize() {
diff --git a/ash/accelerometer/accelerometer_provider_mojo.h b/ash/accelerometer/accelerometer_provider_mojo.h index 5184d66..3767075 100644 --- a/ash/accelerometer/accelerometer_provider_mojo.h +++ b/ash/accelerometer/accelerometer_provider_mojo.h
@@ -15,11 +15,8 @@ #include "ash/accelerometer/accelerometer_reader.h" #include "ash/accelerometer/accelerometer_samples_observer.h" #include "ash/ash_export.h" -#include "ash/public/cpp/tablet_mode_observer.h" -#include "base/observer_list.h" #include "base/optional.h" #include "base/sequence_checker.h" -#include "base/sequenced_task_runner.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -31,7 +28,6 @@ // observers. class ASH_EXPORT AccelerometerProviderMojo : public AccelerometerProviderInterface, - public TabletModeObserver, public chromeos::sensors::mojom::SensorHalClient { public: AccelerometerProviderMojo(); @@ -41,27 +37,19 @@ // AccelerometerProviderInterface: void PrepareAndInitialize() override; - void AddObserver(AccelerometerReader::Observer* observer) override; - void RemoveObserver(AccelerometerReader::Observer* observer) override; - void StartListenToTabletModeController() override; - void StopListenToTabletModeController() override; - void SetEmitEvents(bool emit_events) override; - - // TabletModeObserver: - void OnTabletPhysicalStateChanged() override; + void TriggerRead() override; + void CancelRead() override; // chromeos::sensors::mojom::SensorHalClient: void SetUpChannel(mojo::PendingRemote<chromeos::sensors::mojom::SensorService> pending_remote) override; - // With ChromeOS EC lid angle driver present, it's triggered when the device - // is physically used as a tablet (even thought its UI might be in clamshell - // mode), cancelled otherwise. - void TriggerRead(); - void CancelRead(); - State GetInitializationStateForTesting() const; + protected: + // AccelerometerProviderInterface: + bool ShouldDelayOnTabletPhysicalStateChanged() override; + private: struct AccelerometerData { AccelerometerData(); @@ -117,15 +105,13 @@ void EnableAccelerometerReading(); void DisableAccelerometerReading(); - // Called by |observers_|, containing a sample of the accelerometer. + // Called by |AccelerometerData::samples_observer| stored in the + // |accelerometers_| map, containing a sample of the accelerometer. void OnSampleUpdatedCallback(int iio_device_id, std::vector<float> sample); // Sets FAILED to |initialization_state_| due to an error. void FailedToInitialize(); - // The task runner to use for blocking tasks. - scoped_refptr<base::SequencedTaskRunner> task_runner_; - // The Mojo channel connecting to Sensor Hal Dispatcher. mojo::Receiver<chromeos::sensors::mojom::SensorHalClient> sensor_hal_client_{ this}; @@ -148,20 +134,9 @@ // |ec_lid_angle_driver_status_| is set. bool pending_on_tablet_physical_state_changed_ = false; - // One time read upon |AddObserver|. - // Some observers need to know ECLidAngleDriverStatus, and it's guaranteed to - // be set before reading samples. When adding an observer, trigger at least - // one sample to notify observers that ECLidAngleDriverStatus has been set. - bool one_time_read_ = false; - // True if periodical accelerometer read is on. bool accelerometer_read_on_ = false; - bool emit_events_ = true; - - // The observers to notify of accelerometer updates. - base::ObserverList<AccelerometerReader::Observer>::Unchecked observers_; - // The last seen accelerometer data. AccelerometerUpdate update_;
diff --git a/ash/accelerometer/accelerometer_provider_mojo_unittest.cc b/ash/accelerometer/accelerometer_provider_mojo_unittest.cc index 58ac3b4..46e39740 100644 --- a/ash/accelerometer/accelerometer_provider_mojo_unittest.cc +++ b/ash/accelerometer/accelerometer_provider_mojo_unittest.cc
@@ -32,6 +32,10 @@ class FakeObserver : public AccelerometerReader::Observer { public: + void OnECLidAngleDriverStatusChanged(bool is_supported) override { + CHECK(!is_supported_.has_value()); + is_supported_ = is_supported; + } void OnAccelerometerUpdated(const AccelerometerUpdate& update) override { for (uint32_t index = 0; index < ACCELEROMETER_SOURCE_COUNT; ++index) { auto source = static_cast<AccelerometerSource>(index); @@ -46,6 +50,7 @@ update_ = update; } + base::Optional<bool> is_supported_; AccelerometerUpdate update_; }; @@ -103,7 +108,8 @@ std::unique_ptr<chromeos::sensors::FakeSensorHalServer> sensor_hal_server_; scoped_refptr<AccelerometerProviderMojo> provider_; - base::test::SingleThreadTaskEnvironment task_environment; + base::test::SingleThreadTaskEnvironment task_environment{ + base::test::TaskEnvironment::MainThreadType::UI}; }; TEST_F(AccelerometerProviderMojoTest, CheckNoScale) { @@ -117,6 +123,8 @@ // Wait until initialization failed. base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(observer_.is_supported_.has_value()); + EXPECT_FALSE(observer_.is_supported_.value()); EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::FAILED); } @@ -131,6 +139,8 @@ // Wait until initialization failed. base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(observer_.is_supported_.has_value()); + EXPECT_FALSE(observer_.is_supported_.value()); EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::SUCCESS); } @@ -141,6 +151,8 @@ // Wait until a sample is received. base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(observer_.is_supported_.has_value()); + EXPECT_FALSE(observer_.is_supported_.value()); EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::SUCCESS); EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); @@ -159,6 +171,8 @@ // Wait until samples are received. base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(observer_.is_supported_.has_value()); + EXPECT_FALSE(observer_.is_supported_.value()); EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::SUCCESS); EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); @@ -190,11 +204,13 @@ chromeos::sensors::SensorHalDispatcher::GetInstance()->RegisterServer( sensor_hal_server_->PassRemote()); - // Wait until all setups are finished and the one time read is done. + // Wait until all setups are finished and no samples updated. base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(observer_.is_supported_.has_value()); + EXPECT_TRUE(observer_.is_supported_.value()); EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::SUCCESS); - EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); + EXPECT_FALSE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); EXPECT_FALSE(observer_.update_.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); observer_.update_.Reset();
diff --git a/ash/accelerometer/accelerometer_reader.cc b/ash/accelerometer/accelerometer_reader.cc index 95b90d5..a654401 100644 --- a/ash/accelerometer/accelerometer_reader.cc +++ b/ash/accelerometer/accelerometer_reader.cc
@@ -8,9 +8,12 @@ #include "ash/accelerometer/accelerometer_file_reader.h" #include "ash/accelerometer/accelerometer_provider_mojo.h" +#include "ash/shell.h" +#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/no_destructor.h" #include "base/posix/eintr_wrapper.h" #include "base/sequenced_task_runner.h" +#include "base/task/current_thread.h" #include "base/threading/sequenced_task_runner_handle.h" namespace ash { @@ -52,10 +55,6 @@ accelerometer_provider_->SetEmitEvents(enabled); } -ECLidAngleDriverStatus AccelerometerReader::GetECLidAngleDriverStatus() const { - return accelerometer_provider_->GetECLidAngleDriverStatus(); -} - void AccelerometerReader::SetECLidAngleDriverStatusForTesting( ECLidAngleDriverStatus ec_lid_angle_driver_status) { accelerometer_provider_->SetECLidAngleDriverStatusForTesting( // IN-TEST @@ -78,14 +77,110 @@ AccelerometerReader::~AccelerometerReader() = default; -ECLidAngleDriverStatus -AccelerometerProviderInterface::GetECLidAngleDriverStatus() const { - return ec_lid_angle_driver_status_; +void AccelerometerProviderInterface::OnTabletPhysicalStateChanged() { + DCHECK(base::CurrentUIThread::IsSet()); + + if (ShouldDelayOnTabletPhysicalStateChanged()) + return; + + // When CrOS EC lid angle driver is not present, accelerometer read is always + // ON and can't be tuned. Thus this object no longer listens to tablet mode + // event. + auto* tablet_mode_controller = Shell::Get()->tablet_mode_controller(); + if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::NOT_SUPPORTED) { + tablet_mode_controller->RemoveObserver(this); + return; + } + + // Auto rotation is turned on when the device is physically used as a tablet + // (i.e. flipped or detached), regardless of the UI state (i.e. whether tablet + // mode is turned on or off). + if (tablet_mode_controller->is_in_tablet_physical_state()) + TriggerRead(); + else + CancelRead(); +} + +void AccelerometerProviderInterface::AddObserver( + AccelerometerReader::Observer* observer) { + DCHECK(base::CurrentUIThread::IsSet()); + + if (ec_lid_angle_driver_status_ != ECLidAngleDriverStatus::UNKNOWN) { + observer->OnECLidAngleDriverStatusChanged( + ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED); + } + + observers_.AddObserver(observer); +} + +void AccelerometerProviderInterface::RemoveObserver( + AccelerometerReader::Observer* observer) { + DCHECK(base::CurrentUIThread::IsSet()); + observers_.RemoveObserver(observer); +} + +void AccelerometerProviderInterface::StartListenToTabletModeController() { + Shell::Get()->tablet_mode_controller()->AddObserver(this); +} + +void AccelerometerProviderInterface::StopListenToTabletModeController() { + Shell::Get()->tablet_mode_controller()->RemoveObserver(this); +} + +void AccelerometerProviderInterface::SetEmitEvents(bool emit_events) { + DCHECK(base::CurrentUIThread::IsSet()); + emit_events_ = emit_events; } void AccelerometerProviderInterface::SetECLidAngleDriverStatusForTesting( - ECLidAngleDriverStatus ec_lid_angle_driver_status) { - ec_lid_angle_driver_status_ = ec_lid_angle_driver_status; + ECLidAngleDriverStatus status) { + SetECLidAngleDriverStatus(status); +} + +AccelerometerProviderInterface::AccelerometerProviderInterface() + : ui_task_runner_(base::SequencedTaskRunnerHandle::Get()) { + DCHECK(base::CurrentUIThread::IsSet()); +} + +AccelerometerProviderInterface::~AccelerometerProviderInterface() = default; + +bool AccelerometerProviderInterface::ShouldDelayOnTabletPhysicalStateChanged() { + return false; +} + +void AccelerometerProviderInterface::SetECLidAngleDriverStatus( + ECLidAngleDriverStatus status) { + DCHECK(base::CurrentUIThread::IsSet()); + DCHECK_NE(status, ECLidAngleDriverStatus::UNKNOWN); + + if (status == ec_lid_angle_driver_status_) + return; + + ec_lid_angle_driver_status_ = status; + + for (auto& observer : observers_) { + observer.OnECLidAngleDriverStatusChanged(ec_lid_angle_driver_status_ == + ECLidAngleDriverStatus::SUPPORTED); + } +} + +ECLidAngleDriverStatus +AccelerometerProviderInterface::GetECLidAngleDriverStatus() const { + DCHECK(base::CurrentUIThread::IsSet()); + + return ec_lid_angle_driver_status_; +} + +void AccelerometerProviderInterface::NotifyAccelerometerUpdated( + const AccelerometerUpdate& update) { + DCHECK(base::CurrentUIThread::IsSet()); + DCHECK_NE(ec_lid_angle_driver_status_, ECLidAngleDriverStatus::UNKNOWN); + + if (!emit_events_) + return; + + for (auto& observer : observers_) + observer.OnAccelerometerUpdated(update); } } // namespace ash
diff --git a/ash/accelerometer/accelerometer_reader.h b/ash/accelerometer/accelerometer_reader.h index e039cb70..3c3be67 100644 --- a/ash/accelerometer/accelerometer_reader.h +++ b/ash/accelerometer/accelerometer_reader.h
@@ -7,8 +7,10 @@ #include "ash/accelerometer/accelerometer_types.h" #include "ash/ash_export.h" +#include "ash/public/cpp/tablet_mode_observer.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/observer_list.h" namespace base { template <typename T> @@ -39,6 +41,11 @@ // An interface to receive data from the AccelerometerReader. class Observer { public: + // Called only once, when + // |AcceleromterProviderInterface::ec_lid_angle_driver_status_| is set to + // either SUPPORTED or NOT_SUPPORTED. + // It's also guaranteed to be called before |OnAccelerometerUpdated|. + virtual void OnECLidAngleDriverStatusChanged(bool is_supported) = 0; virtual void OnAccelerometerUpdated(const AccelerometerUpdate& update) = 0; protected: @@ -62,9 +69,6 @@ // be able to control the accelerometer feature. void SetEnabled(bool enabled); - // Return the state of the driver being supported or not. - ECLidAngleDriverStatus GetECLidAngleDriverStatus() const; - void SetECLidAngleDriverStatusForTesting( ECLidAngleDriverStatus ec_lid_angle_driver_status); @@ -83,41 +87,71 @@ scoped_refptr<AccelerometerProviderInterface> accelerometer_provider_; }; -class AccelerometerProviderInterface - : public base::RefCountedThreadSafe<AccelerometerProviderInterface> { +class ASH_EXPORT AccelerometerProviderInterface + : public base::RefCountedThreadSafe<AccelerometerProviderInterface>, + public TabletModeObserver { public: // Prepare and start async initialization. virtual void PrepareAndInitialize() = 0; + // With ChromeOS EC lid angle driver present, it's triggered when the device + // is physically used as a tablet (even thought its UI might be in clamshell + // mode), cancelled otherwise. + virtual void TriggerRead() = 0; + virtual void CancelRead() = 0; + + // TabletModeObserver: + void OnTabletPhysicalStateChanged() override; // Add/Remove observers. - virtual void AddObserver(AccelerometerReader::Observer* observer) = 0; - virtual void RemoveObserver(AccelerometerReader::Observer* observer) = 0; + void AddObserver(AccelerometerReader::Observer* observer); + void RemoveObserver(AccelerometerReader::Observer* observer); // Start/Stop listening to tablet mode controller. - virtual void StartListenToTabletModeController() = 0; - virtual void StopListenToTabletModeController() = 0; + void StartListenToTabletModeController(); + void StopListenToTabletModeController(); // Set emitting events (samples) to observers or not. - virtual void SetEmitEvents(bool emit_events) = 0; + void SetEmitEvents(bool emit_events); - // Return the state of the driver being supported or not. - ECLidAngleDriverStatus GetECLidAngleDriverStatus() const; - - void SetECLidAngleDriverStatusForTesting( - ECLidAngleDriverStatus ec_lid_angle_driver_status); + void SetECLidAngleDriverStatusForTesting(ECLidAngleDriverStatus status); protected: - virtual ~AccelerometerProviderInterface() = default; + AccelerometerProviderInterface(); + ~AccelerometerProviderInterface() override; + + // Used in |OnTabletPhysicalStateChanged()|. As there might be + // initialization steps, each implementation can override this function to + // determine if this class is ready to process the state changed. + // If returns true, |OnTabletPhysicalStateChanged()| will be skipped, and it's + // the implementation's responsibility to call it again when the class is + // ready. If returns false, |OnTabletPhysicalStateChanged()| will be processed + // as usual. + // Default to return false. + virtual bool ShouldDelayOnTabletPhysicalStateChanged(); + + void SetECLidAngleDriverStatus(ECLidAngleDriverStatus status); + ECLidAngleDriverStatus GetECLidAngleDriverStatus() const; + + void NotifyAccelerometerUpdated(const AccelerometerUpdate& update); + + // Set in the constructor. + scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; // The current initialization state of reader. State initialization_state_ = State::INITIALIZING; + private: // State of ChromeOS EC lid angle driver, if SUPPORTED, it means EC can handle // lid angle calculation. ECLidAngleDriverStatus ec_lid_angle_driver_status_ = ECLidAngleDriverStatus::UNKNOWN; - private: + bool emit_events_ = true; + + // The observers to notify of accelerometer updates. + // Bound to the UI thread. + base::ObserverList<AccelerometerReader::Observer>::Unchecked observers_; + friend class base::RefCountedThreadSafe<AccelerometerProviderInterface>; };
diff --git a/ash/display/screen_orientation_controller.h b/ash/display/screen_orientation_controller.h index 00d613f..74b503e6 100644 --- a/ash/display/screen_orientation_controller.h +++ b/ash/display/screen_orientation_controller.h
@@ -152,6 +152,7 @@ void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; // AccelerometerReader::Observer: + void OnECLidAngleDriverStatusChanged(bool is_supported) override {} void OnAccelerometerUpdated(const AccelerometerUpdate& update) override; // WindowTreeHostManager::Observer:
diff --git a/ash/keyboard/ui/keyboard_ui_controller.cc b/ash/keyboard/ui/keyboard_ui_controller.cc index 8e31eacc..7cff1ae 100644 --- a/ash/keyboard/ui/keyboard_ui_controller.cc +++ b/ash/keyboard/ui/keyboard_ui_controller.cc
@@ -295,7 +295,10 @@ parent_container_->RemoveChild(keyboard_window); } } - parent_container_->GetRootWindow()->RemoveObserver(this); + aura::Window* root_window = parent_container_->GetRootWindow(); + if (root_window) { + root_window->RemoveObserver(this); + } parent_container_ = nullptr; }
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 54d2eaa2..84b4d6d 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -287,6 +287,8 @@ "update_types.h", "view_shadow.cc", "view_shadow.h", + "views_text_services_context_menu_impl.cc", + "views_text_services_context_menu_impl.h", "vm_camera_mic_constants.cc", "vm_camera_mic_constants.h", "wallpaper_controller.cc",
diff --git a/ash/public/cpp/test/shell_test_api.h b/ash/public/cpp/test/shell_test_api.h index c4f43123..a0d6891 100644 --- a/ash/public/cpp/test/shell_test_api.h +++ b/ash/public/cpp/test/shell_test_api.h
@@ -30,7 +30,6 @@ class PowerPrefs; class ScreenPositionController; class Shell; -class SystemGestureEventFilter; class WorkspaceController; // Accesses private data from a Shell for testing. @@ -45,7 +44,6 @@ static void SetTabletControllerUseScreenshotForTest(bool use_screenshot); MessageCenterController* message_center_controller(); - SystemGestureEventFilter* system_gesture_event_filter(); WorkspaceController* workspace_controller(); ScreenPositionController* screen_position_controller(); NativeCursorManagerAsh* native_cursor_manager_ash(); @@ -79,9 +77,6 @@ // fullscreen button. void ToggleFullscreen(); - // Returns true if it is in overview selecting mode. - bool IsOverviewSelecting(); - // Used to emulate display change when run in a desktop environment instead // of on a device. void AddRemoveDisplay(); @@ -121,10 +116,6 @@ // It returns nullptr when app-list is not shown. PaginationModel* GetAppListPaginationModel(); - // Returns the list of windows used in overview item. Returns empty - // if not in the overview mode. - std::vector<aura::Window*> GetItemWindowListInOverviewGrids(); - private: Shell* shell_; // not owned
diff --git a/ash/public/cpp/views_text_services_context_menu_impl.cc b/ash/public/cpp/views_text_services_context_menu_impl.cc new file mode 100644 index 0000000..42f1396a --- /dev/null +++ b/ash/public/cpp/views_text_services_context_menu_impl.cc
@@ -0,0 +1,98 @@ +// Copyright 2021 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 "ash/public/cpp/views_text_services_context_menu_impl.h" + +#include "ash/public/cpp/clipboard_history_controller.h" +#include "chromeos/constants/chromeos_features.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/pointer/touch_editing_controller.h" +#include "ui/strings/grit/ui_strings.h" +#include "ui/views/controls/textfield/textfield.h" + +namespace ash { + +ViewsTextServicesContextMenuImpl::ViewsTextServicesContextMenuImpl( + ui::SimpleMenuModel* menu, + views::Textfield* client) + : views::ViewsTextServicesContextMenuBase(menu, client) { + if (chromeos::features::IsClipboardHistoryEnabled()) + AddClipboardHistoryMenuOption(menu); +} + +ViewsTextServicesContextMenuImpl::~ViewsTextServicesContextMenuImpl() = default; + +bool ViewsTextServicesContextMenuImpl::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) { + *accelerator = ui::Accelerator(ui::VKEY_V, ui::EF_COMMAND_DOWN); + return true; + } + + return ViewsTextServicesContextMenuBase::GetAcceleratorForCommandId( + command_id, accelerator); +} + +bool ViewsTextServicesContextMenuImpl::IsCommandIdChecked( + int command_id) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) + return true; + + return ViewsTextServicesContextMenuBase::IsCommandIdChecked(command_id); +} + +bool ViewsTextServicesContextMenuImpl::IsCommandIdEnabled( + int command_id) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) + return ClipboardHistoryController::Get()->CanShowMenu(); + + return ViewsTextServicesContextMenuBase::IsCommandIdEnabled(command_id); +} + +void ViewsTextServicesContextMenuImpl::ExecuteCommand(int command_id, + int event_flags) { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) { + auto* clipboard_history_controller = ClipboardHistoryController::Get(); + + // Calculate the menu source type from `event_flags`. + ui::MenuSourceType source_type; + if (event_flags & ui::EF_LEFT_MOUSE_BUTTON) + source_type = ui::MENU_SOURCE_MOUSE; + else if (event_flags & ui::EF_FROM_TOUCH) + source_type = ui::MENU_SOURCE_TOUCH; + else + source_type = ui::MENU_SOURCE_KEYBOARD; + + clipboard_history_controller->ShowMenu(client()->GetCaretBounds(), + source_type); + return; + } + + ViewsTextServicesContextMenuBase::ExecuteCommand(command_id, event_flags); +} + +bool ViewsTextServicesContextMenuImpl::SupportsCommand(int command_id) const { + if (command_id == IDS_APP_SHOW_CLIPBOARD_HISTORY) + return true; + + return ViewsTextServicesContextMenuBase::SupportsCommand(command_id); +} + +void ViewsTextServicesContextMenuImpl::AddClipboardHistoryMenuOption( + ui::SimpleMenuModel* menu) { + const int index_of_paste = + menu->GetIndexOfCommandId(ui::TouchEditable::kPaste); + + // Only add the clipboard history menu option when having the menu option + // for paste. + if (index_of_paste == -1) + return; + + const int target_index = index_of_paste + 1; + menu->InsertItemAt(target_index, IDS_APP_SHOW_CLIPBOARD_HISTORY, + l10n_util::GetStringUTF16(IDS_APP_SHOW_CLIPBOARD_HISTORY)); +} + +} // namespace ash
diff --git a/ash/public/cpp/views_text_services_context_menu_impl.h b/ash/public/cpp/views_text_services_context_menu_impl.h new file mode 100644 index 0000000..820de19e --- /dev/null +++ b/ash/public/cpp/views_text_services_context_menu_impl.h
@@ -0,0 +1,46 @@ +// Copyright 2021 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 ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_IMPL_H_ +#define ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_IMPL_H_ + +#include "ash/public/cpp/ash_public_export.h" +#include "ui/views/controls/views_text_services_context_menu_base.h" + +namespace views { +class Textfield; +} + +namespace ash { + +// This class supports the text context menu with the exclusive functions under +// the CrOS environment. +class ASH_PUBLIC_EXPORT ViewsTextServicesContextMenuImpl + : public views::ViewsTextServicesContextMenuBase { + public: + ViewsTextServicesContextMenuImpl(ui::SimpleMenuModel* menu, + views::Textfield* client); + ViewsTextServicesContextMenuImpl(const ViewsTextServicesContextMenuImpl&) = + delete; + ViewsTextServicesContextMenuImpl& operator=( + const ViewsTextServicesContextMenuImpl&) = delete; + ~ViewsTextServicesContextMenuImpl() override; + + // ViewsTextServicesContextMenuBase: + bool GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) const override; + bool IsCommandIdChecked(int command_id) const override; + bool IsCommandIdEnabled(int command_id) const override; + void ExecuteCommand(int command_id, int event_flags) override; + bool SupportsCommand(int command_id) const override; + + private: + // Adds the menu option which shows the clipboard history menu after + // activation. + void AddClipboardHistoryMenuOption(ui::SimpleMenuModel* menu); +}; + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_VIEWS_TEXT_SERVICES_CONTEXT_MENU_IMPL_H_
diff --git a/ash/shell.cc b/ash/shell.cc index 764e276..11fb4272 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -84,6 +84,7 @@ #include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shell_window_ids.h" +#include "ash/public/cpp/views_text_services_context_menu_impl.h" #include "ash/quick_answers/quick_answers_controller_impl.h" #include "ash/root_window_controller.h" #include "ash/screenshot_delegate.h" @@ -210,6 +211,7 @@ #include "ui/gfx/image/image_skia.h" #include "ui/message_center/message_center.h" #include "ui/ozone/public/ozone_platform.h" +#include "ui/views/controls/views_text_services_context_menu_chromeos.h" #include "ui/views/corewm/tooltip_aura.h" #include "ui/views/corewm/tooltip_controller.h" #include "ui/views/focus/focus_manager_factory.h" @@ -640,6 +642,10 @@ RemovePreTargetHandler(modality_filter_.get()); RemovePreTargetHandler(tooltip_controller_.get()); + // Resets the text context menu implementation factory. + views::ViewsTextServicesContextMenuChromeos::SetImplFactory( + base::NullCallback()); + event_rewriter_controller_.reset(); screen_orientation_controller_.reset(); @@ -1253,6 +1259,16 @@ std::make_unique<DisplayAlignmentController>(); } + // Injects the factory which fulfills the implementation of the text context + // menu exclusive to CrOS. + views::ViewsTextServicesContextMenuChromeos::SetImplFactory( + base::BindRepeating( + [](ui::SimpleMenuModel* menu_model, views::Textfield* textfield) + -> std::unique_ptr<views::ViewsTextServicesContextMenu> { + return std::make_unique<ViewsTextServicesContextMenuImpl>( + menu_model, textfield); + })); + for (auto& observer : shell_observers_) observer.OnShellInitialized();
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc index 082f30f..d2b28d1 100644 --- a/ash/shell_test_api.cc +++ b/ash/shell_test_api.cc
@@ -118,10 +118,6 @@ return shell_->message_center_controller_.get(); } -SystemGestureEventFilter* ShellTestApi::system_gesture_event_filter() { - return shell_->system_gesture_filter_.get(); -} - WorkspaceController* ShellTestApi::workspace_controller() { // TODO(afakhry): Split this into two, one for root, and one for context. return GetActiveWorkspaceController(shell_->GetPrimaryRootWindow()); @@ -185,10 +181,6 @@ accelerators::ToggleFullscreen(); } -bool ShellTestApi::IsOverviewSelecting() { - return shell_->overview_controller()->InOverviewSession(); -} - void ShellTestApi::AddRemoveDisplay() { shell_->display_manager()->AddRemoveDisplay(); } @@ -260,10 +252,4 @@ return view->GetAppsPaginationModel(); } -std::vector<aura::Window*> ShellTestApi::GetItemWindowListInOverviewGrids() { - return Shell::Get() - ->overview_controller() - ->GetItemWindowListInOverviewGridsForTest(); -} - } // namespace ash
diff --git a/ash/system/holding_space/holding_space_color_provider_impl.cc b/ash/system/holding_space/holding_space_color_provider_impl.cc index d9c5f02..0c097b6 100644 --- a/ash/system/holding_space/holding_space_color_provider_impl.cc +++ b/ash/system/holding_space/holding_space_color_provider_impl.cc
@@ -5,6 +5,7 @@ #include "ash/system/holding_space/holding_space_color_provider_impl.h" #include "ash/style/ash_color_provider.h" +#include "ui/gfx/color_palette.h" namespace ash { @@ -18,8 +19,7 @@ } SkColor HoldingSpaceColorProviderImpl::GetFileIconColor() const { - return AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kIconColorPrimary); + return gfx::kGoogleGrey700; } } // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_chip_view.cc b/ash/system/holding_space/holding_space_item_chip_view.cc index 5b4608a..3f06e6b7 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.cc +++ b/ash/system/holding_space/holding_space_item_chip_view.cc
@@ -12,6 +12,7 @@ #include "ash/system/holding_space/holding_space_util.h" #include "ui/compositor/paint_recorder.h" #include "ui/gfx/skia_paint_util.h" +#include "ui/views/background.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" @@ -87,6 +88,15 @@ image_ = AddChildView(std::make_unique<RoundedImageView>( kHoldingSpaceChipIconSize / 2, RoundedImageView::Alignment::kLeading)); + image_->SetBackground(views::CreateRoundedRectBackground( + SK_ColorWHITE, kHoldingSpaceChipIconSize / 2)); + + // Subscribe to be notified of changes to `item_`'s image. + image_subscription_ = + item->image().AddImageSkiaChangedCallback(base::BindRepeating( + &HoldingSpaceItemChipView::UpdateImage, base::Unretained(this))); + + UpdateImage(); label_and_pin_button_container_ = AddChildView(std::make_unique<views::View>()); @@ -107,13 +117,6 @@ label_->layer()->SetFillsBoundsOpaquely(false); label_->layer()->SetMaskLayer(label_mask_layer_owner_->layer()); - // Subscribe to be notified of changes to `item_`'s image. - image_subscription_ = - item->image().AddImageSkiaChangedCallback(base::BindRepeating( - &HoldingSpaceItemChipView::UpdateImage, base::Unretained(this))); - - UpdateImage(); - views::View* pin_button_container = label_and_pin_button_container_->AddChildView( std::make_unique<views::View>());
diff --git a/ash/system/network/network_state_list_detailed_view.cc b/ash/system/network/network_state_list_detailed_view.cc index 029baeae..7652df3 100644 --- a/ash/system/network/network_state_list_detailed_view.cc +++ b/ash/system/network/network_state_list_detailed_view.cc
@@ -323,10 +323,17 @@ Shell::Get()->metrics()->RecordUserMetricsAction( list_type_ == LIST_TYPE_VPN ? UMA_STATUS_AREA_VPN_SETTINGS_OPENED : UMA_STATUS_AREA_NETWORK_SETTINGS_OPENED); + + SystemTrayClient* system_tray_client = + Shell::Get()->system_tray_model()->client(); + + if (system_tray_client) { + system_tray_client->ShowNetworkSettings( + model_->default_network() ? model_->default_network()->guid + : std::string()); + } + CloseBubble(); // Deletes |this|. - Shell::Get()->system_tray_model()->client()->ShowNetworkSettings( - model_->default_network() ? model_->default_network()->guid - : std::string()); } void NetworkStateListDetailedView::UpdateHeaderButtons() {
diff --git a/ash/system/power/power_button_controller.h b/ash/system/power/power_button_controller.h index ee660aa..703562d 100644 --- a/ash/system/power/power_button_controller.h +++ b/ash/system/power/power_button_controller.h
@@ -138,6 +138,7 @@ // TODO(minch): Remove this if/when all applicable devices expose a tablet // mode switch: https://crbug.com/798646. // AccelerometerReader::Observer: + void OnECLidAngleDriverStatusChanged(bool is_supported) override {} void OnAccelerometerUpdated(const AccelerometerUpdate& update) override; // BacklightsForcedOffSetter::Observer:
diff --git a/ash/wm/cursor_manager_test_api.cc b/ash/wm/cursor_manager_test_api.cc index c835ff86..adddf42 100644 --- a/ash/wm/cursor_manager_test_api.cc +++ b/ash/wm/cursor_manager_test_api.cc
@@ -32,8 +32,4 @@ return ShellTestApi().native_cursor_manager_ash()->GetRotation(); } -float CursorManagerTestApi::GetCurrentCursorScale() const { - return ShellTestApi().native_cursor_manager_ash()->GetScale(); -} - } // namespace ash
diff --git a/ash/wm/cursor_manager_test_api.h b/ash/wm/cursor_manager_test_api.h index b2d267e5..338a7c55 100644 --- a/ash/wm/cursor_manager_test_api.h +++ b/ash/wm/cursor_manager_test_api.h
@@ -29,7 +29,6 @@ ui::CursorSize GetCurrentCursorSize() const; gfx::NativeCursor GetCurrentCursor() const; display::Display::Rotation GetCurrentCursorRotation() const; - float GetCurrentCursorScale() const; private: ::wm::CursorManager* cursor_manager_;
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc index 15bb88f..45d04e1b 100644 --- a/ash/wm/default_state.cc +++ b/ash/wm/default_state.cc
@@ -152,9 +152,13 @@ gfx::Rect bounds = window->bounds(); // When window is added to a workspace, |bounds| may be not the original // not-changed-by-user bounds, for example a resized bounds truncated by - // available workarea. - if (window_state->pre_added_to_workspace_window_bounds()) + // available workarea. If the window is visible on all desks, its + // bounds are global across workspaces so don't restore to pre-added + // bounds. + if (window_state->pre_added_to_workspace_window_bounds() && + !window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)) { bounds = *window_state->pre_added_to_workspace_window_bounds(); + } // Don't adjust window bounds if the bounds are empty as this // happens when a new views::Widget is created.
diff --git a/ash/wm/desks/desk.cc b/ash/wm/desks/desk.cc index df0ba9b..81f07429 100644 --- a/ash/wm/desks/desk.cc +++ b/ash/wm/desks/desk.cc
@@ -1,4 +1,4 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. +// 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. @@ -383,10 +383,13 @@ MoveWindowToDeskInternal(transient_root, target_desk, target_root); // Unminimize the window so that it shows up in the mini_view after it had - // been dragged and moved to another desk. + // been dragged and moved to another desk. Don't unminimize if the window is + // visible on all desks since it's being moved during desk activation. auto* window_state = WindowState::Get(transient_root); - if (window_state->IsMinimized()) + if (window_state->IsMinimized() && + !window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)) { window_state->Unminimize(); + } } NotifyContentChanged();
diff --git a/ash/wm/desks/desk_animation_impl.cc b/ash/wm/desks/desk_animation_impl.cc index b0cf8b79..7dca6a2 100644 --- a/ash/wm/desks/desk_animation_impl.cc +++ b/ash/wm/desks/desk_animation_impl.cc
@@ -116,7 +116,6 @@ // List of animators that need a screenshot. It should be either empty or // match the size of |desk_switch_animators_| as all the animations should be // in sync. - // TODO(sammiequon): Verify all the animations are in sync. std::vector<RootWindowDeskSwitchAnimator*> pending_animators; for (const auto& animator : desk_switch_animators_) { if (animator->ReplaceAnimation(new_ending_desk_index))
diff --git a/ash/wm/desks/desks_animations.cc b/ash/wm/desks/desks_animations.cc index 67b1422f..b266911 100644 --- a/ash/wm/desks/desks_animations.cc +++ b/ash/wm/desks/desks_animations.cc
@@ -12,12 +12,14 @@ #include "ash/wm/overview/overview_controller.h" #include "ash/wm/window_transient_descendant_iterator.h" #include "base/time/time.h" +#include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/layer_tree_owner.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/transform.h" +#include "ui/views/widget/widget.h" #include "ui/wm/core/window_util.h" namespace ash { @@ -116,6 +118,7 @@ void PerformWindowMoveToDeskAnimation(aura::Window* window, bool going_left) { DCHECK(!Shell::Get()->overview_controller()->InOverviewSession()); + DCHECK(!window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); // The entire transient window tree should appear to animate together towards // the target desk.
diff --git a/ash/wm/desks/desks_animations.h b/ash/wm/desks/desks_animations.h index 7b4cb50..7ee200f1 100644 --- a/ash/wm/desks/desks_animations.h +++ b/ash/wm/desks/desks_animations.h
@@ -23,7 +23,8 @@ // tree offscreen in the direction of the target desk indicated by |going_left|. // After this function, |window| can be moved safely immediately to the target // desk without having to wait for the animation to finish, since we're -// animating a completely separate layer tree. +// animating a completely separate layer tree. |window| cannot be visible on all +// desks. // Note: This animation should not be performed on windows in overview. void PerformWindowMoveToDeskAnimation(aura::Window* window, bool going_left);
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index 83c5500..d9f2eb8 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -40,6 +40,7 @@ #include "base/notreached.h" #include "base/numerics/ranges.h" #include "base/timer/timer.h" +#include "ui/aura/client/aura_constants.h" #include "ui/base/l10n/l10n_util.h" #include "ui/wm/public/activation_client.h" @@ -491,6 +492,17 @@ if (!base::Contains(active_desk_->windows(), window)) return false; + if (window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)) { + if (source == DesksMoveWindowFromActiveDeskSource::kDragAndDrop) { + // Since a visible on all desks window is on all desks, prevent users from + // moving them manually in overview. + // TODO(chinsenj): Add a UX indication for users. + return false; + } else if (source == DesksMoveWindowFromActiveDeskSource::kShortcut) { + window->SetProperty(aura::client::kVisibleOnAllWorkspacesKey, false); + } + } + base::AutoReset<bool> in_progress(&are_desks_being_modified_, true); auto* overview_controller = Shell::Get()->overview_controller(); @@ -534,6 +546,15 @@ return true; } +void DesksController::AddVisibleOnAllDesksWindow(aura::Window* window) { + const bool added = visible_on_all_desks_windows_.emplace(window).second; + DCHECK(added); +} + +void DesksController::RemoveVisibleOnAllDesksWindow(aura::Window* window) { + visible_on_all_desks_windows_.erase(window); +} + void DesksController::RevertDeskNameToDefault(Desk* desk) { DCHECK(HasDesk(desk)); desk->SetName(GetDeskDefaultName(GetDeskIndex(desk)), /*set_by_user=*/false); @@ -595,6 +616,9 @@ if (desk_index < 0 || desk_index >= static_cast<int>(desks_.size())) return; + if (window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)) + window->SetProperty(aura::client::kVisibleOnAllWorkspacesKey, false); + const int active_desk_index = GetDeskIndex(active_desk_); if (desk_index == active_desk_index) return; @@ -700,7 +724,9 @@ // `old_active` desk do not activate other windows on the same desk. See // `ash::AshFocusRules::GetNextActivatableWindow()`. Desk* old_active = active_desk_; + MoveVisibleOnAllDesksWindowsFromActiveDeskTo(const_cast<Desk*>(desk)); active_desk_ = const_cast<Desk*>(desk); + RestackAssignedWindowsOnActiveDesk(); // There should always be an active desk at any time. DCHECK(old_active); @@ -821,6 +847,10 @@ // Desk activation should not change overview mode state. DCHECK_EQ(in_overview, overview_controller->InOverviewSession()); + // Now that |target_desk| is activated, we can restack the visible on all + // desks windows that were moved from the old active desk. + RestackAssignedWindowsOnActiveDesk(); + // Now that the windows from the removed and target desks merged, add them // all to the grid in the order of the new MRU. if (in_overview) @@ -872,6 +902,58 @@ DCHECK_LE(available_container_ids_.size(), desks_util::GetMaxNumberOfDesks()); } +void DesksController::MoveVisibleOnAllDesksWindowsFromActiveDeskTo( + Desk* new_desk) { + // Ignore activations in the MRU tracker until we finish moving all visible on + // all desks windows so we maintain global MRU order that is used later + // for stacking visible on all desks windows. + auto* mru_tracker = Shell::Get()->mru_window_tracker(); + mru_tracker->SetIgnoreActivations(true); + + for (auto* visible_on_all_desks_window : visible_on_all_desks_windows_) { + MoveWindowFromActiveDeskTo( + visible_on_all_desks_window, new_desk, + visible_on_all_desks_window->GetRootWindow(), + DesksMoveWindowFromActiveDeskSource::kVisibleOnAllDesks); + } + + mru_tracker->SetIgnoreActivations(false); +} + +void DesksController::RestackAssignedWindowsOnActiveDesk() { + auto mru_windows = + Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk); + for (auto* visible_on_all_desks_window : visible_on_all_desks_windows_) { + auto visible_on_all_desks_window_iter = std::find( + mru_windows.begin(), mru_windows.end(), visible_on_all_desks_window); + DCHECK(visible_on_all_desks_window_iter != mru_windows.end()); + auto* desk_container = + visible_on_all_desks_window->GetRootWindow()->GetChildById( + active_desk_->container_id()); + DCHECK_EQ(desk_container, visible_on_all_desks_window->parent()); + + // Search through the MRU list for the next element that shares the same + // parent. This will be used to stack |visible_on_all_desks_window| in + // the active desk so its stacking respects global MRU order. + auto closest_window_below_iter = + std::next(visible_on_all_desks_window_iter); + while (closest_window_below_iter != mru_windows.end() && + (*closest_window_below_iter)->parent() != + visible_on_all_desks_window->parent()) { + closest_window_below_iter = std::next(closest_window_below_iter); + } + + if (closest_window_below_iter == mru_windows.end()) { + // There was no element in the MRU list that was used after + // |visible_on_all_desks_window| so stack it at the bottom. + desk_container->StackChildAtBottom(visible_on_all_desks_window); + } else { + desk_container->StackChildAbove(visible_on_all_desks_window, + *closest_window_below_iter); + } + } +} + const Desk* DesksController::FindDeskOfWindow(aura::Window* window) const { DCHECK(window);
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h index add52fc..1ac014c8 100644 --- a/ash/wm/desks/desks_controller.h +++ b/ash/wm/desks/desks_controller.h
@@ -16,6 +16,7 @@ #include "ash/wm/desks/desks_histogram_enums.h" #include "ash/wm/desks/root_window_desk_switch_animator.h" #include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/macros.h" #include "base/observer_list.h" #include "components/account_id/account_id.h" @@ -76,6 +77,10 @@ const Desk* active_desk() const { return active_desk_; } + const base::flat_set<aura::Window*>& visible_on_all_desks_windows() const { + return visible_on_all_desks_windows_; + } + DeskAnimationBase* animation() const { return animation_.get(); } // Returns the current |active_desk()| or the soon-to-be active desk if a desk @@ -145,15 +150,23 @@ // |target_root| is provided if |window| is desired to be moved to another // desk on another display, otherwise, you can just provide // |window->GetRootWindow()| if the window should stay on the same display. - // If |window| is minimized, it will be unminimized after it's moved to - // |target_desk|. - // Returns true on success, false otherwise (e.g. if |window| doesn't belong - // to the active desk). + // If |window| is minimized and isn't visible on all desks, it will be + // unminimized after it's moved to |target_desk|. Returns true on success, + // false otherwise (e.g. if |window| doesn't belong to the active desk or + // |window| is visible on all desks and user is manually moving it). If + // |window| is visible on all desks and |source| is kShortcut, it will be made + // not visible on all desks. bool MoveWindowFromActiveDeskTo(aura::Window* window, Desk* target_desk, aura::Window* target_root, DesksMoveWindowFromActiveDeskSource source); + // Adds |window| to |visible_on_all_desks_windows_|. + void AddVisibleOnAllDesksWindow(aura::Window* window); + + // Removes |window| if it is in |visible_on_all_desks_windows_|. + void RemoveVisibleOnAllDesksWindow(aura::Window* window); + // Reverts the name of the given |desk| to the default value (i.e. "Desk 1", // "Desk 2", ... etc.) according to its position in the |desks_| list, as if // it was never modified by users. @@ -218,6 +231,15 @@ // Removes `desk` without animation. void RemoveDeskInternal(const Desk* desk, DesksCreationRemovalSource source); + // Moves all the windows that are visible on all desks that currently + // reside on |active_desk_| to |new_desk|. + void MoveVisibleOnAllDesksWindowsFromActiveDeskTo(Desk* new_desk); + + // Iterates through the visible on all desks windows on the active desk + // and restacks them based on their position in the global MRU tracker. This + // should be called after desk activation. + void RestackAssignedWindowsOnActiveDesk(); + // Returns the desk to which |window| belongs or nullptr if it doesn't belong // to any desk. const Desk* FindDeskOfWindow(aura::Window* window) const; @@ -243,6 +265,9 @@ // Stores the per-user last active desk index. base::flat_map<AccountId, int> user_to_active_desk_index_; + // Stores the visible on all desks windows. + base::flat_set<aura::Window*> visible_on_all_desks_windows_; + // True when desks addition, removal, or activation change are in progress. // This can be checked when overview mode is active to avoid exiting overview // mode as a result of desks modifications.
diff --git a/ash/wm/desks/desks_histogram_enums.h b/ash/wm/desks/desks_histogram_enums.h index 4cfaea15..703f655 100644 --- a/ash/wm/desks/desks_histogram_enums.h +++ b/ash/wm/desks/desks_histogram_enums.h
@@ -25,7 +25,8 @@ kDragAndDrop = 0, kShortcut = 1, kSendToDesk = 2, - kMaxValue = kSendToDesk, + kVisibleOnAllDesks = 3, + kMaxValue = kVisibleOnAllDesks, }; // These values are logged to UMA. Entries should not be renumbered and
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc index 6b584c45..5adfe22c 100644 --- a/ash/wm/desks/desks_unittests.cc +++ b/ash/wm/desks/desks_unittests.cc
@@ -3832,6 +3832,238 @@ EXPECT_FALSE(display_bounds.Contains(new_desk_button->GetBoundsInScreen())); } +// Tests that the bounds of a window that is visible on all desks is shared +// across desks. +TEST_F(DesksBentoTest, VisibleOnAllDesksGlobalBounds) { + auto* controller = DesksController::Get(); + NewDesk(); + const Desk* desk_1 = controller->desks()[0].get(); + const Desk* desk_2 = controller->desks()[1].get(); + auto* root = Shell::GetPrimaryRootWindow(); + const gfx::Rect window_initial_bounds(1, 1, 200, 200); + const gfx::Rect window_moved_bounds(200, 200, 250, 250); + + auto window = CreateAppWindow(window_initial_bounds); + auto* widget = views::Widget::GetWidgetForNativeWindow(window.get()); + ASSERT_EQ(window_initial_bounds, window->bounds()); + + // Assign |window| to all desks. It shouldn't change bounds. + widget->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + EXPECT_EQ(window_initial_bounds, window->bounds()); + EXPECT_EQ(1u, controller->visible_on_all_desks_windows().size()); + + // Move to desk 2. The only window on the new desk should be |window| + // and it should have the same bounds. + ActivateDesk(desk_2); + auto desk_2_children = desk_2->GetDeskContainerForRoot(root)->children(); + EXPECT_EQ(1u, desk_2_children.size()); + EXPECT_EQ(window.get(), desk_2_children[0]); + EXPECT_EQ(window_initial_bounds, window->bounds()); + + // Change |window|'s bounds and move to desk 1. It should retain its moved + // bounds. + window->SetBounds(window_moved_bounds); + EXPECT_EQ(window_moved_bounds, window->bounds()); + ActivateDesk(desk_1); + auto desk_1_children = desk_1->GetDeskContainerForRoot(root)->children(); + EXPECT_EQ(1u, desk_1_children.size()); + EXPECT_EQ(window.get(), desk_1_children[0]); + EXPECT_EQ(window_moved_bounds, window->bounds()); +} + +// Tests that the z-ordering of windows that are visible on all desks respects +// its global MRU ordering. +TEST_F(DesksBentoTest, VisibleOnAllDesksGlobalZOrder) { + auto* controller = DesksController::Get(); + NewDesk(); + const Desk* desk_1 = controller->desks()[0].get(); + const Desk* desk_2 = controller->desks()[1].get(); + auto* root = Shell::GetPrimaryRootWindow(); + + auto win0 = CreateAppWindow(gfx::Rect(0, 0, 100, 100)); + auto win1 = CreateAppWindow(gfx::Rect(1, 1, 150, 150)); + auto win2 = CreateAppWindow(gfx::Rect(2, 2, 200, 200)); + auto* widget0 = views::Widget::GetWidgetForNativeWindow(win0.get()); + auto* widget1 = views::Widget::GetWidgetForNativeWindow(win1.get()); + auto* widget2 = views::Widget::GetWidgetForNativeWindow(win2.get()); + ASSERT_TRUE(IsStackedBelow(win0.get(), win1.get())); + ASSERT_TRUE(IsStackedBelow(win1.get(), win2.get())); + + // Assign |win1| to all desks. It shouldn't change stacking order. + widget1->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(win1->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + EXPECT_TRUE(IsStackedBelow(win0.get(), win1.get())); + EXPECT_TRUE(IsStackedBelow(win1.get(), win2.get())); + EXPECT_EQ(1u, controller->visible_on_all_desks_windows().size()); + + // Move to desk 2. The only window on the new desk should be |win1|. + ActivateDesk(desk_2); + auto desk_2_children = desk_2->GetDeskContainerForRoot(root)->children(); + EXPECT_EQ(1u, desk_2_children.size()); + EXPECT_EQ(win1.get(), desk_2_children[0]); + + // Move to desk 1. Since |win1| was activated last, |win1| should be on top + // of the stacking order. + ActivateDesk(desk_1); + auto desk_1_children = desk_1->GetDeskContainerForRoot(root)->children(); + EXPECT_EQ(3u, desk_1_children.size()); + EXPECT_TRUE(IsStackedBelow(win0.get(), win2.get())); + EXPECT_TRUE(IsStackedBelow(win2.get(), win1.get())); + + // Assign all the other windows and rearrange the order by activating the + // windows. + widget0->SetVisibleOnAllWorkspaces(true); + widget2->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(win0->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + ASSERT_TRUE(win1->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + wm::ActivateWindow(win2.get()); + wm::ActivateWindow(win1.get()); + wm::ActivateWindow(win0.get()); + EXPECT_TRUE(IsStackedBelow(win2.get(), win1.get())); + EXPECT_TRUE(IsStackedBelow(win1.get(), win0.get())); + EXPECT_EQ(3u, controller->visible_on_all_desks_windows().size()); + + // Move to desk 2. All the windows should move to the new desk and maintain + // their order. + ActivateDesk(desk_2); + desk_2_children = desk_2->GetDeskContainerForRoot(root)->children(); + EXPECT_EQ(3u, desk_2_children.size()); + EXPECT_TRUE(IsStackedBelow(win2.get(), win1.get())); + EXPECT_TRUE(IsStackedBelow(win1.get(), win0.get())); +} + +// Tests the behavior of windows that are visible on all desks when the active +// desk is removed. +TEST_F(DesksBentoTest, VisibleOnAllDesksActiveDeskRemoval) { + auto* controller = DesksController::Get(); + NewDesk(); + const Desk* desk_1 = controller->desks()[0].get(); + const Desk* desk_2 = controller->desks()[1].get(); + auto* root = Shell::GetPrimaryRootWindow(); + + auto win0 = CreateAppWindow(gfx::Rect(0, 0, 100, 100)); + auto win1 = CreateAppWindow(gfx::Rect(1, 1, 150, 150)); + auto* widget0 = views::Widget::GetWidgetForNativeWindow(win0.get()); + auto* widget1 = views::Widget::GetWidgetForNativeWindow(win1.get()); + + // Assign |win0| and |win1| to all desks. + widget0->SetVisibleOnAllWorkspaces(true); + widget1->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(win0->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + ASSERT_TRUE(win1->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + + // Remove the active desk. The visible on all desks windows should be on + // |desk_2|. + controller->RemoveDesk(desk_1, DesksCreationRemovalSource::kKeyboard); + auto desk_2_children = desk_2->GetDeskContainerForRoot(root)->children(); + EXPECT_EQ(2u, desk_2_children.size()); + EXPECT_TRUE(IsStackedBelow(win0.get(), win1.get())); + EXPECT_EQ(2u, controller->visible_on_all_desks_windows().size()); +} + +// Tests the behavior of a minimized window that is visible on all desks. +TEST_F(DesksBentoTest, VisibleOnAllDesksMinimizedWindow) { + auto* controller = DesksController::Get(); + NewDesk(); + const Desk* desk_2 = controller->desks()[1].get(); + auto* root = Shell::GetPrimaryRootWindow(); + auto window = CreateAppWindow(gfx::Rect(0, 0, 100, 100)); + auto* widget = views::Widget::GetWidgetForNativeWindow(window.get()); + + // Minimize |window| and then assign it to all desks. This shouldn't + // unminimize it. + auto* window_state = WindowState::Get(window.get()); + window_state->Minimize(); + ASSERT_TRUE(window_state->IsMinimized()); + widget->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + EXPECT_TRUE(window_state->IsMinimized()); + + // Switch desks. |window| should be on the newly active desk and should still + // be minimized. + ActivateDesk(desk_2); + auto desk_2_children = desk_2->GetDeskContainerForRoot(root)->children(); + EXPECT_EQ(1u, desk_2_children.size()); + EXPECT_EQ(window.get(), desk_2_children[0]); + EXPECT_TRUE(window_state->IsMinimized()); +} + +// Tests the behavior of a window that is visible on all desks when a user tries +// to move it to another desk using drag and drop (overview mode). +TEST_F(DesksBentoTest, VisibleOnAllDesksMoveWindowToDeskViaDragAndDrop) { + auto* controller = DesksController::Get(); + auto* root = Shell::GetPrimaryRootWindow(); + NewDesk(); + const Desk* desk_1 = controller->desks()[0].get(); + const Desk* desk_2 = controller->desks()[1].get(); + + auto window = CreateAppWindow(gfx::Rect(0, 0, 100, 100)); + auto* widget = views::Widget::GetWidgetForNativeWindow(window.get()); + + // Assign |window| to all desks. + widget->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + + // Try to move |window| to |desk_2| via drag and drop. It should not be moved. + EXPECT_FALSE(controller->MoveWindowFromActiveDeskTo( + window.get(), const_cast<Desk*>(desk_2), root, + DesksMoveWindowFromActiveDeskSource::kDragAndDrop)); + EXPECT_TRUE(desks_util::BelongsToActiveDesk(window.get())); + EXPECT_EQ(1u, controller->visible_on_all_desks_windows().size()); + EXPECT_TRUE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + EXPECT_TRUE(base::Contains(desk_1->windows(), window.get())); +} + +// Tests the behavior of a window that is visible on all desks when a user tries +// to move it to another desk using keyboard shorcuts. +TEST_F(DesksBentoTest, VisibleOnAllDesksMoveWindowToDeskViaShortcuts) { + auto* controller = DesksController::Get(); + auto* root = Shell::GetPrimaryRootWindow(); + NewDesk(); + const Desk* desk_2 = controller->desks()[1].get(); + + auto window = CreateAppWindow(gfx::Rect(0, 0, 100, 100)); + auto* widget = views::Widget::GetWidgetForNativeWindow(window.get()); + + // Assign |window| to all desks. + widget->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + + // Move |window| to |desk_2| via keyboard shortcut. It should be on |desk_2| + // and should no longer be visible on all desks. + EXPECT_TRUE(controller->MoveWindowFromActiveDeskTo( + window.get(), const_cast<Desk*>(desk_2), root, + DesksMoveWindowFromActiveDeskSource::kShortcut)); + EXPECT_FALSE(desks_util::BelongsToActiveDesk(window.get())); + EXPECT_EQ(0u, controller->visible_on_all_desks_windows().size()); + EXPECT_FALSE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + EXPECT_TRUE(base::Contains(desk_2->windows(), window.get())); +} + +// Tests the behavior of a window that is visible on all desks when a user tries +// to move it using the context menu. +TEST_F(DesksBentoTest, VisibleOnAllDesksMoveWindowToDeskViaContextMenu) { + auto* controller = DesksController::Get(); + NewDesk(); + const Desk* desk_2 = controller->desks()[1].get(); + + auto window = CreateAppWindow(gfx::Rect(0, 0, 100, 100)); + auto* widget = views::Widget::GetWidgetForNativeWindow(window.get()); + + // Assign |window| to all desks. + widget->SetVisibleOnAllWorkspaces(true); + ASSERT_TRUE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + + // Move |window| to |desk_2| via keyboard shortcut. It should be on |desk_2| + // and should no longer be visible on all desks. + controller->SendToDeskAtIndex(window.get(), controller->GetDeskIndex(desk_2)); + EXPECT_FALSE(desks_util::BelongsToActiveDesk(window.get())); + EXPECT_EQ(0u, controller->visible_on_all_desks_windows().size()); + EXPECT_FALSE(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)); + EXPECT_TRUE(base::Contains(desk_2->windows(), window.get())); +} + // TODO(afakhry): Add more tests: // - Always on top windows are not tracked by any desk. // - Reusing containers when desks are removed and created.
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc index 211b6f40..2bb68d7c 100644 --- a/ash/wm/overview/overview_controller.cc +++ b/ash/wm/overview/overview_controller.cc
@@ -251,17 +251,6 @@ return windows; } -std::vector<aura::Window*> -OverviewController::GetItemWindowListInOverviewGridsForTest() { - std::vector<aura::Window*> windows; - for (const std::unique_ptr<OverviewGrid>& grid : - overview_session_->grid_list()) { - for (const auto& overview_item : grid->window_list()) - windows.push_back(overview_item->item_widget()->GetNativeWindow()); - } - return windows; -} - void OverviewController::ToggleOverview(OverviewEnterExitType type) { // Hide the virtual keyboard as it obstructs the overview mode. // Don't need to hide if it's the a11y keyboard, as overview mode
diff --git a/ash/wm/overview/overview_controller.h b/ash/wm/overview/overview_controller.h index 138ae9d..0200cf9e 100644 --- a/ash/wm/overview/overview_controller.h +++ b/ash/wm/overview/overview_controller.h
@@ -102,7 +102,6 @@ // Gets the windows list that are shown in the overview windows grids if the // overview mode is active for testing. std::vector<aura::Window*> GetWindowsListInOverviewGridsForTest(); - std::vector<aura::Window*> GetItemWindowListInOverviewGridsForTest(); private: friend class OverviewSessionTest;
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index be06bf31..04e15e5 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -155,8 +155,6 @@ } // namespace -// TODO(bruthig): Move all non-simple method definitions out of class -// declaration. class OverviewSessionTest : public AshTestBase { public: OverviewSessionTest() = default;
diff --git a/ash/wm/overview/overview_test_util.cc b/ash/wm/overview/overview_test_util.cc index ba645bc3..3d01d395 100644 --- a/ash/wm/overview/overview_test_util.cc +++ b/ash/wm/overview/overview_test_util.cc
@@ -35,8 +35,6 @@ } // namespace -// TODO(sammiequon): Consider adding an overload for this function to trigger -// the key event |count| times. void SendKey(ui::KeyboardCode key, int flags) { ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); generator.PressKey(key, flags);
diff --git a/ash/wm/tablet_mode/DIR_METADATA b/ash/wm/tablet_mode/DIR_METADATA index 3ab7038a..8e8a6a7 100644 --- a/ash/wm/tablet_mode/DIR_METADATA +++ b/ash/wm/tablet_mode/DIR_METADATA
@@ -1,3 +1,3 @@ monorail { - component: "UI>Shell>TouchView" + component: "UI>Shell>TabletMode" }
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc index 8e6ad19a..403250bb 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -627,27 +627,27 @@ } } +void TabletModeController::OnECLidAngleDriverStatusChanged(bool is_supported) { + is_ec_lid_angle_driver_supported_ = is_supported; + + if (!is_supported) + return; + + // When ChromeOS EC lid angle driver is supported, EC can handle lid angle + // calculation, thus Chrome side lid angle calculation is disabled. In this + // case, TabletModeController no longer listens to accelerometer samples. + + // Reset lid angle that might be calculated before lid angle driver is + // read. + lid_angle_ = 0.f; + can_detect_lid_angle_ = false; + if (record_lid_angle_timer_.IsRunning()) + record_lid_angle_timer_.Stop(); + AccelerometerReader::GetInstance()->RemoveObserver(this); +} + void TabletModeController::OnAccelerometerUpdated( const AccelerometerUpdate& update) { - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::UNKNOWN) { - ec_lid_angle_driver_status_ = - AccelerometerReader::GetInstance()->GetECLidAngleDriverStatus(); - } - - // When ChromeOS EC lid angle driver is present, EC can handle lid angle - // calculation, thus Chrome side lid angle calculation is disabled. In this - // case, TabletModeController no longer listens to accelerometer events. - if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED) { - // Reset lid angle that might be calculated before lid angle driver is - // read. - lid_angle_ = 0.f; - can_detect_lid_angle_ = false; - if (record_lid_angle_timer_.IsRunning()) - record_lid_angle_timer_.Stop(); - AccelerometerReader::GetInstance()->RemoveObserver(this); - return; - } - have_seen_accelerometer_data_ = true; can_detect_lid_angle_ = update.has(ACCELEROMETER_SOURCE_SCREEN) && update.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD); @@ -1300,7 +1300,7 @@ const bool can_enter_tablet_mode = IsBoardTypeMarkedAsTabletCapable() && HasActiveInternalDisplay() && - (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::SUPPORTED || + (is_ec_lid_angle_driver_supported_.value_or(false) || have_seen_accelerometer_data_); return !has_internal_pointing_device_ && can_enter_tablet_mode &&
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.h b/ash/wm/tablet_mode/tablet_mode_controller.h index 056908d..a1e37ab1 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.h +++ b/ash/wm/tablet_mode/tablet_mode_controller.h
@@ -147,6 +147,7 @@ void OnChromeTerminating() override; // AccelerometerReader::Observer: + void OnECLidAngleDriverStatusChanged(bool is_supported) override; void OnAccelerometerUpdated(const AccelerometerUpdate& update) override; // chromeos::PowerManagerClient::Observer: @@ -351,15 +352,17 @@ // internal keyboard and touchpad. std::unique_ptr<InternalInputDevicesEventBlocker> event_blocker_; - // Whether we have ever seen accelerometer data. When ChromeOS EC lid angle is - // present, convertible device cannot see accelerometer data. + // Whether we have ever seen accelerometer data. When ChromeOS EC lid angle + // driver is supported, convertible device cannot see accelerometer data. bool have_seen_accelerometer_data_ = false; // If ECLidAngleDriverStatus is supported, Chrome does not calculate lid angle - // itself, but will reply on the tablet-mode flag that EC sends to decide if + // itself, but will rely on the tablet-mode flag that EC sends to decide if // the device should in tablet mode. - ECLidAngleDriverStatus ec_lid_angle_driver_status_ = - ECLidAngleDriverStatus::UNKNOWN; + // As it's set in |OnECLidAngleDriverStatusChanged|, which is a callback by + // AccelerometerReader, we make it optional to indicate a lack of value until + // the accelerometer reader is initialized. + base::Optional<bool> is_ec_lid_angle_driver_supported_; // Whether the lid angle can be detected by browser. If it's true, the device // is a convertible device (both screen acclerometer and keyboard acclerometer
diff --git a/ash/wm/window_properties.cc b/ash/wm/window_properties.cc index 52630ab..fc3e42ca 100644 --- a/ash/wm/window_properties.cc +++ b/ash/wm/window_properties.cc
@@ -5,7 +5,6 @@ #include "ash/wm/window_properties.h" #include "ash/wm/window_state.h" -#include "ui/gfx/geometry/rect.h" DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(ASH_EXPORT, ash::WindowState*) @@ -15,8 +14,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kLockedToRootKey, false) -DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowIsJanky, false) - DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(WindowState, kWindowStateKey, nullptr) } // namespace ash
diff --git a/ash/wm/window_properties.h b/ash/wm/window_properties.h index 8d4305da..b0c9278 100644 --- a/ash/wm/window_properties.h +++ b/ash/wm/window_properties.h
@@ -31,10 +31,6 @@ // bounds outside of its root window is set. ASH_EXPORT extern const aura::WindowProperty<bool>* const kLockedToRootKey; -// Set to true if the window server tells us the window is janky (see -// WindowManagerDelegate::OnWmClientJankinessChanged()). -ASH_EXPORT extern const aura::WindowProperty<bool>* const kWindowIsJanky; - // A property key to store WindowState in the window. The window state // is owned by the window. ASH_EXPORT extern const aura::WindowProperty<WindowState*>* const
diff --git a/ash/wm/workspace/multi_window_resize_controller_unittest.cc b/ash/wm/workspace/multi_window_resize_controller_unittest.cc index 291d48c..2bd5fca 100644 --- a/ash/wm/workspace/multi_window_resize_controller_unittest.cc +++ b/ash/wm/workspace/multi_window_resize_controller_unittest.cc
@@ -77,8 +77,6 @@ bool HasPendingShow() { return resize_controller_->show_timer_.IsRunning(); } - void Hide() { resize_controller_->Hide(); } - bool HasTarget(aura::Window* window) { if (!resize_controller_->windows_.is_valid()) return false;
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc index 483572b4..a9725b6 100644 --- a/ash/wm/workspace/workspace_layout_manager.cc +++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -19,6 +19,8 @@ #include "ash/shelf/shelf.h" #include "ash/shell.h" #include "ash/wm/always_on_top_controller.h" +#include "ash/wm/desks/desk.h" +#include "ash/wm/desks/desks_controller.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/fullscreen_window_finder.h" #include "ash/wm/screen_pinning_controller.h" @@ -315,6 +317,19 @@ } else if (key == kWindowBackdropKey) { // kWindowBackdropKey is not supposed to be cleared. DCHECK(window->GetProperty(kWindowBackdropKey)); + } else if (key == aura::client::kVisibleOnAllWorkspacesKey) { + auto* desks_controller = Shell::Get()->desks_controller(); + + if (window->type() != aura::client::WindowType::WINDOW_TYPE_NORMAL || + window->GetProperty(aura::client::kZOrderingKey) != + ui::ZOrderLevel::kNormal) { + return; + } + + if (window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)) + desks_controller->AddVisibleOnAllDesksWindow(window); + else + desks_controller->RemoveVisibleOnAllDesksWindow(window); } }
diff --git a/ash/wm/workspace_controller_test_api.cc b/ash/wm/workspace_controller_test_api.cc index 5a6f64e..eb2aac8 100644 --- a/ash/wm/workspace_controller_test_api.cc +++ b/ash/wm/workspace_controller_test_api.cc
@@ -22,11 +22,6 @@ return controller_->event_handler_.get(); } -MultiWindowResizeController* -WorkspaceControllerTestApi::GetMultiWindowResizeController() { - return WorkspaceEventHandlerTestHelper(GetEventHandler()).resize_controller(); -} - aura::Window* WorkspaceControllerTestApi::GetBackdropWindow() { return controller_->layout_manager_->backdrop_controller_->backdrop_window_; }
diff --git a/ash/wm/workspace_controller_test_api.h b/ash/wm/workspace_controller_test_api.h index 96777dae..f98441e 100644 --- a/ash/wm/workspace_controller_test_api.h +++ b/ash/wm/workspace_controller_test_api.h
@@ -6,26 +6,28 @@ #define ASH_WM_WORKSPACE_CONTROLLER_TEST_API_H_ #include "ash/ash_export.h" -#include "ash/wm/workspace_controller.h" -#include "base/macros.h" + +namespace aura { +class Window; +} namespace ash { -class MultiWindowResizeController; +class WorkspaceController; class WorkspaceEventHandler; class ASH_EXPORT WorkspaceControllerTestApi { public: explicit WorkspaceControllerTestApi(WorkspaceController* controller); + WorkspaceControllerTestApi(const WorkspaceControllerTestApi&) = delete; + WorkspaceControllerTestApi& operator=(const WorkspaceControllerTestApi&) = + delete; ~WorkspaceControllerTestApi(); WorkspaceEventHandler* GetEventHandler(); - MultiWindowResizeController* GetMultiWindowResizeController(); aura::Window* GetBackdropWindow(); private: WorkspaceController* controller_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTestApi); }; } // namespace ash
diff --git a/base/allocator/allocator_shim.h b/base/allocator/allocator_shim.h index 6c1bf3b..2cdcfad 100644 --- a/base/allocator/allocator_shim.h +++ b/base/allocator/allocator_shim.h
@@ -146,7 +146,7 @@ // in malloc(), which we really don't want. BASE_EXPORT void RemoveAllocatorDispatchForTesting(AllocatorDispatch* dispatch); -#if defined(OS_WIN) +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && defined(OS_WIN) // Configures the allocator for the caller's allocation domain. Allocations that // take place prior to this configuration step will succeed, but will not // benefit from its one-time mitigations. As such, this function must be called
diff --git a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc index 2b9ab96..20c07457 100644 --- a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc +++ b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -5,6 +5,7 @@ #include "base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h" #include "base/allocator/allocator_shim_internals.h" +#include "base/allocator/buildflags.h" #include "base/allocator/partition_allocator/memory_reclaimer.h" #include "base/allocator/partition_allocator/partition_alloc.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h" @@ -117,6 +118,7 @@ } #if defined(OS_WIN) && defined(ARCH_CPU_X86) +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) bool IsRunning32bitEmulatedOnArm64() { using IsWow64Process2Function = decltype(&IsWow64Process2); @@ -135,6 +137,7 @@ return true; return false; } +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) // The number of bytes to add to every allocation. Ordinarily zero, but set to 8 // when emulating an x86 on ARM64 to avoid a bug in the Windows x86 emulator.
diff --git a/base/metrics/field_trial_param_associator.cc b/base/metrics/field_trial_param_associator.cc index ea76b79..8414b52 100644 --- a/base/metrics/field_trial_param_associator.cc +++ b/base/metrics/field_trial_param_associator.cc
@@ -62,7 +62,7 @@ FieldTrialParams* params) { AutoLock scoped_lock(lock_); - const FieldTrialKey key(trial_name, group_name); + const FieldTrialRefKey key(trial_name, group_name); if (!Contains(field_trial_params_, key)) return false; @@ -82,7 +82,7 @@ const std::string& trial_name, const std::string& group_name) { AutoLock scoped_lock(lock_); - const FieldTrialKey key(trial_name, group_name); + const FieldTrialRefKey key(trial_name, group_name); field_trial_params_.erase(key); }
diff --git a/base/metrics/field_trial_param_associator.h b/base/metrics/field_trial_param_associator.h index 17c2b3c7..27c5904 100644 --- a/base/metrics/field_trial_param_associator.h +++ b/base/metrics/field_trial_param_associator.h
@@ -62,6 +62,8 @@ // (field_trial_name, field_trial_group) typedef std::pair<std::string, std::string> FieldTrialKey; + // The following type can be used for lookups without needing to copy strings. + typedef std::pair<const std::string&, const std::string&> FieldTrialRefKey; Lock lock_; std::map<FieldTrialKey, FieldTrialParams> field_trial_params_;
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index cc1ca9ba..116eafeff 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -11,6 +11,7 @@ #include "base/location.h" #include "base/macros.h" #include "base/threading/hang_watcher.h" +#include "build/build_config.h" // ----------------------------------------------------------------------------- // Usage documentation @@ -228,6 +229,9 @@ } namespace printing { class LocalPrinterHandlerDefault; +#if defined(OS_MAC) +class PrintBackendServiceImpl; +#endif class PrintJobWorker; class PrinterQuery; } @@ -399,6 +403,9 @@ friend class module_installer::ScopedAllowModulePakLoad; friend class mojo::CoreLibraryInitializer; friend class printing::LocalPrinterHandlerDefault; +#if defined(OS_MAC) + friend class printing::PrintBackendServiceImpl; +#endif friend class printing::PrintJobWorker; friend class resource_coordinator::TabManagerDelegate; // crbug.com/778703 friend class web::WebSubThread;
diff --git a/build/chromeos/test_runner.py b/build/chromeos/test_runner.py index 72aaac8..1628d3f 100755 --- a/build/chromeos/test_runner.py +++ b/build/chromeos/test_runner.py
@@ -264,6 +264,13 @@ self._tests = args.tests self._conditional = args.conditional self._should_strip = args.strip_chrome + self._deploy_lacros = args.deploy_lacros + + if self._deploy_lacros and self._should_strip: + raise TestFormatError( + '--strip-chrome is only applicable to ash-chrome because ' + 'lacros-chrome deployment uses --nostrip by default, so it cannot ' + 'be specificed with --deploy-lacros.') if not self._llvm_profile_var and not self._logs_dir: # The host-side Tast bin returns 0 when tests fail, so we need to capture @@ -290,11 +297,12 @@ if not arg.startswith('--gtest_repeat') ] + # Lacros deployment mounts itself by default. + self._test_cmd.extend( + ['--deploy-lacros'] if self._deploy_lacros else ['--deploy', '--mount']) self._test_cmd += [ - '--deploy', - '--mount', '--build-dir', - os.path.relpath(self._path_to_outdir, CHROMIUM_SRC_PATH), + os.path.relpath(self._path_to_outdir, CHROMIUM_SRC_PATH) ] + self._additional_args # Coverage tests require some special pre-test setup, so use an @@ -329,10 +337,6 @@ './' + os.path.relpath(self._on_device_script, self._path_to_outdir) ] else: - # Mounting the browser gives it enough disk space to not need stripping, - # but only for browsers not instrumented with code coverage. - if not self._should_strip: - self._test_cmd.append('--nostrip') # Capture tast's results in the logs dir as well. if self._logs_dir: self._test_cmd += [ @@ -356,6 +360,12 @@ for v in self._tast_vars or []: self._test_cmd.extend(['--tast-var', v]) + # Mounting ash-chrome gives it enough disk space to not need stripping, + # but only for one not instrumented with code coverage. + # Lacros uses --nostrip by default, so there is no need to specify. + if not self._deploy_lacros and not self._should_strip: + self._test_cmd.append('--nostrip') + def post_run(self, return_code): # If we don't need to parse the host-side Tast tool's results, fall back to # the parent method's default behavior. @@ -705,7 +715,7 @@ if args.deploy_chrome: cros_run_test_cmd += [ '--deploy', - # Mounting the browser gives it enough disk space to not need stripping. + # Mounting ash-chrome gives it enough disk space to not need stripping. '--mount', '--nostrip', '--build-dir', @@ -822,8 +832,9 @@ host_cmd_parser.add_argument( '--deploy-chrome', action='store_true', - help='Will deploy a locally built Chrome binary to the device before ' + help='Will deploy a locally built ash-chrome binary to the device before ' 'running the host-cmd.') + # GTest args. # TODO(bpastene): Rename 'vm-test' arg to 'gtest'. gtest_parser = subparsers.add_parser( @@ -890,7 +901,11 @@ tast_test_parser.add_argument( '--strip-chrome', action='store_true', - help='Strips symbols from the browser before deploying to the device.') + help='Strips symbols from ash-chrome before deploying to the device.') + tast_test_parser.add_argument( + '--deploy-lacros', + action='store_true', + help='Deploy a lacros-chrome instead of ash-chrome.') tast_test_parser.add_argument( '--tast-var', action='append',
diff --git a/build/chromeos/test_runner_test.py b/build/chromeos/test_runner_test.py index cc5b192c..03cc0dc 100755 --- a/build/chromeos/test_runner_test.py +++ b/build/chromeos/test_runner_test.py
@@ -34,7 +34,12 @@ test_runner.result_sink, 'TryInitClient', return_value=None) self.mock_rdb.start() - self.common_tast_args = [ + def tearDown(self): + shutil.rmtree(self._tmp_dir, ignore_errors=True) + self.mock_rdb.stop() + + def get_common_tast_args(self, use_vm): + return [ 'script_name', 'tast', '--suite-name=chrome_all_tast_tests', @@ -42,8 +47,11 @@ '--flash', '--path-to-outdir=out_eve/Release', '--logs-dir=%s' % self._tmp_dir, + '--use-vm' if use_vm else '--device=localhost:2222', ] - self.common_tast_expectations = [ + + def get_common_tast_expectations(self, use_vm, is_lacros=False): + expectation = [ test_runner.CROS_RUN_TEST_PATH, '--board', 'eve', @@ -51,9 +59,6 @@ test_runner.DEFAULT_CROS_CACHE, '--results-dest-dir', '%s/system_logs' % self._tmp_dir, - '--mount', - '--deploy', - '--nostrip', '--flash', '--build-dir', 'out_eve/Release', @@ -62,10 +67,18 @@ '--tast-total-shards=1', '--tast-shard-index=0', ] + expectation.extend(['--start', '--copy-on-write'] + if use_vm else ['--device', 'localhost:2222']) + for p in test_runner.SYSTEM_LOG_LOCATIONS: + expectation.extend(['--results-src', p]) - def tearDown(self): - shutil.rmtree(self._tmp_dir, ignore_errors=True) - self.mock_rdb.stop() + if not is_lacros: + expectation += [ + '--mount', + '--deploy', + '--nostrip', + ] + return expectation @parameterized.expand([ [True], @@ -121,22 +134,17 @@ with open(os.path.join(self._tmp_dir, 'streamed_results.jsonl'), 'w') as f: json.dump(_TAST_TEST_RESULTS_JSON, f) - args = self.common_tast_args + [ + args = self.get_common_tast_args(use_vm) + [ '-t=ui.ChromeLogin', - '--use-vm' if use_vm else '--device=localhost:2222', ] with mock.patch.object(sys, 'argv', args),\ mock.patch.object(test_runner.subprocess, 'Popen') as mock_popen: mock_popen.return_value.returncode = 0 test_runner.main() - expected_cmd = self.common_tast_expectations + [ + expected_cmd = self.get_common_tast_expectations(use_vm) + [ '--tast', 'ui.ChromeLogin' ] - expected_cmd.extend(['--start', '--copy-on-write'] - if use_vm else ['--device', 'localhost:2222']) - for p in test_runner.SYSTEM_LOG_LOCATIONS: - expected_cmd.extend(['--results-src', p]) self.assertItemsEqual(expected_cmd, mock_popen.call_args[0][0]) @@ -149,25 +157,47 @@ with open(os.path.join(self._tmp_dir, 'streamed_results.jsonl'), 'w') as f: json.dump(_TAST_TEST_RESULTS_JSON, f) - args = self.common_tast_args + [ + args = self.get_common_tast_args(use_vm) + [ '--attr-expr=( "group:mainline" && "dep:chrome" && !informational)', - '--use-vm' if use_vm else '--device=localhost:2222', ] with mock.patch.object(sys, 'argv', args),\ mock.patch.object(test_runner.subprocess, 'Popen') as mock_popen: mock_popen.return_value.returncode = 0 test_runner.main() - expected_cmd = self.common_tast_expectations + [ + expected_cmd = self.get_common_tast_expectations(use_vm) + [ '--tast=( "group:mainline" && "dep:chrome" && !informational)', ] - expected_cmd.extend(['--start', '--copy-on-write'] - if use_vm else ['--device', 'localhost:2222']) - for p in test_runner.SYSTEM_LOG_LOCATIONS: - expected_cmd.extend(['--results-src', p]) self.assertItemsEqual(expected_cmd, mock_popen.call_args[0][0]) + @parameterized.expand([ + [True], + [False], + ]) + def test_tast_lacros(self, use_vm): + """Tests running a tast tests for Lacros.""" + with open(os.path.join(self._tmp_dir, 'streamed_results.jsonl'), 'w') as f: + json.dump(_TAST_TEST_RESULTS_JSON, f) + + args = self.get_common_tast_args(use_vm) + [ + '-t=lacros.Basic', + '--deploy-lacros', + ] + + with mock.patch.object(sys, 'argv', args),\ + mock.patch.object(test_runner.subprocess, 'Popen') as mock_popen: + mock_popen.return_value.returncode = 0 + + test_runner.main() + expected_cmd = self.get_common_tast_expectations( + use_vm, is_lacros=True) + [ + '--tast', + 'lacros.Basic', + '--deploy-lacros', + ] + + self.assertItemsEqual(expected_cmd, mock_popen.call_args[0][0]) @parameterized.expand([ [True], @@ -178,22 +208,17 @@ with open(os.path.join(self._tmp_dir, 'streamed_results.jsonl'), 'w') as f: json.dump(_TAST_TEST_RESULTS_JSON, f) - args = self.common_tast_args + [ + args = self.get_common_tast_args(use_vm) + [ '-t=ui.ChromeLogin', '--tast-var=key=value', - '--use-vm' if use_vm else '--device=localhost:2222', ] with mock.patch.object(sys, 'argv', args),\ mock.patch.object(test_runner.subprocess, 'Popen') as mock_popen: mock_popen.return_value.returncode = 0 test_runner.main() - expected_cmd = self.common_tast_expectations + [ + expected_cmd = self.get_common_tast_expectations(use_vm) + [ '--tast', 'ui.ChromeLogin', '--tast-var', 'key=value' ] - expected_cmd.extend(['--start', '--copy-on-write'] - if use_vm else ['--device', 'localhost:2222']) - for p in test_runner.SYSTEM_LOG_LOCATIONS: - expected_cmd.extend(['--results-src', p]) self.assertItemsEqual(expected_cmd, mock_popen.call_args[0][0])
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index d8eb6546..1cff8218 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -162,6 +162,17 @@ is_component_build = is_debug && current_os != "ios" } +declare_args() { + # Regression Test Selection (RTS). + # https://chromium.googlesource.com/chromium/src/+/master/docs/testing/regression-test-selection.md + # + # Exclude unittest/browsertest files listed in this file. + # + # Entries should be newline separated. + # Each entry much be an source-absolute path starting with //. + rts_exclude_file = "" +} + assert(!(is_debug && is_official_build), "Can't do official debug builds") # ============================================================================== @@ -575,3 +586,32 @@ configs = default_compiler_configs } } + +# ============================================================================== +# Regression Test Selection (RTS) +# https://chromium.googlesource.com/chromium/src/+/master/docs/testing/regression-test-selection.md +# ============================================================================== +if (rts_exclude_file != "") { + rts_exclusions = read_file(rts_exclude_file, "list lines") + + # Many tests are included in source_sets + template("source_set") { + _target_name = target_name + target("source_set", _target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + if (defined(sources) && sources != []) { + # Normalize paths + abs_paths = get_path_info(sources, "abspath") + + # Filter + filtered_sources = filter_exclude(abs_paths, rts_exclusions) + + # Do the replacement + sources = [] + sources = filtered_sources + } + } + } +}
diff --git a/cc/animation/animation_unittest.cc b/cc/animation/animation_unittest.cc index 360400e..15fe896 100644 --- a/cc/animation/animation_unittest.cc +++ b/cc/animation/animation_unittest.cc
@@ -456,30 +456,33 @@ animation_->id(), element_id_.ToString().c_str()), animation_->ToString()); - animation_->AddKeyframeModel( - KeyframeModel::Create(std::make_unique<FakeFloatAnimationCurve>(15), 42, - 73, TargetProperty::OPACITY)); + animation_->AddKeyframeModel(KeyframeModel::Create( + std::make_unique<FakeFloatAnimationCurve>(15), 42, 73, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); EXPECT_EQ( base::StringPrintf("Animation{id=%d, element_id=%s, " "keyframe_models=[KeyframeModel{id=42, " - "group=73, target_property_id=1, " - "run_state=WAITING_FOR_TARGET_AVAILABILITY}]}", + "group=73, target_property_type=1, " + "custom_property_name=, native_property_type=1, " + "run_state=WAITING_FOR_TARGET_AVAILABILITY, " + "element_id=(0)}]}", animation_->id(), element_id_.ToString().c_str()), animation_->ToString()); - animation_->AddKeyframeModel( - KeyframeModel::Create(std::make_unique<FakeFloatAnimationCurve>(18), 45, - 76, TargetProperty::BOUNDS)); - EXPECT_EQ( - base::StringPrintf( - "Animation{id=%d, element_id=%s, " - "keyframe_models=[KeyframeModel{id=42, " - "group=73, target_property_id=1, " - "run_state=WAITING_FOR_TARGET_AVAILABILITY}, KeyframeModel{id=45, " - "group=76, " - "target_property_id=5, run_state=WAITING_FOR_TARGET_AVAILABILITY}]}", - animation_->id(), element_id_.ToString().c_str()), - animation_->ToString()); + animation_->AddKeyframeModel(KeyframeModel::Create( + std::make_unique<FakeFloatAnimationCurve>(18), 45, 76, + KeyframeModel::TargetPropertyId(TargetProperty::BOUNDS))); + EXPECT_EQ(base::StringPrintf( + "Animation{id=%d, element_id=%s, " + "keyframe_models=[KeyframeModel{id=42, " + "group=73, target_property_type=1, custom_property_name=, " + "native_property_type=1, " + "run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}, " + "KeyframeModel{id=45, group=76, target_property_type=5, " + "custom_property_name=, native_property_type=1, " + "run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}]}", + animation_->id(), element_id_.ToString().c_str()), + animation_->ToString()); } } // namespace
diff --git a/cc/animation/element_animations.cc b/cc/animation/element_animations.cc index 7c3ef87..2427573 100644 --- a/cc/animation/element_animations.cc +++ b/cc/animation/element_animations.cc
@@ -223,7 +223,7 @@ float value, int target_property_id, KeyframeModel* keyframe_model) { - switch (keyframe_model->target_property_id()) { + switch (keyframe_model->target_property_type()) { case TargetProperty::CSS_CUSTOM_PROPERTY: case TargetProperty::NATIVE_PROPERTY: // Custom properties are only tracked on the pending tree, where they may @@ -251,7 +251,7 @@ const FilterOperations& filters, int target_property_id, KeyframeModel* keyframe_model) { - switch (keyframe_model->target_property_id()) { + switch (keyframe_model->target_property_type()) { case TargetProperty::BACKDROP_FILTER: if (KeyframeModelAffectsActiveElements(keyframe_model)) OnBackdropFilterAnimated(ElementListType::ACTIVE, filters, @@ -275,7 +275,7 @@ SkColor value, int target_property_id, KeyframeModel* keyframe_model) { - DCHECK_EQ(keyframe_model->target_property_id(), + DCHECK_EQ(keyframe_model->target_property_type(), TargetProperty::CSS_CUSTOM_PROPERTY); OnCustomPropertyAnimated(PaintWorkletInput::PropertyValue(value), keyframe_model, target_property_id);
diff --git a/cc/animation/element_animations_unittest.cc b/cc/animation/element_animations_unittest.cc index 9e1fa83..3486db3 100644 --- a/cc/animation/element_animations_unittest.cc +++ b/cc/animation/element_animations_unittest.cc
@@ -4,6 +4,9 @@ #include "cc/animation/element_animations.h" +#include <limits> +#include <utility> + #include "base/memory/ptr_util.h" #include "cc/animation/animation.h" #include "cc/animation/animation_delegate.h" @@ -269,7 +272,8 @@ curve_fixed->SetInitialValue(initial_value); const int animation1_id = 1; std::unique_ptr<KeyframeModel> animation_fixed(KeyframeModel::Create( - std::move(curve_fixed), animation1_id, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve_fixed), animation1_id, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); animation_->AddKeyframeModel(std::move(animation_fixed)); PushProperties(); EXPECT_VECTOR2DF_EQ(initial_value, animation_impl_->keyframe_effect() @@ -285,7 +289,8 @@ target_value)); const int animation2_id = 2; std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), animation2_id, 1, TargetProperty::SCROLL_OFFSET)); + std::move(curve), animation2_id, 1, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); animation_->AddKeyframeModel(std::move(keyframe_model)); PushProperties(); EXPECT_VECTOR2DF_EQ(provider_initial_value, @@ -751,7 +756,8 @@ std::unique_ptr<AnimationCurve> curve, int group_id, TargetProperty::Type property) { - return KeyframeModel::Create(std::move(curve), 0, group_id, property); + return KeyframeModel::Create(std::move(curve), 0, group_id, + KeyframeModel::TargetPropertyId(property)); } TEST_F(ElementAnimationsTest, TrivialTransition) { @@ -807,8 +813,9 @@ curve->AddKeyframe(FilterKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), end_filters, nullptr)); - std::unique_ptr<KeyframeModel> keyframe_model( - KeyframeModel::Create(std::move(curve), 1, 0, TargetProperty::FILTER)); + std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::FILTER))); animation_->AddKeyframeModel(std::move(keyframe_model)); animation_->Tick(kInitialTickTime); @@ -850,7 +857,8 @@ end_filters, nullptr)); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::BACKDROP_FILTER)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::BACKDROP_FILTER))); animation_->AddKeyframeModel(std::move(keyframe_model)); animation_->Tick(kInitialTickTime); @@ -889,7 +897,8 @@ target_value)); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); animation_->AddKeyframeModel(std::move(keyframe_model)); @@ -961,7 +970,8 @@ double duration_in_seconds = curve->Duration().InSecondsF(); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->SetIsImplOnly(); animation_impl_->AddKeyframeModel(std::move(keyframe_model)); @@ -1060,7 +1070,8 @@ target_value)); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); animation_->AddKeyframeModel(std::move(keyframe_model)); @@ -1139,7 +1150,8 @@ int keyframe_model_id = 1; std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), keyframe_model_id, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), keyframe_model_id, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); animation_->AddKeyframeModel(std::move(keyframe_model)); PushProperties(); @@ -1166,8 +1178,9 @@ // Now, test the 2-argument version of RemoveKeyframeModel. curve = ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( target_value); - keyframe_model = KeyframeModel::Create(std::move(curve), keyframe_model_id, 0, - TargetProperty::SCROLL_OFFSET); + keyframe_model = KeyframeModel::Create( + std::move(curve), keyframe_model_id, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET)); keyframe_model->set_needs_synchronized_start_time(true); animation_->AddKeyframeModel(std::move(keyframe_model)); PushProperties(); @@ -1261,7 +1274,8 @@ curve->SetInitialValue(initial_value); TimeDelta duration = curve->Duration(); std::unique_ptr<KeyframeModel> to_add(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); to_add->SetIsImplOnly(); animation_impl_->AddKeyframeModel(std::move(to_add)); @@ -1379,10 +1393,12 @@ int animation2_id = 2; animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), - animation1_id, 1, TargetProperty::OPACITY)); + animation1_id, 1, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.5f)), - animation2_id, 2, TargetProperty::OPACITY)); + animation2_id, 2, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); animation_->Tick(kInitialTickTime); @@ -1679,13 +1695,14 @@ const int keyframe_model_id = 2; animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1)), 1, 1, - TargetProperty::TRANSFORM)); + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)), - keyframe_model_id, 1, TargetProperty::OPACITY)); + keyframe_model_id, 1, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 1.f, 0.75f)), - 3, 2, TargetProperty::OPACITY)); + 3, 2, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); animation_->Tick(kInitialTickTime); animation_->UpdateState(true, events.get()); @@ -1873,19 +1890,19 @@ // state. animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 1, 1, - TargetProperty::TRANSFORM)); + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), - 2, 2, TargetProperty::OPACITY)); + 2, 2, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 3, 3, - TargetProperty::TRANSFORM)); + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(2.0)), 4, 4, - TargetProperty::TRANSFORM)); + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), - 5, 5, TargetProperty::OPACITY)); + 5, 5, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); animation_->Tick(kInitialTickTime); animation_->UpdateState(true, nullptr); @@ -2047,7 +2064,8 @@ target_value)); curve->SetInitialValue(initial_value); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), keyframe_model_id, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), keyframe_model_id, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_start_time(TicksFromSecondsF(123)); keyframe_model->SetIsImplOnly(); animation_impl_->AddKeyframeModel(std::move(keyframe_model)); @@ -2113,13 +2131,13 @@ // Add two animations with the same group id but different durations. std::unique_ptr<KeyframeModel> first_keyframe_model(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(2.0)), 1, - group_id, TargetProperty::TRANSFORM)); + group_id, KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); first_keyframe_model->set_is_controlling_instance_for_test(true); animation_impl_->AddKeyframeModel(std::move(first_keyframe_model)); std::unique_ptr<KeyframeModel> second_keyframe_model(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), - 2, group_id, TargetProperty::OPACITY)); + 2, group_id, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); second_keyframe_model->set_is_controlling_instance_for_test(true); animation_impl_->AddKeyframeModel(std::move(second_keyframe_model)); @@ -2242,7 +2260,8 @@ base::TimeDelta::FromSecondsD(1.0), operations1, nullptr)); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve1), 2, 2, TargetProperty::TRANSFORM)); + std::move(curve1), 2, 2, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); animation_impl_->AddKeyframeModel(std::move(keyframe_model)); // The only transform animation we've added is a translation. @@ -2273,7 +2292,8 @@ curve1->AddKeyframe(TransformKeyframe::Create( base::TimeDelta::FromSecondsD(1.0), operations1b, nullptr)); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve1), 1, 1, TargetProperty::TRANSFORM)); + std::move(curve1), 1, 1, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); keyframe_model->set_affects_active_elements(false); animation_impl_->AddKeyframeModel(std::move(keyframe_model)); @@ -2311,8 +2331,9 @@ base::TimeDelta::FromSecondsD(1.0), operations2b, nullptr)); animation_impl_->RemoveKeyframeModel(1); - keyframe_model = - KeyframeModel::Create(std::move(curve2), 2, 2, TargetProperty::TRANSFORM); + keyframe_model = KeyframeModel::Create( + std::move(curve2), 2, 2, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM)); // Reverse Direction keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); @@ -2331,8 +2352,9 @@ curve3->AddKeyframe(TransformKeyframe::Create( base::TimeDelta::FromSecondsD(1.0), operations3b, nullptr)); - keyframe_model = - KeyframeModel::Create(std::move(curve3), 3, 3, TargetProperty::TRANSFORM); + keyframe_model = KeyframeModel::Create( + std::move(curve3), 3, 3, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM)); keyframe_model->set_affects_active_elements(false); animation_impl_->AddKeyframeModel(std::move(keyframe_model)); @@ -2386,7 +2408,8 @@ base::TimeDelta::FromSecondsD(1.0), operations2, nullptr)); std::unique_ptr<KeyframeModel> keyframe_model_owned(KeyframeModel::Create( - std::move(curve1), 1, 1, TargetProperty::TRANSFORM)); + std::move(curve1), 1, 1, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); KeyframeModel* keyframe_model = keyframe_model_owned.get(); animation_impl_->AddKeyframeModel(std::move(keyframe_model_owned)); @@ -3883,10 +3906,10 @@ animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 1, 1, - TargetProperty::TRANSFORM)); + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); animation_->AddKeyframeModel(KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(2.0, 0.f, 1.f)), - 2, 2, TargetProperty::OPACITY)); + 2, 2, KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); // Finish the first keyframe model. animation_->Tick(kInitialTickTime);
diff --git a/cc/animation/keyframe_effect.cc b/cc/animation/keyframe_effect.cc index e6979e5..dc9b8d6 100644 --- a/cc/animation/keyframe_effect.cc +++ b/cc/animation/keyframe_effect.cc
@@ -137,32 +137,32 @@ case AnimationCurve::TRANSFORM: target->NotifyClientTransformOperationsAnimated( curve->ToTransformAnimationCurve()->GetValue(trimmed), - keyframe_model->target_property_id(), keyframe_model); + keyframe_model->target_property_type(), keyframe_model); break; case AnimationCurve::FLOAT: target->NotifyClientFloatAnimated( curve->ToFloatAnimationCurve()->GetValue(trimmed), - keyframe_model->target_property_id(), keyframe_model); + keyframe_model->target_property_type(), keyframe_model); break; case AnimationCurve::FILTER: target->NotifyClientFilterAnimated( curve->ToFilterAnimationCurve()->GetValue(trimmed), - keyframe_model->target_property_id(), keyframe_model); + keyframe_model->target_property_type(), keyframe_model); break; case AnimationCurve::COLOR: target->NotifyClientColorAnimated( curve->ToColorAnimationCurve()->GetValue(trimmed), - keyframe_model->target_property_id(), keyframe_model); + keyframe_model->target_property_type(), keyframe_model); break; case AnimationCurve::SCROLL_OFFSET: target->NotifyClientScrollOffsetAnimated( curve->ToScrollOffsetAnimationCurve()->GetValue(trimmed), - keyframe_model->target_property_id(), keyframe_model); + keyframe_model->target_property_type(), keyframe_model); break; case AnimationCurve::SIZE: target->NotifyClientSizeAnimated( curve->ToSizeAnimationCurve()->GetValue(trimmed), - keyframe_model->target_property_id(), keyframe_model); + keyframe_model->target_property_type(), keyframe_model); break; } } @@ -243,29 +243,30 @@ void KeyframeEffect::AddKeyframeModel( std::unique_ptr<KeyframeModel> keyframe_model) { - DCHECK(keyframe_model->target_property_id() != + DCHECK(keyframe_model->target_property_type() != TargetProperty::SCROLL_OFFSET || (animation_->animation_host()->SupportsScrollAnimations())); DCHECK(!keyframe_model->is_impl_only() || - keyframe_model->target_property_id() == TargetProperty::SCROLL_OFFSET); + keyframe_model->target_property_type() == + TargetProperty::SCROLL_OFFSET); // This is to make sure that keyframe models in the same group, i.e., start // together, don't animate the same property. DCHECK(std::none_of( keyframe_models_.begin(), keyframe_models_.end(), [&](const auto& existing_keyframe_model) { - return keyframe_model->target_property_id() == - existing_keyframe_model->target_property_id() && + return keyframe_model->target_property_type() == + existing_keyframe_model->target_property_type() && keyframe_model->group() == existing_keyframe_model->group(); })); - if (keyframe_model->target_property_id() == TargetProperty::SCROLL_OFFSET) { + if (keyframe_model->target_property_type() == TargetProperty::SCROLL_OFFSET) { // We should never have more than one scroll offset animation queued on the // same scrolling element as this would result in multiple automated // scrolls. DCHECK(std::none_of( keyframe_models_.begin(), keyframe_models_.end(), [&](const auto& existing_keyframe_model) { - return existing_keyframe_model->target_property_id() == + return existing_keyframe_model->target_property_type() == TargetProperty::SCROLL_OFFSET && !existing_keyframe_model->is_finished() && (!existing_keyframe_model->is_controlling_instance() || @@ -309,7 +310,7 @@ }); for (auto it = keyframe_models_to_remove; it != keyframe_models_.end(); ++it) { - if ((*it)->target_property_id() == TargetProperty::SCROLL_OFFSET) { + if ((*it)->target_property_type() == TargetProperty::SCROLL_OFFSET) { if (has_bound_element_animations()) scroll_offset_animation_was_interrupted_ = true; } else if (!(*it)->is_finished()) { @@ -352,7 +353,7 @@ bool aborted_keyframe_model = false; for (auto& keyframe_model : keyframe_models_) { - if (keyframe_model->target_property_id() == target_property && + if (keyframe_model->target_property_type() == target_property && !keyframe_model->is_finished()) { // Currently only impl-only scroll offset KeyframeModels can be completed // on the main thread. @@ -477,7 +478,7 @@ bool KeyframeEffect::AffectsCustomProperty() const { for (const auto& it : keyframe_models_) - if (it->target_property_id() == TargetProperty::CSS_CUSTOM_PROPERTY) + if (it->target_property_type() == TargetProperty::CSS_CUSTOM_PROPERTY) return true; return false; } @@ -493,7 +494,7 @@ bool KeyframeEffect::AnimationsPreserveAxisAlignment() const { for (const auto& keyframe_model : keyframe_models_) { if (keyframe_model->is_finished() || - keyframe_model->target_property_id() != TargetProperty::TRANSFORM) + keyframe_model->target_property_type() != TargetProperty::TRANSFORM) continue; const TransformAnimationCurve* transform_animation_curve = @@ -513,7 +514,7 @@ bool starting_scale_valid = true; for (const auto& keyframe_model : keyframe_models_) { if (keyframe_model->is_finished() || - keyframe_model->target_property_id() != TargetProperty::TRANSFORM) + keyframe_model->target_property_type() != TargetProperty::TRANSFORM) continue; if ((list_type == ElementListType::ACTIVE && @@ -573,7 +574,7 @@ ElementListType list_type) const { for (const auto& keyframe_model : keyframe_models_) { if (!keyframe_model->is_finished() && - keyframe_model->target_property_id() == target_property) { + keyframe_model->target_property_type() == target_property) { if ((list_type == ElementListType::ACTIVE && keyframe_model->affects_active_elements()) || (list_type == ElementListType::PENDING && @@ -590,7 +591,7 @@ for (const auto& keyframe_model : keyframe_models_) { if (!keyframe_model->is_finished() && keyframe_model->InEffect(last_tick_time_.value_or(base::TimeTicks())) && - keyframe_model->target_property_id() == target_property) { + keyframe_model->target_property_type() == target_property) { if ((list_type == ElementListType::ACTIVE && keyframe_model->affects_active_elements()) || (list_type == ElementListType::PENDING && @@ -605,7 +606,7 @@ TargetProperty::Type target_property) const { for (size_t i = 0; i < keyframe_models_.size(); ++i) { size_t index = keyframe_models_.size() - i - 1; - if (keyframe_models_[index]->target_property_id() == target_property) + if (keyframe_models_[index]->target_property_type() == target_property) return keyframe_models_[index].get(); } return nullptr; @@ -631,7 +632,7 @@ keyframe_model->InEffect(last_tick_time_.value_or(base::TimeTicks())); bool active = keyframe_model->affects_active_elements(); bool pending = keyframe_model->affects_pending_elements(); - int property = keyframe_model->target_property_id(); + int property = keyframe_model->target_property_type(); if (pending) pending_state->potentially_animating[property] = true; @@ -706,7 +707,8 @@ if (keyframe_effect_impl->GetKeyframeModelById(keyframe_model->id())) continue; - if (keyframe_model->target_property_id() == TargetProperty::SCROLL_OFFSET && + if (keyframe_model->target_property_type() == + TargetProperty::SCROLL_OFFSET && !keyframe_model->curve() ->ToScrollOffsetAnimationCurve() ->HasSetInitialValue()) { @@ -841,7 +843,7 @@ auto& keyframe_model = keyframe_models_[i]; if (keyframe_model->run_state() == KeyframeModel::STARTING || keyframe_model->run_state() == KeyframeModel::RUNNING) { - int property = keyframe_model->target_property_id(); + int property = keyframe_model->target_property_type(); if (keyframe_model->affects_active_elements()) { blocked_properties_for_active_elements[property] = true; } @@ -871,12 +873,13 @@ bool affects_pending_elements = keyframe_model_waiting_for_target->affects_pending_elements(); enqueued_properties[keyframe_model_waiting_for_target - ->target_property_id()] = true; + ->target_property_type()] = true; for (size_t j = keyframe_model_index + 1; j < keyframe_models_.size(); ++j) { if (keyframe_model_waiting_for_target->group() == keyframe_models_[j]->group()) { - enqueued_properties[keyframe_models_[j]->target_property_id()] = true; + enqueued_properties[keyframe_models_[j]->target_property_type()] = + true; affects_active_elements |= keyframe_models_[j]->affects_active_elements(); affects_pending_elements |= @@ -1095,7 +1098,7 @@ {animation_->animation_timeline()->id(), animation_->id(), keyframe_model.id()}, keyframe_model.group(), - keyframe_model.target_property_id(), monotonic_time); + keyframe_model.target_property_type(), monotonic_time); event.is_impl_only = keyframe_model.is_impl_only(); if (!event.is_impl_only) { events->events_.push_back(event); @@ -1109,7 +1112,8 @@ AnimationEvents* events, const KeyframeModel& keyframe_model, base::TimeTicks monotonic_time) { - DCHECK_EQ(keyframe_model.target_property_id(), TargetProperty::SCROLL_OFFSET); + DCHECK_EQ(keyframe_model.target_property_type(), + TargetProperty::SCROLL_OFFSET); if (!events) return; @@ -1117,7 +1121,7 @@ {animation_->animation_timeline()->id(), animation_->id(), keyframe_model.id()}, keyframe_model.group(), - keyframe_model.target_property_id(), + keyframe_model.target_property_type(), monotonic_time); takeover_event.animation_start_time = keyframe_model.start_time(); const ScrollOffsetAnimationCurve* scroll_offset_animation_curve = @@ -1130,7 +1134,7 @@ {animation_->animation_timeline()->id(), animation_->id(), keyframe_model.id()}, keyframe_model.group(), - keyframe_model.target_property_id(), + keyframe_model.target_property_type(), monotonic_time); // Notify the compositor that the animation is finished. finished_event.is_impl_only = true;
diff --git a/cc/animation/keyframe_model.cc b/cc/animation/keyframe_model.cc index b30d719..c718ea9 100644 --- a/cc/animation/keyframe_model.cc +++ b/cc/animation/keyframe_model.cc
@@ -48,6 +48,30 @@ namespace cc { +KeyframeModel::TargetPropertyId::TargetPropertyId(int target_property_type) + : target_property_type_(target_property_type), + custom_property_name_(""), + native_property_type_(PaintWorkletInput::NativePropertyType::kInvalid) {} + +KeyframeModel::TargetPropertyId::TargetPropertyId( + int target_property_type, + const std::string& custom_property_name) + : target_property_type_(target_property_type), + custom_property_name_(custom_property_name), + native_property_type_(PaintWorkletInput::NativePropertyType::kInvalid) {} + +KeyframeModel::TargetPropertyId::TargetPropertyId( + int target_property_type, + PaintWorkletInput::NativePropertyType native_property_type) + : target_property_type_(target_property_type), + custom_property_name_(""), + native_property_type_(native_property_type) {} + +KeyframeModel::TargetPropertyId::TargetPropertyId( + const TargetPropertyId& other) = default; + +KeyframeModel::TargetPropertyId::~TargetPropertyId() = default; + std::string KeyframeModel::ToString(RunState state) { return s_runStateNames[state]; } @@ -56,12 +80,9 @@ std::unique_ptr<AnimationCurve> curve, int keyframe_model_id, int group_id, - int target_property_id, - const std::string& custom_property_name, - PaintWorkletInput::NativePropertyType native_property_type) { - return base::WrapUnique(new KeyframeModel( - std::move(curve), keyframe_model_id, group_id, target_property_id, - custom_property_name, native_property_type)); + TargetPropertyId target_property_id) { + return base::WrapUnique(new KeyframeModel(std::move(curve), keyframe_model_id, + group_id, target_property_id)); } std::unique_ptr<KeyframeModel> KeyframeModel::CreateImplInstance( @@ -70,8 +91,7 @@ // creating multiple controlling instances. DCHECK(!is_controlling_instance_); std::unique_ptr<KeyframeModel> to_return( - new KeyframeModel(curve_->Clone(), id_, group_, target_property_id_, - custom_property_name_, native_property_type_)); + new KeyframeModel(curve_->Clone(), id_, group_, target_property_id_)); to_return->element_id_ = element_id_; to_return->run_state_ = initial_run_state; to_return->iterations_ = iterations_; @@ -88,19 +108,14 @@ return to_return; } -KeyframeModel::KeyframeModel( - std::unique_ptr<AnimationCurve> curve, - int keyframe_model_id, - int group_id, - int target_property_id, - const std::string& custom_property_name, - PaintWorkletInput::NativePropertyType native_property_type) +KeyframeModel::KeyframeModel(std::unique_ptr<AnimationCurve> curve, + int keyframe_model_id, + int group_id, + TargetPropertyId target_property_id) : curve_(std::move(curve)), id_(keyframe_model_id), group_(group_id), target_property_id_(target_property_id), - custom_property_name_(custom_property_name), - native_property_type_(native_property_type), run_state_(WAITING_FOR_TARGET_AVAILABILITY), iterations_(1), iteration_start_(0), @@ -112,10 +127,7 @@ is_controlling_instance_(false), is_impl_only_(false), affects_active_elements_(true), - affects_pending_elements_(true) { - DCHECK(custom_property_name_.empty() || - target_property_id_ == TargetProperty::CSS_CUSTOM_PROPERTY); -} + affects_pending_elements_(true) {} KeyframeModel::~KeyframeModel() { if (run_state_ == RUNNING || run_state_ == PAUSED) @@ -126,7 +138,8 @@ base::TimeTicks monotonic_time) { char name_buffer[256]; base::snprintf(name_buffer, sizeof(name_buffer), "%s-%d-%d", - s_curveTypeNames[curve_->Type()], target_property_id_, group_); + s_curveTypeNames[curve_->Type()], + target_property_id_.target_property_type(), group_); bool is_waiting_to_start = run_state_ == WAITING_FOR_TARGET_AVAILABILITY || run_state_ == STARTING; @@ -354,10 +367,14 @@ std::string KeyframeModel::ToString() const { return base::StringPrintf( - "KeyframeModel{id=%d, group=%d, target_property_id=%d, " - "run_state=%s}", - id_, group_, target_property_id_, - KeyframeModel::ToString(run_state_).c_str()); + "KeyframeModel{id=%d, group=%d, target_property_type=%d, " + "custom_property_name=%s, native_property_type=%d, run_state=%s, " + "element_id=%s}", + id_, group_, target_property_id_.target_property_type(), + target_property_id_.custom_property_name().c_str(), + static_cast<int>(target_property_id_.native_property_type()), + KeyframeModel::ToString(run_state_).c_str(), + element_id_.ToString().c_str()); } void KeyframeModel::SetIsImplOnly() {
diff --git a/cc/animation/keyframe_model.h b/cc/animation/keyframe_model.h index 23fd3d0..ad88bc07 100644 --- a/cc/animation/keyframe_model.h +++ b/cc/animation/keyframe_model.h
@@ -56,17 +56,44 @@ enum class Phase { BEFORE, ACTIVE, AFTER }; - // The |custom_property_name| has a default value of an empty string, - // indicating that the animated property is a native property. When it is an - // animated custom property, it should be the property name. + class CC_ANIMATION_EXPORT TargetPropertyId { + public: + // For a property that is neither TargetProperty::CSS_CUSTOM_PROPERTY nor + // TargetProperty::NATIVE_PROPERTY. + explicit TargetPropertyId(int target_property_type); + // For TargetProperty::CSS_CUSTOM_PROPERTY, the string is the custom + // property name. + TargetPropertyId(int target_property_type, + const std::string& custom_property_name); + // For TargetProperty::NATIVE_PROPERTY. + TargetPropertyId( + int target_property_type, + PaintWorkletInput::NativePropertyType native_property_type); + TargetPropertyId(const TargetPropertyId&); + ~TargetPropertyId(); + + int target_property_type() const { return target_property_type_; } + const std::string& custom_property_name() const { + return custom_property_name_; + } + PaintWorkletInput::NativePropertyType native_property_type() const { + return native_property_type_; + } + + private: + int target_property_type_; + // Name of the animated custom property. Empty if it is an animated native + // property. + std::string custom_property_name_; + // Type of the animated native property. + PaintWorkletInput::NativePropertyType native_property_type_; + }; + static std::unique_ptr<KeyframeModel> Create( std::unique_ptr<AnimationCurve> curve, int keyframe_model_id, int group_id, - int target_property_id, - const std::string& custom_property_name = "", - PaintWorkletInput::NativePropertyType native_property_type = - PaintWorkletInput::NativePropertyType::kInvalid); + TargetPropertyId target_property_id); std::unique_ptr<KeyframeModel> CreateImplInstance( RunState initial_run_state) const; @@ -78,7 +105,9 @@ int id() const { return id_; } int group() const { return group_; } - int target_property_id() const { return target_property_id_; } + int target_property_type() const { + return target_property_id_.target_property_type(); + } ElementId element_id() const { return element_id_; } void set_element_id(ElementId element_id) { element_id_ = element_id; } @@ -180,11 +209,11 @@ bool affects_pending_elements() const { return affects_pending_elements_; } const std::string& custom_property_name() const { - return custom_property_name_; + return target_property_id_.custom_property_name(); } PaintWorkletInput::NativePropertyType native_property_type() const { - return native_property_type_; + return target_property_id_.native_property_type(); } KeyframeModel::Phase CalculatePhaseForTesting( @@ -194,9 +223,7 @@ KeyframeModel(std::unique_ptr<AnimationCurve> curve, int keyframe_model_id, int group_id, - int target_property_id, - const std::string& custom_property_name, - PaintWorkletInput::NativePropertyType native_property_type); + TargetPropertyId target_property_id); // Return local time for this keyframe model given the absolute monotonic // time. @@ -240,17 +267,7 @@ // properties until all KeyframeModels in the group have finished animating. int group_; - // TODO(crbug.com/1156631): wrap the following 3 attributes into a class. - // If this is CSS_CUSTOM_PROPERTY then |custom_property_name_| should be - // non-empty which identifies which custom property it is. If this is - // NATIVE_PROPERTY then |native_property_type_| should be set to targeted - // property. - int target_property_id_; - // Name of the animated custom property. Empty if it is an animated native - // property. - std::string custom_property_name_; - // Type of the animated native property. - PaintWorkletInput::NativePropertyType native_property_type_; + TargetPropertyId target_property_id_; // If specified, overrides the ElementId to apply this KeyframeModel's effect // value on.
diff --git a/cc/animation/keyframe_model_unittest.cc b/cc/animation/keyframe_model_unittest.cc index 2d4e94b..1e01ad2a 100644 --- a/cc/animation/keyframe_model_unittest.cc +++ b/cc/animation/keyframe_model_unittest.cc
@@ -4,6 +4,8 @@ #include "cc/animation/keyframe_model.h" +#include <limits> + #include "base/strings/stringprintf.h" #include "cc/test/animation_test_common.h" #include "cc/trees/target_property.h" @@ -22,9 +24,9 @@ std::unique_ptr<KeyframeModel> CreateKeyframeModel(double iterations, double duration, double playback_rate) { - std::unique_ptr<KeyframeModel> to_return( - KeyframeModel::Create(std::make_unique<FakeFloatAnimationCurve>(duration), - 0, 1, TargetProperty::OPACITY)); + std::unique_ptr<KeyframeModel> to_return(KeyframeModel::Create( + std::make_unique<FakeFloatAnimationCurve>(duration), 0, 1, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); to_return->set_iterations(iterations); to_return->set_playback_rate(playback_rate); return to_return; @@ -1381,27 +1383,29 @@ } TEST(KeyframeModelTest, ToString) { - std::unique_ptr<KeyframeModel> keyframe_model = - KeyframeModel::Create(std::make_unique<FakeFloatAnimationCurve>(15), 42, - 73, TargetProperty::OPACITY); - EXPECT_EQ( - base::StringPrintf("KeyframeModel{id=%d, group=73, target_property_id=1, " - "run_state=WAITING_FOR_TARGET_AVAILABILITY}", - keyframe_model->id()), - keyframe_model->ToString()); + std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create( + std::make_unique<FakeFloatAnimationCurve>(15), 42, 73, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY)); + EXPECT_EQ(base::StringPrintf( + "KeyframeModel{id=%d, group=73, target_property_type=1, " + "custom_property_name=, native_property_type=1, " + "run_state=WAITING_FOR_TARGET_AVAILABILITY, element_id=(0)}", + keyframe_model->id()), + keyframe_model->ToString()); } TEST(KeyframeModelTest, CustomPropertyKeyframe) { std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create(std::make_unique<FakeFloatAnimationCurve>(1), 1, 1, - TargetProperty::CSS_CUSTOM_PROPERTY, "foo"); + KeyframeModel::TargetPropertyId( + TargetProperty::CSS_CUSTOM_PROPERTY, "foo")); EXPECT_EQ(keyframe_model->custom_property_name(), "foo"); } TEST(KeyframeModelTest, NonCustomPropertyKeyframe) { - std::unique_ptr<KeyframeModel> keyframe_model = - KeyframeModel::Create(std::make_unique<FakeFloatAnimationCurve>(1), 1, 1, - TargetProperty::TRANSFORM); + std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create( + std::make_unique<FakeFloatAnimationCurve>(1), 1, 1, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM)); EXPECT_EQ(keyframe_model->custom_property_name(), ""); }
diff --git a/cc/animation/scroll_offset_animations_impl.cc b/cc/animation/scroll_offset_animations_impl.cc index 4989921..d6c44889 100644 --- a/cc/animation/scroll_offset_animations_impl.cc +++ b/cc/animation/scroll_offset_animations_impl.cc
@@ -4,6 +4,9 @@ #include "cc/animation/scroll_offset_animations_impl.h" +#include <memory> +#include <utility> + #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "cc/animation/animation.h" @@ -76,7 +79,8 @@ std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create( std::move(curve), AnimationIdProvider::NextKeyframeModelId(), - AnimationIdProvider::NextGroupId(), TargetProperty::SCROLL_OFFSET); + AnimationIdProvider::NextGroupId(), + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET)); keyframe_model->set_time_offset(animation_start_offset); keyframe_model->SetIsImplOnly(); @@ -171,7 +175,8 @@ std::unique_ptr<KeyframeModel> new_keyframe_model = KeyframeModel::Create( std::move(new_curve), AnimationIdProvider::NextKeyframeModelId(), - AnimationIdProvider::NextGroupId(), TargetProperty::SCROLL_OFFSET); + AnimationIdProvider::NextGroupId(), + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET)); new_keyframe_model->set_start_time(keyframe_model->start_time()); new_keyframe_model->SetIsImplOnly(); new_keyframe_model->set_affects_active_elements(false);
diff --git a/cc/test/animation_test_common.cc b/cc/test/animation_test_common.cc index 562dcdbe..981cc6c 100644 --- a/cc/test/animation_test_common.cc +++ b/cc/test/animation_test_common.cc
@@ -54,7 +54,7 @@ std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), id, AnimationIdProvider::NextGroupId(), - TargetProperty::OPACITY)); + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); keyframe_model->set_needs_synchronized_start_time(true); target->AddKeyframeModel(std::move(keyframe_model)); @@ -80,7 +80,7 @@ std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), id, AnimationIdProvider::NextGroupId(), - TargetProperty::TRANSFORM)); + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); keyframe_model->set_needs_synchronized_start_time(true); target->AddKeyframeModel(std::move(keyframe_model)); @@ -125,7 +125,7 @@ std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), id, AnimationIdProvider::NextGroupId(), - TargetProperty::FILTER)); + KeyframeModel::TargetPropertyId(TargetProperty::FILTER))); keyframe_model->set_needs_synchronized_start_time(true); target->AddKeyframeModel(std::move(keyframe_model)); @@ -155,7 +155,7 @@ std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), id, AnimationIdProvider::NextGroupId(), - TargetProperty::BACKDROP_FILTER)); + KeyframeModel::TargetPropertyId(TargetProperty::BACKDROP_FILTER))); keyframe_model->set_needs_synchronized_start_time(true); target->AddKeyframeModel(std::move(keyframe_model)); @@ -252,7 +252,7 @@ std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), id, AnimationIdProvider::NextGroupId(), - TargetProperty::SCROLL_OFFSET)); + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->SetIsImplOnly(); animation->AddKeyframeModel(std::move(keyframe_model)); @@ -320,7 +320,7 @@ std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( std::move(curve), id, AnimationIdProvider::NextGroupId(), - TargetProperty::OPACITY)); + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); keyframe_model->set_needs_synchronized_start_time(true); animation->AddKeyframeModel(std::move(keyframe_model));
diff --git a/cc/trees/draw_properties_unittest.cc b/cc/trees/draw_properties_unittest.cc index 7eaca3e3..93183a35 100644 --- a/cc/trees/draw_properties_unittest.cc +++ b/cc/trees/draw_properties_unittest.cc
@@ -1747,7 +1747,7 @@ // Add a transform animation with a start delay to |grand_child|. std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), 0, 1, - TargetProperty::TRANSFORM); + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000)); AddKeyframeModelToElementWithAnimation( @@ -6410,7 +6410,8 @@ int keyframe_model_id = 0; std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeTransformTransition(1.0)), - keyframe_model_id, 1, TargetProperty::TRANSFORM); + keyframe_model_id, 1, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000)); AddKeyframeModelToElementWithAnimation(child->element_id(), timeline(), @@ -6437,7 +6438,8 @@ keyframe_model_id = 1; keyframe_model = KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), - keyframe_model_id, 1, TargetProperty::OPACITY); + keyframe_model_id, 1, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000)); AddKeyframeModelToElementWithExistingKeyframeEffect( @@ -6555,8 +6557,9 @@ TransformKeyframe::Create(base::TimeDelta(), start, nullptr)); curve->AddKeyframe(TransformKeyframe::Create( base::TimeDelta::FromSecondsD(1.0), operation, nullptr)); - std::unique_ptr<KeyframeModel> transform_animation( - KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::TRANSFORM)); + std::unique_ptr<KeyframeModel> transform_animation(KeyframeModel::Create( + std::move(curve), 3, 3, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); scoped_refptr<Animation> animation(Animation::Create(1)); timeline()->AttachAnimation(animation); animation->AttachElement(parent->element_id()); @@ -6587,8 +6590,9 @@ TransformKeyframe::Create(base::TimeDelta(), start, nullptr)); curve->AddKeyframe(TransformKeyframe::Create( base::TimeDelta::FromSecondsD(1.0), operation, nullptr)); - std::unique_ptr<KeyframeModel> transform_animation( - KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::TRANSFORM)); + std::unique_ptr<KeyframeModel> transform_animation(KeyframeModel::Create( + std::move(curve), 3, 3, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); scoped_refptr<Animation> animation(Animation::Create(1)); timeline_impl()->AttachAnimation(animation); animation->AddKeyframeModel(std::move(transform_animation)); @@ -6699,8 +6703,9 @@ FloatKeyframe::Create(base::TimeDelta(), 0.9f, std::move(func))); curve->AddKeyframe( FloatKeyframe::Create(base::TimeDelta::FromSecondsD(1.0), 0.3f, nullptr)); - std::unique_ptr<KeyframeModel> keyframe_model( - KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::OPACITY)); + std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( + std::move(curve), 3, 3, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); scoped_refptr<Animation> animation(Animation::Create(1)); timeline()->AttachAnimation(animation); animation->AddKeyframeModel(std::move(keyframe_model)); @@ -7505,7 +7510,8 @@ int keyframe_model_id = 0; std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create( std::unique_ptr<AnimationCurve>(new FakeFloatTransition(1.0, 0.f, 1.f)), - keyframe_model_id, 1, TargetProperty::OPACITY); + keyframe_model_id, 1, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000)); KeyframeModel* keyframe_model_ptr = keyframe_model.get(); @@ -7561,8 +7567,9 @@ TransformKeyframe::Create(base::TimeDelta(), start, nullptr)); curve->AddKeyframe(TransformKeyframe::Create( base::TimeDelta::FromSecondsD(1.0), operation, nullptr)); - std::unique_ptr<KeyframeModel> keyframe_model( - KeyframeModel::Create(std::move(curve), 3, 3, TargetProperty::TRANSFORM)); + std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( + std::move(curve), 3, 3, + KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000)); KeyframeModel* keyframe_model_ptr = keyframe_model.get();
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index a3a4c36..0c19447 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -556,7 +556,8 @@ // Any valid AnimationCurve will do here. std::unique_ptr<AnimationCurve> curve(new FakeFloatAnimationCurve()); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 1, TargetProperty::OPACITY)); + std::move(curve), 1, 1, + KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); animation_->AddKeyframeModel(std::move(keyframe_model)); // We add the animation *before* attaching the layer to the tree. @@ -794,7 +795,8 @@ CreateEaseInOutAnimationForTesting( gfx::ScrollOffset(500.f, 550.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); bool impl_scrolling_supported = proxy()->SupportsImplScrolling(); if (impl_scrolling_supported) @@ -1006,7 +1008,8 @@ ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( gfx::ScrollOffset(6500.f, 7500.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); AttachAnimationsToTimeline(); @@ -1086,7 +1089,8 @@ ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( gfx::ScrollOffset(6500.f, 7500.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); AttachAnimationsToTimeline(); @@ -1211,7 +1215,8 @@ ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( final_position_)); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); AttachAnimationsToTimeline(); @@ -2167,7 +2172,8 @@ ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting( gfx::ScrollOffset(500.f, 550.f))); std::unique_ptr<KeyframeModel> keyframe_model(KeyframeModel::Create( - std::move(curve), 1, 0, TargetProperty::SCROLL_OFFSET)); + std::move(curve), 1, 0, + KeyframeModel::TargetPropertyId(TargetProperty::SCROLL_OFFSET))); keyframe_model->set_needs_synchronized_start_time(true); ASSERT_TRUE(proxy()->SupportsImplScrolling()); animation_child_->AddKeyframeModel(std::move(keyframe_model));
diff --git a/cc/trees/property_tree_builder_unittest.cc b/cc/trees/property_tree_builder_unittest.cc index c824607..c517b917 100644 --- a/cc/trees/property_tree_builder_unittest.cc +++ b/cc/trees/property_tree_builder_unittest.cc
@@ -552,8 +552,9 @@ FilterKeyframe::Create(base::TimeDelta(), start_filters, nullptr)); curve->AddKeyframe(FilterKeyframe::Create( base::TimeDelta::FromMilliseconds(100), end_filters, nullptr)); - std::unique_ptr<KeyframeModel> keyframe_model = - KeyframeModel::Create(std::move(curve), 0, 1, TargetProperty::FILTER); + std::unique_ptr<KeyframeModel> keyframe_model = KeyframeModel::Create( + std::move(curve), 0, 1, + KeyframeModel::TargetPropertyId(TargetProperty::FILTER)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); keyframe_model->set_time_offset(base::TimeDelta::FromMilliseconds(-1000));
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 170aeec..0827f3d 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2344,7 +2344,6 @@ "include_64_bit_webview", "is_64_bit_browser", "is_base_module", - "module_descs", "resource_ids_provider_dep", "static_library_provider", "static_library_synchronized_proguard", @@ -2996,9 +2995,6 @@ target_type = "android_app_bundle_module" is_base_module = true version_code = _version_code - if (enable_chrome_module) { - module_descs = _module_descs - } if (!_is_trichrome || !defined(invoker.static_library_synchronized_proguard) || @@ -3230,7 +3226,6 @@ # Files under a feature's public/ dir are included in chrome_java's source # files, so include these files in chrome_jni_headers. "feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedImageFetchClient.java", - "feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedPersistentKeyValueCache.java", "feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedServiceBridge.java", "feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java", "java/src/org/chromium/chrome/browser/AfterStartupTaskUtils.java", @@ -3268,7 +3263,6 @@ "java/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncChromeWakeUpTask.java", "java/src/org/chromium/chrome/browser/background_task_scheduler/ChromeBackgroundTaskFactory.java", "java/src/org/chromium/chrome/browser/background_task_scheduler/ProxyNativeTask.java", - "java/src/org/chromium/chrome/browser/banners/AppBannerManagerHelper.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java", "java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java", "java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappBridge.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index c9ba4690..c5fd07d 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -141,7 +141,6 @@ "java/src/org/chromium/chrome/browser/background_task_scheduler/ChromeBackgroundTaskFactory.java", "java/src/org/chromium/chrome/browser/background_task_scheduler/ChromeNativeBackgroundTaskDelegate.java", "java/src/org/chromium/chrome/browser/background_task_scheduler/ProxyNativeTask.java", - "java/src/org/chromium/chrome/browser/banners/AppBannerManagerHelper.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java", "java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddActivity.java", @@ -1194,6 +1193,7 @@ "java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java", "java/src/org/chromium/chrome/browser/read_later/ReadLaterIPHController.java", "java/src/org/chromium/chrome/browser/read_later/ReadingListBridge.java", + "java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java", "java/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationController.java", "java/src/org/chromium/chrome/browser/resources/ResourceMapper.java", "java/src/org/chromium/chrome/browser/rlz/RevenueStats.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 67c9128..d862b63a 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -198,6 +198,7 @@ "junit/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarMediatorTest.java", "junit/src/org/chromium/chrome/browser/policy/EnterpriseInfoTest.java", "junit/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerImplTest.java", + "junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java", "junit/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerTest.java", "junit/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingReferringAppBridgeTest.java", "junit/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceMetricsTest.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 8c6cd1c..e95b16f 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -464,9 +464,6 @@ _enable_chrome_module = _is_bundle_module && invoker.is_base_module && enable_chrome_module if (_enable_chrome_module) { - # TODO(crbug.com/1150459): Remove this once internal repo is updated. - not_needed(invoker, [ "module_descs" ]) - # If the manifest is being verified, add the chrome module's manifest. if (defined(invoker.expected_android_manifest)) { _bundle_target_gen_dir =
diff --git a/chrome/android/features/dev_ui/dev_ui_module.gni b/chrome/android/features/dev_ui/dev_ui_module.gni index 69ddc274..8c098e7 100644 --- a/chrome/android/features/dev_ui/dev_ui_module.gni +++ b/chrome/android/features/dev_ui/dev_ui_module.gni
@@ -19,5 +19,4 @@ # DevUI DFM does not need to call Module.getImpl(), and manages loading on # install and on use. Therefore disable auto-load on Module.getImpl(). load_native_on_get_impl = false - supports_isolated_split = true }
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java index 83a3c141..6113db3 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java
@@ -154,7 +154,10 @@ @Test @EnormousTest @CommandLineFlags.Add({BASE_PARAMS + "/downsampling-scale/1"}) - public void testTabToGridFromLiveTabWith10TabsNoDownsample() throws InterruptedException { + @DisableIf.Build(message = "Flaky on Android P, see https://crbug.com/1161731", + sdk_is_greater_than = VERSION_CODES.O_MR1, sdk_is_less_than = VERSION_CODES.Q) + public void + testTabToGridFromLiveTabWith10TabsNoDownsample() throws InterruptedException { prepareTabs(10, NTP_URL); reportTabToGridPerf(mUrl, "Tab-to-Grid from live tab with 10 tabs (no downsample)"); } @@ -162,7 +165,10 @@ @Test @EnormousTest @CommandLineFlags.Add({BASE_PARAMS + "/max-duty-cycle/1"}) - public void testTabToGridFromLiveTabWith10TabsNoRateLimit() throws InterruptedException { + @DisableIf.Build(message = "Flaky on Android P, see https://crbug.com/1161731", + sdk_is_greater_than = VERSION_CODES.O_MR1, sdk_is_less_than = VERSION_CODES.Q) + public void + testTabToGridFromLiveTabWith10TabsNoRateLimit() throws InterruptedException { prepareTabs(10, NTP_URL); reportTabToGridPerf(mUrl, "Tab-to-Grid from live tab with 10 tabs (no rate-limit)"); }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedPersistentKeyValueCache.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedPersistentKeyValueCache.java deleted file mode 100644 index c93ba50..0000000 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedPersistentKeyValueCache.java +++ /dev/null
@@ -1,49 +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. - -package org.chromium.chrome.browser.feed.v2; - -import androidx.annotation.Nullable; - -import org.chromium.base.Callback; -import org.chromium.base.ThreadUtils; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.annotations.NativeMethods; -import org.chromium.chrome.browser.xsurface.PersistentKeyValueCache; - -/** - * Implementation of xsurface's PersistentKeyValueCache. - */ -@JNINamespace("feed") -public class FeedPersistentKeyValueCache implements PersistentKeyValueCache { - @Override - public void lookup(byte[] key, ValueConsumer consumer) { - assert ThreadUtils.runningOnUiThread(); - FeedPersistentKeyValueCacheJni.get().lookup(key, new Callback<byte[]>() { - @Override - public void onResult(byte[] result) { - consumer.run(result); - } - }); - } - - @Override - public void put(byte[] key, byte[] value, @Nullable Runnable onComplete) { - assert ThreadUtils.runningOnUiThread(); - FeedPersistentKeyValueCacheJni.get().put(key, value, onComplete); - } - - @Override - public void evict(byte[] key, @Nullable Runnable onComplete) { - assert ThreadUtils.runningOnUiThread(); - FeedPersistentKeyValueCacheJni.get().evict(key, onComplete); - } - - @NativeMethods - interface Natives { - void lookup(byte[] key, Object consumer); - void put(byte[] key, byte[] value, Runnable onComplete); - void evict(byte[] key, Runnable onComplete); - } -}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java index 8def531..c767a3c2 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java
@@ -21,7 +21,6 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.xsurface.ImageFetchClient; -import org.chromium.chrome.browser.xsurface.PersistentKeyValueCache; import org.chromium.chrome.browser.xsurface.ProcessScopeDependencyProvider; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.identitymanager.ConsentLevel; @@ -35,7 +34,6 @@ private Context mContext; private ImageFetchClient mImageFetchClient; - private FeedPersistentKeyValueCache mPersistentKeyValueCache; private LibraryResolver mLibraryResolver; @VisibleForTesting @@ -44,7 +42,6 @@ FeedProcessScopeDependencyProvider() { mContext = createFeedContext(ContextUtils.getApplicationContext()); mImageFetchClient = new FeedImageFetchClient(); - mPersistentKeyValueCache = new FeedPersistentKeyValueCache(); if (BundleUtils.isIsolatedSplitInstalled(mContext, FEED_SPLIT_NAME)) { mLibraryResolver = (libName) -> { return BundleUtils.getNativeLibraryPath(libName, FEED_SPLIT_NAME); @@ -88,11 +85,6 @@ } @Override - public PersistentKeyValueCache getPersistentKeyValueCache() { - return mPersistentKeyValueCache; - } - - @Override public void logError(String tag, String format, Object... args) { Log.e(tag, format, args); }
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProviderTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProviderTest.java deleted file mode 100644 index e0ffb18..0000000 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProviderTest.java +++ /dev/null
@@ -1,113 +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. - -package org.chromium.chrome.browser.feed.v2; - -import androidx.test.filters.MediumTest; - -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.Criteria; -import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.browser.xsurface.PersistentKeyValueCache; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.util.browser.Features; -import org.chromium.content_public.browser.test.util.TestThreadUtils; - -import java.util.ArrayList; - -/** - * Tests for FeedProcessScopeDependencyProvider. - */ -@RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@Features.EnableFeatures(ChromeFeatureList.INTEREST_FEED_V2) -public class FeedProcessScopeDependencyProviderTest { - static final byte[] VALUE_1 = "one".getBytes(); - static final byte[] VALUE_2 = "two".getBytes(); - - String toString(byte[] array) { - if (array == null) return "null"; - return new String(array); - } - - @Rule - private final ChromeTabbedActivityTestRule mActivityTestRule = - new ChromeTabbedActivityTestRule(); - - @Before - public void setUp() throws Exception { - mActivityTestRule.startMainActivityWithURL("about:blank"); - } - - @Test - @MediumTest - @Feature({"Feed"}) - public void testPersistentKeyValueCachePutAndLookup() { - FeedProcessScopeDependencyProvider dependencyProvider = - new FeedProcessScopeDependencyProvider(); - ArrayList<String> calls = new ArrayList<String>(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - PersistentKeyValueCache cache = dependencyProvider.getPersistentKeyValueCache(); - cache.put(VALUE_1, VALUE_2, () -> calls.add("put")); - cache.lookup(VALUE_1, (byte[] v) -> calls.add("lookup1 " + toString(v))); - cache.lookup(VALUE_2, (byte[] v) -> calls.add("lookup2 " + toString(v))); - }); - CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat( - "Calls match", calls, Matchers.contains("put", "lookup1 two", "lookup2 null")); - }); - } - - @Test - @MediumTest - @Feature({"Feed"}) - public void testPersistentKeyValueCacheEvict() { - FeedProcessScopeDependencyProvider dependencyProvider = - new FeedProcessScopeDependencyProvider(); - ArrayList<String> calls = new ArrayList<String>(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - PersistentKeyValueCache cache = dependencyProvider.getPersistentKeyValueCache(); - cache.put(VALUE_1, VALUE_2, () -> calls.add("put")); - cache.evict(VALUE_1, () -> calls.add("evict")); - cache.lookup(VALUE_1, (byte[] v) -> calls.add("lookup " + toString(v))); - }); - - CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat( - "Calls match", calls, Matchers.contains("put", "evict", "lookup null")); - }); - } - - @Test - @MediumTest - @Feature({"Feed"}) - public void testPersistentKeyValueCacheNullRunnables() { - // Verify put() and evict() accept null runnables. - FeedProcessScopeDependencyProvider dependencyProvider = - new FeedProcessScopeDependencyProvider(); - ArrayList<String> calls = new ArrayList<String>(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - PersistentKeyValueCache cache = dependencyProvider.getPersistentKeyValueCache(); - cache.put(VALUE_1, VALUE_2, null); - cache.evict(VALUE_1, null); - cache.put(VALUE_1, VALUE_2, () -> calls.add("put")); - }); - - CriteriaHelper.pollUiThread( - () -> { Criteria.checkThat("Calls match", calls, Matchers.contains("put")); }); - } -}
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni index b38f40e..fd330a0 100644 --- a/chrome/android/feed/feed_java_sources.gni +++ b/chrome/android/feed/feed_java_sources.gni
@@ -47,7 +47,6 @@ "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/CardMenuBottomSheetContent.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedImageFetchClient.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedListContentManager.java", - "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedPersistentKeyValueCache.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProvider.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedServiceBridge.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTracker.java", @@ -735,7 +734,6 @@ if (enable_feed_v2) { feed_test_java_sources += [ - "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedProcessScopeDependencyProviderTest.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedV2NewTabPageTest.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedV2TestHelper.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/TestFeedServer.java", @@ -745,10 +743,9 @@ feed_test_deps = [] if (enable_feed_v1 || enable_feed_v2) { feed_test_deps += feed_deps + [ - "//chrome/browser/privacy:java", "//chrome/browser/user_education:java", - "//chrome/browser/xsurface:java", - "//third_party/android_deps:guava_android_java", "//third_party/google-truth:google_truth_java", + "//third_party/android_deps:guava_android_java", + "//chrome/browser/privacy:java", ] }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java index c489e46..df62afdc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -49,6 +49,7 @@ import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher; import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.read_later.ReadingListUtils; import org.chromium.chrome.browser.share.ShareHelper; import org.chromium.chrome.browser.share.ShareUtils; import org.chromium.chrome.browser.tab.Tab; @@ -448,6 +449,7 @@ addToMenuItem.getSubMenu().findItem(R.id.add_to_reading_list_menu_id); addToReadingListMenuItem.setVisible( CachedFeatureFlags.isEnabled(ChromeFeatureList.READ_LATER)); + addToReadingListMenuItem.setEnabled(ReadingListUtils.isReadingListSupported(url)); MenuItem addToDownloadsMenuItem = addToMenuItem.getSubMenu().findItem(R.id.add_to_downloads_menu_id);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerHelper.java deleted file mode 100644 index 15d027b..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerHelper.java +++ /dev/null
@@ -1,50 +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. - -package org.chromium.chrome.browser.banners; - -import androidx.annotation.VisibleForTesting; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.components.webapps.WebappsUtils; - -/** - * This class is a helper class for the C++ layer. It responds whether the - * feature is supported (and facilitates testing). It was split out of - * AppBannerManager during a modularization effort because ShortcutHelper hadn't - * been modularized. TODO(estade): That's now done, so this functionality can move back into - * AppBannerManager. - */ -@JNINamespace("webapps") -public class AppBannerManagerHelper { - /** Whether add to home screen is permitted by the system. */ - private static Boolean sIsSupported; - - /** - * Checks if the add to home screen intent is supported. - * @return true if add to home screen is supported, false otherwise. - */ - public static boolean isSupported() { - if (sIsSupported == null) { - sIsSupported = WebappsUtils.isAddToHomeIntentSupported(); - } - return sIsSupported; - } - - /** - * Checks if app banners are enabled for the tab which this manager is attached to. - * @return true if app banners can be shown for this tab, false otherwise. - */ - @CalledByNative - private static boolean isEnabledForTab() { - return isSupported(); - } - - /** Overrides whether the system supports add to home screen. Used in testing. */ - @VisibleForTesting - public static void setIsSupported(boolean state) { - sIsSupported = state; - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java index 04c22be..c1fd6ad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
@@ -840,10 +840,9 @@ * bookmark ID will be returned. * @param title The title to be used for the reading list item. * @param url The URL of the reading list item. - * @return The bookmark ID created after saving the article to the reading list, or null on - * error. + * @return The bookmark ID created after saving the article to the reading list. */ - public @Nullable BookmarkId addToReadingList(String title, String url) { + public BookmarkId addToReadingList(String title, String url) { ThreadUtils.assertOnUiThread(); assert title != null; assert url != null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java index bbe0181..6be8b9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java
@@ -5,6 +5,10 @@ package org.chromium.chrome.browser.bookmarks.bottomsheet; import android.content.Context; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.SuperscriptSpan; import android.view.LayoutInflater; import android.view.View; @@ -15,22 +19,29 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; import org.chromium.chrome.R; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; import org.chromium.chrome.browser.bookmarks.bottomsheet.BookmarkBottomSheetItemProperties.ItemType; +import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.bookmarks.BookmarkType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; +import org.chromium.components.feature_engagement.FeatureConstants; +import org.chromium.components.feature_engagement.Tracker; import org.chromium.ui.modelutil.LayoutViewBuilder; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter; +import org.chromium.ui.text.SpanApplier; +import org.chromium.ui.text.SpanApplier.SpanInfo; import java.util.List; @@ -110,7 +121,7 @@ int type = bookmarkItem.getId().getType(); PropertyModel model = new PropertyModel.Builder(BookmarkBottomSheetItemProperties.ALL_KEYS) - .with(BookmarkBottomSheetItemProperties.TITLE, bookmarkItem.getTitle()) + .with(BookmarkBottomSheetItemProperties.TITLE, getTitle(bookmarkItem)) .with(BookmarkBottomSheetItemProperties.SUBTITLE, getSubtitle(bookmarkItem)) .with(BookmarkBottomSheetItemProperties.ICON_DRAWABLE_AND_COLOR, new Pair<>(BookmarkUtils.getFolderIcon(mContext, type), @@ -121,7 +132,36 @@ return model; } - private @Nullable String getSubtitle(@NonNull final BookmarkItem bookmarkItem) { + private CharSequence getTitle(@NonNull final BookmarkItem bookmarkItem) { + if (bookmarkItem.getId().getType() == BookmarkType.READING_LIST) { + Tracker tracker = + TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile()); + boolean showNew = tracker.isInitialized() + && tracker.shouldTriggerHelpUI( + FeatureConstants.READ_LATER_BOTTOM_SHEET_FEATURE); + SpannableString spannableString = new SpannableString( + mContext.getResources().getString(R.string.reading_list_title_new)); + + // Maybe show a "New" text after the reading list title. + if (showNew) { + tracker.dismissed(FeatureConstants.READ_LATER_BOTTOM_SHEET_FEATURE); + spannableString = SpanApplier.applySpans(spannableString.toString(), + new SpanInfo("<new>", "</new>", new RelativeSizeSpan(0.75f), + new SuperscriptSpan(), + new ForegroundColorSpan( + ApiCompatibilityUtils.getColor(mContext.getResources(), + R.color.default_text_color_blue)))); + } else { + spannableString = new SpannableString(SpanApplier.removeSpanText( + spannableString.toString(), new SpanInfo("<new>", "</new>"))); + } + return spannableString; + } + + return bookmarkItem.getTitle(); + } + + private @Nullable CharSequence getSubtitle(@NonNull final BookmarkItem bookmarkItem) { switch (bookmarkItem.getId().getType()) { case BookmarkType.NORMAL: int totalCount = mBookmarkModel.getTotalBookmarkCount(bookmarkItem.getId());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java index 68b6757..377d148 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetFolderRow.java
@@ -33,11 +33,11 @@ super(context, attrs); } - void setTitle(@NonNull String title) { + void setTitle(@NonNull CharSequence title) { mTitleView.setText(title); } - void setSubtitle(@Nullable String subtitle) { + void setSubtitle(@Nullable CharSequence subtitle) { mDescriptionView.setText(subtitle == null ? "" : subtitle); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java index f8a5455..3591d9c7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetItemProperties.java
@@ -32,13 +32,13 @@ /** * The title of the bottom sheet item. e.g. Mobile bookmarks, reading list. */ - static final PropertyModel.ReadableObjectPropertyKey<String> TITLE = + static final PropertyModel.ReadableObjectPropertyKey<CharSequence> TITLE = new PropertyModel.ReadableObjectPropertyKey<>(); /** * The subtitle of the bottom sheet item. e.g. 4 bookmarks, 8 unread pages. */ - static final PropertyModel.ReadableObjectPropertyKey<String> SUBTITLE = + static final PropertyModel.ReadableObjectPropertyKey<CharSequence> SUBTITLE = new PropertyModel.ReadableObjectPropertyKey<>(); /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java index 305b266..1a96be98 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FreIntentCreator.java
@@ -9,6 +9,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; +import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.text.TextUtils; @@ -142,6 +143,9 @@ Intent intentToLaunchAfterFreComplete, boolean requiresBroadcast) { final PendingIntent pendingIntent; int pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + pendingIntentFlags |= PendingIntent.FLAG_IMMUTABLE; + } if (requiresBroadcast) { pendingIntent = PendingIntent.getBroadcast( context, 0, intentToLaunchAfterFreComplete, pendingIntentFlags);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java new file mode 100644 index 0000000..a86177a --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java
@@ -0,0 +1,26 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.read_later; + +import android.text.TextUtils; + +import org.chromium.components.embedder_support.util.UrlConstants; + +/** + * Utility functions for reading list feature. + */ +public final class ReadingListUtils { + /** + * @return Whether the URL can be added as reading list article. + */ + public static boolean isReadingListSupported(String url) { + if (TextUtils.isEmpty(url)) return false; + + // This should match ReadingListModel::IsUrlSupported(), having a separate function since + // the UI may not load native library. + return url.startsWith(UrlConstants.HTTP_URL_PREFIX) + || url.startsWith(UrlConstants.HTTPS_URL_PREFIX); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java index 742dbf0e..9442632 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
@@ -18,13 +18,10 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.util.BookmarkTestUtil; -import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.bookmarks.BookmarkId; -import org.chromium.components.bookmarks.BookmarkType; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.ArrayList; @@ -317,21 +314,4 @@ + "over partner bookmarks", expectedSearchResults, searchResults); } - - @Test - @SmallTest - @UiThreadTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER}) - public void testAddToReadingList() { - Assert.assertNull("Should return null for non http/https URLs.", - mBookmarkBridge.addToReadingList("a", "chrome://flags")); - BookmarkId readingListId = mBookmarkBridge.addToReadingList("a", "https://www.google.com/"); - Assert.assertNotNull(readingListId); - Assert.assertEquals(BookmarkType.READING_LIST, readingListId.getType()); - BookmarkItem readingListItem = - mBookmarkBridge.getReadingListItem("https://www.google.com/"); - Assert.assertNotNull(readingListItem); - Assert.assertEquals("https://www.google.com/", readingListItem.getUrl()); - Assert.assertEquals("a", readingListItem.getTitle()); - } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java index b30f151..f9f04fe0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -1706,7 +1706,7 @@ mActivityTestRule.getActivity(), R.id.bookmark_this_page_id); // Click the reading list folder in the bottom sheet, and wait for reading list item added. - onView(withText("Reading list")).check(matches(isDisplayed())).perform(click()); + onView(withText("Reading list ")).check(matches(isDisplayed())).perform(click()); CriteriaHelper.pollUiThread(() -> mBookmarkModel.getReadingListItem(mTestPage) != null); TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetTest.java index 1aa488f..7fc769fa 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetTest.java
@@ -11,6 +11,10 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.mockito.Mockito.when; + +import static org.chromium.components.feature_engagement.FeatureConstants.READ_LATER_BOTTOM_SHEET_FEATURE; + import android.view.View; import androidx.recyclerview.widget.RecyclerView; @@ -22,6 +26,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -30,6 +35,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkModel; +import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; @@ -41,6 +47,7 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; +import org.chromium.components.feature_engagement.Tracker; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.ArrayList; @@ -60,19 +67,27 @@ private static final String TITLE = "bookmark title"; private static final String TEST_URL_A = "http://a.com"; private static final String TEST_URL_B = "http://b.com"; + private static final String READING_LIST_TITLE = "Reading list "; + private static final String READING_LIST_TITLE_NEW = "Reading list New"; private BookmarkBottomSheetCoordinator mBottomSheetCoordinator; private BottomSheetController mBottomSheetController; private BookmarkModel mBookmarkModel; private BookmarkItem mItemClicked; private boolean mCallbackInvoked; + @Mock + private Tracker mTracker; @Before public void setUp() { + when(mTracker.isInitialized()).thenReturn(true); + when(mTracker.shouldTriggerHelpUI(READ_LATER_BOTTOM_SHEET_FEATURE)).thenReturn(false); + mActivityTestRule.startMainActivityOnBlankPage(); TestThreadUtils.runOnUiThreadBlocking(() -> { mBookmarkModel = new BookmarkModel(Profile.fromWebContents( mActivityTestRule.getActivity().getActivityTab().getWebContents())); + TrackerFactory.setTrackerForTests(mTracker); }); mBottomSheetController = mActivityTestRule.getActivity() @@ -88,6 +103,11 @@ mItemClicked = null; } + private void setShouldShowNew(boolean shouldShowNew) { + when(mTracker.shouldTriggerHelpUI(READ_LATER_BOTTOM_SHEET_FEATURE)) + .thenReturn(shouldShowNew); + } + private void bottomSheetCallback(BookmarkItem item) { mItemClicked = item; mCallbackInvoked = true; @@ -144,7 +164,7 @@ public void testBottomSheetShowWithoutBookmarks() throws InterruptedException { showBottomSheet(); onView(withId(R.id.sheet_title)).check(matches(isDisplayed())); - onView(withText("Reading list")).check(matches(isDisplayed())); + onView(withText(READING_LIST_TITLE)).check(matches(isDisplayed())); assertViewHolderHasString(0, "Save this page for later and get a reminder"); assertNoOverflowMenu(0, "No overflow menu for reading list folder."); @@ -155,6 +175,14 @@ @Test @MediumTest + public void testBottomSheetNewIPH() { + setShouldShowNew(true); + showBottomSheet(); + onView(withText(READING_LIST_TITLE_NEW)).check(matches(isDisplayed())); + } + + @Test + @MediumTest public void testBottomSheetShowWithOneBookmark() { // Add 1 bookmark and 1 unread page. TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -163,7 +191,7 @@ }); showBottomSheet(); - onView(withText("Reading list")).check(matches(isDisplayed())); + onView(withText(READING_LIST_TITLE)).check(matches(isDisplayed())); assertViewHolderHasString(0, "1 unread page"); onView(withText("Mobile bookmarks")).check(matches(isDisplayed())); @@ -182,7 +210,7 @@ }); showBottomSheet(); - onView(withText("Reading list")).check(matches(isDisplayed())); + onView(withText(READING_LIST_TITLE)).check(matches(isDisplayed())); assertViewHolderHasString(0, "2 unread pages"); onView(withText("Mobile bookmarks")).check(matches(isDisplayed())); @@ -194,7 +222,7 @@ public void testBottomSheetClickThrough() { showBottomSheet(); onView(withText("Mobile bookmarks")).check(matches(isDisplayed())); - onView(withText("Reading list")).check(matches(isDisplayed())).perform(click()); + onView(withText(READING_LIST_TITLE)).check(matches(isDisplayed())).perform(click()); waitForBookmarkClicked(); Assert.assertEquals(BookmarkType.READING_LIST, mItemClicked.getId().getType()); @@ -205,7 +233,7 @@ @MediumTest public void testBottomSheetCloseInvokeCallback() { showBottomSheet(); - onView(withText("Reading list")).check(matches(isDisplayed())); + onView(withText(READING_LIST_TITLE)).check(matches(isDisplayed())); hideBottomSheet(); Assert.assertNull(mItemClicked); Assert.assertTrue(mCallbackInvoked);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java index ba40386..51d2cc5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java
@@ -411,6 +411,26 @@ @MediumTest @Feature({"Browser"}) @Features.EnableFeatures({ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_CHIP}) + public void testLensChipNotShowingIfNotEnabled() throws Throwable { + // Required to avoid runtime error. + Looper.prepare(); + + Tab tab = mDownloadTestRule.getActivity().getActivityTab(); + hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION); + + RevampedContextMenuCoordinator menuCoordinator = + RevampedContextMenuUtils.openContextMenu(tab, "testImage"); + // Needs to run on UI thread so creation happens on same thread as dismissal. + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertNull("Chip popoup was initialized.", + menuCoordinator.getCurrentPopupWindowForTesting()); + }); + } + + @Test + @MediumTest + @Feature({"Browser"}) + @Features.EnableFeatures({ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_CHIP}) public void testSelectLensChip() throws Throwable { // Required to avoid runtime error. Looper.prepare();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java index be40f40..c1b6828 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java
@@ -11,6 +11,7 @@ import android.content.Context; import android.view.Menu; +import android.view.MenuItem; import android.view.SubMenu; import android.view.View; import android.widget.PopupMenu; @@ -70,7 +71,10 @@ import org.chromium.ui.modaldialog.ModalDialogManager; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Unit tests for {@link AppMenuPropertiesDelegateImpl}. @@ -575,6 +579,8 @@ assertMenuItemsAreEqual(menu, expectedItems); assertActionBarItemsAreEqual(menu, expectedActionBarItems); assertAddToItemsAreEqual(menu, expectedAddToItems); + assertAddToItemsEnableState( + menu, new HashSet<>(Arrays.asList(R.id.add_to_reading_list_menu_id)), null); } @Test @@ -915,6 +921,20 @@ Matchers.containsInAnyOrder(expectedItems)); } + private void assertAddToItemsEnableState( + Menu menu, Set<Integer> enabledItems, Set<Integer> disabledItems) { + SubMenu addToSubMenu = menu.findItem(R.id.add_to_menu_id).getSubMenu(); + for (int i = 0; i < addToSubMenu.size(); i++) { + MenuItem item = addToSubMenu.getItem(i); + if (enabledItems != null && enabledItems.contains(item.getItemId())) { + Assert.assertTrue(item.isEnabled()); + } + if (disabledItems != null && disabledItems.contains(item.getItemId())) { + Assert.assertFalse(item.isEnabled()); + } + } + } + private String getMenuTitles(Menu menu) { StringBuilder items = new StringBuilder(); for (int i = 0; i < menu.size(); i++) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java new file mode 100644 index 0000000..b380f57a --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java
@@ -0,0 +1,31 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.read_later; + +import android.support.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; + +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +/** + * Unit test for {@link ReadingListUtils}. + */ +public class ReadingListUtilsUnitTest { + @Test + @SmallTest + public void testIsReadingListSupport() { + Assert.assertFalse(ReadingListUtils.isReadingListSupported(null)); + Assert.assertFalse(ReadingListUtils.isReadingListSupported("")); + Assert.assertFalse(ReadingListUtils.isReadingListSupported("chrome://flags")); + Assert.assertTrue(ReadingListUtils.isReadingListSupported("http://www.example.com")); + Assert.assertTrue(ReadingListUtils.isReadingListSupported("https://www.example.com")); + } +}
diff --git a/chrome/android/modules/chrome_feature_modules.gni b/chrome/android/modules/chrome_feature_modules.gni index e9fa100..cae0d233 100644 --- a/chrome/android/modules/chrome_feature_modules.gni +++ b/chrome/android/modules/chrome_feature_modules.gni
@@ -40,8 +40,6 @@ # library files going into module if the module is executed in 64 bit. # pak_deps: (Optional) Grit or repack targets of PAKs going into module. # paks: (Optional) PAKs going into module. -# supports_isolated_split: (Optional) Whether this module can be in its own -# isolated split. # Each new module needs to add a desc to one of the lists below. # Modules shipped in Chrome Modern (Android L+).
diff --git a/chrome/android/modules/extra_icu/extra_icu_module.gni b/chrome/android/modules/extra_icu/extra_icu_module.gni index f6bf8ddbb..65a0c94b 100644 --- a/chrome/android/modules/extra_icu/extra_icu_module.gni +++ b/chrome/android/modules/extra_icu/extra_icu_module.gni
@@ -10,5 +10,4 @@ "//chrome/android/modules/extra_icu/internal:java", "//third_party/icu:icu_extra_assets", ] - supports_isolated_split = true }
diff --git a/chrome/android/modules/stack_unwinder/stack_unwinder_module.gni b/chrome/android/modules/stack_unwinder/stack_unwinder_module.gni index 3eed55d..ea292d5 100644 --- a/chrome/android/modules/stack_unwinder/stack_unwinder_module.gni +++ b/chrome/android/modules/stack_unwinder/stack_unwinder_module.gni
@@ -10,5 +10,4 @@ java_deps = [ "//chrome/android/modules/stack_unwinder/internal:java" ] native_deps = [ "//chrome/android/modules/stack_unwinder/internal:native" ] load_native_on_get_impl = false - supports_isolated_split = true }
diff --git a/chrome/android/modules/test_dummy/test_dummy_module.gni b/chrome/android/modules/test_dummy/test_dummy_module.gni index 3ca44b39..c28e917 100644 --- a/chrome/android/modules/test_dummy/test_dummy_module.gni +++ b/chrome/android/modules/test_dummy/test_dummy_module.gni
@@ -19,5 +19,4 @@ paks = [ "$root_gen_dir/chrome/test_dummy_resources.pak" ] pak_deps = [ "//chrome/browser/test_dummy/internal:resources_native" ] load_native_on_get_impl = true - supports_isolated_split = true }
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index 54f336b..0a636d2 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -92,15 +92,16 @@ #define IDC_VISIT_DESKTOP_OF_LRU_USER_LAST IDC_VISIT_DESKTOP_OF_LRU_USER_5 // Assign to desk commands -#define IDC_ASSIGN_TO_DESKS_MENU 34084 -#define IDC_SEND_TO_DESK_1 34085 -#define IDC_SEND_TO_DESK_2 34086 -#define IDC_SEND_TO_DESK_3 34087 -#define IDC_SEND_TO_DESK_4 34088 -#define IDC_SEND_TO_DESK_5 34089 -#define IDC_SEND_TO_DESK_6 34090 -#define IDC_SEND_TO_DESK_7 34091 -#define IDC_SEND_TO_DESK_8 34092 +#define IDC_ASSIGN_TO_DESKS_MENU 34090 +#define IDC_SEND_TO_DESK_1 34091 +#define IDC_SEND_TO_DESK_2 34092 +#define IDC_SEND_TO_DESK_3 34093 +#define IDC_SEND_TO_DESK_4 34094 +#define IDC_SEND_TO_DESK_5 34095 +#define IDC_SEND_TO_DESK_6 34096 +#define IDC_SEND_TO_DESK_7 34097 +#define IDC_SEND_TO_DESK_8 34098 +#define IDC_TOGGLE_ASSIGN_TO_ALL_DESKS 34099 #endif // Page-related commands
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc index d353778d..8b473c6 100644 --- a/chrome/app/chrome_main.cc +++ b/chrome/app/chrome_main.cc
@@ -68,7 +68,7 @@ #endif #if defined(OS_WIN) -#if BUILDFLAG(USE_ALLOCATOR_SHIM) +#if BUILDFLAG(USE_ALLOCATOR_SHIM) && BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) // Call this early on in order to configure heap workarounds. This must be // called from chrome.dll. This may be a NOP on some platforms. base::allocator::ConfigurePartitionAlloc();
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 476e5ca7e..7b663f10 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -351,6 +351,15 @@ <message name="IDS_CELLULAR_SETUP_ESTABLISH_NETWORK_CONNECTION" desc="Message, informing user that a network connection is being established during cellular setup"> Establishing network connection ... </message> + <message name="IDS_CELLULAR_SETUP_EID_POPUP_TITLE" desc="Label shown when vewing EID and QR code popup describing device EID"> + Your device EID + </message> + <message name="IDS_CELLULAR_SETUP_EID_POPUP_DESCRIPTION" desc="Label shown when veiwing EID and QR code popup describing what an EID number is used for"> + A customer service rep can use the EID number to help you activate service. + </message> + <message name="IDS_CELLULAR_SETUP_CLOSE_EID_POPUP_BUTTON_LABEL" desc="A11y and tooltip label for EID and QR code popup close button when viewing EID and QR code popup"> + Close EID and QR code popup + </message> <!-- Upgrade notifications --> <message name="IDS_RELAUNCH_REQUIRED_TITLE_DAYS" desc="The title of a dialog that tells users the device must be restarted within two or more days."> @@ -1632,9 +1641,18 @@ <message name="IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_WITH_PROVIDER_NAME" desc="A11y label for an eSIM profile that's ready to be installed, shown in a list in settings and oobe. Includes the provider name. Clicking the profile installs the eSIM profile so that the cellular network is available for connecting."> Download mobile profile, Network <ph name="NETWORK_INDEX">$1<ex>1</ex></ph> of <ph name="NETWORK_COUNT">$2<ex>10</ex></ph>, <ph name="NETWORK_NAME">$3<ex>Verizon Wireless</ex></ph>, <ph name="NETWORK_PROVIDER_NAME">$4<ex>Verizon LTE</ex></ph> </message> + <message name="IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_INSTALLING" desc="A11y label for an eSIM profile that is currently installing, shown in a list in settings and oobe."> + Installing mobile profile, Network <ph name="NETWORK_INDEX">$1<ex>1</ex></ph> of <ph name="NETWORK_COUNT">$2<ex>10</ex></ph>, <ph name="NETWORK_NAME">$3<ex>Verizon Wireless</ex></ph> + </message> + <message name="IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_WITH_PROVIDER_NAME_INSTALLING" desc="A11y label for an eSIM profile that is currently installing, shown in a list in settings and oobe. Includes the provider name."> + Installing mobile profile, Network <ph name="NETWORK_INDEX">$1<ex>1</ex></ph> of <ph name="NETWORK_COUNT">$2<ex>10</ex></ph>, <ph name="NETWORK_NAME">$3<ex>Verizon Wireless</ex></ph>, <ph name="NETWORK_PROVIDER_NAME">$4<ex>Verizon LTE</ex></ph> + </message> <message name="IDS_NETWORK_LIST_ITEM_DOWNLOAD" desc="Text for the button displayed for pending eSIM profiles that installs the profile when pressed."> Download </message> + <message name="IDS_NETWORK_LIST_ITEM_ADDING_PROFILE" desc="Loading text indicating that an eSIM profile is currently installing."> + Adding Profile... + </message> <message name="IDS_WIFI_NETWORK_STATUS_SECURED" desc="a11y label used when a Wi-Fi network is secured."> Secured </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_CLOSE_EID_POPUP_BUTTON_LABEL.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_CLOSE_EID_POPUP_BUTTON_LABEL.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_CLOSE_EID_POPUP_BUTTON_LABEL.png.sha1 rename to chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_CLOSE_EID_POPUP_BUTTON_LABEL.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_EID_POPUP_DESCRIPTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_EID_POPUP_DESCRIPTION.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_EID_POPUP_DESCRIPTION.png.sha1 rename to chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_EID_POPUP_DESCRIPTION.png.sha1
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_EID_POPUP_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_EID_POPUP_TITLE.png.sha1 similarity index 100% rename from chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INTERNET_EID_POPUP_TITLE.png.sha1 rename to chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_EID_POPUP_TITLE.png.sha1
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_ADDING_PROFILE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_ADDING_PROFILE.png.sha1 new file mode 100644 index 0000000..dac87ddb --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_ADDING_PROFILE.png.sha1
@@ -0,0 +1 @@ +185afb896fdb3fe2f34d173871deaba7e1037e09 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_INSTALLING.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_INSTALLING.png.sha1 new file mode 100644 index 0000000..29d7e0c --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_INSTALLING.png.sha1
@@ -0,0 +1 @@ +747335c6e34eecfa25233f914c1a5338c518f981 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_WITH_PROVIDER_NAME_INSTALLING.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_WITH_PROVIDER_NAME_INSTALLING.png.sha1 new file mode 100644 index 0000000..70cd3809 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_WITH_PROVIDER_NAME_INSTALLING.png.sha1
@@ -0,0 +1 @@ +087aebeabd87d98b9c132dd4246801c35d60c2f8 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 484f830..2c075d95 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -1161,6 +1161,9 @@ <message name="IDS_ASSIGN_TO_DESKS_MENU" desc="The text label of the Assign to Desks submenu"> Assign to desk </message> + <message name="IDS_ASSIGN_TO_ALL_DESKS" desc="The text label of the Assign to All Desks menu item"> + All desks + </message> </if> <message name="IDS_ACCNAME_ZOOM_PLUS2" desc="The accessible description of the Make Text Larger menu item in the merged menu"> @@ -5985,7 +5988,7 @@ Reopen a tab if you accidentally closed it </message> <message name="IDS_DESKTOP_PWA_INSTALL_PROMO" desc="Text shown on promotional UI appearing next to the PWA install icon"> - To get back here quickly, install <ph name="APP_NAME">$1<ex>Google Maps</ex></ph> + To get back here quickly, install <ph name="APP_NAME">$1<ex>Google Maps</ex></ph> by clicking the install button </message> <message name="IDS_REOPEN_TAB_PROMO_SCREENREADER" desc="Text announced encouraging users to reopen a tab with the given shortcut"> <ph name="SHORTCUT">$1<ex>CTRL+SHIFT+T</ex></ph> can reopen accidentally closed tabs
diff --git a/chrome/app/generated_resources_grd/IDS_ASSIGN_TO_ALL_DESKS.png.sha1 b/chrome/app/generated_resources_grd/IDS_ASSIGN_TO_ALL_DESKS.png.sha1 new file mode 100644 index 0000000..3e52249f --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ASSIGN_TO_ALL_DESKS.png.sha1
@@ -0,0 +1 @@ +9b0aad1bc68655b35dd4aec3e1547b5896010d9b \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DESKTOP_PWA_INSTALL_PROMO.png.sha1 b/chrome/app/generated_resources_grd/IDS_DESKTOP_PWA_INSTALL_PROMO.png.sha1 index f46e5869..6d25783 100644 --- a/chrome/app/generated_resources_grd/IDS_DESKTOP_PWA_INSTALL_PROMO.png.sha1 +++ b/chrome/app/generated_resources_grd/IDS_DESKTOP_PWA_INSTALL_PROMO.png.sha1
@@ -1 +1 @@ -34a9e96d0617141c5d1e542741566260cb823b75 \ No newline at end of file +aa0c0ad4cc0e1bf32e30103572a06666c14b01c3 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 606aa240..68b872e 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -2400,15 +2400,6 @@ <message name="IDS_SETTINGS_INTERNET_TETHER_NOT_SETUP_WITH_LEARN_MORE_LINK" desc="Text shown when viewing the Mobile data page and no instant tether network is available"> No device detected <ph name="BEGIN_LINK"><a target="_blank" href="$1"></ph>Learn more<ph name="END_LINK"></a></ph> </message> - <message name="IDS_SETTINGS_INTERNET_EID_POPUP_TITLE" desc="Label shown when vewing EID and QR code popup describing device EID"> - Your device EID - </message> - <message name="IDS_SETTINGS_INTERNET_EID_POPUP_DESCRIPTION" desc="Label shown when veiwing EID and QR code popup describing what an EID number is used for"> - A customer service rep can use the EID number to help you activate service. - </message> - <message name="IDS_SETTINGS_INTERNET_CLOSE_EID_POPUP_BUTTON_LABEL" desc="A11y and tooltip label for EID and QR code popup close button when viewing EID and QR code popup"> - Close EID and QR code popup - </message> <message name="IDS_SETTINGS_INTERNET_SHOW_EID_POPUP_BUTTON_LABEL" desc="A11y and tooltop label for EID and QR code popup show button when viewing cellular network list"> Show device EID and QR code popup </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e1a76b7..c50fad4 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -980,8 +980,6 @@ "optimization_guide/optimization_guide_navigation_data.h", "optimization_guide/optimization_guide_permissions_util.cc", "optimization_guide/optimization_guide_permissions_util.h", - "optimization_guide/optimization_guide_session_statistic.cc", - "optimization_guide/optimization_guide_session_statistic.h", "optimization_guide/optimization_guide_top_host_provider.cc", "optimization_guide/optimization_guide_top_host_provider.h", "optimization_guide/optimization_guide_web_contents_observer.cc", @@ -993,10 +991,6 @@ "optimization_guide/prediction/prediction_model_download_manager.cc", "optimization_guide/prediction/prediction_model_download_manager.h", "optimization_guide/prediction/prediction_model_download_observer.h", - "optimization_guide/prediction/prediction_model_fetcher.cc", - "optimization_guide/prediction/prediction_model_fetcher.h", - "optimization_guide/prediction/prediction_model_file.cc", - "optimization_guide/prediction/prediction_model_file.h", "page_load_metrics/observers/aborts_page_load_metrics_observer.cc", "page_load_metrics/observers/aborts_page_load_metrics_observer.h", "page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc", @@ -1324,6 +1318,8 @@ "prefetch/no_state_prefetch/prerender_link_manager_factory.h", "prefetch/no_state_prefetch/prerender_manager_factory.cc", "prefetch/no_state_prefetch/prerender_manager_factory.h", + "prefetch/pref_names.cc", + "prefetch/pref_names.h", "prefetch/prefetch_proxy/prefetch_proxy_features.cc", "prefetch/prefetch_proxy/prefetch_proxy_features.h", "prefetch/prefetch_proxy/prefetch_proxy_from_string_url_loader.cc", @@ -2718,7 +2714,6 @@ "android/feed/v2/background_refresh_task.cc", "android/feed/v2/background_refresh_task.h", "android/feed/v2/feed_image_fetch_client.cc", - "android/feed/v2/feed_persistent_key_value_cache.cc", "android/feed/v2/feed_service_bridge.cc", "android/feed/v2/feed_service_bridge.h", "android/feed/v2/feed_service_factory.cc", @@ -3941,6 +3936,8 @@ "send_tab_to_self/send_tab_to_self_desktop_util.h", "serial/chrome_serial_delegate.cc", "serial/chrome_serial_delegate.h", + "serial/serial_blocklist.cc", + "serial/serial_blocklist.h", "serial/serial_chooser_context.cc", "serial/serial_chooser_context.h", "serial/serial_chooser_context_factory.cc", @@ -4516,7 +4513,7 @@ "//chrome/browser/nearby_sharing/scheduling", "//chrome/browser/ui/webui/nearby_share:mojom", "//chrome/browser/ui/webui/nearby_share/public/mojom", - "//chrome/browser/webshare/chromeos:storage", + "//chrome/browser/webshare:storage", "//chromeos/components/account_manager", "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser", "//chromeos/components/quick_answers", @@ -4615,6 +4612,8 @@ "lacros/cert_db_initializer_impl.h", "lacros/client_cert_store_lacros.cc", "lacros/client_cert_store_lacros.h", + "lacros/crosapi_pref_observer.cc", + "lacros/crosapi_pref_observer.h", "lacros/feedback_util.cc", "lacros/feedback_util.h", "lacros/immersive_context_lacros.cc",
diff --git a/chrome/browser/android/bookmarks/bookmark_bridge.cc b/chrome/browser/android/bookmarks/bookmark_bridge.cc index 048b4ce7..52ef5096 100644 --- a/chrome/browser/android/bookmarks/bookmark_bridge.cc +++ b/chrome/browser/android/bookmarks/bookmark_bridge.cc
@@ -828,9 +828,8 @@ const BookmarkNode* node = reading_list_manager_->Add( GURL(base::android::ConvertJavaStringToUTF16(env, j_url)), base::android::ConvertJavaStringToUTF8(env, j_title)); - return node ? JavaBookmarkIdCreateBookmarkId(env, node->id(), - GetBookmarkType(node)) - : ScopedJavaLocalRef<jobject>(); + DCHECK(node); + return JavaBookmarkIdCreateBookmarkId(env, node->id(), GetBookmarkType(node)); } ScopedJavaLocalRef<jobject> BookmarkBridge::GetReadingListItem(
diff --git a/chrome/browser/android/feed/v2/feed_persistent_key_value_cache.cc b/chrome/browser/android/feed/v2/feed_persistent_key_value_cache.cc deleted file mode 100644 index ca8b363a9..0000000 --- a/chrome/browser/android/feed/v2/feed_persistent_key_value_cache.cc +++ /dev/null
@@ -1,111 +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 <memory> - -#include "base/android/callback_android.h" -#include "base/android/jni_android.h" -#include "base/android/jni_array.h" -#include "chrome/android/chrome_jni_headers/FeedPersistentKeyValueCache_jni.h" -#include "chrome/browser/android/feed/v2/feed_service_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "components/feed/core/v2/public/feed_service.h" -#include "components/feed/core/v2/public/feed_stream_api.h" -#include "components/feed/core/v2/public/persistent_key_value_store.h" - -namespace feed { -namespace { -using base::android::JavaParamRef; - -std::string JavaByteArrayToString( - JNIEnv* env, - const base::android::JavaRef<jbyteArray>& byte_array) { - std::string result; - base::android::JavaByteArrayToString(env, byte_array, &result); - return result; -} - -void OnLookupFinished(JNIEnv* env, - base::android::ScopedJavaGlobalRef<jobject> callback, - PersistentKeyValueStore::Result result) { - base::android::ScopedJavaLocalRef<jbyteArray> j_result; - if (result.get_result) { - j_result = base::android::ToJavaByteArray(env, *result.get_result); - } - base::android::RunObjectCallbackAndroid(callback, j_result); -} - -void CallRunnable(base::android::ScopedJavaGlobalRef<jobject> runnable, - PersistentKeyValueStore::Result result) { - if (runnable) - base::android::RunRunnableAndroid(runnable); -} - -PersistentKeyValueStore* GetStore() { - Profile* profile = ProfileManager::GetLastUsedProfile(); - if (!profile) - return nullptr; - - FeedService* feed_service = FeedServiceFactory::GetForBrowserContext(profile); - if (!feed_service) - return nullptr; - - return feed_service->GetStream()->GetPersistentKeyValueStore(); -} - -} // namespace - -void JNI_FeedPersistentKeyValueCache_Lookup( - JNIEnv* env, - const JavaParamRef<jbyteArray>& j_key, - const JavaParamRef<jobject>& j_response_callback) { - base::android::ScopedJavaGlobalRef<jobject> callback(j_response_callback); - - PersistentKeyValueStore* store = GetStore(); - if (!store) { - OnLookupFinished(env, std::move(callback), {}); - return; - } - return store->Get( - JavaByteArrayToString(env, j_key), - base::BindOnce(&OnLookupFinished, env, std::move(callback))); -} - -void JNI_FeedPersistentKeyValueCache_Put( - JNIEnv* env, - const JavaParamRef<jbyteArray>& j_key, - const JavaParamRef<jbyteArray>& j_value, - const JavaParamRef<jobject>& j_runnable) { - base::android::ScopedJavaGlobalRef<jobject> callback(j_runnable); - - PersistentKeyValueStore* store = GetStore(); - if (!store) { - base::android::RunRunnableAndroid(j_runnable); - return; - } - return store->Put( - JavaByteArrayToString(env, j_key), JavaByteArrayToString(env, j_value), - base::BindOnce(&CallRunnable, - base::android::ScopedJavaGlobalRef<jobject>(j_runnable))); -} - -void JNI_FeedPersistentKeyValueCache_Evict( - JNIEnv* env, - const JavaParamRef<jbyteArray>& j_key, - const JavaParamRef<jobject>& j_runnable) { - base::android::ScopedJavaGlobalRef<jobject> callback(j_runnable); - - PersistentKeyValueStore* store = GetStore(); - if (!store) { - base::android::RunRunnableAndroid(j_runnable); - return; - } - return store->Delete( - JavaByteArrayToString(env, j_key), - base::BindOnce(&CallRunnable, - base::android::ScopedJavaGlobalRef<jobject>(j_runnable))); -} - -} // namespace feed
diff --git a/chrome/browser/android/feed/v2/feed_service_factory.cc b/chrome/browser/android/feed/v2/feed_service_factory.cc index a19b022..472d37b 100644 --- a/chrome/browser/android/feed/v2/feed_service_factory.cc +++ b/chrome/browser/android/feed/v2/feed_service_factory.cc
@@ -23,7 +23,6 @@ #include "chrome/common/chrome_version.h" #include "components/background_task_scheduler/background_task_scheduler_factory.h" #include "components/feed/buildflags.h" -#include "components/feed/core/proto/v2/keyvalue_store.pb.h" #include "components/feed/core/proto/v2/store.pb.h" #include "components/feed/core/v2/public/feed_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" @@ -130,9 +129,6 @@ storage_partition->GetProtoDatabaseProvider()->GetDB<feedstore::Record>( leveldb_proto::ProtoDbType::FEED_STREAM_DATABASE, feed_dir.AppendASCII("streamdb"), background_task_runner), - storage_partition->GetProtoDatabaseProvider()->GetDB<feedkvstore::Entry>( - leveldb_proto::ProtoDbType::FEED_KEY_VALUE_DATABASE, - feed_dir.AppendASCII("keyvaldb"), background_task_runner), identity_manager, HistoryServiceFactory::GetForProfile(profile, ServiceAccessType::IMPLICIT_ACCESS),
diff --git a/chrome/browser/apps/app_service/app_launch_params.h b/chrome/browser/apps/app_service/app_launch_params.h index 417b33b..49b918cb 100644 --- a/chrome/browser/apps/app_service/app_launch_params.h +++ b/chrome/browser/apps/app_service/app_launch_params.h
@@ -62,6 +62,9 @@ // If non-empty, use override_app_name in place of generating one normally. std::string override_app_name; + // The id from the restore data to restore the browser window. + int32_t restore_id = 0; + // If non-empty, information from the command line may be passed on to the // application. base::CommandLine command_line;
diff --git a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java index 548806b..782fede 100644 --- a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java +++ b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
@@ -15,6 +15,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; +import org.chromium.components.webapps.WebappsUtils; import org.chromium.content_public.browser.WebContents; /** @@ -56,6 +57,27 @@ /** Pointer to the native side AppBannerManager. */ private long mNativePointer; + /** Whether add to home screen is permitted by the system. */ + private static Boolean sIsSupported; + + /** + * Checks if the add to home screen intent is supported. + * @return true if add to home screen is supported, false otherwise. + */ + @CalledByNative + private static boolean isSupported() { + if (sIsSupported == null) { + sIsSupported = WebappsUtils.isAddToHomeIntentSupported(); + } + return sIsSupported; + } + + /** Overrides whether the system supports add to home screen. Used in testing. */ + @VisibleForTesting + public static void setIsSupported(boolean state) { + sIsSupported = state; + } + /** * Sets the delegate that provides information about a given package. * @param delegate Delegate to use. Previously set ones are destroyed.
diff --git a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 1008b68..8deaf41 100644 --- a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -226,7 +226,7 @@ @Before public void setUp() throws Exception { - AppBannerManagerHelper.setIsSupported(true); + AppBannerManager.setIsSupported(true); ShortcutHelper.setDelegateForTests(new ShortcutHelper.Delegate() { @Override public void addShortcutToHomescreen( @@ -793,7 +793,7 @@ @Test @MediumTest @Feature({"AppBanners"}) - @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.INSTALLABLE_AMBIENT_BADGE_INFOBAR) + @CommandLineFlags.Add("enable-features=" + FeatureConstants.PWA_INSTALL_AVAILABLE_FEATURE) public void testInProductHelp() throws Exception { // Visit a site that is a PWA. The ambient badge should show. String webBannerUrl = WebappTestPage.getServiceWorkerUrl(mTestServer);
diff --git a/chrome/browser/banners/app_banner_manager_android.cc b/chrome/browser/banners/app_banner_manager_android.cc index 592a9b7e..9fa23ab4 100644 --- a/chrome/browser/banners/app_banner_manager_android.cc +++ b/chrome/browser/banners/app_banner_manager_android.cc
@@ -13,7 +13,6 @@ #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/android/chrome_jni_headers/AppBannerManagerHelper_jni.h" #include "chrome/browser/android/webapk/webapk_metrics.h" #include "chrome/browser/android/webapk/webapk_ukm_recorder.h" #include "chrome/browser/android/webapps/add_to_homescreen_coordinator.h" @@ -117,7 +116,7 @@ void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url) { JNIEnv* env = base::android::AttachCurrentThread(); - if (!Java_AppBannerManagerHelper_isEnabledForTab(env) || + if (!Java_AppBannerManager_isSupported(env) || !WebappsClient::Get()->CanShowAppBanners(web_contents())) { return; } @@ -452,6 +451,12 @@ } bool AppBannerManagerAndroid::MaybeShowInProductHelp() const { + if (!base::FeatureList::IsEnabled( + feature_engagement::kIPHPwaInstallAvailableFeature)) { + DVLOG(2) << "Feature not enabled"; + return false; + } + if (!web_contents()) { DVLOG(2) << "IPH for PWA aborted: null WebContents"; return false;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index f590c2f..f0d4bf1 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1075,6 +1075,8 @@ "crosapi/message_center_ash.h", "crosapi/metrics_reporting_ash.cc", "crosapi/metrics_reporting_ash.h", + "crosapi/prefs_ash.cc", + "crosapi/prefs_ash.h", "crosapi/screen_manager_ash.cc", "crosapi/screen_manager_ash.h", "crosapi/select_file_ash.cc", @@ -1456,6 +1458,8 @@ "first_run/drive_first_run_controller.h", "first_run/first_run.cc", "first_run/first_run.h", + "full_restore/app_launch_handler.cc", + "full_restore/app_launch_handler.h", "full_restore/full_restore_prefs.cc", "full_restore/full_restore_prefs.h", "full_restore/full_restore_service.cc", @@ -3502,6 +3506,7 @@ "crosapi/browser_util_unittest.cc", "crosapi/message_center_ash_unittest.cc", "crosapi/metrics_reporting_ash_unittest.cc", + "crosapi/prefs_ash_unittest.cc", "crosapi/test_mojo_connection_manager_unittest.cc", "crostini/ansible/ansible_management_service_unittest.cc", "crostini/crostini_disk_unittest.cc",
diff --git a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc index c775548..41f78ad 100644 --- a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc +++ b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/chromeos/crosapi/keystore_service_ash.h" #include "chrome/browser/chromeos/crosapi/message_center_ash.h" #include "chrome/browser/chromeos/crosapi/metrics_reporting_ash.h" +#include "chrome/browser/chromeos/crosapi/prefs_ash.h" #include "chrome/browser/chromeos/crosapi/screen_manager_ash.h" #include "chrome/browser/chromeos/crosapi/select_file_ash.h" #include "chrome/browser/chromeos/crosapi/test_controller_ash.h" @@ -45,6 +46,9 @@ : receiver_(this, std::move(pending_receiver)), metrics_reporting_ash_(std::make_unique<MetricsReportingAsh>( g_browser_process->local_state())), + prefs_ash_(std::make_unique<PrefsAsh>( + g_browser_process->local_state(), + ProfileManager::GetPrimaryUserProfile()->GetPrefs())), screen_manager_ash_(std::make_unique<ScreenManagerAsh>()), cert_database_ash_(std::make_unique<CertDatabaseAsh>()), test_controller_ash_(std::make_unique<TestControllerAsh>()), @@ -175,6 +179,11 @@ clipboard_ash_->BindReceiver(std::move(receiver)); } +void AshChromeServiceImpl::BindPrefs( + mojo::PendingReceiver<mojom::Prefs> receiver) { + prefs_ash_->BindReceiver(std::move(receiver)); +} + void AshChromeServiceImpl::OnLacrosStartup(mojom::LacrosInfoPtr lacros_info) { BrowserManager::Get()->set_lacros_version(lacros_info->lacros_version); }
diff --git a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.h b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.h index 594d52f..2c18931a 100644 --- a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.h +++ b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.h
@@ -21,6 +21,7 @@ class KeystoreServiceAsh; class MessageCenterAsh; class MetricsReportingAsh; +class PrefsAsh; class ScreenManagerAsh; class SelectFileAsh; class TestControllerAsh; @@ -47,6 +48,7 @@ mojo::PendingReceiver<mojom::MessageCenter> receiver) override; void BindMetricsReporting( mojo::PendingReceiver<mojom::MetricsReporting> receiver) override; + void BindPrefs(mojo::PendingReceiver<mojom::Prefs> receiver) override; void BindScreenManager( mojo::PendingReceiver<mojom::ScreenManager> receiver) override; void BindSelectFile( @@ -75,6 +77,7 @@ std::unique_ptr<KeystoreServiceAsh> keystore_service_ash_; std::unique_ptr<MessageCenterAsh> message_center_ash_; std::unique_ptr<MetricsReportingAsh> metrics_reporting_ash_; + std::unique_ptr<PrefsAsh> prefs_ash_; std::unique_ptr<ScreenManagerAsh> screen_manager_ash_; std::unique_ptr<SelectFileAsh> select_file_ash_; std::unique_ptr<FeedbackAsh> feedback_ash_;
diff --git a/chrome/browser/chromeos/crosapi/browser_util.cc b/chrome/browser/chromeos/crosapi/browser_util.cc index 2815d6c..afaf136 100644 --- a/chrome/browser/chromeos/crosapi/browser_util.cc +++ b/chrome/browser/chromeos/crosapi/browser_util.cc
@@ -198,7 +198,7 @@ base::flat_map<base::Token, uint32_t> GetInterfaceVersions() { static_assert( - crosapi::mojom::AshChromeService::Version_ == 10, + crosapi::mojom::AshChromeService::Version_ == 11, "if you add a new crosapi, please add it to the version map here"); InterfaceVersions versions; AddVersion<crosapi::mojom::AccountManager>(&versions); @@ -210,6 +210,7 @@ AddVersion<crosapi::mojom::KeystoreService>(&versions); AddVersion<crosapi::mojom::MessageCenter>(&versions); AddVersion<crosapi::mojom::MetricsReporting>(&versions); + AddVersion<crosapi::mojom::Prefs>(&versions); AddVersion<crosapi::mojom::ScreenManager>(&versions); AddVersion<crosapi::mojom::SnapshotCapturer>(&versions); AddVersion<crosapi::mojom::TestController>(&versions);
diff --git a/chrome/browser/chromeos/crosapi/prefs_ash.cc b/chrome/browser/chromeos/crosapi/prefs_ash.cc new file mode 100644 index 0000000..d76410e --- /dev/null +++ b/chrome/browser/chromeos/crosapi/prefs_ash.cc
@@ -0,0 +1,110 @@ +// Copyright 2021 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/crosapi/prefs_ash.h" + +#include <utility> + +#include "ash/public/cpp/ash_pref_names.h" +#include "base/bind.h" +#include "base/check.h" +#include "chromeos/crosapi/mojom/prefs.mojom.h" +#include "components/metrics/metrics_pref_names.h" +#include "components/prefs/pref_service.h" + +namespace crosapi { + +PrefsAsh::PrefsAsh(PrefService* local_state, PrefService* profile_prefs) + : local_state_(local_state), profile_prefs_(profile_prefs) { + DCHECK(local_state_); + DCHECK(profile_prefs_); + local_state_registrar_.Init(local_state_); + profile_prefs_registrar_.Init(profile_prefs_); +} + +PrefsAsh::~PrefsAsh() = default; + +void PrefsAsh::BindReceiver(mojo::PendingReceiver<mojom::Prefs> receiver) { + receivers_.Add(this, std::move(receiver)); +} + +void PrefsAsh::GetPref(mojom::PrefPath path, GetPrefCallback callback) { + auto state = GetState(path); + const base::Value* value = + state ? state->pref_service->Get(state->path) : nullptr; + std::move(callback).Run(value ? base::Optional<base::Value>(value->Clone()) + : base::nullopt); +} + +void PrefsAsh::SetPref(mojom::PrefPath path, + base::Value value, + SetPrefCallback callback) { + auto state = GetState(path); + if (state) { + state->pref_service->Set(state->path, value); + } + std::move(callback).Run(); +} + +void PrefsAsh::AddObserver(mojom::PrefPath path, + mojo::PendingRemote<mojom::PrefObserver> observer) { + auto state = GetState(path); + const base::Value* value = + state ? state->pref_service->Get(state->path) : nullptr; + if (!value) { + return; + } + + // Fire the observer with the initial value. + mojo::Remote<mojom::PrefObserver> remote(std::move(observer)); + remote->OnPrefChanged(value->Clone()); + + if (!state->registrar->IsObserved(state->path)) { + // Unretained() is safe since PrefChangeRegistrar and RemoteSet within + // observers_ are owned by this and wont invoke if PrefsAsh is destroyed. + state->registrar->Add(state->path, + base::BindRepeating(&PrefsAsh::OnPrefChanged, + base::Unretained(this), path)); + observers_[path].set_disconnect_handler(base::BindRepeating( + &PrefsAsh::OnDisconnect, base::Unretained(this), path)); + } + observers_[path].Add(std::move(remote)); +} + +base::Optional<PrefsAsh::State> PrefsAsh::GetState(mojom::PrefPath path) { + switch (path) { + case mojom::PrefPath::kMetricsReportingEnabled: + return State{local_state_, &local_state_registrar_, + metrics::prefs::kMetricsReportingEnabled}; + case mojom::PrefPath::kAccessibilitySpokenFeedbackEnabled: + return State{profile_prefs_, &profile_prefs_registrar_, + ash::prefs::kAccessibilitySpokenFeedbackEnabled}; + default: + LOG(WARNING) << "Unknown pref path: " << path; + return base::nullopt; + } +} + +void PrefsAsh::OnPrefChanged(mojom::PrefPath path) { + auto state = GetState(path); + const base::Value* value = + state ? state->pref_service->Get(state->path) : nullptr; + if (value) { + for (auto& observer : observers_[path]) { + observer->OnPrefChanged(value->Clone()); + } + } +} + +void PrefsAsh::OnDisconnect(mojom::PrefPath path, mojo::RemoteSetElementId id) { + const auto& it = observers_.find(path); + if (it != observers_.end() && it->second.empty()) { + if (auto state = GetState(path)) { + state->registrar->Remove(state->path); + } + observers_.erase(it); + } +} + +} // namespace crosapi
diff --git a/chrome/browser/chromeos/crosapi/prefs_ash.h b/chrome/browser/chromeos/crosapi/prefs_ash.h new file mode 100644 index 0000000..82374ee --- /dev/null +++ b/chrome/browser/chromeos/crosapi/prefs_ash.h
@@ -0,0 +1,73 @@ +// Copyright 2021 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_CROSAPI_PREFS_ASH_H_ +#define CHROME_BROWSER_CHROMEOS_CROSAPI_PREFS_ASH_H_ + +#include <map> +#include <memory> +#include <utility> + +#include "base/gtest_prod_util.h" +#include "base/optional.h" +#include "chromeos/crosapi/mojom/prefs.mojom.h" +#include "components/prefs/pref_change_registrar.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "mojo/public/cpp/bindings/remote_set.h" + +class PrefService; +class PrefChangeRegistrar; + +namespace crosapi { + +// The ash-chrome implementation of the Prefs crosapi interface. +// This class must only be used from the main thread. +class PrefsAsh : public mojom::Prefs { + public: + PrefsAsh(PrefService* local_state, PrefService* profile_prefs); + PrefsAsh(const PrefsAsh&) = delete; + PrefsAsh& operator=(const PrefsAsh&) = delete; + ~PrefsAsh() override; + + void BindReceiver(mojo::PendingReceiver<mojom::Prefs> receiver); + + // crosapi::mojom::Prefs: + void GetPref(mojom::PrefPath path, GetPrefCallback callback) override; + void SetPref(mojom::PrefPath path, + base::Value value, + SetPrefCallback callback) override; + void AddObserver(mojom::PrefPath path, + mojo::PendingRemote<mojom::PrefObserver> observer) override; + + private: + FRIEND_TEST_ALL_PREFIXES(PrefsAshTest, LocalStatePrefs); + + struct State { + PrefService* pref_service; + PrefChangeRegistrar* registrar; + std::string path; + }; + base::Optional<State> GetState(mojom::PrefPath path); + + void OnPrefChanged(mojom::PrefPath path); + void OnDisconnect(mojom::PrefPath path, mojo::RemoteSetElementId id); + + // In production, owned by g_browser_process, which outlives this object. + PrefService* const local_state_; + // From GetPrimaryUserProfile()->GetPrefs(), which outlives this object. + PrefService* const profile_prefs_; + PrefChangeRegistrar local_state_registrar_; + PrefChangeRegistrar profile_prefs_registrar_; + + // This class supports any number of connections. + mojo::ReceiverSet<mojom::Prefs> receivers_; + + // This class supports any number of observers. + std::map<mojom::PrefPath, mojo::RemoteSet<mojom::PrefObserver>> observers_; +}; + +} // namespace crosapi + +#endif // CHROME_BROWSER_CHROMEOS_CROSAPI_PREFS_ASH_H_
diff --git a/chrome/browser/chromeos/crosapi/prefs_ash_unittest.cc b/chrome/browser/chromeos/crosapi/prefs_ash_unittest.cc new file mode 100644 index 0000000..826b608 --- /dev/null +++ b/chrome/browser/chromeos/crosapi/prefs_ash_unittest.cc
@@ -0,0 +1,173 @@ +// Copyright 2021 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/crosapi/prefs_ash.h" + +#include <memory> + +#include "ash/public/cpp/ash_pref_names.h" +#include "base/optional.h" +#include "base/test/bind.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 "components/metrics/metrics_pref_names.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" +#include "content/public/test/browser_task_environment.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crosapi { +namespace { + +class TestObserver : public mojom::PrefObserver { + public: + TestObserver() = default; + TestObserver(const TestObserver&) = delete; + TestObserver& operator=(const TestObserver&) = delete; + ~TestObserver() override = default; + + // crosapi::mojom::PrefObserver: + void OnPrefChanged(base::Value value) override { value_ = std::move(value); } + + base::Optional<base::Value> value_; + mojo::Receiver<mojom::PrefObserver> receiver_{this}; +}; + +} // namespace + +class PrefsAshTest : public testing::Test { + public: + PrefsAshTest() + : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()), + local_state_(scoped_testing_local_state_.Get()), + profile_prefs_(profile_.GetPrefs()) {} + PrefsAshTest(const PrefsAshTest&) = delete; + PrefsAshTest& operator=(const PrefsAshTest&) = delete; + ~PrefsAshTest() override = default; + + content::BrowserTaskEnvironment task_environment_; + ScopedTestingLocalState scoped_testing_local_state_; + TestingProfile profile_; + PrefService* const local_state_; + PrefService* const profile_prefs_; +}; + +TEST_F(PrefsAshTest, LocalStatePrefs) { + local_state_->SetBoolean(metrics::prefs::kMetricsReportingEnabled, false); + PrefsAsh prefs_ash(local_state_, profile_prefs_); + mojo::Remote<mojom::Prefs> prefs_remote; + prefs_ash.BindReceiver(prefs_remote.BindNewPipeAndPassReceiver()); + mojom::PrefPath path = mojom::PrefPath::kMetricsReportingEnabled; + + // Get returns value. + base::Value get_value; + prefs_remote->GetPref( + path, base::BindLambdaForTesting([&](base::Optional<base::Value> value) { + get_value = std::move(*value); + })); + prefs_remote.FlushForTesting(); + EXPECT_FALSE(get_value.GetBool()); + + // Set updates value. + prefs_remote->SetPref(path, base::Value(true), base::DoNothing()); + prefs_remote.FlushForTesting(); + EXPECT_TRUE( + local_state_->GetBoolean(metrics::prefs::kMetricsReportingEnabled)); + + // Adding an observer results in it being fired with the current state. + EXPECT_FALSE(prefs_ash.local_state_registrar_.IsObserved( + metrics::prefs::kMetricsReportingEnabled)); + auto observer1 = std::make_unique<TestObserver>(); + prefs_remote->AddObserver(path, + observer1->receiver_.BindNewPipeAndPassRemote()); + prefs_remote.FlushForTesting(); + EXPECT_TRUE(observer1->value_->GetBool()); + EXPECT_TRUE(prefs_ash.local_state_registrar_.IsObserved( + metrics::prefs::kMetricsReportingEnabled)); + EXPECT_EQ(1, prefs_ash.observers_[path].size()); + + // Multiple observers is ok. + auto observer2 = std::make_unique<TestObserver>(); + prefs_remote->AddObserver(path, + observer2->receiver_.BindNewPipeAndPassRemote()); + prefs_remote.FlushForTesting(); + EXPECT_TRUE(observer2->value_->GetBool()); + EXPECT_EQ(2, prefs_ash.observers_[path].size()); + + // Observer should be notified when value changes. + local_state_->SetBoolean(metrics::prefs::kMetricsReportingEnabled, false); + task_environment_.RunUntilIdle(); + EXPECT_FALSE(observer1->value_->GetBool()); + EXPECT_FALSE(observer2->value_->GetBool()); + + // Disconnect should remove PrefChangeRegistrar. + observer1.reset(); + prefs_remote.FlushForTesting(); + EXPECT_EQ(1, prefs_ash.observers_[path].size()); + observer2.reset(); + prefs_remote.FlushForTesting(); + EXPECT_EQ(0, prefs_ash.observers_[path].size()); + EXPECT_FALSE(prefs_ash.local_state_registrar_.IsObserved( + metrics::prefs::kMetricsReportingEnabled)); +} + +TEST_F(PrefsAshTest, ProfilePrefs) { + profile_prefs_->SetBoolean(ash::prefs::kAccessibilitySpokenFeedbackEnabled, + false); + PrefsAsh prefs_ash(local_state_, profile_prefs_); + mojo::Remote<mojom::Prefs> prefs_remote; + prefs_ash.BindReceiver(prefs_remote.BindNewPipeAndPassReceiver()); + mojom::PrefPath path = mojom::PrefPath::kAccessibilitySpokenFeedbackEnabled; + + // Get returns value. + base::Value get_value; + prefs_remote->GetPref( + path, base::BindLambdaForTesting([&](base::Optional<base::Value> value) { + get_value = std::move(*value); + })); + prefs_remote.FlushForTesting(); + EXPECT_FALSE(get_value.GetBool()); + + // Set updates value. + prefs_remote->SetPref(path, base::Value(true), base::DoNothing()); + prefs_remote.FlushForTesting(); + EXPECT_TRUE(profile_prefs_->GetBoolean( + ash::prefs::kAccessibilitySpokenFeedbackEnabled)); + + // Adding an observer results in it being fired with the current state. + TestObserver observer; + prefs_remote->AddObserver(path, + observer.receiver_.BindNewPipeAndPassRemote()); + prefs_remote.FlushForTesting(); + EXPECT_TRUE(observer.value_->GetBool()); +} + +TEST_F(PrefsAshTest, GetUnknown) { + PrefsAsh prefs_ash(local_state_, profile_prefs_); + mojo::Remote<mojom::Prefs> prefs_remote; + prefs_ash.BindReceiver(prefs_remote.BindNewPipeAndPassReceiver()); + mojom::PrefPath path = mojom::PrefPath::kUnknown; + + // Get for an unknown value returns base::nullopt. + bool has_value = true; + prefs_remote->GetPref( + path, base::BindLambdaForTesting([&](base::Optional<base::Value> value) { + has_value = value.has_value(); + })); + prefs_remote.FlushForTesting(); + EXPECT_FALSE(has_value); + + // Set or AddObserver for an unknown value does nothing. + prefs_remote->SetPref(path, base::Value(false), base::DoNothing()); + TestObserver observer; + prefs_remote->AddObserver(path, + observer.receiver_.BindNewPipeAndPassRemote()); + prefs_remote.FlushForTesting(); + EXPECT_FALSE(observer.value_.has_value()); +} + +} // namespace crosapi
diff --git a/chrome/browser/chromeos/full_restore/app_launch_handler.cc b/chrome/browser/chromeos/full_restore/app_launch_handler.cc new file mode 100644 index 0000000..375b9b8 --- /dev/null +++ b/chrome/browser/chromeos/full_restore/app_launch_handler.cc
@@ -0,0 +1,188 @@ +// Copyright 2021 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/full_restore/app_launch_handler.h" + +#include <set> +#include <vector> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/apps/app_service/browser_app_launcher.h" +#include "chrome/browser/profiles/profile.h" +#include "components/full_restore/full_restore_read_handler.h" +#include "components/full_restore/full_restore_save_handler.h" +#include "components/full_restore/restore_data.h" +#include "components/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/mojom/types.mojom.h" +#include "ui/base/window_open_disposition.h" + +namespace chromeos { +namespace full_restore { + +AppLaunchHandler::AppLaunchHandler(Profile* profile) : profile_(profile) { + // FullRestoreReadHandler reads the full restore data from the full restore + // data file on a background task runner. + ::full_restore::FullRestoreReadHandler::GetInstance()->ReadFromFile( + profile_->GetPath(), base::BindOnce(&AppLaunchHandler::OnGetRestoreData, + weak_ptr_factory_.GetWeakPtr())); +} + +AppLaunchHandler::~AppLaunchHandler() = default; + +void AppLaunchHandler::OnAppUpdate(const apps::AppUpdate& update) { + // If the restore flag |should_restore_| is false, or the restore data has not + // been read yet, or the app is not ready, don't launch the app for the + // restoration. + if (!should_restore_ || !restore_data_ || !update.ReadinessChanged() || + update.Readiness() != apps::mojom::Readiness::kReady) { + return; + } + + // If there is no restore data or the launch list for the app is empty, don't + // launch the app. + const auto& app_id_to_launch_list = restore_data_->app_id_to_launch_list(); + if (app_id_to_launch_list.find(update.AppId()) == + app_id_to_launch_list.end()) { + return; + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&AppLaunchHandler::LaunchApp, + weak_ptr_factory_.GetWeakPtr(), + update.AppType(), update.AppId())); +} + +void AppLaunchHandler::OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) { + apps::AppRegistryCache::Observer::Observe(nullptr); +} + +void AppLaunchHandler::SetShouldRestore() { + should_restore_ = true; + MaybePostRestore(); +} + +void AppLaunchHandler::OnGetRestoreData( + std::unique_ptr<::full_restore::RestoreData> restore_data) { + restore_data_ = std::move(restore_data); + + // After reading the restore data, the restore data can be cleared from the + // restore file to save the new restore data. + ::full_restore::FullRestoreSaveHandler::GetInstance()->Flush( + profile_->GetPath()); + + MaybePostRestore(); +} + +void AppLaunchHandler::MaybePostRestore() { + // If the restore flag |should_restore_| is not true, or reading the restore + // data hasn't finished, don't restore. + if (!should_restore_ || !restore_data_) + return; + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&AppLaunchHandler::MaybeRestore, + weak_ptr_factory_.GetWeakPtr())); +} + +void AppLaunchHandler::MaybeRestore() { + // If there is no launch list from the restore data, we don't need to handle + // the restoration. + const auto& launch_list = restore_data_->app_id_to_launch_list(); + if (launch_list.empty()) + return; + + // Observe AppRegistryCache to get the notification when the app is ready. + DCHECK( + apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile_)); + auto* cache = &apps::AppServiceProxyFactory::GetForProfile(profile_) + ->AppRegistryCache(); + Observe(cache); + + // Add the app to |app_ids| if there is a launch list from the restore data + // for the app. + std::set<std::string> app_ids; + cache->ForEachApp([&app_ids, &launch_list](const apps::AppUpdate& update) { + if (update.Readiness() == apps::mojom::Readiness::kReady && + launch_list.find(update.AppId()) != launch_list.end()) { + app_ids.insert(update.AppId()); + } + }); + + for (const auto& app_id : app_ids) + LaunchApp(cache->GetAppType(app_id), app_id); +} + +void AppLaunchHandler::LaunchApp(apps::mojom::AppType app_type, + const std::string& app_id) { + DCHECK(restore_data_); + + // For the Chrome browser, the browser session restore is used to restore the + // web pages, so we don't need to launch the app. + if (app_id == extension_misc::kChromeAppId) { + restore_data_->RemoveApp(app_id); + return; + } + + const auto it = restore_data_->app_id_to_launch_list().find(app_id); + if (it == restore_data_->app_id_to_launch_list().end() || + it->second.empty()) { + restore_data_->RemoveApp(app_id); + return; + } + + switch (app_type) { + case apps::mojom::AppType::kArc: + // TODO(crbug.com/1146900): Handle ARC apps + break; + case apps::mojom::AppType::kExtension: + case apps::mojom::AppType::kWeb: + LaunchWebAppOrExtension(app_id, it->second); + break; + case apps::mojom::AppType::kBuiltIn: + case apps::mojom::AppType::kCrostini: + case apps::mojom::AppType::kPluginVm: + case apps::mojom::AppType::kUnknown: + case apps::mojom::AppType::kMacOs: + case apps::mojom::AppType::kLacros: + case apps::mojom::AppType::kRemote: + case apps::mojom::AppType::kBorealis: + NOTREACHED(); + break; + } + restore_data_->RemoveApp(app_id); +} + +void AppLaunchHandler::LaunchWebAppOrExtension( + const std::string& app_id, + const ::full_restore::RestoreData::LaunchList& launch_list) { + auto* launcher = apps::AppServiceProxyFactory::GetForProfile(profile_) + ->BrowserAppLauncher(); + if (!launcher) + return; + + for (const auto& it : launch_list) { + DCHECK(it.second->container.has_value()); + DCHECK(it.second->disposition.has_value()); + DCHECK(it.second->display_id.has_value()); + apps::mojom::IntentPtr intent; + apps::AppLaunchParams params( + app_id, + static_cast<apps::mojom::LaunchContainer>(it.second->container.value()), + static_cast<WindowOpenDisposition>(it.second->disposition.value()), + it.second->display_id.value(), + it.second->file_paths.has_value() ? it.second->file_paths.value() + : std::vector<base::FilePath>{}, + it.second->intent.has_value() ? it.second->intent.value() : intent); + params.restore_id = it.first; + launcher->LaunchAppWithParams(std::move(params)); + } +} + +} // namespace full_restore +} // namespace chromeos
diff --git a/chrome/browser/chromeos/full_restore/app_launch_handler.h b/chrome/browser/chromeos/full_restore/app_launch_handler.h new file mode 100644 index 0000000..8211dea2 --- /dev/null +++ b/chrome/browser/chromeos/full_restore/app_launch_handler.h
@@ -0,0 +1,78 @@ +// Copyright 2021 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_FULL_RESTORE_APP_LAUNCH_HANDLER_H_ +#define CHROME_BROWSER_CHROMEOS_FULL_RESTORE_APP_LAUNCH_HANDLER_H_ + +#include "base/memory/weak_ptr.h" +#include "components/full_restore/restore_data.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/mojom/types.mojom.h" + +namespace apps { +class AppUpdate; +} + +class Profile; + +namespace chromeos { +namespace full_restore { + +// The AppLaunchHandler class calls FullRestoreReadHandler to read the full +// restore data from the full restore data file on a background task runner, and +// restore apps and web pages based on the user preference or the user's choice. +// +// The apps can be re-launched for the restoration when: +// 1. There is the restore data for the app. +// 2. The user preference sets always restore or the user selects 'Restore' from +// the notification dialog. +// 3. The app is ready. +// +// TODO(crbug.com/1146900): Implement ARC apps launching. +class AppLaunchHandler : public apps::AppRegistryCache::Observer { + public: + explicit AppLaunchHandler(Profile* profile); + AppLaunchHandler(const AppLaunchHandler&) = delete; + AppLaunchHandler& operator=(const AppLaunchHandler&) = delete; + ~AppLaunchHandler() override; + + // apps::AppRegistryCache::Observer: + void OnAppUpdate(const apps::AppUpdate& update) override; + void OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) override; + + // If the user preference sets always restore or the user selects 'Restore' + // from the notification dialog, sets the restore flag |should_restore_| as + // true to allow the restoration. + void SetShouldRestore(); + + private: + void OnGetRestoreData( + std::unique_ptr<::full_restore::RestoreData> restore_data); + + void MaybePostRestore(); + + // If there is the restore data, and the restore flag |should_restore_| is + // true, launches apps based on the restore data when apps are ready. + void MaybeRestore(); + + void LaunchApp(apps::mojom::AppType app_type, const std::string& app_id); + + void LaunchWebAppOrExtension( + const std::string& app_id, + const ::full_restore::RestoreData::LaunchList& launch_list); + + Profile* profile_ = nullptr; + + bool should_restore_ = false; + + std::unique_ptr<::full_restore::RestoreData> restore_data_; + + base::WeakPtrFactory<AppLaunchHandler> weak_ptr_factory_{this}; +}; + +} // namespace full_restore +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
diff --git a/chrome/browser/chromeos/full_restore/full_restore_service.cc b/chrome/browser/chromeos/full_restore/full_restore_service.cc index a6b8ab78..8e86c53 100644 --- a/chrome/browser/chromeos/full_restore/full_restore_service.cc +++ b/chrome/browser/chromeos/full_restore/full_restore_service.cc
@@ -7,6 +7,7 @@ #include "ash/public/cpp/notification_utils.h" #include "base/strings/string_util.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/chromeos/full_restore/app_launch_handler.h" #include "chrome/browser/chromeos/full_restore/full_restore_prefs.h" #include "chrome/browser/chromeos/full_restore/full_restore_service_factory.h" #include "chrome/browser/chromeos/full_restore/new_user_restore_pref_handler.h" @@ -29,7 +30,9 @@ const char kRestoreForCrashNotificationId[] = "restore_for_crash_notification"; const char kRestoreNotificationId[] = "restore_notification"; -FullRestoreService::FullRestoreService(Profile* profile) : profile_(profile) { +FullRestoreService::FullRestoreService(Profile* profile) + : profile_(profile), + app_launch_handler_(std::make_unique<AppLaunchHandler>(profile_)) { // If the system crashed before reboot, show the restore notification. if (profile->GetLastSessionExitType() == Profile::EXIT_CRASHED) { ShowRestoreNotification(kRestoreForCrashNotificationId); @@ -140,8 +143,7 @@ user->GetAccountId(), true); } - // TODO(crbug.com/909794): Implement the restoration. And move the heavy load - // out of this KeyedService class. + app_launch_handler_->SetShouldRestore(); } } // namespace full_restore
diff --git a/chrome/browser/chromeos/full_restore/full_restore_service.h b/chrome/browser/chromeos/full_restore/full_restore_service.h index 59bd750..fcbec4f 100644 --- a/chrome/browser/chromeos/full_restore/full_restore_service.h +++ b/chrome/browser/chromeos/full_restore/full_restore_service.h
@@ -17,6 +17,7 @@ namespace chromeos { namespace full_restore { +class AppLaunchHandler; class NewUserRestorePrefHandler; extern const char kRestoreForCrashNotificationId[]; @@ -65,6 +66,10 @@ std::unique_ptr<NewUserRestorePrefHandler> new_user_pref_handler_; + // |app_launch_handler_| is responsible for launching apps based on the + // restore data. + std::unique_ptr<AppLaunchHandler> app_launch_handler_; + base::WeakPtrFactory<FullRestoreService> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.cc b/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.cc index 7eb0c21f..e458f342 100644 --- a/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.cc +++ b/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.cc
@@ -40,10 +40,13 @@ } // namespace ToastDialogView::ToastDialogView(const base::string16& app_name, - base::OnceClosure dismissed_callback) - : app_name_(app_name) { - DialogDelegate::SetButtons(ui::DIALOG_BUTTON_NONE); - DialogDelegate::SetCloseCallback(std::move(dismissed_callback)); + base::OnceClosure dismissed_callback) { + SetButtons(ui::DIALOG_BUTTON_NONE); + SetCloseCallback(std::move(dismissed_callback)); + SetModalType(ui::MODAL_TYPE_NONE); + SetShowCloseButton(true); + SetTitle(l10n_util::GetStringFUTF16( + IDS_LOCK_SCREEN_NOTE_APP_TOAST_DIALOG_TITLE, app_name)); chrome::RecordDialogCreation( chrome::DialogIdentifier::LOCK_SCREEN_NOTE_APP_TOAST); @@ -59,7 +62,7 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); auto* label = new views::Label(l10n_util::GetStringFUTF16( - IDS_LOCK_SCREEN_NOTE_APP_TOAST_DIALOG_MESSAGE, app_name_)); + IDS_LOCK_SCREEN_NOTE_APP_TOAST_DIALOG_MESSAGE, app_name)); label->SetMultiLine(true); label->SetHorizontalAlignment(gfx::ALIGN_LEFT); label->SetEnabledColor(SkColorSetARGB(138, 0, 0, 0)); @@ -75,15 +78,6 @@ ToastDialogView::~ToastDialogView() = default; -ui::ModalType ToastDialogView::GetModalType() const { - return ui::MODAL_TYPE_NONE; -} - -base::string16 ToastDialogView::GetWindowTitle() const { - return l10n_util::GetStringFUTF16(IDS_LOCK_SCREEN_NOTE_APP_TOAST_DIALOG_TITLE, - app_name_); -} - void ToastDialogView::AddedToWidget() { std::unique_ptr<views::Label> title = views::BubbleFrameView::CreateDefaultTitleLabel(GetWindowTitle()); @@ -92,10 +86,6 @@ GetBubbleFrameView()->SetTitleView(std::move(title)); } -bool ToastDialogView::ShouldShowCloseButton() const { - return true; -} - void ToastDialogView::OnBeforeBubbleWidgetInit( views::Widget::InitParams* params, views::Widget* widget) const {
diff --git a/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.h b/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.h index 6b52794e..efc63e17 100644 --- a/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.h +++ b/chrome/browser/chromeos/lock_screen_apps/toast_dialog_view.h
@@ -22,17 +22,11 @@ ~ToastDialogView() override; // views::BubbleDialogDelegateView: - ui::ModalType GetModalType() const override; - base::string16 GetWindowTitle() const override; void AddedToWidget() override; - bool ShouldShowCloseButton() const override; void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const override; private: - // The name of the app for which the dialog is shown. - const base::string16 app_name_; - // Callback to be called when the user closes the dialog. base::OnceClosure dismissed_callback_;
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc index 43b29ca..492bf7a 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_screenlock_state_handler.cc
@@ -322,6 +322,8 @@ } bool autoshow = true; + // TODO(crbug.com/1152491): Only call into SetHasShownLoginDisabledMessage() + // if this is a signin screen, not lock screen, context. if (hardlock_state_ == LOGIN_DISABLED) { // If Signin with Smart Lock is disabled, only automatically show the // tooltip if it hasn't been shown yet. See https://crbug.com/848893 for
diff --git a/chrome/browser/chromeos/printing/printer_configurer.cc b/chrome/browser/chromeos/printing/printer_configurer.cc index 3f0062d..ad392f0 100644 --- a/chrome/browser/chromeos/printing/printer_configurer.cc +++ b/chrome/browser/chromeos/printing/printer_configurer.cc
@@ -103,17 +103,6 @@ } } -// Records whether a |printer| contains a valid PpdReference defined as having -// either autoconf or a ppd reference set. -void RecordValidPpdReference(const Printer& printer) { - const auto& ppd_ref = printer.ppd_reference(); - // A PpdReference is valid if exactly one field is set in PpdReference. - int refs = ppd_ref.autoconf ? 1 : 0; - refs += !ppd_ref.user_supplied_ppd_url.empty() ? 1 : 0; - refs += !ppd_ref.effective_make_and_model.empty() ? 1 : 0; - base::UmaHistogramBoolean("Printing.CUPS.ValidPpdReference", refs == 1); -} - // Configures printers by downloading PPDs then adding them to CUPS through // debugd. This class must be used on the UI thread. class PrinterConfigurerImpl : public PrinterConfigurer { @@ -129,8 +118,6 @@ DCHECK(!printer.id().empty()); DCHECK(printer.HasUri()); PRINTER_LOG(USER) << printer.make_and_model() << " Printer setup requested"; - // Record if autoconf and a PPD are set. crbug.com/814374. - RecordValidPpdReference(printer); if (!printer.IsIppEverywhere()) { PRINTER_LOG(DEBUG) << printer.make_and_model() << " Lookup PPD";
diff --git a/chrome/browser/error_reporting/BUILD.gn b/chrome/browser/error_reporting/BUILD.gn index 101eb5e2..15cff0c9 100644 --- a/chrome/browser/error_reporting/BUILD.gn +++ b/chrome/browser/error_reporting/BUILD.gn
@@ -14,10 +14,12 @@ deps = [ "//base", "//build:chromeos_buildflags", + "//chrome/common:constants", "//components/crash/content/browser/error_reporting", "//components/crash/core/app", "//components/feedback", "//components/startup_metric_utils/browser", + "//components/upload_list", "//content/public/browser", "//net", "//services/network:network_service", @@ -34,6 +36,9 @@ deps = [ ":error_reporting", "//base", + "//base/test:test_support", + "//build:chromeos_buildflags", + "//chrome/common:constants", "//components/crash/content/browser/error_reporting:mock_crash_endpoint", ] } @@ -49,6 +54,7 @@ "//components/crash/content/browser/error_reporting", "//components/crash/content/browser/error_reporting:mock_crash_endpoint", "//components/crash/core/app", + "//components/upload_list", "//content/test:test_support", "//net:test_support", "//testing/gtest",
diff --git a/chrome/browser/error_reporting/chrome_js_error_report_processor.cc b/chrome/browser/error_reporting/chrome_js_error_report_processor.cc index 9e2f876..ff6454ce 100644 --- a/chrome/browser/error_reporting/chrome_js_error_report_processor.cc +++ b/chrome/browser/error_reporting/chrome_js_error_report_processor.cc
@@ -10,8 +10,11 @@ #include "base/callback.h" #include "base/callback_helpers.h" +#include "base/files/file.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/scoped_refptr.h" +#include "base/path_service.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -20,11 +23,13 @@ #include "base/task/thread_pool.h" #include "base/time/default_clock.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" +#include "chrome/common/chrome_paths.h" #include "components/crash/content/browser/error_reporting/javascript_error_report.h" #include "components/crash/core/app/client_upload_info.h" +#include "components/crash/core/app/crashpad.h" #include "components/feedback/redaction_tool.h" #include "components/startup_metric_utils/browser/startup_metric_utils.h" +#include "components/upload_list/crash_upload_list.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -100,17 +105,58 @@ : clock_(base::DefaultClock::GetInstance()) {} ChromeJsErrorReportProcessor::~ChromeJsErrorReportProcessor() = default; +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +void ChromeJsErrorReportProcessor::UpdateReportDatabase( + std::string remote_report_id, + base::Time report_time) { + // Uploads.log format is "seconds_since_epoch,crash_id\n" + base::FilePath crash_dir_path; + if (!base::PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dir_path)) { + VLOG(1) << "Nowhere to write uploads.log"; + return; + } + base::FilePath upload_log_path = + crash_dir_path.AppendASCII(CrashUploadList::kReporterLogFilename); + base::File upload_log(upload_log_path, + base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND); + if (!upload_log.IsValid()) { + VLOG(1) << "Could not open upload.log: " + << base::File::ErrorToString(upload_log.error_details()); + return; + } + std::string line = base::StrCat({base::NumberToString(report_time.ToTimeT()), + ",", remote_report_id, "\n"}); + // WriteAtCurrentPos because O_APPEND. + if (upload_log.WriteAtCurrentPos(line.c_str(), line.length()) != + static_cast<int>(line.length())) { + VLOG(1) << "Could not write to upload.log"; + return; + } +} +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + void ChromeJsErrorReportProcessor::OnRequestComplete( std::unique_ptr<network::SimpleURLLoader> url_loader, base::ScopedClosureRunner callback_runner, + base::Time report_time, std::unique_ptr<std::string> response_body) { if (response_body) { - // TODO(iby): Update the crash log (uploads.log) VLOG(1) << "Uploaded crash report. ID: " << *response_body; + // On Chrome OS, we use a different format than other platforms. Since we + // will soon not call this function at all on Chrome OS (crbug.com/986166), + // don't bother writing code to write to that format. +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + base::ThreadPool::PostTaskAndReply( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&ChromeJsErrorReportProcessor::UpdateReportDatabase, + this, *response_body, report_time), + callback_runner.Release()); +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) } else { LOG(ERROR) << "Failed to upload crash report"; } - // callback_runner will implicitly run the callback when we reach this line. + // callback_runner may implicitly run the callback when we reach this line if + // we didn't add a task to update the report database. } // Returns the redacted, fixed-up error report if the user consented to have it @@ -166,6 +212,7 @@ const GURL& url, const std::string& body, base::ScopedClosureRunner callback_runner, + base::Time report_time, network::SharedURLLoaderFactory* loader_factory) { auto resource_request = std::make_unique<network::ResourceRequest>(); resource_request->method = "POST"; @@ -220,7 +267,8 @@ loader->DownloadToString( loader_factory, base::BindOnce(&ChromeJsErrorReportProcessor::OnRequestComplete, this, - std::move(url_loader), std::move(callback_runner)), + std::move(url_loader), std::move(callback_runner), + report_time), kCrashEndpointResponseMaxSizeInBytes); } @@ -229,6 +277,7 @@ base::ScopedClosureRunner callback_runner, scoped_refptr<network::SharedURLLoaderFactory> loader_factory, base::TimeDelta browser_process_uptime, + base::Time report_time, base::Optional<JavaScriptErrorReport> error_report) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!error_report) { @@ -292,7 +341,8 @@ body = std::move(*error_report->stack_trace); } - SendReport(url, body, std::move(callback_runner), loader_factory.get()); + SendReport(url, body, std::move(callback_runner), report_time, + loader_factory.get()); } void ChromeJsErrorReportProcessor::CheckAndUpdateRecentErrorReports( @@ -417,7 +467,8 @@ std::move(error_report)), base::BindOnce(&ChromeJsErrorReportProcessor::OnConsentCheckCompleted, this, std::move(callback_runner), - std::move(loader_factory), browser_process_uptime)); + std::move(loader_factory), browser_process_uptime, + clock_->Now())); } std::string ChromeJsErrorReportProcessor::GetCrashEndpoint() {
diff --git a/chrome/browser/error_reporting/chrome_js_error_report_processor.h b/chrome/browser/error_reporting/chrome_js_error_report_processor.h index bf1cb2d9..1ac534e 100644 --- a/chrome/browser/error_reporting/chrome_js_error_report_processor.h +++ b/chrome/browser/error_reporting/chrome_js_error_report_processor.h
@@ -15,6 +15,7 @@ #include "base/containers/flat_map.h" #include "base/time/clock.h" #include "base/time/time.h" +#include "build/chromeos_buildflags.h" #include "components/crash/content/browser/error_reporting/js_error_report_processor.h" namespace content { @@ -68,11 +69,20 @@ int32_t& os_minor_version, int32_t& os_bugfix_version); +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + // Update the uploads.log file with a record of this error report. This + // ensures that the error appears on chrome://crashes and is listed in the + // feedback reports. + virtual void UpdateReportDatabase(std::string remote_report_id, + base::Time report_time); +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + private: struct PlatformInfo; void OnRequestComplete(std::unique_ptr<network::SimpleURLLoader> url_loader, base::ScopedClosureRunner callback_runner, + base::Time report_time, std::unique_ptr<std::string> response_body); base::Optional<JavaScriptErrorReport> CheckConsentAndRedact( @@ -83,12 +93,14 @@ void SendReport(const GURL& url, const std::string& body, base::ScopedClosureRunner callback_runner, + base::Time report_time, network::SharedURLLoaderFactory* loader_factory); void OnConsentCheckCompleted( base::ScopedClosureRunner callback_runner, scoped_refptr<network::SharedURLLoaderFactory> loader_factory, base::TimeDelta browser_process_uptime, + base::Time report_time, base::Optional<JavaScriptErrorReport> error_report); // To avoid spamming the error collection system, do not send duplicate
diff --git a/chrome/browser/error_reporting/chrome_js_error_report_processor_unittest.cc b/chrome/browser/error_reporting/chrome_js_error_report_processor_unittest.cc index 0be985020..6df0d6d9 100644 --- a/chrome/browser/error_reporting/chrome_js_error_report_processor_unittest.cc +++ b/chrome/browser/error_reporting/chrome_js_error_report_processor_unittest.cc
@@ -9,12 +9,18 @@ #include "base/callback.h" #include "base/callback_helpers.h" +#include "base/strings/strcat.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/simple_test_clock.h" #include "build/build_config.h" +#include "chrome/browser/crash_upload_list/crash_upload_list.h" #include "chrome/browser/error_reporting/mock_chrome_js_error_report_processor.h" +#include "chrome/common/chrome_paths.h" #include "chrome/test/base/testing_profile.h" #include "components/crash/content/browser/error_reporting/javascript_error_report.h" #include "components/crash/content/browser/error_reporting/mock_crash_endpoint.h" +#include "components/crash/core/app/crashpad.h" +#include "components/upload_list/upload_list.h" #include "content/public/test/browser_task_environment.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gmock/include/gmock/gmock.h" @@ -38,7 +44,7 @@ void SetUp() override { // Set clock to something arbitrary which is not the null value. - test_clock_.SetNow(base::Time::FromTimeT(1586581472)); + test_clock_.SetNow(base::Time::FromTimeT(kFakeNow)); test_server_ = std::make_unique<net::test_server::EmbeddedTestServer>(); endpoint_ = std::make_unique<MockCrashEndpoint>(test_server_.get()); processor_->SetCrashEndpoint(endpoint_->GetCrashEndpointURL()); @@ -73,6 +79,7 @@ bool finish_callback_was_called_ = false; scoped_refptr<MockChromeJsErrorReportProcessor> processor_; + static constexpr time_t kFakeNow = 1586581472; static constexpr char kFirstMessage[] = "An Error Is Me"; static constexpr char kFirstMessageQuery[] = "error_message=An%20Error%20Is%20Me"; @@ -85,6 +92,7 @@ static constexpr char kSecondProduct[] = "Chrome_Linux"; }; +constexpr time_t ChromeJsErrorReportProcessorTest::kFakeNow; constexpr char ChromeJsErrorReportProcessorTest::kFirstMessage[]; constexpr char ChromeJsErrorReportProcessorTest::kFirstMessageQuery[]; constexpr char ChromeJsErrorReportProcessorTest::kSecondMessage[]; @@ -421,3 +429,82 @@ SendErrorReport(std::move(report3)); EXPECT_EQ(endpoint_->report_count(), 3); } + +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +static std::string UploadInfoStateToString( + UploadList::UploadInfo::State state) { + switch (state) { + case UploadList::UploadInfo::State::NotUploaded: + return "NotUploaded"; + case UploadList::UploadInfo::State::Pending: + return "Pending"; + case UploadList::UploadInfo::State::Pending_UserRequested: + return "Pending_UserRequested"; + case UploadList::UploadInfo::State::Uploaded: + return "Uploaded"; + default: + return base::StrCat({"Unknown upload state ", + base::NumberToString(static_cast<int>(state))}); + } +} + +static std::string UploadInfoVectorToString( + const std::vector<UploadList::UploadInfo>& uploads) { + std::string result = "["; + bool first = true; + for (const UploadList::UploadInfo& upload : uploads) { + if (first) { + first = false; + } else { + result += ", "; + } + base::StrAppend(&result, + {"{state ", UploadInfoStateToString(upload.state), + ", upload_id ", upload.upload_id, ", upload_time ", + base::NumberToString(upload.upload_time.ToTimeT()), + ", local_id ", upload.local_id, ", capture_time ", + base::NumberToString(upload.capture_time.ToTimeT()), + ", source ", upload.source, ", file size ", + base::UTF16ToUTF8(upload.file_size), "}"}); + } + result += "]"; + return result; +} + +TEST_F(ChromeJsErrorReportProcessorTest, UpdatesUploadsLog) { + if (crash_reporter::IsCrashpadEnabled()) { + // TODO(crbug.com/1162356): Combine uploads.log with Crashpad database when + // getting list of crashes. + GTEST_SKIP(); + } + + base::ScopedPathOverride crash_dir_override(chrome::DIR_CRASH_DUMPS); + processor_->set_update_report_database(true); + + constexpr char kCrashId[] = "123abc456def"; + endpoint_->set_response(net::HTTP_OK, kCrashId); + + SendErrorReport(MakeErrorReport(kFirstMessage)); + EXPECT_EQ(endpoint_->report_count(), 1); + + auto upload_list = CreateCrashUploadList(); + base::RunLoop run_loop; + upload_list->Load(run_loop.QuitClosure()); + run_loop.Run(); + std::vector<UploadList::UploadInfo> uploads; + upload_list->GetUploads(50, &uploads); + EXPECT_EQ(uploads.size(), 1U) << UploadInfoVectorToString(uploads); + + bool found = false; + for (const UploadList::UploadInfo& upload : uploads) { + if (upload.state == UploadList::UploadInfo::State::Uploaded && + upload.upload_id == kCrashId) { + EXPECT_FALSE(found) << "Found twice"; + found = true; + EXPECT_EQ(upload.upload_time.ToTimeT(), kFakeNow); + } + } + EXPECT_TRUE(found) << "Didn't find upload record in " + << UploadInfoVectorToString(uploads); +} +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.cc b/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.cc index 0f155c82..69ecc89c 100644 --- a/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.cc +++ b/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.cc
@@ -9,6 +9,7 @@ #include "components/crash/content/browser/error_reporting/mock_crash_endpoint.h" MockChromeJsErrorReportProcessor::MockChromeJsErrorReportProcessor() = default; + MockChromeJsErrorReportProcessor::~MockChromeJsErrorReportProcessor() = default; void MockChromeJsErrorReportProcessor::SetAsDefault() { @@ -50,6 +51,17 @@ os_bugfix_version = 1; } +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) +void MockChromeJsErrorReportProcessor::UpdateReportDatabase( + std::string remote_report_id, + base::Time report_time) { + if (update_report_database_) { + ChromeJsErrorReportProcessor::UpdateReportDatabase( + std::move(remote_report_id), report_time); + } +} +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + ScopedMockChromeJsErrorReportProcessor::ScopedMockChromeJsErrorReportProcessor( const MockCrashEndpoint& endpoint) : processor_(base::MakeRefCounted<MockChromeJsErrorReportProcessor>()),
diff --git a/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.h b/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.h index 0925989a..ca84262 100644 --- a/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.h +++ b/chrome/browser/error_reporting/mock_chrome_js_error_report_processor.h
@@ -7,9 +7,12 @@ #include <stdint.h> +#include <memory> #include <string> #include "base/memory/scoped_refptr.h" +#include "base/test/scoped_path_override.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/error_reporting/chrome_js_error_report_processor.h" class MockCrashEndpoint; @@ -31,6 +34,17 @@ // return the given (other) JsErrorReportProcessor. static void SetDefaultTo(scoped_refptr<JsErrorReportProcessor> new_default); +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + // By default, a MockChromeJsErrorReportProcessor will suppress the updating + // of the crash database (a.k.a. uploads.log) to avoid contaminating the real + // database with test uploads. Set |update_report_database| to true to have + // ChromeJsErrorReportProcessor::UpdateReportDatabase called like it normally + // would be. + void set_update_report_database(bool update_report_database) { + update_report_database_ = update_report_database; + } +#endif + protected: std::string GetCrashEndpoint() override; std::string GetCrashEndpointStaging() override; @@ -40,10 +54,18 @@ int32_t& os_minor_version, int32_t& os_bugfix_version) override; +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + void UpdateReportDatabase(std::string remote_report_id, + base::Time report_time) override; +#endif + private: ~MockChromeJsErrorReportProcessor() override; std::string crash_endpoint_; std::string crash_endpoint_staging_; +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) + bool update_report_database_ = false; +#endif }; // Wrapper for MockChromeJsErrorReportProcessor. Will automatically create, set @@ -63,6 +85,8 @@ // JsErrorReportProcessor::Get() will return nullptr. ~ScopedMockChromeJsErrorReportProcessor(); + MockChromeJsErrorReportProcessor& processor() const { return *processor_; } + private: scoped_refptr<MockChromeJsErrorReportProcessor> processor_; scoped_refptr<JsErrorReportProcessor> previous_;
diff --git a/chrome/browser/extensions/extension_webkit_preferences.cc b/chrome/browser/extensions/extension_webkit_preferences.cc index 4155812..4a11471 100644 --- a/chrome/browser/extensions/extension_webkit_preferences.cc +++ b/chrome/browser/extensions/extension_webkit_preferences.cc
@@ -34,6 +34,8 @@ webkit_prefs->local_storage_enabled = false; webkit_prefs->sync_xhr_in_documents_enabled = false; webkit_prefs->cookie_enabled = false; + webkit_prefs->target_blank_implies_no_opener_enabled_will_be_removed = + false; } // Enable WebGL features that regular pages can't access, since they add
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index aa12241..84cee16 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -450,7 +450,7 @@ { "name": "calculate-native-win-occlusion", "owners": [ "davidbienvenu", "fdoray" ], - "expiry_milestone": 88 + "expiry_milestone": 92 }, { "name": "camera-system-web-app",
diff --git a/chrome/browser/lacros/crosapi_pref_observer.cc b/chrome/browser/lacros/crosapi_pref_observer.cc new file mode 100644 index 0000000..3fc83f1d --- /dev/null +++ b/chrome/browser/lacros/crosapi_pref_observer.cc
@@ -0,0 +1,26 @@ +// 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/lacros/crosapi_pref_observer.h" + +#include "base/callback.h" +#include "chromeos/lacros/lacros_chrome_service_impl.h" + +CrosapiPrefObserver::CrosapiPrefObserver(crosapi::mojom::PrefPath path, + PrefChangedCallback callback) + : callback_(std::move(callback)) { + auto* lacros_service = chromeos::LacrosChromeServiceImpl::Get(); + if (!lacros_service->IsPrefsAvailable()) { + LOG(WARNING) << "crosapi: Prefs API not available"; + return; + } + lacros_service->prefs_remote()->AddObserver( + path, receiver_.BindNewPipeAndPassRemote()); +} + +CrosapiPrefObserver::~CrosapiPrefObserver() = default; + +void CrosapiPrefObserver::OnPrefChanged(base::Value value) { + callback_.Run(std::move(value)); +}
diff --git a/chrome/browser/lacros/crosapi_pref_observer.h b/chrome/browser/lacros/crosapi_pref_observer.h new file mode 100644 index 0000000..79a8a41 --- /dev/null +++ b/chrome/browser/lacros/crosapi_pref_observer.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 CHROME_BROWSER_LACROS_CROSAPI_PREF_OBSERVER_H_ +#define CHROME_BROWSER_LACROS_CROSAPI_PREF_OBSERVER_H_ + +#include "base/callback_forward.h" +#include "base/gtest_prod_util.h" +#include "base/values.h" +#include "chromeos/crosapi/mojom/prefs.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" + +// Helper to simplify the crosapi::mojom::PrefObserver API. +// Observes ash-chrome for changes in specified pref. +class CrosapiPrefObserver : public crosapi::mojom::PrefObserver { + public: + using PrefChangedCallback = base::RepeatingCallback<void(base::Value value)>; + + CrosapiPrefObserver(crosapi::mojom::PrefPath path, + PrefChangedCallback callback); + CrosapiPrefObserver(const CrosapiPrefObserver&) = delete; + CrosapiPrefObserver& operator=(const CrosapiPrefObserver&) = delete; + ~CrosapiPrefObserver() override; + + private: + FRIEND_TEST_ALL_PREFIXES(CrosapiPrefObserverLacrosBrowserTest, Basics); + + // crosapi::mojom::PrefObserver: + void OnPrefChanged(base::Value value) override; + + PrefChangedCallback callback_; + + // Receives mojo messages from ash. + mojo::Receiver<crosapi::mojom::PrefObserver> receiver_{this}; +}; + +#endif // CHROME_BROWSER_LACROS_CROSAPI_PREF_OBSERVER_H_
diff --git a/chrome/browser/lacros/crosapi_pref_observer_lacros_browsertest.cc b/chrome/browser/lacros/crosapi_pref_observer_lacros_browsertest.cc new file mode 100644 index 0000000..801294a --- /dev/null +++ b/chrome/browser/lacros/crosapi_pref_observer_lacros_browsertest.cc
@@ -0,0 +1,46 @@ +// 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 "base/run_loop.h" +#include "base/test/bind.h" +#include "base/values.h" +#include "chrome/browser/lacros/crosapi_pref_observer.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" + +using CrosapiPrefObserverLacrosBrowserTest = InProcessBrowserTest; + +// Tests multiple observers reading ash::kAccessibilitySpokenFeedbackEnabled. +// TODO(crbug.com/1157314): Not safe to run with other test since this assumes +// the pref is false and does not change during test. +IN_PROC_BROWSER_TEST_F(CrosapiPrefObserverLacrosBrowserTest, Basics) { + // Register an observer. + bool value1 = true; + base::RunLoop run_loop1; + CrosapiPrefObserver observer1( + crosapi::mojom::PrefPath::kAccessibilitySpokenFeedbackEnabled, + base::BindLambdaForTesting([&](base::Value value) { + value1 = value.GetBool(); + run_loop1.Quit(); + })); + run_loop1.Run(); + EXPECT_FALSE(value1); + + // Additional observers are OK. + bool value2 = true; + base::RunLoop run_loop2; + CrosapiPrefObserver observer2( + crosapi::mojom::PrefPath::kAccessibilitySpokenFeedbackEnabled, + base::BindLambdaForTesting([&](base::Value value) { + value2 = value.GetBool(); + run_loop2.Quit(); + })); + run_loop2.Run(); + EXPECT_FALSE(value2); + + // OnPrefChanged should fire callback. + observer1.OnPrefChanged(base::Value(true)); + EXPECT_TRUE(value1); + EXPECT_FALSE(value2); +}
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc index 6a199dc0..c964d00 100644 --- a/chrome/browser/lifetime/browser_close_manager_browsertest.cc +++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -398,11 +398,16 @@ // Test that the tab closed after the aborted shutdown attempt is not re-opened // when restoring the session. -// Flaky on Windows trybots, see https://crbug.com/737860. // Flaky on chromium.chromeos, chromium.linux, and chromium.mac bots. See -// https://crbug.com/1145235. +// https://crbug.com/1145235. It was flaky on Windows, but crrev.com/c/2559156, +// which added retries to ReplaceFile, should fix the Windows flakiness. +#if defined(OS_WIN) +#define MAYBE_TestSessionRestore TestSessionRestore +#else +#define MAYBE_TestSessionRestore DISABLED_TestSessionRestore +#endif IN_PROC_BROWSER_TEST_F(BrowserCloseManagerBrowserTest, - DISABLED_TestSessionRestore) { + MAYBE_TestSessionRestore) { // The testing framework launches Chrome with about:blank as args. EXPECT_EQ(2, browser()->tab_strip_model()->count()); EXPECT_EQ(GURL(chrome::kChromeUIVersionURL),
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc index 73d21d4..f5df625 100644 --- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc +++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/optimization_guide/optimization_guide_hints_manager.h" #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h" #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" -#include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" #include "chrome/browser/optimization_guide/optimization_guide_top_host_provider.h" #include "chrome/browser/optimization_guide/prediction/prediction_manager.h" #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc index ed87a42..5f0d201 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -13,6 +13,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros_local.h" +#include "base/path_service.h" #include "base/rand_util.h" #include "base/sequence_checker.h" #include "base/sequenced_task_runner.h" @@ -21,14 +22,14 @@ #include "base/task/thread_pool.h" #include "base/time/default_clock.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" #include "chrome/browser/optimization_guide/optimization_guide_permissions_util.h" -#include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" #include "chrome/browser/optimization_guide/prediction/prediction_model_download_manager.h" -#include "chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h" -#include "chrome/browser/optimization_guide/prediction/prediction_model_file.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_key.h" +#include "chrome/common/chrome_paths.h" #include "components/optimization_guide/content/optimization_guide_decider.h" #include "components/optimization_guide/core/optimization_guide_constants.h" #include "components/optimization_guide/core/optimization_guide_enums.h" @@ -38,11 +39,14 @@ #include "components/optimization_guide/core/optimization_guide_switches.h" #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/core/prediction_model.h" +#include "components/optimization_guide/core/prediction_model_fetcher.h" +#include "components/optimization_guide/core/prediction_model_file.h" #include "components/optimization_guide/core/store_update_data.h" #include "components/optimization_guide/core/top_host_provider.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/prefs/pref_service.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/web_contents.h" #include "mojo/public/cpp/bindings/remote.h" @@ -228,13 +232,7 @@ Profile* profile) : host_model_features_cache_( std::max(features::MaxHostModelFeaturesCacheSize(), size_t(1))), - prediction_model_download_manager_( - features::IsModelDownloadingEnabled() - ? std::make_unique<PredictionModelDownloadManager>( - profile, - base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT})) - : nullptr), + prediction_model_download_manager_(nullptr), top_host_provider_(top_host_provider), model_and_features_store_(model_and_features_store), url_loader_factory_(url_loader_factory), @@ -242,8 +240,20 @@ profile_(profile), clock_(base::DefaultClock::GetInstance()) { DCHECK(model_and_features_store_); - if (prediction_model_download_manager_) + + if (features::IsModelDownloadingEnabled()) { + base::FilePath models_dir; + base::PathService::Get(chrome::DIR_OPTIMIZATION_GUIDE_PREDICTION_MODELS, + &models_dir); + prediction_model_download_manager_ = + std::make_unique<PredictionModelDownloadManager>( + DownloadServiceFactory::GetForKey(profile->GetProfileKey()), + models_dir, + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT})); prediction_model_download_manager_->AddObserver(this); + } + Initialize(); } @@ -645,7 +655,8 @@ if (!prediction_model_fetcher_) { prediction_model_fetcher_ = std::make_unique<PredictionModelFetcher>( url_loader_factory_, - features::GetOptimizationGuideServiceGetModelsURL()); + features::GetOptimizationGuideServiceGetModelsURL(), + content::GetNetworkConnectionTracker()); } std::vector<proto::ModelInfo> models_info = std::vector<proto::ModelInfo>();
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.h b/chrome/browser/optimization_guide/prediction/prediction_manager.h index 43aca7b..49b1f73 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager.h +++ b/chrome/browser/optimization_guide/prediction/prediction_manager.h
@@ -18,9 +18,9 @@ #include "base/sequence_checker.h" #include "base/time/clock.h" #include "base/timer/timer.h" -#include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" #include "chrome/browser/optimization_guide/prediction/prediction_model_download_observer.h" #include "components/optimization_guide/core/optimization_guide_enums.h" +#include "components/optimization_guide/core/optimization_guide_session_statistic.h" #include "components/optimization_guide/proto/models.pb.h" #include "services/network/public/cpp/network_quality_tracker.h" #include "url/origin.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc index eaa05a1..5b72b41 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h" #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h" -#include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" #include "chrome/browser/optimization_guide/prediction/prediction_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" @@ -26,6 +25,7 @@ #include "components/metrics/content/subprocess_metrics_provider.h" #include "components/optimization_guide/core/optimization_guide_constants.h" #include "components/optimization_guide/core/optimization_guide_features.h" +#include "components/optimization_guide/core/optimization_guide_session_statistic.h" #include "components/optimization_guide/core/optimization_guide_store.h" #include "components/optimization_guide/core/optimization_guide_switches.h" #include "components/optimization_guide/core/optimization_guide_test_util.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc index 5f9847dc..f1dd17a 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h" #include "chrome/browser/optimization_guide/optimization_guide_web_contents_observer.h" #include "chrome/browser/optimization_guide/prediction/prediction_model_download_manager.h" -#include "chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h" #include "chrome/services/machine_learning/public/cpp/test_support/fake_service_connection.h" #include "chrome/services/machine_learning/public/mojom/decision_tree.mojom.h" #include "chrome/test/base/testing_profile.h" @@ -30,6 +29,7 @@ #include "components/optimization_guide/core/optimization_guide_switches.h" #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/core/prediction_model.h" +#include "components/optimization_guide/core/prediction_model_fetcher.h" #include "components/optimization_guide/core/proto_database_provider_test_base.h" #include "components/optimization_guide/core/top_host_provider.h" #include "components/optimization_guide/proto/hint_cache.pb.h" @@ -41,6 +41,7 @@ #include "content/public/test/web_contents_tester.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_network_connection_tracker.h" #include "services/network/test/test_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/page_transition_types.h" @@ -193,9 +194,10 @@ : public PredictionModelDownloadManager { public: FakePredictionModelDownloadManager( - Profile* profile, scoped_refptr<base::SequencedTaskRunner> task_runner) - : PredictionModelDownloadManager(profile, task_runner) {} + : PredictionModelDownloadManager(/*download_service=*/nullptr, + base::FilePath(), + task_runner) {} ~FakePredictionModelDownloadManager() override = default; void StartDownload(const GURL& url) override { @@ -230,10 +232,12 @@ public: TestPredictionModelFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - GURL optimization_guide_service_get_models_url, + const GURL& optimization_guide_service_get_models_url, + network::NetworkConnectionTracker* network_connection_tracker, PredictionModelFetcherEndState fetch_state) : PredictionModelFetcher(url_loader_factory, - optimization_guide_service_get_models_url), + optimization_guide_service_get_models_url, + network_connection_tracker), fetch_state_(fetch_state) {} bool FetchOptimizationGuideServiceModels( @@ -539,7 +543,8 @@ PredictionModelFetcherEndState end_state) { std::unique_ptr<TestPredictionModelFetcher> prediction_model_fetcher = std::make_unique<TestPredictionModelFetcher>( - url_loader_factory_, GURL("https://hintsserver.com"), end_state); + url_loader_factory_, GURL("https://hintsserver.com"), + network::TestNetworkConnectionTracker::GetInstance(), end_state); return prediction_model_fetcher; } @@ -1178,7 +1183,7 @@ PredictionModelFetcherEndState::kFetchSuccessWithModelDownloadUrls)); prediction_manager()->SetPredictionModelDownloadManagerForTesting( std::make_unique<FakePredictionModelDownloadManager>( - profile(), task_environment()->GetMainThreadTaskRunner())); + task_environment()->GetMainThreadTaskRunner())); prediction_model_download_manager()->SetAvailableForDownloads(false); prediction_manager()->RegisterOptimizationTargets( @@ -1208,7 +1213,7 @@ PredictionModelFetcherEndState::kFetchSuccessWithModelDownloadUrls)); prediction_manager()->SetPredictionModelDownloadManagerForTesting( std::make_unique<FakePredictionModelDownloadManager>( - profile(), task_environment()->GetMainThreadTaskRunner())); + task_environment()->GetMainThreadTaskRunner())); prediction_manager()->RegisterOptimizationTargets( {proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD});
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc index ad08f8b10..c1c8d854 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc
@@ -8,18 +8,13 @@ #include "base/files/file_util.h" #include "base/guid.h" #include "base/metrics/histogram_functions.h" -#include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "build/build_config.h" -#include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/optimization_guide/prediction/prediction_model_download_observer.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_key.h" -#include "chrome/common/chrome_paths.h" #include "components/crx_file/crx_verifier.h" #include "components/download/public/background_service/download_service.h" #include "components/optimization_guide/core/optimization_guide_enums.h" @@ -28,8 +23,6 @@ #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/services/unzip/content/unzip_service.h" #include "components/services/unzip/public/cpp/unzip.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace optimization_guide { @@ -76,11 +69,9 @@ base_name_value == kModelInfoFileName; } -base::FilePath GetFilePathForModelInfo(const proto::ModelInfo& model_info) { - base::FilePath models_dir; - base::PathService::Get(chrome::DIR_OPTIMIZATION_GUIDE_PREDICTION_MODELS, - &models_dir); - return models_dir.AppendASCII(base::StringPrintf( +base::FilePath GetFilePathForModelInfo(const base::FilePath& dir, + const proto::ModelInfo& model_info) { + return dir.AppendASCII(base::StringPrintf( "%s_%s.tflite", proto::OptimizationTarget_Name(model_info.optimization_target()).c_str(), base::NumberToString(model_info.version()).c_str())); @@ -96,10 +87,11 @@ } // namespace PredictionModelDownloadManager::PredictionModelDownloadManager( - Profile* profile, + download::DownloadService* download_service, + const base::FilePath& models_dir, scoped_refptr<base::SequencedTaskRunner> background_task_runner) - : download_service_( - DownloadServiceFactory::GetForKey(profile->GetProfileKey())), + : download_service_(download_service), + models_dir_(models_dir), is_available_for_downloads_(true), api_key_(features::GetOptimizationGuideServiceAPIKey()), background_task_runner_(background_task_runner) {} @@ -152,14 +144,14 @@ void PredictionModelDownloadManager::AddObserver( PredictionModelDownloadObserver* observer) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); observers_.AddObserver(observer); } void PredictionModelDownloadManager::RemoveObserver( PredictionModelDownloadObserver* observer) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); observers_.RemoveObserver(observer); } @@ -250,7 +242,7 @@ void PredictionModelDownloadManager::StartUnzipping( const base::Optional<std::pair<base::FilePath, base::FilePath>>& unzip_paths) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!unzip_paths) return; @@ -267,7 +259,7 @@ const base::FilePath& original_file_path, const base::FilePath& unzipped_dir_path, bool success) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Clean up original download file when this function finishes. background_task_runner_->PostTask( @@ -320,7 +312,7 @@ // Move model file away from temp directory. base::FilePath temp_model_path = unzipped_dir_path.Append(kModelFileName); - base::FilePath model_path = GetFilePathForModelInfo(model_info); + base::FilePath model_path = GetFilePathForModelInfo(models_dir_, model_info); base::File::Error file_error; if (!base::ReplaceFile(temp_model_path, model_path, &file_error)) { if (file_error == base::File::FILE_ERROR_NOT_FOUND) { @@ -343,7 +335,7 @@ void PredictionModelDownloadManager::NotifyModelReady( const base::Optional<proto::PredictionModel>& model) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!model) return;
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.h b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.h index e846615..405c92a 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.h +++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager.h
@@ -13,8 +13,6 @@ #include "base/observer_list.h" #include "components/download/public/background_service/download_params.h" -class Profile; - namespace download { class DownloadService; } // namespace download @@ -32,7 +30,8 @@ class PredictionModelDownloadManager { public: PredictionModelDownloadManager( - Profile* profile, + download::DownloadService* download_service, + const base::FilePath& models_dir, scoped_refptr<base::SequencedTaskRunner> background_task_runner); virtual ~PredictionModelDownloadManager(); PredictionModelDownloadManager(const PredictionModelDownloadManager&) = @@ -124,6 +123,9 @@ // Guaranteed to outlive |this|. download::DownloadService* download_service_; + // The directory to store verified models in. + base::FilePath models_dir_; + // Whether the download service is available. bool is_available_for_downloads_; @@ -139,6 +141,10 @@ // Background thread where download file processing should be performed. scoped_refptr<base::SequencedTaskRunner> background_task_runner_; + // Sequence checker used to verify all public API methods are called on the + // UI thread. + SEQUENCE_CHECKER(sequence_checker_); + // Used to get weak ptr to self on the UI thread. base::WeakPtrFactory<PredictionModelDownloadManager> ui_weak_ptr_factory_{ this};
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc index 32df535..b89fcc4 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
@@ -8,17 +8,14 @@ #include "base/files/scoped_temp_dir.h" #include "base/optional.h" #include "base/path_service.h" +#include "base/sequence_checker.h" #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" -#include "base/test/scoped_path_override.h" +#include "base/test/task_environment.h" #include "build/build_config.h" -#include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/optimization_guide/prediction/prediction_model_download_observer.h" -#include "chrome/browser/profiles/profile_key.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/download/public/background_service/test/mock_download_service.h" #include "components/optimization_guide/core/optimization_guide_enums.h" #include "components/optimization_guide/core/optimization_guide_features.h" @@ -62,41 +59,26 @@ kUnverifiedFile, }; -class PredictionModelDownloadManagerTest - : public ChromeRenderViewHostTestHarness { +class PredictionModelDownloadManagerTest : public testing::Test { public: PredictionModelDownloadManagerTest() = default; ~PredictionModelDownloadManagerTest() override = default; void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - mock_download_service_ = static_cast<download::test::MockDownloadService*>( - DownloadServiceFactory::GetInstance()->SetTestingFactoryAndUse( - profile()->GetProfileKey(), - base::BindRepeating([](SimpleFactoryKey* key) - -> std::unique_ptr<KeyedService> { - return std::make_unique<download::test::MockDownloadService>(); - }))); + mock_download_service_ = + std::make_unique<download::test::MockDownloadService>(); download_manager_ = std::make_unique<PredictionModelDownloadManager>( - profile(), task_environment()->GetMainThreadTaskRunner()); + mock_download_service_.get(), temp_dir_.GetPath(), + task_environment_.GetMainThreadTaskRunner()); unzip::SetUnzipperLaunchOverrideForTesting( base::BindRepeating(&unzip::LaunchInProcessUnzipper)); - - path_override_ = std::make_unique<base::ScopedPathOverride>( - chrome::DIR_OPTIMIZATION_GUIDE_PREDICTION_MODELS, temp_dir_.GetPath(), - /*is_absolute=*/true, - /*create=*/false); } void TearDown() override { download_manager_.reset(); mock_download_service_ = nullptr; - path_override_.reset(); - - ChromeRenderViewHostTestHarness::TearDown(); } PredictionModelDownloadManager* download_manager() { @@ -104,7 +86,7 @@ } download::test::MockDownloadService* download_service() { - return mock_download_service_; + return mock_download_service_.get(); } protected: @@ -137,7 +119,7 @@ } void RunUntilIdle() { - task_environment()->RunUntilIdle(); + task_environment_.RunUntilIdle(); // Wait for all delayed tasks to finish. base::RunLoop run_loop; @@ -221,9 +203,9 @@ zip::Zip(zip_dir, GetFilePathForDownloadFileStatus(status), true)); } + base::test::TaskEnvironment task_environment_; base::ScopedTempDir temp_dir_; - std::unique_ptr<base::ScopedPathOverride> path_override_; - download::test::MockDownloadService* mock_download_service_; + std::unique_ptr<download::test::MockDownloadService> mock_download_service_; std::unique_ptr<PredictionModelDownloadManager> download_manager_; };
diff --git a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.cc index 481bb7a6..1a94f922 100644 --- a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.cc
@@ -43,6 +43,14 @@ } page_load_metrics::PageLoadMetricsObserver::ObservePolicy +TranslatePageLoadMetricsObserver::OnCommit( + content::NavigationHandle* navigation_handle, + ukm::SourceId source_id) { + translate_metrics_logger_->SetUkmSourceId(source_id); + return CONTINUE_OBSERVING; +} + +page_load_metrics::PageLoadMetricsObserver::ObservePolicy TranslatePageLoadMetricsObserver::OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) { translate_metrics_logger_->OnForegroundChange(false);
diff --git a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.h index c4902b6..608e954 100644 --- a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer.h
@@ -41,6 +41,8 @@ ObservePolicy OnStart(content::NavigationHandle* navigation_handle, const GURL& currently_committed_url, bool started_in_foreground) override; + ObservePolicy OnCommit(content::NavigationHandle* navigation_handle, + ukm::SourceId source_id) override; ObservePolicy OnHidden( const page_load_metrics::mojom::PageLoadTiming& timing) override; ObservePolicy OnShown() override;
diff --git a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc index c6a623e..1c94ce8 100644 --- a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc
@@ -34,6 +34,10 @@ mock_translate_metrics_logger_->RecordMetrics(is_final); } + void SetUkmSourceId(ukm::SourceId ukm_source_id) override { + mock_translate_metrics_logger_->SetUkmSourceId(ukm_source_id); + } + void LogRankerMetrics(translate::RankerDecision ranker_decision, uint32_t ranker_version) override { mock_translate_metrics_logger_->LogRankerMetrics(ranker_decision,
diff --git a/chrome/browser/policy/messaging_layer/encryption/decryption.cc b/chrome/browser/policy/messaging_layer/encryption/decryption.cc index 0f0ffc6..40cf237 100644 --- a/chrome/browser/policy/messaging_layer/encryption/decryption.cc +++ b/chrome/browser/policy/messaging_layer/encryption/decryption.cc
@@ -152,8 +152,8 @@ " actual=", base::NumberToString(public_key.size())})); } else { // Assign a random number to be public key id for testing purposes - // only (in production it will be Java Fingerprint2011 which is - // 'long'). + // only (in production it will be retrieved from the server as + // 'int32'). Encryptor::PublicKeyId public_key_id; base::RandBytes(&public_key_id, sizeof(public_key_id)); if (!decryptor->keys_.emplace(public_key_id, key_info).second) {
diff --git a/chrome/browser/policy/messaging_layer/public/report_client.cc b/chrome/browser/policy/messaging_layer/public/report_client.cc index e87d29d..70d7589 100644 --- a/chrome/browser/policy/messaging_layer/public/report_client.cc +++ b/chrome/browser/policy/messaging_layer/public/report_client.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/containers/queue.h" +#include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" #include "base/memory/singleton.h" @@ -507,6 +508,15 @@ void ReportingClient::CreateReportQueue( std::unique_ptr<ReportQueueConfiguration> config, CreateReportQueueCallback create_cb) { + if (!IsEncryptedReportingPipelineEnabled()) { + Status not_enabled = Status( + error::FAILED_PRECONDITION, + "The Encrypted Reporting Pipeline is not enabled. Please enable it on " + "the command line using --enable-features=EncryptedReportingPipeline"); + VLOG(1) << not_enabled; + std::move(create_cb).Run(not_enabled); + return; + } auto* instance = GetInstance(); instance->create_request_queue_->Push( CreateReportQueueRequest(std::move(config), std::move(create_cb)), @@ -514,6 +524,15 @@ base::Unretained(instance))); } +// static +bool ReportingClient::IsEncryptedReportingPipelineEnabled() { + return base::FeatureList::IsEnabled(kEncryptedReportingPipeline); +} + +// static +const base::Feature ReportingClient::kEncryptedReportingPipeline{ + "EncryptedReportingPipeline", base::FEATURE_DISABLED_BY_DEFAULT}; + void ReportingClient::OnPushComplete() { init_state_tracker_->GetInitState( base::BindOnce(&ReportingClient::OnInitState, base::Unretained(this)));
diff --git a/chrome/browser/policy/messaging_layer/public/report_client.h b/chrome/browser/policy/messaging_layer/public/report_client.h index 1aac6d9..aae3452 100644 --- a/chrome/browser/policy/messaging_layer/public/report_client.h +++ b/chrome/browser/policy/messaging_layer/public/report_client.h
@@ -9,6 +9,7 @@ #include <utility> #include "base/containers/queue.h" +#include "base/feature_list.h" #include "base/memory/singleton.h" #include "chrome/browser/policy/messaging_layer/public/report_queue.h" #include "chrome/browser/policy/messaging_layer/public/report_queue_configuration.h" @@ -24,6 +25,9 @@ // ReportingClient acts a single point for creating |reporting::ReportQueue|s. // It ensures that all ReportQueues are created with the same storage settings. // +// In order to utilize the ReportingClient the EncryptedReportingPipeline +// feature must be turned on using --enable-features=EncryptedReportingPipeline. +// // Example Usage: // void SendMessage(google::protobuf::ImportantMessage important_message, // reporting::ReportQueue::EnqueueCallback done_cb) { @@ -211,6 +215,9 @@ std::unique_ptr<ReportQueueConfiguration> config, CreateReportQueueCallback create_cb); + static bool IsEncryptedReportingPipelineEnabled(); + static const base::Feature kEncryptedReportingPipeline; + private: class Uploader;
diff --git a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc index fce944d..e68fca6 100644 --- a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc +++ b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
@@ -7,6 +7,7 @@ #include "base/memory/singleton.h" #include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "chrome/browser/policy/messaging_layer/public/report_queue.h" #include "chrome/browser/policy/messaging_layer/public/report_queue_configuration.h" @@ -94,6 +95,9 @@ policy::DMToken::CreateValidTokenForTesting("FAKE_DM_TOKEN").value()); test_reporting_ = std::make_unique<ReportingClient::TestEnvironment>(client_.get()); + + scoped_feature_list_.InitAndEnableFeature( + ReportingClient::kEncryptedReportingPipeline); } void TearDown() override { @@ -115,6 +119,9 @@ const Destination destination_ = Destination::UPLOAD_EVENTS; ReportQueueConfiguration::PolicyCheckCallback policy_checker_callback_ = base::BindRepeating([]() { return Status::StatusOK(); }); + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; // Tests that a ReportQueue can be created using the ReportingClient.
diff --git a/chrome/browser/prefetch/pref_names.cc b/chrome/browser/prefetch/pref_names.cc new file mode 100644 index 0000000..ede6c972 --- /dev/null +++ b/chrome/browser/prefetch/pref_names.cc
@@ -0,0 +1,26 @@ +// 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/prefetch/pref_names.h" + +namespace prefetch { +namespace prefs { + +// This pref contains a dictionary value whose keys are string representations +// of a URL. The values are a tuple (as a List Value) where the first value is a +// string representation of a URL and a a base::Time. This pref is limited to 10 +// entries in the dictionary. +// The two URLs are not the same URL. +const char kCachePrefPath[] = "prefetch.search_prefetch.cache"; + +// This pref contains a dictionary value whose keys are string representations +// of a url::Origin and values are a base::Time. The recorded base::Time is the +// time at which prefetch requests to the corresponding origin can resume, (any +// base::Time that is in the past can be removed). Entries to the dictionary are +// created when a prefetch request gets a 503 response with Retry-After header. +const char kRetryAfterPrefPath[] = + "chrome.prefetch_proxy.origin_decider.retry_after"; + +} // namespace prefs +} // namespace prefetch
diff --git a/chrome/browser/prefetch/pref_names.h b/chrome/browser/prefetch/pref_names.h new file mode 100644 index 0000000..553d176 --- /dev/null +++ b/chrome/browser/prefetch/pref_names.h
@@ -0,0 +1,18 @@ +// 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_PREFETCH_PREF_NAMES_H_ +#define CHROME_BROWSER_PREFETCH_PREF_NAMES_H_ + +namespace prefetch { +namespace prefs { + +extern const char kCachePrefPath[]; + +extern const char kRetryAfterPrefPath[]; + +} // namespace prefs +} // namespace prefetch + +#endif // CHROME_BROWSER_PREFETCH_PREF_NAMES_H_
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_decider.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_decider.cc index 04c55f6..59e714e9 100644 --- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_decider.cc +++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_decider.cc
@@ -9,26 +9,17 @@ #include "base/metrics/histogram_macros.h" #include "base/util/values/values_util.h" +#include "chrome/browser/prefetch/pref_names.h" #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_params.h" #include "chrome/browser/profiles/profile.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" -namespace { -// This pref contains a dictionary value whose keys are string representations -// of a url::Origin and values are a base::Time. The recorded base::Time is the -// time at which prefetch requests to the corresponding origin can resume, (any -// base::Time that is in the past can be removed). Entries to the dictionary are -// created when a prefetch request gets a 503 response with Retry-After header. -const char kRetryAfterPrefPath[] = - "chrome.prefetch_proxy.origin_decider.retry_after"; -} // namespace - // static void PrefetchProxyOriginDecider::RegisterPrefs(PrefRegistrySimple* registry) { // Some loss in this pref (especially following a browser crash) is well // tolerated and helps ensure the pref service isn't slammed. - registry->RegisterDictionaryPref(kRetryAfterPrefPath, + registry->RegisterDictionaryPref(prefetch::prefs::kRetryAfterPrefPath, PrefRegistry::LOSSY_PREF); } @@ -90,7 +81,7 @@ origin_retry_afters_.clear(); const base::DictionaryValue* dictionary = - pref_service_->GetDictionary(kRetryAfterPrefPath); + pref_service_->GetDictionary(prefetch::prefs::kRetryAfterPrefPath); DCHECK(dictionary); for (const auto& element : *dictionary) { @@ -122,7 +113,7 @@ base::Value value = util::TimeToValue(element.second); dictionary.SetKey(std::move(key), std::move(value)); } - pref_service_->Set(kRetryAfterPrefPath, dictionary); + pref_service_->Set(prefetch::prefs::kRetryAfterPrefPath, dictionary); } bool PrefetchProxyOriginDecider::ClearPastEntries() {
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc index ec5feba..8574f467 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc
@@ -8,8 +8,11 @@ #include "base/callback.h" #include "base/location.h" #include "base/metrics/histogram_macros.h" +#include "base/util/values/values_util.h" +#include "base/values.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/net/prediction_options.h" +#include "chrome/browser/prefetch/pref_names.h" #include "chrome/browser/prefetch/search_prefetch/back_forward_search_prefetch_url_loader.h" #include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h" #include "chrome/browser/prefetch/search_prefetch/full_body_search_prefetch_request.h" @@ -25,6 +28,7 @@ #include "components/omnibox/browser/base_search_provider.h" #include "components/omnibox/browser/omnibox_event_global_tracker.h" #include "components/omnibox/browser/omnibox_log.h" +#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/search_engines/template_url_service.h" #include "url/origin.h" @@ -75,9 +79,20 @@ } // namespace +// static +void SearchPrefetchService::RegisterProfilePrefs(PrefRegistrySimple* registry) { + // Some loss in this pref (especially following a browser crash) is well + // tolerated and helps ensure the pref service isn't slammed. + registry->RegisterDictionaryPref(prefetch::prefs::kCachePrefPath, + PrefRegistry::LOSSY_PREF); +} + SearchPrefetchService::SearchPrefetchService(Profile* profile) : profile_(profile) { DCHECK(!profile_->IsOffTheRecord()); + + if (LoadFromPrefs()) + SaveToPrefs(); } SearchPrefetchService::~SearchPrefetchService() = default; @@ -328,6 +343,7 @@ prefetches_.clear(); prefetch_expiry_timers_.clear(); prefetch_cache_.clear(); + SaveToPrefs(); } void SearchPrefetchService::DeletePrefetch(base::string16 search_terms) { @@ -438,19 +454,28 @@ } void SearchPrefetchService::ClearCacheEntry(const GURL& navigation_url) { + if (prefetch_cache_.find(navigation_url) == prefetch_cache_.end()) { + return; + } + prefetch_cache_.erase(navigation_url); + SaveToPrefs(); } void SearchPrefetchService::UpdateServeTime(const GURL& navigation_url) { if (prefetch_cache_.find(navigation_url) == prefetch_cache_.end()) return; + prefetch_cache_[navigation_url].second = base::Time::Now(); + SaveToPrefs(); } void SearchPrefetchService::AddCacheEntry(const GURL& navigation_url, const GURL& prefetch_url) { - // TODO(ryansturm): Add prefs support to handle session restore. - // https://crbug.com/1162121. + if (navigation_url == prefetch_url) { + return; + } + prefetch_cache_.emplace(navigation_url, std::make_pair(prefetch_url, base::Time::Now())); @@ -468,4 +493,100 @@ } } ClearCacheEntry(url_to_remove); + SaveToPrefs(); +} + +bool SearchPrefetchService::LoadFromPrefs() { + prefetch_cache_.clear(); + const base::DictionaryValue* dictionary = + profile_->GetPrefs()->GetDictionary(prefetch::prefs::kCachePrefPath); + DCHECK(dictionary); + + auto* template_url_service = + TemplateURLServiceFactory::GetForProfile(profile_); + if (!template_url_service || + !template_url_service->GetDefaultSearchProvider()) { + return dictionary->size() > 0; + } + + for (const auto& element : *dictionary) { + GURL navigation_url(element.first); + if (!navigation_url.is_valid()) { + continue; + } + + if (!element.second) { + continue; + } + + base::Value::ConstListView const prefetch_url_and_time = + base::Value::AsListValue(*element.second).GetList(); + + if (prefetch_url_and_time.size() != 2 || + !prefetch_url_and_time[0].is_string() || + !prefetch_url_and_time[1].is_string()) { + continue; + } + + std::string prefetch_url; + if (!prefetch_url_and_time[0].GetAsString(&prefetch_url)) { + continue; + } + + // Make sure we are only mapping same origin in case of corrupted prefs. + if (url::Origin::Create(navigation_url) != + url::Origin::Create(GURL(prefetch_url))) { + continue; + } + + // Don't redirect same URL. + if (navigation_url == prefetch_url) { + continue; + } + + // Make sure the navigation URL is still a search URL. + base::string16 search_terms; + template_url_service->GetDefaultSearchProvider()->ExtractSearchTermsFromURL( + navigation_url, template_url_service->search_terms_data(), + &search_terms); + + if (search_terms.size() == 0) { + continue; + } + + base::Optional<base::Time> last_update = + util::ValueToTime(prefetch_url_and_time[1]); + if (!last_update) { + continue; + } + + // This time isn't valid. + if (last_update.value() > base::Time::Now()) { + continue; + } + + prefetch_cache_.emplace( + navigation_url, + std::make_pair(GURL(prefetch_url), last_update.value())); + } + return dictionary->size() > prefetch_cache_.size(); +} + +void SearchPrefetchService::SaveToPrefs() const { + base::DictionaryValue dictionary; + for (const auto& element : prefetch_cache_) { + std::string navigation_url = element.first.spec(); + std::string prefetch_url = element.second.first.spec(); + auto time = + std::make_unique<base::Value>(util::TimeToValue(element.second.second)); + base::ListValue value; + value.AppendString(prefetch_url); + value.Append(std::move(time)); + dictionary.SetKey(std::move(navigation_url), std::move(value)); + } + profile_->GetPrefs()->Set(prefetch::prefs::kCachePrefPath, dictionary); +} + +bool SearchPrefetchService::LoadFromPrefsForTesting() { + return LoadFromPrefs(); }
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h index 5038f7b..093d4588 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h
@@ -22,6 +22,7 @@ class AutocompleteController; struct OmniboxLog; +class PrefRegistrySimple; class Profile; class SearchPrefetchURLLoader; @@ -117,6 +118,11 @@ base::Optional<SearchPrefetchStatus> GetSearchPrefetchStatusForTesting( base::string16 search_terms); + // Calls |LoadFromPrefs()|. + bool LoadFromPrefsForTesting(); + + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + private: // Records a cache entry for a navigation that is being served. void AddCacheEntry(const GURL& navigation_url, const GURL& prefetch_url); @@ -132,6 +138,14 @@ // closes. void OnURLOpenedFromOmnibox(OmniboxLog* log); + // These methods serialize and deserialize |prefetch_cache_| to + // |profile_| pref service in a dictionary value. + // + // Returns true iff loading the prefs removed at least one entry, so the pref + // should be saved. + bool LoadFromPrefs(); + void SaveToPrefs() const; + // Prefetches that are started are stored using search terms as a key. Only // one prefetch should be started for a given search term until the old // prefetch expires.
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc index 2611411..b1ea39aa 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -1261,6 +1261,72 @@ } IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, + BackPrefetchServedAfterPrefs) { + // This test prefetches and serves two SRP responses. It then navigates back + // then forward, the back navigation should not be cached, due to cache limit + // size of 1, the second navigation should be cached. + + base::HistogramTester histogram_tester; + auto* search_prefetch_service = + SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); + EXPECT_NE(nullptr, search_prefetch_service); + + std::string search_terms = "prefetch_content"; + GURL prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); + EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); + WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), + SearchPrefetchStatus::kComplete); + ui_test_utils::NavigateToURL(browser(), + GetSearchServerQueryURL(search_terms)); + + // The prefetch should be served, and only 1 request should be issued. + EXPECT_EQ(1u, search_server_requests().size()); + auto inner_html = GetDocumentInnerHTML(); + EXPECT_FALSE(base::Contains(inner_html, "regular")); + EXPECT_TRUE(base::Contains(inner_html, "prefetch")); + + search_terms = "prefetch_content_2"; + prefetch_url = GetSearchServerQueryURL(search_terms + "&pf=cs"); + EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url)); + WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), + SearchPrefetchStatus::kComplete); + ui_test_utils::NavigateToURL(browser(), + GetSearchServerQueryURL(search_terms)); + + // The prefetch should be served, and only 1 request (now the second total + // request) should be issued. + EXPECT_EQ(2u, search_server_requests().size()); + inner_html = GetDocumentInnerHTML(); + EXPECT_FALSE(base::Contains(inner_html, "regular")); + EXPECT_TRUE(base::Contains(inner_html, "prefetch")); + + content::TestNavigationObserver back_load_observer(GetWebContents()); + GetWebContents()->GetController().GoBack(); + back_load_observer.Wait(); + + // There should not be a cached prefetch request, so there should be a network + // request. + EXPECT_EQ(3u, search_server_requests().size()); + inner_html = GetDocumentInnerHTML(); + EXPECT_TRUE(base::Contains(inner_html, "regular")); + EXPECT_FALSE(base::Contains(inner_html, "prefetch")); + + // Reload the map from prefs. + EXPECT_FALSE(search_prefetch_service->LoadFromPrefsForTesting()); + + content::TestNavigationObserver forward_load_observer(GetWebContents()); + GetWebContents()->GetController().GoForward(); + forward_load_observer.Wait(); + + // There should be a cached prefetch request, so there should not be a new + // network request. + EXPECT_EQ(3u, search_server_requests().size()); + inner_html = GetDocumentInnerHTML(); + EXPECT_FALSE(base::Contains(inner_html, "regular")); + EXPECT_TRUE(base::Contains(inner_html, "prefetch")); +} + +IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledBrowserTest, EvictedCacheFallsback) { // This test prefetches and serves a SRP responses. It then navigates to a // different URL. Then it clears cache as if it was evicted. Then it navigates
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 637d7c0..b73a41e2 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -54,6 +54,7 @@ #include "chrome/browser/permissions/quiet_notification_permission_ui_state.h" #include "chrome/browser/policy/developer_tools_policy_handler.h" #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_decider.h" +#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h" #include "chrome/browser/prefs/chrome_pref_service_factory.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/prefs/origin_trial_prefs.h" @@ -883,6 +884,7 @@ QuietNotificationPermissionUiState::RegisterProfilePrefs(registry); RegisterBrowserUserPrefs(registry); safe_browsing::RegisterProfilePrefs(registry); + SearchPrefetchService::RegisterProfilePrefs(registry); blocked_content::SafeBrowsingTriggeredPopupBlocker::RegisterProfilePrefs( registry); security_interstitials::InsecureFormBlockingPage::RegisterProfilePrefs(
diff --git a/chrome/browser/printing/print_backend_browsertest.cc b/chrome/browser/printing/print_backend_browsertest.cc index 4b34cf945..a9b3a0f1 100644 --- a/chrome/browser/printing/print_backend_browsertest.cc +++ b/chrome/browser/printing/print_backend_browsertest.cc
@@ -110,6 +110,21 @@ CheckForQuit(); } + void OnDidFetchCapabilities( + base::Optional<PrinterBasicInfo>* capture_printer_info, + base::Optional<PrinterSemanticCapsAndDefaults::Papers>* + capture_user_defined_papers, + base::Optional<PrinterSemanticCapsAndDefaults>* capture_printer_caps, + const base::Optional<PrinterBasicInfo>& printer_info, + const base::Optional<PrinterSemanticCapsAndDefaults::Papers>& + user_defined_papers, + const base::Optional<PrinterSemanticCapsAndDefaults>& printer_caps) { + *capture_printer_info = printer_info; + *capture_user_defined_papers = user_defined_papers; + *capture_printer_caps = printer_caps; + CheckForQuit(); + } + // The following are helper functions for having a wait loop in the test and // exit when expected messages are received. Expect to only have to wait for // one message. @@ -209,4 +224,37 @@ EXPECT_FALSE(printer_caps.has_value()); } +IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FetchCapabilities) { + base::Optional<PrinterBasicInfo> printer_info; + base::Optional<PrinterSemanticCapsAndDefaults::Papers> user_defined_papers; + base::Optional<PrinterSemanticCapsAndDefaults> printer_caps; + + DoInitAndSetupTestData(); + + // Safe to use base::Unretained(this) since waiting locally on the callback + // forces a shorter lifetime than `this`. + GetPrintBackendService()->FetchCapabilities( + kDefaultPrinterName, + base::BindOnce(&PrintBackendBrowserTest::OnDidFetchCapabilities, + base::Unretained(this), &printer_info, + &user_defined_papers, &printer_caps)); + WaitUntilCallbackReceived(); + EXPECT_TRUE(printer_info.has_value()); + EXPECT_TRUE(user_defined_papers.has_value()); + EXPECT_TRUE(printer_caps.has_value()); + EXPECT_TRUE(printer_info->is_default); + EXPECT_EQ(printer_caps->copies_max, kCopiesMax); + + // Requesting for an invalid printer should not return capabilities. + GetPrintBackendService()->FetchCapabilities( + kInvalidPrinterName, + base::BindOnce(&PrintBackendBrowserTest::OnDidFetchCapabilities, + base::Unretained(this), &printer_info, + &user_defined_papers, &printer_caps)); + WaitUntilCallbackReceived(); + EXPECT_FALSE(printer_info.has_value()); + EXPECT_FALSE(user_defined_papers.has_value()); + EXPECT_FALSE(printer_caps.has_value()); +} + } // namespace printing
diff --git a/chrome/browser/reading_list/android/reading_list_manager.h b/chrome/browser/reading_list/android/reading_list_manager.h index 28b589a3..efa7e53 100644 --- a/chrome/browser/reading_list/android/reading_list_manager.h +++ b/chrome/browser/reading_list/android/reading_list_manager.h
@@ -47,7 +47,7 @@ // Adds a reading list article to the unread section, and return the bookmark // node representation. The bookmark node is owned by this class. If there is // a duplicate URL, a new bookmark node will be created, and the old bookmark - // node pointer will be invalidated. May return nullptr on error. + // node pointer will be invalidated. virtual const bookmarks::BookmarkNode* Add(const GURL& url, const std::string& title) = 0;
diff --git a/chrome/browser/reading_list/android/reading_list_manager_impl.cc b/chrome/browser/reading_list/android/reading_list_manager_impl.cc index b2bf08d..98b8bcc 100644 --- a/chrome/browser/reading_list/android/reading_list_manager_impl.cc +++ b/chrome/browser/reading_list/android/reading_list_manager_impl.cc
@@ -132,13 +132,13 @@ const BookmarkNode* ReadingListManagerImpl::Add(const GURL& url, const std::string& title) { DCHECK(reading_list_model_->loaded()); - if (!reading_list_model_->IsUrlSupported(url)) - return nullptr; // Add or swap the reading list entry. const auto& new_entry = reading_list_model_->AddEntry( url, title, reading_list::ADDED_VIA_CURRENT_APP); const auto* node = FindBookmarkByURL(new_entry.URL()); + DCHECK(node) + << "Bookmark node should have been create in ReadingListDidAddEntry()."; return node; }
diff --git a/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc b/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc index 57670f5..1ca6a98 100644 --- a/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc +++ b/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc
@@ -32,7 +32,6 @@ constexpr char kReadStatusKey[] = "read_status"; constexpr char kReadStatusRead[] = "true"; constexpr char kReadStatusUnread[] = "false"; -constexpr char kInvalidUTF8[] = "\xc3\x28"; class MockObserver : public ReadingListManager::Observer { public: @@ -229,31 +228,6 @@ EXPECT_EQ(url, new_node->url()); } -// If Add() with an invalid title, nullptr will be returned. -TEST_F(ReadingListManagerImplTest, AddInvalidTitle) { - GURL url(kURL); - - // Use an invalid UTF8 string. - base::string16 dummy; - EXPECT_FALSE( - base::UTF8ToUTF16(kInvalidUTF8, base::size(kInvalidUTF8), &dummy)); - const auto* new_node = Add(url, std::string(kInvalidUTF8)); - EXPECT_EQ(nullptr, new_node) - << "Should return nullptr when failed to parse the title."; -} - -// If Add() with an invalid URL, nullptr will be returned. -TEST_F(ReadingListManagerImplTest, AddInvalidURL) { - GURL invalid_url("chrome://flags"); - EXPECT_FALSE(reading_list_model()->IsUrlSupported(invalid_url)); - - // Use an invalid URL, the observer method ReadingListDidAddEntry() won't be - // invoked. - const auto* new_node = manager()->Add(invalid_url, kTitle); - EXPECT_EQ(nullptr, new_node) - << "Should return nullptr when the URL scheme is not supported."; -} - // Verifes SetReadStatus()/GetReadStatus() API. TEST_F(ReadingListManagerImplTest, ReadStatus) { GURL url(kURL);
diff --git a/chrome/browser/resources/chromeos/accessibility/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/BUILD.gn index e220a7c..f4d49f2 100644 --- a/chrome/browser/resources/chromeos/accessibility/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/BUILD.gn
@@ -147,11 +147,6 @@ sources = [ "braille_ime/braille_ime_unittest.js", "common/rect_util_unittest.js", - "select_to_speak/node_utils_unittest.js", - "select_to_speak/paragraph_utils_unittest.js", - "select_to_speak/select_to_speak_unittest.js", - "select_to_speak/sentence_utils_unittest.js", - "select_to_speak/word_utils_unittest.js", ] gen_include_files = [ "common/closure_shim.js" ] extra_js_files = [ @@ -163,7 +158,6 @@ "common/tree_walker.js", "select_to_speak/paragraph_utils.js", "select_to_speak/select_to_speak.js", - "select_to_speak/test_support.js", "select_to_speak/word_utils.js", "select_to_speak/node_utils.js", "select_to_speak/sentence_utils.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js index a835bec..f8c710f7 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js
@@ -167,3 +167,18 @@ * No UI in the background context. */ E2ETestBase.prototype.runAccessibilityChecks = false; + +/** + * Similar to |TEST_F|. Generates a test for the given |testFixture|, + * |testName|, and |testFunction|. + * Used this variant when an |isAsync| fixture wants to temporarily mix in an + * sync test. + * @param {string} testFixture Fixture name. + * @param {string} testName Test name. + * @param {function} testFunction The test impl. + */ +function SYNC_TEST_F(testFixture, testName, testFunction) { + TEST_F(testFixture, testName, function() { + this.newCallback(testFunction)(); + }); +}
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn index 75750e9..5a312ef 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
@@ -26,6 +26,7 @@ mode = "copy" dest_dir = select_to_speak_out_dir sources = [ + "background.html", "checked.png", "earcons/null_selection.ogg", "input_handler.js", @@ -37,6 +38,7 @@ "prefs_manager.js", "select_to_speak-2x.svg", "select_to_speak.js", + "select_to_speak_constants.js", "select_to_speak_main.js", "select_to_speak_options.js", "sentence_utils.js", @@ -81,6 +83,15 @@ "select_to_speak_navigation_control_test.js", "select_to_speak_prefs_test.js", ] + + # These are unit tests run under an extension environment to get ES6 module support. + sources += [ + "node_utils_unittest.js", + "paragraph_utils_unittest.js", + "select_to_speak_unittest.js", + "sentence_utils_unittest.js", + "word_utils_unittest.js", + ] gen_include_files = [ "../common/testing/callback_helper.js", "../common/testing/e2e_test_base.js", @@ -113,6 +124,7 @@ ":paragraph_utils", ":prefs_manager", ":select_to_speak", + ":select_to_speak_constants", ":select_to_speak_options", ":sentence_utils", ":word_utils", @@ -197,3 +209,6 @@ deps = [ ":prefs_manager" ] externs_list = [ "$externs_path/metrics_private.js" ] } + +js_library("select_to_speak_constants") { +}
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/background.html b/chrome/browser/resources/chromeos/accessibility/select_to_speak/background.html new file mode 100644 index 0000000..cad25b8 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/background.html
@@ -0,0 +1,13 @@ +<!-- Global scripts. --> +<script src="/common/closure_shim.js"></script> +<script src="/common/constants.js"></script> +<script src="/common/array_util.js"></script> +<script src="/common/automation_predicate.js"></script> +<script src="/common/automation_util.js"></script> +<script src="/common/key_code.js"></script> +<script src="/common/instance_checker.js"></script> +<script src="/common/rect_util.js"></script> +<script src="/common/tree_walker.js"></script> + +<!-- Module entrypoint. --> +<script type="module" src="/select_to_speak/select_to_speak_main.js"></script>
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js index 7ed45f1..d1a4ced 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/input_handler.js
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {SelectToSpeakConstants} from './select_to_speak_constants.js'; + const SelectToSpeakState = chrome.accessibilityPrivate.SelectToSpeakState; /** @@ -29,7 +31,7 @@ /** * Class to handle user-input, from mouse, keyboard, and copy-paste events. */ -class InputHandler { +export class InputHandler { /** * @param {SelectToSpeakCallbacks} callbacks */ @@ -233,7 +235,7 @@ } this.onMouseMove_(evt); this.trackingMouse_ = false; - if (!this.keysCurrentlyDown_.has(SelectToSpeak.SEARCH_KEY_CODE)) { + if (!this.keysCurrentlyDown_.has(SelectToSpeakConstants.SEARCH_KEY_CODE)) { // This is only needed to cancel something started with the search key. this.didTrackMouse_ = false; } @@ -257,11 +259,11 @@ this.keysCurrentlyDown_.add(evt.keyCode); this.keysPressedTogether_.add(evt.keyCode); if (this.keysPressedTogether_.size === 1 && - evt.keyCode === SelectToSpeak.SEARCH_KEY_CODE) { + evt.keyCode === SelectToSpeakConstants.SEARCH_KEY_CODE) { this.isSearchKeyDown_ = true; } else if ( this.keysCurrentlyDown_.size === 2 && - evt.keyCode === SelectToSpeak.READ_SELECTION_KEY_CODE && + evt.keyCode === SelectToSpeakConstants.READ_SELECTION_KEY_CODE && !this.trackingMouse_) { // Only go into selection mode if we aren't already tracking the mouse. this.isSelectionKeyDown_ = true; @@ -276,14 +278,15 @@ * @param {!Event} evt */ onKeyUp_(evt) { - if (evt.keyCode === SelectToSpeak.READ_SELECTION_KEY_CODE) { + if (evt.keyCode === SelectToSpeakConstants.READ_SELECTION_KEY_CODE) { if (this.isSelectionKeyDown_ && this.keysPressedTogether_.size === 2 && this.keysPressedTogether_.has(evt.keyCode) && - this.keysPressedTogether_.has(SelectToSpeak.SEARCH_KEY_CODE)) { + this.keysPressedTogether_.has( + SelectToSpeakConstants.SEARCH_KEY_CODE)) { this.callbacks_.onKeystrokeSelection(); } this.isSelectionKeyDown_ = false; - } else if (evt.keyCode === SelectToSpeak.SEARCH_KEY_CODE) { + } else if (evt.keyCode === SelectToSpeakConstants.SEARCH_KEY_CODE) { this.isSearchKeyDown_ = false; // If we were in the middle of tracking the mouse, cancel it. @@ -296,8 +299,8 @@ // Stop speech when the user taps and releases Control or Search // without using the mouse or pressing any other keys along the way. if (!this.didTrackMouse_ && - (evt.keyCode === SelectToSpeak.SEARCH_KEY_CODE || - evt.keyCode === SelectToSpeak.CONTROL_KEY_CODE) && + (evt.keyCode === SelectToSpeakConstants.SEARCH_KEY_CODE || + evt.keyCode === SelectToSpeakConstants.CONTROL_KEY_CODE) && this.keysPressedTogether_.has(evt.keyCode) && this.keysPressedTogether_.size === 1) { this.trackingMouse_ = false;
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js index 963b853..8ddacaae 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {PrefsManager} from './prefs_manager.js'; + // Utilities for UMA metrics. -class MetricsUtils { +export class MetricsUtils { constructor() {} /**
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js index 204efc6..891e436 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js
@@ -2,9 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {ParagraphUtils} from './paragraph_utils.js'; + +const AutomationNode = chrome.automation.AutomationNode; +const RoleType = chrome.automation.RoleType; + // Utilities for automation nodes in Select-to-Speak. -class NodeUtils { +export class NodeUtils { constructor() {} /**
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js index d57859a7..11af58c 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils_unittest.js
@@ -2,75 +2,80 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +GEN_INCLUDE(['select_to_speak_e2e_test_base.js']); + /** * Test fixture for node_utils.js. */ -SelectToSpeakNodeUtilsUnitTest = class extends testing.Test {}; +SelectToSpeakNodeUtilsUnitTest = class extends SelectToSpeakE2ETest { + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + (async function() { + let module = await import('/select_to_speak/node_utils.js'); + window.NodeUtils = module.NodeUtils; -/** @override */ -SelectToSpeakNodeUtilsUnitTest.prototype.extraLibraries = [ - 'test_support.js', - 'paragraph_utils.js', - 'node_utils.js', - 'word_utils.js', - '../common/closure_shim.js', - '../common/constants.js', - '../common/automation_predicate.js', - '../common/automation_util.js', - '../common/rect_util.js', - '../common/tree_walker.js', -]; + module = await import('/select_to_speak/paragraph_utils.js'); + window.ParagraphUtils = module.ParagraphUtils; + module = await import('/select_to_speak/word_utils.js'); + window.WordUtils = module.WordUtils; -TEST_F('SelectToSpeakNodeUtilsUnitTest', 'GetNodeVisibilityState', function() { - const nodeWithoutRoot1 = {root: null}; - const nodeWithoutRoot2 = {root: null, state: {invisible: true}}; - assertEquals( - NodeUtils.getNodeState(nodeWithoutRoot1), - NodeUtils.NodeState.NODE_STATE_INVALID); - assertEquals( - NodeUtils.getNodeState(nodeWithoutRoot2), - NodeUtils.NodeState.NODE_STATE_INVALID); + runTest(); + })(); + } +}; - const invisibleNode1 = { - root: {}, - parent: {role: ''}, - state: {invisible: true} - }; - // Currently nodes aren't actually marked 'invisible', so we need to navigate - // up their tree. - const invisibleNode2 = { - root: {}, - parent: {role: 'window', state: {invisible: true}}, - state: {} - }; - const invisibleNode3 = {root: {}, parent: invisibleNode2, state: {}}; - const invisibleNode4 = {root: {}, parent: invisibleNode3, state: {}}; - assertEquals( - NodeUtils.getNodeState(invisibleNode1), - NodeUtils.NodeState.NODE_STATE_INVISIBLE); - assertEquals( - NodeUtils.getNodeState(invisibleNode2), - NodeUtils.NodeState.NODE_STATE_INVISIBLE); - assertEquals( - NodeUtils.getNodeState(invisibleNode3), - NodeUtils.NodeState.NODE_STATE_INVISIBLE); +SYNC_TEST_F( + 'SelectToSpeakNodeUtilsUnitTest', 'GetNodeVisibilityState', function() { + const nodeWithoutRoot1 = {root: null}; + const nodeWithoutRoot2 = {root: null, state: {invisible: true}}; + assertEquals( + NodeUtils.getNodeState(nodeWithoutRoot1), + NodeUtils.NodeState.NODE_STATE_INVALID); + assertEquals( + NodeUtils.getNodeState(nodeWithoutRoot2), + NodeUtils.NodeState.NODE_STATE_INVALID); - const normalNode1 = { - root: {}, - parent: {role: 'window', state: {}}, - state: {} - }; - const normalNode2 = {root: {}, parent: {normalNode1}, state: {}}; - assertEquals( - NodeUtils.getNodeState(normalNode1), - NodeUtils.NodeState.NODE_STATE_NORMAL); - assertEquals( - NodeUtils.getNodeState(normalNode2), - NodeUtils.NodeState.NODE_STATE_NORMAL); -}); + const invisibleNode1 = { + root: {}, + parent: {role: ''}, + state: {invisible: true} + }; + // Currently nodes aren't actually marked 'invisible', so we need to + // navigate up their tree. + const invisibleNode2 = { + root: {}, + parent: {role: 'window', state: {invisible: true}}, + state: {} + }; + const invisibleNode3 = {root: {}, parent: invisibleNode2, state: {}}; + const invisibleNode4 = {root: {}, parent: invisibleNode3, state: {}}; + assertEquals( + NodeUtils.getNodeState(invisibleNode1), + NodeUtils.NodeState.NODE_STATE_INVISIBLE); + assertEquals( + NodeUtils.getNodeState(invisibleNode2), + NodeUtils.NodeState.NODE_STATE_INVISIBLE); + assertEquals( + NodeUtils.getNodeState(invisibleNode3), + NodeUtils.NodeState.NODE_STATE_INVISIBLE); -TEST_F( + const normalNode1 = { + root: {}, + parent: {role: 'window', state: {}}, + state: {} + }; + const normalNode2 = {root: {}, parent: {normalNode1}, state: {}}; + assertEquals( + NodeUtils.getNodeState(normalNode1), + NodeUtils.NodeState.NODE_STATE_NORMAL); + assertEquals( + NodeUtils.getNodeState(normalNode2), + NodeUtils.NodeState.NODE_STATE_NORMAL); + }); + +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'GetNodeVisibilityStateWithRootWebArea', function() { // Currently nodes aren't actually marked 'invisible', so we need to @@ -121,7 +126,7 @@ NodeUtils.NodeState.NODE_STATE_NORMAL); }); -TEST_F('SelectToSpeakNodeUtilsUnitTest', 'findAllMatching', function() { +SYNC_TEST_F('SelectToSpeakNodeUtilsUnitTest', 'findAllMatching', function() { const rect = {left: 0, top: 0, width: 100, height: 100}; const rootNode = { root: {}, @@ -255,7 +260,7 @@ assertEquals(container2, result[0]); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'findAllMatchingWithInputs', function() { const rect = {left: 0, top: 0, width: 100, height: 100}; const rootNode = { @@ -281,7 +286,7 @@ assertEquals(checkbox, result[0]); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getDeepEquivalentForSelectionDeprecatedNoChildren', function() { const node = {name: 'Hello, world', children: []}; @@ -294,7 +299,7 @@ assertEquals(6, result.offset); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getDeepEquivalentForSelectionDeprecatedSimpleChildren', function() { const child1 = @@ -330,7 +335,7 @@ assertEquals(3, result.offset); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getDeepEquivalentForSelectionDeprecatedComplexChildren', function() { const child1 = @@ -403,7 +408,7 @@ assertEquals(0, result.offset); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'sortSvgNodesByReadingOrder', function() { const svgRootNode = {role: 'svgRoot'}; const gNode1 = { @@ -442,7 +447,7 @@ assertEquals(nodes[2].name, 'three'); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'sortNodesByReadingOrderMultipleSVGs', function() { const textNode1 = {role: 'staticText', name: 'Text Node 1'}; @@ -490,7 +495,7 @@ assertEquals(nodes[6].name, 'Text Node 3'); }); -TEST_F('SelectToSpeakNodeUtilsUnitTest', 'getNextParagraph', function() { +SYNC_TEST_F('SelectToSpeakNodeUtilsUnitTest', 'getNextParagraph', function() { const root = createMockNode({role: 'rootWebArea'}); const paragraph1 = createMockNode({role: 'paragraph', display: 'block', parent: root, root}); @@ -551,7 +556,7 @@ assertEquals(result.length, 0); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextParagraphContainedWithinRoot', function() { const desktop = createMockNode({role: 'desktop'}); @@ -584,7 +589,7 @@ assertEquals(result.length, 0); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextParagraphThroughIframe', function() { const desktop = createMockNode({role: 'desktop'}); @@ -623,7 +628,7 @@ assertEquals(result[0], text3); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextParagraphNonBlockNodes', function() { /** @@ -663,7 +668,7 @@ assertEquals(result[0], text2); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextParagraphNestedBlocks', function() { const root = createMockNode({role: 'rootWebArea'}); @@ -695,142 +700,146 @@ assertEquals(result[0], text1); }); -TEST_F('SelectToSpeakNodeUtilsUnitTest', 'getNextParagraphAndroid', function() { - const root = createMockNode({role: 'application'}); - const container1 = - createMockNode({role: 'genericContainer', parent: root, root}); - const text1 = createMockNode( - {role: 'staticText', parent: container1, root, name: 'Line 1'}); - const text2 = createMockNode( - {role: 'staticText', parent: container1, root, name: 'Line 2'}); - const container2 = - createMockNode({role: 'genericContainer', parent: root, root}); - const text3 = createMockNode( - {role: 'staticText', parent: container2, root, name: 'Line 3'}); +SYNC_TEST_F( + 'SelectToSpeakNodeUtilsUnitTest', 'getNextParagraphAndroid', function() { + const root = createMockNode({role: 'application'}); + const container1 = + createMockNode({role: 'genericContainer', parent: root, root}); + const text1 = createMockNode( + {role: 'staticText', parent: container1, root, name: 'Line 1'}); + const text2 = createMockNode( + {role: 'staticText', parent: container1, root, name: 'Line 2'}); + const container2 = + createMockNode({role: 'genericContainer', parent: root, root}); + const text3 = createMockNode( + {role: 'staticText', parent: container2, root, name: 'Line 3'}); - // Without paragraphs, navigate node to node. - let result = NodeUtils.getNextParagraph(text1, constants.Dir.FORWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text2); + // Without paragraphs, navigate node to node. + let result = NodeUtils.getNextParagraph(text1, constants.Dir.FORWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text2); - result = NodeUtils.getNextParagraph(text2, constants.Dir.FORWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text3); + result = NodeUtils.getNextParagraph(text2, constants.Dir.FORWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text3); - result = NodeUtils.getNextParagraph(container1, constants.Dir.FORWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text3); + result = NodeUtils.getNextParagraph(container1, constants.Dir.FORWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text3); - result = NodeUtils.getNextParagraph(text3, constants.Dir.FORWARD); - assertEquals(result.length, 0); + result = NodeUtils.getNextParagraph(text3, constants.Dir.FORWARD); + assertEquals(result.length, 0); - result = NodeUtils.getNextParagraph(container2, constants.Dir.FORWARD); - assertEquals(result.length, 0); + result = NodeUtils.getNextParagraph(container2, constants.Dir.FORWARD); + assertEquals(result.length, 0); - result = NodeUtils.getNextParagraph(text3, constants.Dir.BACKWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text2); + result = NodeUtils.getNextParagraph(text3, constants.Dir.BACKWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text2); - result = NodeUtils.getNextParagraph(container2, constants.Dir.BACKWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text2); + result = NodeUtils.getNextParagraph(container2, constants.Dir.BACKWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text2); - result = NodeUtils.getNextParagraph(text2, constants.Dir.BACKWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text1); + result = NodeUtils.getNextParagraph(text2, constants.Dir.BACKWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text1); - result = NodeUtils.getNextParagraph(text1, constants.Dir.BACKWARD); - assertEquals(result.length, 0); + result = NodeUtils.getNextParagraph(text1, constants.Dir.BACKWARD); + assertEquals(result.length, 0); - result = NodeUtils.getNextParagraph(container1, constants.Dir.BACKWARD); - assertEquals(result.length, 0); -}); + result = NodeUtils.getNextParagraph(container1, constants.Dir.BACKWARD); + assertEquals(result.length, 0); + }); -TEST_F('SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraph', function() { - const root = createMockNode({role: 'rootWebArea'}); - createMockNode({role: 'paragraph', display: 'block', parent: root, root}); - const paragraph2 = +SYNC_TEST_F( + 'SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraph', function() { + const root = createMockNode({role: 'rootWebArea'}); createMockNode({role: 'paragraph', display: 'block', parent: root, root}); - const text1 = createMockNode( - {role: 'staticText', parent: paragraph2, root, name: 'Line 1'}); - const text2 = createMockNode( - {role: 'staticText', parent: paragraph2, root, name: 'Line 2'}); - const text3 = createMockNode( - {role: 'staticText', parent: paragraph2, root, name: 'Line 3'}); - createMockNode({role: 'paragraph', display: 'block', parent: root, root}); - - let result = NodeUtils.getNextNodesInParagraph(text2, constants.Dir.FORWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text3); - - result = NodeUtils.getNextNodesInParagraph(text1, constants.Dir.FORWARD); - assertEquals(result.length, 2); - assertEquals(result[0], text2); - assertEquals(result[1], text3); - - result = NodeUtils.getNextNodesInParagraph(text3, constants.Dir.FORWARD); - assertEquals(result.length, 0); - - result = NodeUtils.getNextNodesInParagraph(text3, constants.Dir.BACKWARD); - assertEquals(result.length, 2); - assertEquals(result[0], text1); - assertEquals(result[1], text2); - - result = NodeUtils.getNextNodesInParagraph(text2, constants.Dir.BACKWARD); - assertEquals(result.length, 1); - assertEquals(result[0], text1); - - result = NodeUtils.getNextNodesInParagraph(text1, constants.Dir.BACKWARD); - assertEquals(result.length, 0); -}); - -TEST_F('SelectToSpeakNodeUtilsUnitTest', 'getAllNodesInParagraph', function() { - const root = createMockNode({role: 'rootWebArea'}); - const paragraph1 = + const paragraph2 = createMockNode( + {role: 'paragraph', display: 'block', parent: root, root}); + const text1 = createMockNode( + {role: 'staticText', parent: paragraph2, root, name: 'Line 1'}); + const text2 = createMockNode( + {role: 'staticText', parent: paragraph2, root, name: 'Line 2'}); + const text3 = createMockNode( + {role: 'staticText', parent: paragraph2, root, name: 'Line 3'}); createMockNode({role: 'paragraph', display: 'block', parent: root, root}); - const text1 = createMockNode( - {role: 'staticText', parent: paragraph1, root, name: 'Line 1'}); - const text2 = createMockNode( - {role: 'staticText', parent: paragraph1, root, name: 'Line 2'}); - const paragraph2 = - createMockNode({role: 'paragraph', display: 'block', parent: root, root}); - const text3 = createMockNode( - {role: 'staticText', parent: paragraph2, root, name: 'Line 3'}); - const text4 = createMockNode( - {role: 'staticText', parent: paragraph2, root, name: 'Line 4'}); - const text5 = createMockNode( - {role: 'staticText', parent: paragraph2, root, name: 'Line 5'}); - let result = NodeUtils.getAllNodesInParagraph(text1); - assertEquals(result.length, 2); - assertEquals(result[0], text1); - assertEquals(result[1], text2); + let result = + NodeUtils.getNextNodesInParagraph(text2, constants.Dir.FORWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text3); - result = NodeUtils.getAllNodesInParagraph(text2); - assertEquals(result.length, 2); - assertEquals(result[0], text1); - assertEquals(result[1], text2); + result = NodeUtils.getNextNodesInParagraph(text1, constants.Dir.FORWARD); + assertEquals(result.length, 2); + assertEquals(result[0], text2); + assertEquals(result[1], text3); - result = NodeUtils.getAllNodesInParagraph(text3); - assertEquals(result.length, 3); - assertEquals(result[0], text3); - assertEquals(result[1], text4); - assertEquals(result[2], text5); + result = NodeUtils.getNextNodesInParagraph(text3, constants.Dir.FORWARD); + assertEquals(result.length, 0); - result = NodeUtils.getAllNodesInParagraph(text4); - assertEquals(result.length, 3); - assertEquals(result[0], text3); - assertEquals(result[1], text4); - assertEquals(result[2], text5); + result = NodeUtils.getNextNodesInParagraph(text3, constants.Dir.BACKWARD); + assertEquals(result.length, 2); + assertEquals(result[0], text1); + assertEquals(result[1], text2); - result = NodeUtils.getAllNodesInParagraph(text5); - assertEquals(result.length, 3); - assertEquals(result[0], text3); - assertEquals(result[1], text4); - assertEquals(result[2], text5); -}); + result = NodeUtils.getNextNodesInParagraph(text2, constants.Dir.BACKWARD); + assertEquals(result.length, 1); + assertEquals(result[0], text1); -TEST_F( + result = NodeUtils.getNextNodesInParagraph(text1, constants.Dir.BACKWARD); + assertEquals(result.length, 0); + }); + +SYNC_TEST_F( + 'SelectToSpeakNodeUtilsUnitTest', 'getAllNodesInParagraph', function() { + const root = createMockNode({role: 'rootWebArea'}); + const paragraph1 = createMockNode( + {role: 'paragraph', display: 'block', parent: root, root}); + const text1 = createMockNode( + {role: 'staticText', parent: paragraph1, root, name: 'Line 1'}); + const text2 = createMockNode( + {role: 'staticText', parent: paragraph1, root, name: 'Line 2'}); + const paragraph2 = createMockNode( + {role: 'paragraph', display: 'block', parent: root, root}); + const text3 = createMockNode( + {role: 'staticText', parent: paragraph2, root, name: 'Line 3'}); + const text4 = createMockNode( + {role: 'staticText', parent: paragraph2, root, name: 'Line 4'}); + const text5 = createMockNode( + {role: 'staticText', parent: paragraph2, root, name: 'Line 5'}); + + let result = NodeUtils.getAllNodesInParagraph(text1); + assertEquals(result.length, 2); + assertEquals(result[0], text1); + assertEquals(result[1], text2); + + result = NodeUtils.getAllNodesInParagraph(text2); + assertEquals(result.length, 2); + assertEquals(result[0], text1); + assertEquals(result[1], text2); + + result = NodeUtils.getAllNodesInParagraph(text3); + assertEquals(result.length, 3); + assertEquals(result[0], text3); + assertEquals(result[1], text4); + assertEquals(result[2], text5); + + result = NodeUtils.getAllNodesInParagraph(text4); + assertEquals(result.length, 3); + assertEquals(result[0], text3); + assertEquals(result[1], text4); + assertEquals(result[2], text5); + + result = NodeUtils.getAllNodesInParagraph(text5); + assertEquals(result.length, 3); + assertEquals(result[0], text3); + assertEquals(result[1], text4); + assertEquals(result[2], text5); + }); + +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraphFromNodeGroup_forward', function() { // The nodeGroup has four inline text nodes and one static text node. @@ -868,7 +877,7 @@ assertEquals(result.nodes.length, 0); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraphFromNodeGroup_backward', function() { // The nodeGroup has four inline text nodes and one static text node. @@ -909,7 +918,7 @@ assertEquals(result.nodes.length, 0); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraphFromNodeGroup_forwardWithEmptyTail', function() { // The nodeGroup consists of three inline text nodes: "Hello", "world ", @@ -935,7 +944,7 @@ assertEquals(result.nodes[0].name, 'world '); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraphFromNodeGroup_backwardWithEmptyHeads', function() { // The nodeGroup consists of three inline text nodes: " ", " Hello", @@ -961,7 +970,7 @@ assertEquals(result.nodes[0].name, ' Hello'); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraphFromNodeGroup_forwardFromPartialParagraph', function() { @@ -982,7 +991,7 @@ assertEquals(result.offset, 0); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakNodeUtilsUnitTest', 'getNextNodesInParagraphFromNodeGroup_backwardFromPartialParagraph', function() { @@ -1154,4 +1163,4 @@ return ParagraphUtils.buildNodeGroup( [text2], 0, false /* do not split on language */); -} \ No newline at end of file +}
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js index fe2f669..60fc5417 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js
@@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {WordUtils} from './word_utils.js'; + var AutomationNode = chrome.automation.AutomationNode; var RoleType = chrome.automation.RoleType; -class ParagraphUtils { +export class ParagraphUtils { constructor() {} /**
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_overflow_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_overflow_test.js index ed78f27b..9f36d50 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_overflow_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_overflow_test.js
@@ -8,6 +8,17 @@ * Browser tests for select-to-speak's feature to filter out overflow text. */ SelectToSpeakParagraphOverflowTest = class extends SelectToSpeakE2ETest { + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + (async function() { + const module = await import('/select_to_speak/paragraph_utils.js'); + window.ParagraphUtils = module.ParagraphUtils; + + runTest(); + })(); + } + generateHorizentalOverflowText(text) { return ( '<div style="width: 50px; overflow: hidden">' +
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_unittest.js index 82c46834..ac492404 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils_unittest.js
@@ -2,46 +2,56 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +GEN_INCLUDE(['select_to_speak_e2e_test_base.js']); + /** * Test fixture for paragraph_utils.js. */ -SelectToSpeakParagraphUnitTest = class extends testing.Test {}; +SelectToSpeakParagraphUnitTest = class extends SelectToSpeakE2ETest { + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + (async function() { + const module = await import('/select_to_speak/paragraph_utils.js'); + window.ParagraphUtils = module.ParagraphUtils; -/** @override */ -SelectToSpeakParagraphUnitTest.prototype.extraLibraries = - ['test_support.js', 'paragraph_utils.js']; + runTest(); + })(); + } +}; +SYNC_TEST_F( + 'SelectToSpeakParagraphUnitTest', 'GetFirstBlockAncestor', function() { + const root = {role: 'rootWebArea'}; + const paragraph = {role: 'paragraph', parent: root, root}; + const text1 = + {role: 'staticText', parent: paragraph, display: 'block', root}; + const text2 = {role: 'staticText', parent: root, root}; + const text3 = {role: 'inlineTextBox', parent: text1, root}; + const div = + {role: 'genericContainer', parent: paragraph, display: 'block', root}; + const text4 = {role: 'staticText', parent: div, root}; + assertEquals(paragraph, ParagraphUtils.getFirstBlockAncestor(text1)); + assertEquals(root, ParagraphUtils.getFirstBlockAncestor(text2)); + assertEquals(paragraph, ParagraphUtils.getFirstBlockAncestor(text3)); + assertEquals(div, ParagraphUtils.getFirstBlockAncestor(text4)); + }); -TEST_F('SelectToSpeakParagraphUnitTest', 'GetFirstBlockAncestor', function() { - const root = {role: 'rootWebArea'}; - const paragraph = {role: 'paragraph', parent: root, root}; - const text1 = {role: 'staticText', parent: paragraph, display: 'block', root}; - const text2 = {role: 'staticText', parent: root, root}; - const text3 = {role: 'inlineTextBox', parent: text1, root}; - const div = - {role: 'genericContainer', parent: paragraph, display: 'block', root}; - const text4 = {role: 'staticText', parent: div, root}; - assertEquals(paragraph, ParagraphUtils.getFirstBlockAncestor(text1)); - assertEquals(root, ParagraphUtils.getFirstBlockAncestor(text2)); - assertEquals(paragraph, ParagraphUtils.getFirstBlockAncestor(text3)); - assertEquals(div, ParagraphUtils.getFirstBlockAncestor(text4)); -}); +SYNC_TEST_F( + 'SelectToSpeakParagraphUnitTest', 'SVGRootIsBlockAncestor', function() { + const root = {role: 'rootWebArea'}; + const svgRoot = {role: 'svgRoot', parent: root, root}; + const text1 = {role: 'staticText', parent: svgRoot, root}; + const inline1 = {role: 'inlineTextBox', parent: text1, root}; + const text2 = {role: 'staticText', parent: svgRoot, root}; + const inline2 = {role: 'inlineTextBox', parent: text2, root}; + assertEquals(svgRoot, ParagraphUtils.getFirstBlockAncestor(text1)); + assertEquals(svgRoot, ParagraphUtils.getFirstBlockAncestor(inline1)); + assertEquals(svgRoot, ParagraphUtils.getFirstBlockAncestor(inline2)); + assertTrue(ParagraphUtils.inSameParagraph(inline1, inline2)); + }); -TEST_F('SelectToSpeakParagraphUnitTest', 'SVGRootIsBlockAncestor', function() { - const root = {role: 'rootWebArea'}; - const svgRoot = {role: 'svgRoot', parent: root, root}; - const text1 = {role: 'staticText', parent: svgRoot, root}; - const inline1 = {role: 'inlineTextBox', parent: text1, root}; - const text2 = {role: 'staticText', parent: svgRoot, root}; - const inline2 = {role: 'inlineTextBox', parent: text2, root}; - assertEquals(svgRoot, ParagraphUtils.getFirstBlockAncestor(text1)); - assertEquals(svgRoot, ParagraphUtils.getFirstBlockAncestor(inline1)); - assertEquals(svgRoot, ParagraphUtils.getFirstBlockAncestor(inline2)); - assertTrue(ParagraphUtils.inSameParagraph(inline1, inline2)); -}); - - -TEST_F('SelectToSpeakParagraphUnitTest', 'InSameParagraph', function() { +SYNC_TEST_F('SelectToSpeakParagraphUnitTest', 'InSameParagraph', function() { const root = {role: 'rootWebArea'}; const paragraph1 = {role: 'paragraph', display: 'block', parent: 'rootWebArea', root}; @@ -54,7 +64,7 @@ assertFalse(ParagraphUtils.inSameParagraph(text1, text3)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BlockDivBreaksSameParagraph', function() { const root = {role: 'rootWebArea'}; @@ -70,7 +80,7 @@ assertTrue(ParagraphUtils.inSameParagraph(text3, text4)); }); -TEST_F('SelectToSpeakParagraphUnitTest', 'IsWhitespace', function() { +SYNC_TEST_F('SelectToSpeakParagraphUnitTest', 'IsWhitespace', function() { assertTrue(ParagraphUtils.isWhitespace('')); assertTrue(ParagraphUtils.isWhitespace(' ')); assertTrue(ParagraphUtils.isWhitespace(' \n \t ')); @@ -79,7 +89,7 @@ assertFalse(ParagraphUtils.isWhitespace(' cats ')); }); -TEST_F('SelectToSpeakParagraphUnitTest', 'GetNodeName', function() { +SYNC_TEST_F('SelectToSpeakParagraphUnitTest', 'GetNodeName', function() { assertEquals( ParagraphUtils.getNodeName({role: 'staticText', name: 'cat'}), 'cat'); assertEquals( @@ -115,7 +125,7 @@ 'partially selected'); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'GetStartCharIndexInParent', function() { const staticText = { role: 'staticText', @@ -145,7 +155,7 @@ assertEquals(ParagraphUtils.getStartCharIndexInParent(inline3), 17); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'FindInlineTextNodeByCharIndex', function() { const staticText = { @@ -180,7 +190,7 @@ null); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'FindInlineTextNodeIndexByCharIndex', function() { const staticText = { @@ -221,7 +231,7 @@ -1); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupStopsAtNewParagraph', function() { const root = {role: 'rootWebArea'}; @@ -247,7 +257,7 @@ assertEquals(paragraph1, result.blockParent); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupAcrossParagraphs', function() { const root = {role: 'rootWebArea'}; @@ -274,7 +284,7 @@ assertEquals(text3, result.nodes[2].node); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupStopsAtLanguageBoundary', function() { const splitOnLanguage = true; @@ -325,7 +335,7 @@ assertEquals('fr-FR', result2.detectedLanguage); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupStopsAtLanguageBoundaryAllUndefined', function() { const splitOnLanguage = true; @@ -349,7 +359,7 @@ assertEquals(undefined, result.detectedLanguage); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupStopsAtLanguageBoundaryLastNode', function() { const splitOnLanguage = true; @@ -379,7 +389,7 @@ assertEquals('fr-FR', result.detectedLanguage); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupSplitOnLanguageDisabled', function() { // Test behaviour with splitOnLanguage disabled. This is to show that we @@ -413,7 +423,7 @@ assertEquals(undefined, result.detectedLanguage); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupStopsAtLanguageBoundarySomeUndefined', function() { const splitOnLanguage = true; @@ -453,7 +463,7 @@ assertEquals('en-US', result.detectedLanguage); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupIncludesLinks', function() { const root = {role: 'rootWebArea'}; @@ -478,7 +488,7 @@ assertEquals(paragraph1, result.blockParent); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupNativeTextBox', function() { const root = {role: 'desktop'}; @@ -499,20 +509,23 @@ assertEquals('Address and search bar ', result.text); }); -TEST_F('SelectToSpeakParagraphUnitTest', 'BuildNodeGroupWithSvg', function() { - const root = {role: 'rootWebArea'}; - const svgRoot = {role: 'svgRoot', parent: root, root}; - const text1 = {role: 'staticText', parent: svgRoot, root, name: 'Hello,'}; - const inline1 = {role: 'inlineTextBox', parent: text1, root, name: 'Hello,'}; - const text2 = {role: 'staticText', parent: svgRoot, root, name: 'world!'}; - const inline2 = {role: 'inlineTextBox', parent: text2, root, name: 'world!'}; +SYNC_TEST_F( + 'SelectToSpeakParagraphUnitTest', 'BuildNodeGroupWithSvg', function() { + const root = {role: 'rootWebArea'}; + const svgRoot = {role: 'svgRoot', parent: root, root}; + const text1 = {role: 'staticText', parent: svgRoot, root, name: 'Hello,'}; + const inline1 = + {role: 'inlineTextBox', parent: text1, root, name: 'Hello,'}; + const text2 = {role: 'staticText', parent: svgRoot, root, name: 'world!'}; + const inline2 = + {role: 'inlineTextBox', parent: text2, root, name: 'world!'}; - const result = ParagraphUtils.buildNodeGroup( - [inline1, inline2], 0, {splitOnLanguage: false}); - assertEquals('Hello, world! ', result.text); -}); + const result = ParagraphUtils.buildNodeGroup( + [inline1, inline2], 0, {splitOnLanguage: false}); + assertEquals('Hello, world! ', result.text); + }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'findNodeFromNodeGroupByCharIndex', function() { // The array has four inline text nodes and one static text node. @@ -564,7 +577,7 @@ assertEquals(result.node, null); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakParagraphUnitTest', 'BuildSingleNodeGroupWithOffset', function() { // The array has four inline text nodes and one static text node. @@ -675,4 +688,4 @@ }; return [inlineText1, inlineText2, inlineText3, inlineText4, text3]; -} \ No newline at end of file +}
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js index 009063d..b49af183 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
@@ -5,7 +5,7 @@ /** * Manages getting and storing user preferences. */ -class PrefsManager { +export class PrefsManager { constructor() { /** @private {?string} */ this.voiceNameFromPrefs_ = null;
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js index 50f0d2d..66db632 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js
@@ -2,18 +2,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var AutomationEvent = chrome.automation.AutomationEvent; -var EventType = chrome.automation.EventType; -var RoleType = chrome.automation.RoleType; +import {InputHandler} from './input_handler.js'; +import {MetricsUtils} from './metrics_utils.js'; +import {NodeUtils} from './node_utils.js'; +import {ParagraphUtils} from './paragraph_utils.js'; +import {PrefsManager} from './prefs_manager.js'; +import {SelectToSpeakConstants} from './select_to_speak_constants.js'; +import {SentenceUtils} from './sentence_utils.js'; +import {WordUtils} from './word_utils.js'; + +const AutomationNode = chrome.automation.AutomationNode; +const AutomationEvent = chrome.automation.AutomationEvent; +const EventType = chrome.automation.EventType; +const RoleType = chrome.automation.RoleType; const AccessibilityFeature = chrome.accessibilityPrivate.AccessibilityFeature; const SelectToSpeakPanelAction = chrome.accessibilityPrivate.SelectToSpeakPanelAction; const FocusRingStackingOrder = chrome.accessibilityPrivate.FocusRingStackingOrder; +const SelectToSpeakState = chrome.accessibilityPrivate.SelectToSpeakState; // This must be the same as in ash/system/accessibility/select_to_speak_tray.cc: // ash::kSelectToSpeakTrayClassName. -const SELECT_TO_SPEAK_TRAY_CLASS_NAME = +export const SELECT_TO_SPEAK_TRAY_CLASS_NAME = 'tray/TrayBackgroundView/SelectToSpeakTray'; // This must match the name of view class that implements the menu view: @@ -56,7 +67,7 @@ * @return {?AutomationNode} The root node of the GSuite app, or null if none is * found. */ -function getGSuiteAppRoot(node) { +export function getGSuiteAppRoot(node) { while (node !== undefined && node.root !== undefined) { if (node.root.url !== undefined && GSUITE_APP_REGEXP.exec(node.root.url)) { return node.root; @@ -66,7 +77,7 @@ return null; } -class SelectToSpeak { +export class SelectToSpeak { constructor() { /** * The current state of the SelectToSpeak extension, from @@ -331,8 +342,9 @@ return; } if (this.shouldShowNavigationControls_() && nodes.length > 0 && - (rect.width <= SelectToSpeak.PARAGRAPH_SELECTION_MAX_SIZE || - rect.height <= SelectToSpeak.PARAGRAPH_SELECTION_MAX_SIZE)) { + (rect.width <= SelectToSpeakConstants.PARAGRAPH_SELECTION_MAX_SIZE || + rect.height <= + SelectToSpeakConstants.PARAGRAPH_SELECTION_MAX_SIZE)) { // If this is a single click (zero sized selection) on a text node, then // expand to entire paragraph. nodes = NodeUtils.getAllNodesInParagraph(nodes[0]); @@ -1653,7 +1665,7 @@ } this.intervalRef_ = setInterval( this.testCurrentNode_.bind(this), - SelectToSpeak.NODE_STATE_TEST_INTERVAL_MS); + SelectToSpeakConstants.NODE_STATE_TEST_INTERVAL_MS); } /** @@ -2067,30 +2079,3 @@ this.inputHandler_.onMouseUp_(event); } } - -/** @const {number} */ -SelectToSpeak.SEARCH_KEY_CODE = KeyCode.SEARCH; - -/** @const {number} */ -SelectToSpeak.CONTROL_KEY_CODE = KeyCode.CONTROL; - -/** @const {number} */ -SelectToSpeak.READ_SELECTION_KEY_CODE = KeyCode.S; - -/** - * How often (in ms) to check that the currently spoken node is - * still valid and in the same position. Decreasing this will make - * STS seem more reactive to page changes but decreasing it too much - * could cause performance issues. - * @const {number} - */ -SelectToSpeak.NODE_STATE_TEST_INTERVAL_MS = 500; - -/** - * Max size in pixels for a region selection to be considered a paragraph - * selection vs a selection of specific nodes. Generally paragraph - * selection is a single click (size 0), though allow for a little - * jitter. - * @const {number} - */ -SelectToSpeak.PARAGRAPH_SELECTION_MAX_SIZE = 5;
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_constants.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_constants.js new file mode 100644 index 0000000..db268cb --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_constants.js
@@ -0,0 +1,32 @@ +// 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. + +export class SelectToSpeakConstants {} + +/** @const {number} */ +SelectToSpeakConstants.SEARCH_KEY_CODE = KeyCode.SEARCH; + +/** @const {number} */ +SelectToSpeakConstants.CONTROL_KEY_CODE = KeyCode.CONTROL; + +/** @const {number} */ +SelectToSpeakConstants.READ_SELECTION_KEY_CODE = KeyCode.S; + +/** + * How often (in ms) to check that the currently spoken node is + * still valid and in the same position. Decreasing this will make + * STS seem more reactive to page changes but decreasing it too much + * could cause performance issues. + * @const {number} + */ +SelectToSpeakConstants.NODE_STATE_TEST_INTERVAL_MS = 500; + +/** + * Max size in pixels for a region selection to be considered a paragraph + * selection vs a selection of specific nodes. Generally paragraph + * selection is a single click (size 0), though allow for a little + * jitter. + * @const {number} + */ +SelectToSpeakConstants.PARAGRAPH_SELECTION_MAX_SIZE = 5;
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_e2e_test_base.js index 92e614c4..179af3e 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_e2e_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_e2e_test_base.js
@@ -67,13 +67,14 @@ assertFalse(this.mockTts.currentlySpeaking()); assertEquals(this.mockTts.pendingUtterances().length, 0); selectToSpeak.fireMockKeyDownEvent( - {keyCode: SelectToSpeak.SEARCH_KEY_CODE}); + {keyCode: SelectToSpeakConstants.SEARCH_KEY_CODE}); selectToSpeak.fireMockKeyDownEvent( - {keyCode: SelectToSpeak.READ_SELECTION_KEY_CODE}); + {keyCode: SelectToSpeakConstants.READ_SELECTION_KEY_CODE}); assertTrue(selectToSpeak.inputHandler_.isSelectionKeyDown_); selectToSpeak.fireMockKeyUpEvent( - {keyCode: SelectToSpeak.READ_SELECTION_KEY_CODE}); - selectToSpeak.fireMockKeyUpEvent({keyCode: SelectToSpeak.SEARCH_KEY_CODE}); + {keyCode: SelectToSpeakConstants.READ_SELECTION_KEY_CODE}); + selectToSpeak.fireMockKeyUpEvent( + {keyCode: SelectToSpeakConstants.SEARCH_KEY_CODE}); } /** @@ -83,10 +84,11 @@ */ triggerReadMouseSelectedText(downEvent, upEvent) { selectToSpeak.fireMockKeyDownEvent( - {keyCode: SelectToSpeak.SEARCH_KEY_CODE}); + {keyCode: SelectToSpeakConstants.SEARCH_KEY_CODE}); selectToSpeak.fireMockMouseDownEvent(downEvent); selectToSpeak.fireMockMouseUpEvent(upEvent); - selectToSpeak.fireMockKeyUpEvent({keyCode: SelectToSpeak.SEARCH_KEY_CODE}); + selectToSpeak.fireMockKeyUpEvent( + {keyCode: SelectToSpeakConstants.SEARCH_KEY_CODE}); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js index c3dd794..4dee458 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_keystroke_selection_test.js
@@ -16,6 +16,20 @@ chrome.tts = this.mockTts; } + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + (async function() { + let module = await import('/select_to_speak/select_to_speak_main.js'); + window.selectToSpeak = module.selectToSpeak; + + module = await import('/select_to_speak/select_to_speak_constants.js'); + window.SelectToSpeakConstants = module.SelectToSpeakConstants; + + runTest(); + })(); + } + /** * Function to load a simple webpage, select some of the single text * node, and trigger Select-to-Speak to read that partial node. Tests @@ -690,4 +704,4 @@ this.assertEqualsCollapseWhitespace( this.mockTts.pendingUtterances()[0], 'My cat is Grumpy!'); }); - }); \ No newline at end of file + });
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.js index cec34e8..6f2df8f59 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_main.js
@@ -2,5 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {SelectToSpeak} from './select_to_speak.js'; + InstanceChecker.closeExtraInstances(); -const selectToSpeak = new SelectToSpeak(); +export const selectToSpeak = new SelectToSpeak();
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js index 25937af..f2426e2 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js
@@ -16,11 +16,33 @@ chrome.tts = this.mockTts; } + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + + window.EventType = chrome.automation.EventType; + window.SelectToSpeakState = chrome.accessibilityPrivate.SelectToSpeakState; + + (async function() { + let module = await import('/select_to_speak/select_to_speak_main.js'); + window.selectToSpeak = module.selectToSpeak; + + module = await import('/select_to_speak/select_to_speak.js'); + window.SELECT_TO_SPEAK_TRAY_CLASS_NAME = + module.SELECT_TO_SPEAK_TRAY_CLASS_NAME; + + module = await import('/select_to_speak/select_to_speak_constants.js'); + window.SelectToSpeakConstants = module.SelectToSpeakConstants; + + runTest(); + })(); + } + tapTrayButton(desktop, callback) { const button = desktop.find({ - roleType: 'button', attributes: {className: SELECT_TO_SPEAK_TRAY_CLASS_NAME} }); + callback = this.newCallback(callback); selectToSpeak.onStateChangeRequestedCallbackForTest_ = this.newCallback(() => { @@ -231,7 +253,6 @@ this.tapTrayButton(desktop, () => { assertEquals(selectToSpeak.state_, SelectToSpeakState.SELECTING); const button = desktop.find({ - roleType: 'button', attributes: {className: SELECT_TO_SPEAK_TRAY_CLASS_NAME} });
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js index 8df3661..8ca7a00e 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js
@@ -16,6 +16,28 @@ } /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + + window.EventType = chrome.automation.EventType; + window.SelectToSpeakState = chrome.accessibilityPrivate.SelectToSpeakState; + + (async function() { + let module = await import('/select_to_speak/select_to_speak_main.js'); + window.selectToSpeak = module.selectToSpeak; + + module = await import('/select_to_speak/select_to_speak.js'); + window.SELECT_TO_SPEAK_TRAY_CLASS_NAME = + module.SELECT_TO_SPEAK_TRAY_CLASS_NAME; + + module = await import('/select_to_speak/select_to_speak_constants.js'); + window.SelectToSpeakConstants = module.SelectToSpeakConstants; + + runTest(); + })(); + } + + /** @override */ get featureList() { return {enabled: ['features::kSelectToSpeakNavigationControl']}; } @@ -637,4 +659,4 @@ // Perform resize. resizeButton.doDefault(); }); -}); \ No newline at end of file +});
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js index a7ea4ef..378c980 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {PrefsManager} from './prefs_manager.js'; + class SelectToSpeakOptionsPage { constructor() { this.init_();
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js index 1ebdae7..b2a2c80 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js
@@ -31,8 +31,23 @@ return msgid; } }; + } - this.resetStorage(); + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + + (async () => { + let module = await import('/select_to_speak/select_to_speak_main.js'); + window.selectToSpeak = module.selectToSpeak; + + module = await import('/select_to_speak/select_to_speak_constants.js'); + window.SelectToSpeakConstants = module.SelectToSpeakConstants; + + this.resetStorage(); + + runTest(); + })(); } resetStorage() {
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js index 1671ea4..ba1da17 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_unittest.js
@@ -2,19 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +GEN_INCLUDE(['select_to_speak_e2e_test_base.js']); + /** * Test fixture for select_to_speak.js. */ -SelectToSpeakUnitTest = class extends testing.Test {}; +SelectToSpeakUnitTest = class extends SelectToSpeakE2ETest { + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + (async function() { + const module = await import('/select_to_speak/select_to_speak.js'); + window.getGSuiteAppRoot = module.getGSuiteAppRoot; -/** @override */ -SelectToSpeakUnitTest.prototype.extraLibraries = [ - '../common/closure_shim.js', '../common/key_code.js', 'test_support.js', - 'select_to_speak.js' -]; + runTest(); + })(); + } +}; - -TEST_F('SelectToSpeakUnitTest', 'getGSuiteAppRoot', function() { +SYNC_TEST_F('SelectToSpeakUnitTest', 'getGSuiteAppRoot', function() { const root = {url: 'https://docs.google.com/presentation/p/cats_r_awesome'}; const div1 = {root}; const frame1 = {url: 'about:blank', parent: div1};
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils.js index 36cf91e2..8637d2f 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils.js
@@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {ParagraphUtils} from './paragraph_utils.js'; + +const RoleType = chrome.automation.RoleType; + /** * Utilities for processing sentences within strings and node groups. */ -class SentenceUtils { +export class SentenceUtils { constructor() {} /** @@ -80,7 +84,7 @@ return null; } // Check if this nodeGroupItem has a non-empty static text node. - if (!nodeGroupItem.node.role === RoleType.STATIC_TEXT || + if (nodeGroupItem.node.role !== RoleType.STATIC_TEXT || nodeGroupItem.node.name.length === 0) { return null; } @@ -157,7 +161,7 @@ for (let i = 0; i < nodeGroup.nodes.length; i++) { const nodeGroupItem = nodeGroup.nodes[i]; // Check if this nodeGroupItem has a non-empty static text node. - if (!nodeGroupItem.node.role === RoleType.STATIC_TEXT || + if (nodeGroupItem.node.role !== RoleType.STATIC_TEXT || nodeGroupItem.node.name.length === 0) { continue; } @@ -186,4 +190,4 @@ // We did not find a sentence start equal to |currentCharIndex|. return false; } -} \ No newline at end of file +}
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils_unittest.js index c689f8d4..a86e3fa 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/sentence_utils_unittest.js
@@ -2,25 +2,28 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +GEN_INCLUDE(['select_to_speak_e2e_test_base.js']); + /** * Test fixture for sentence_utils.js. */ -SelectToSpeakSentenceUtilsUnitTest = class extends testing.Test {}; +SelectToSpeakSentenceUtilsUnitTest = class extends SelectToSpeakE2ETest { + /** @override */ + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + (async function() { + const module = await import('/select_to_speak/sentence_utils.js'); + window.SentenceUtils = module.SentenceUtils; -/** @override */ -SelectToSpeakSentenceUtilsUnitTest.prototype.extraLibraries = [ - 'test_support.js', - 'sentence_utils.js', - 'paragraph_utils.js', - '../common/closure_shim.js', - '../common/constants.js', -]; + runTest(); + })(); + } +}; -TEST_F( +SYNC_TEST_F( 'SelectToSpeakSentenceUtilsUnitTest', 'getNextSentenceStart', function() { // The text of the test node group is "Hello. New. World." const nodeGroup = getTestNodeGroupWithOneNode(); - assertEquals( 7, SentenceUtils.getSentenceStart( @@ -48,7 +51,7 @@ constants.Dir.FORWARD /* direction */)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakSentenceUtilsUnitTest', 'getPrevSentenceStart', function() { // The text of the test node group is "Hello. New. World." const nodeGroup = getTestNodeGroupWithOneNode(); @@ -80,7 +83,7 @@ constants.Dir.BACKWARD /* direction */)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakSentenceUtilsUnitTest', 'getNextSentenceStartMultiNodes', function() { // The text of the test node group is "Hello. New. Beautiful. World." The @@ -114,7 +117,7 @@ constants.Dir.FORWARD /* direction */)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakSentenceUtilsUnitTest', 'getPrevSentenceStartMultiNodes', function() { // The text of the test node group is "Hello. New. Beautiful. World." The @@ -148,7 +151,7 @@ constants.Dir.BACKWARD /* direction */)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakSentenceUtilsUnitTest', 'getNextSentenceStartSentenceSpanningAcrossMultiNodes', function() { // The text of the test node group is "Hello world. New world." The @@ -177,7 +180,7 @@ constants.Dir.FORWARD /* direction */)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakSentenceUtilsUnitTest', 'getPrevSentenceStartSentenceSpanningAcrossMultiNodes', function() { // The text of the test node group is "Hello world. New world." The @@ -211,34 +214,34 @@ constants.Dir.BACKWARD /* direction */)); }); +SYNC_TEST_F( + 'SelectToSpeakSentenceUtilsUnitTest', 'isSentenceStart', function() { + // The text of the test node group is "Hello. New. World." + const nodeGroup = getTestNodeGroupWithOneNode(); -TEST_F('SelectToSpeakSentenceUtilsUnitTest', 'isSentenceStart', function() { - // The text of the test node group is "Hello. New. World." - const nodeGroup = getTestNodeGroupWithOneNode(); + assertEquals( + true, + SentenceUtils.isSentenceStart( + nodeGroup /* nodeGroup */, 0 /* startCharIndex */)); + assertEquals( + false, + SentenceUtils.isSentenceStart( + nodeGroup /* nodeGroup */, 3 /* startCharIndex */)); + assertEquals( + true, + SentenceUtils.isSentenceStart( + nodeGroup /* nodeGroup */, 7 /* startCharIndex */)); + assertEquals( + false, + SentenceUtils.isSentenceStart( + nodeGroup /* nodeGroup */, 11 /* startCharIndex */)); + assertEquals( + true, + SentenceUtils.isSentenceStart( + nodeGroup /* nodeGroup */, 12 /* startCharIndex */)); + }); - assertEquals( - true, - SentenceUtils.isSentenceStart( - nodeGroup /* nodeGroup */, 0 /* startCharIndex */)); - assertEquals( - false, - SentenceUtils.isSentenceStart( - nodeGroup /* nodeGroup */, 3 /* startCharIndex */)); - assertEquals( - true, - SentenceUtils.isSentenceStart( - nodeGroup /* nodeGroup */, 7 /* startCharIndex */)); - assertEquals( - false, - SentenceUtils.isSentenceStart( - nodeGroup /* nodeGroup */, 11 /* startCharIndex */)); - assertEquals( - true, - SentenceUtils.isSentenceStart( - nodeGroup /* nodeGroup */, 12 /* startCharIndex */)); -}); - -TEST_F( +SYNC_TEST_F( 'SelectToSpeakSentenceUtilsUnitTest', 'isSentenceStartMultiNodes', function() { // The text of the test node group is "Hello. New. Beautiful. World." The @@ -275,7 +278,11 @@ nodeGroup /* nodeGroup */, 23 /* startCharIndex */)); }); function getTestNodeGroupWithOneNode() { - const staticText = {sentenceStarts: [0, 7, 12], name: 'Hello. New. World.'}; + const staticText = { + sentenceStarts: [0, 7, 12], + name: 'Hello. New. World.', + role: 'staticText' + }; const node = {node: staticText, startChar: 0}; return {nodes: [node], text: 'Hello. New. World.'}; } @@ -313,4 +320,4 @@ const node3 = {node: staticText3, startChar: 16}; return {nodes: [node1, node2, node3], text: 'Hello world. New world.'}; -} \ No newline at end of file +}
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/test_support.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/test_support.js deleted file mode 100644 index 4ac8144..0000000 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/test_support.js +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Stubs out extension API functions so that SelectToSpeakUnitTest - * can load. - */ - -chrome.automation = {}; - -/** - * Stub - */ -chrome.automation.getDesktop = function() {}; - -/** - * Set necessary constants. - */ -chrome.automation.RoleType = { - CHECK_BOX: 'checkBox', - INLINE_TEXT_BOX: 'inlineTextBox', - MENU_ITEM_CHECK_BOX: 'menuItemCheckBox', - MENU_ITEM_RADIO: 'menuItemRadio', - PARAGRAPH: 'paragraph', - RADIO_BUTTON: 'radioButton', - ROOT_WEB_AREA: 'rootWebArea', - STATIC_TEXT: 'staticText', - SVG_ROOT: 'svgRoot', - TEXT_FIELD: 'textField', - WINDOW: 'window' -}; - -chrome.automation.StateType = { - INVISIBLE: 'invisible' -}; - -chrome.metricsPrivate = { - recordUserAction() {}, - recordValue() {}, - MetricTypeType: {HISTOGRAM_LINEAR: 1} -}; - -chrome.commandLinePrivate = { - hasSwitch() {} -}; - -chrome.accessibilityPrivate = {}; - -chrome.accessibilityPrivate.SelectToSpeakState = { - INACTIVE: 'inactive', - SELECTING: 'selecting', - SPEAKING: 'speaking' -}; - -chrome.i18n = { - getMessage(key) { - if (key === 'select_to_speak_checkbox_checked') { - return 'checked'; - } - if (key === 'select_to_speak_checkbox_unchecked') { - return 'unchecked'; - } - if (key === 'select_to_speak_checkbox_mixed') { - return 'partially checked'; - } - if (key === 'select_to_speak_radiobutton_selected') { - return 'selected'; - } - if (key === 'select_to_speak_radiobutton_unselected') { - return 'unselected'; - } - if (key === 'select_to_speak_radiobutton_mixed') { - return 'partially selected'; - } - return ''; - } -};
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils.js index fe4f86c1..a46c7ec4 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils.js
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {ParagraphUtils} from './paragraph_utils.js'; + // Utilities for processing words within strings and nodes. -class WordUtils { +export class WordUtils { constructor() {} /**
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils_unittest.js index 76e34082..7affeb6 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/word_utils_unittest.js
@@ -2,20 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +GEN_INCLUDE(['select_to_speak_e2e_test_base.js']); + /** * Test fixture for word_utils.js. */ -SelectToSpeakWordUtilsUnitTest = class extends testing.Test {}; +SelectToSpeakWordUtilsUnitTest = class extends SelectToSpeakE2ETest { + setUp() { + var runTest = this.deferRunTest(WhenTestDone.EXPECT); + (async function() { + const module = await import('/select_to_speak/word_utils.js'); + window.WordUtils = module.WordUtils; -/** @override */ -SelectToSpeakWordUtilsUnitTest.prototype.extraLibraries = [ - 'test_support.js', - 'paragraph_utils.js', - 'word_utils.js', -]; + runTest(); + })(); + } +}; - -TEST_F( +SYNC_TEST_F( 'SelectToSpeakWordUtilsUnitTest', 'getNextWordStartWithoutWordStarts', function() { const node = {node: {}}; @@ -26,7 +30,7 @@ assertEquals(7, WordUtils.getNextWordStart('kitty "cat"', 5, node)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakWordUtilsUnitTest', 'getNextWordEndWithoutWordEnds', function() { const node = {node: {}}; @@ -36,7 +40,7 @@ assertEquals(9, WordUtils.getNextWordEnd('kitty cat', 7, node)); }); -TEST_F('SelectToSpeakWordUtilsUnitTest', 'getNextWordStart', function() { +SYNC_TEST_F('SelectToSpeakWordUtilsUnitTest', 'getNextWordStart', function() { const inlineText = {wordStarts: [0, 6], name: 'kitty cat'}; const staticText = {children: [inlineText], name: 'kitty cat'}; const node = {node: staticText, startChar: 0, hasInlineText: true}; @@ -54,7 +58,7 @@ 10, WordUtils.getNextWordStart('once upon a kitty cat', 10, node)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakWordUtilsUnitTest', 'getNextWordStartIgnoresStartCharOffset', function() { const inlineText = { @@ -78,7 +82,7 @@ 10, WordUtils.getNextWordStart('once upon a kitty cat', 10, node)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakWordUtilsUnitTest', 'getNextWordStartMultipleChildren', function() { const inlineText1 = { @@ -104,7 +108,7 @@ 13, WordUtils.getNextWordStart('kitty cat is cute', 11, node)); }); -TEST_F('SelectToSpeakWordUtilsUnitTest', 'getNextWordEnd', function() { +SYNC_TEST_F('SelectToSpeakWordUtilsUnitTest', 'getNextWordEnd', function() { const inlineText = {wordEnds: [5, 9], name: 'kitty cat'}; const staticText = {children: [inlineText], name: 'kitty cat'}; const node = {node: staticText, startChar: 0, hasInlineText: true}; @@ -122,7 +126,7 @@ assertEquals(5, WordUtils.getNextWordEnd('kitty cat', 4, node)); }); -TEST_F( +SYNC_TEST_F( 'SelectToSpeakWordUtilsUnitTest', 'getNextWordEndMultipleChildren', function() { const inlineText1 = {
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2 b/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2 index cca4540..9583ec1b 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2 +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak_manifest.json.jinja2
@@ -10,25 +10,7 @@ "incognito": "split", {% endif %} "background": { - "scripts": [ - "common/closure_shim.js", - "common/constants.js", - "common/key_code.js", - "common/automation_predicate.js", - "common/instance_checker.js", - "common/rect_util.js", - "common/tree_walker.js", - "common/automation_util.js", - "select_to_speak/input_handler.js", - "select_to_speak/metrics_utils.js", - "select_to_speak/node_utils.js", - "select_to_speak/paragraph_utils.js", - "select_to_speak/prefs_manager.js", - "select_to_speak/word_utils.js", - "select_to_speak/sentence_utils.js", - "select_to_speak/select_to_speak.js", - "select_to_speak/select_to_speak_main.js" - ] + "page": "select_to_speak/background.html" }, "permissions": [ "accessibilityPrivate",
diff --git a/chrome/browser/resources/pdf/gesture_detector.js b/chrome/browser/resources/pdf/gesture_detector.js index 827725f..5c08d70 100644 --- a/chrome/browser/resources/pdf/gesture_detector.js +++ b/chrome/browser/resources/pdf/gesture_detector.js
@@ -102,7 +102,7 @@ this.pinchStartEvent_ = event; this.lastEvent_ = event; - this.notify_('pinchstart', {center: GestureDetector.center_(event)}); + this.notify_('pinchstart', {center: center(event)}); } /** @@ -120,27 +120,23 @@ // Check if the pinch ends with the current event. if (event.touches.length < 2 || lastEvent.touches.length !== event.touches.length) { - const startScaleRatio = - GestureDetector.pinchScaleRatio_(lastEvent, this.pinchStartEvent_); - const center = GestureDetector.center_(lastEvent); + const startScaleRatio = pinchScaleRatio(lastEvent, this.pinchStartEvent_); this.pinchStartEvent_ = null; this.lastEvent_ = null; this.notify_('pinchend', { startScaleRatio: startScaleRatio, - center: center, + center: center(lastEvent), }); return; } - const scaleRatio = GestureDetector.pinchScaleRatio_(event, lastEvent); - const startScaleRatio = - GestureDetector.pinchScaleRatio_(event, this.pinchStartEvent_); - const center = GestureDetector.center_(event); + const scaleRatio = pinchScaleRatio(event, lastEvent); + const startScaleRatio = pinchScaleRatio(event, this.pinchStartEvent_); this.notify_('pinchupdate', { scaleRatio: scaleRatio, direction: scaleRatio > 1.0 ? 'in' : 'out', startScaleRatio: startScaleRatio, - center: center, + center: center(event), }); this.lastEvent_ = event; @@ -222,50 +218,47 @@ e.preventDefault(); } } +} - /** - * Computes the change in scale between this touch event - * and a previous one. - * @param {!TouchEvent} event Latest touch event on the element. - * @param {!TouchEvent} prevEvent A previous touch event on the element. - * @return {?number} The ratio of the scale of this event and the - * scale of the previous one. - * @private - */ - static pinchScaleRatio_(event, prevEvent) { - const distance1 = GestureDetector.distance_(prevEvent); - const distance2 = GestureDetector.distance_(event); - return distance1 === 0 ? null : distance2 / distance1; - } +/** + * Computes the change in scale between this touch event + * and a previous one. + * @param {!TouchEvent} event Latest touch event on the element. + * @param {!TouchEvent} prevEvent A previous touch event on the element. + * @return {?number} The ratio of the scale of this event and the + * scale of the previous one. + */ +function pinchScaleRatio(event, prevEvent) { + const distance1 = distance(prevEvent); + const distance2 = distance(event); + return distance1 === 0 ? null : distance2 / distance1; +} - /** - * Computes the distance between fingers. - * @param {!TouchEvent} event Touch event with at least 2 touch points. - * @return {number} Distance between touch[0] and touch[1]. - * @private - */ - static distance_(event) { - const touch1 = event.touches[0]; - const touch2 = event.touches[1]; - const dx = touch1.clientX - touch2.clientX; - const dy = touch1.clientY - touch2.clientY; - return Math.sqrt(dx * dx + dy * dy); - } +/** + * Computes the distance between fingers. + * @param {!TouchEvent} event Touch event with at least 2 touch points. + * @return {number} Distance between touch[0] and touch[1]. + */ +function distance(event) { + const touch1 = event.touches[0]; + const touch2 = event.touches[1]; + const dx = touch1.clientX - touch2.clientX; + const dy = touch1.clientY - touch2.clientY; + return Math.sqrt(dx * dx + dy * dy); +} - /** - * Computes the midpoint between fingers. - * @param {!TouchEvent} event Touch event with at least 2 touch points. - * @return {!Point} Midpoint between touch[0] and touch[1]. - * @private - */ - static center_(event) { - const touch1 = event.touches[0]; - const touch2 = event.touches[1]; - return { - x: (touch1.clientX + touch2.clientX) / 2, - y: (touch1.clientY + touch2.clientY) / 2 - }; - } +/** + * Computes the midpoint between fingers. + * @param {!TouchEvent} event Touch event with at least 2 touch points. + * @return {!Point} Midpoint between touch[0] and touch[1]. + */ +function center(event) { + const touch1 = event.touches[0]; + const touch2 = event.touches[1]; + return { + x: (touch1.clientX + touch2.clientX) / 2, + y: (touch1.clientY + touch2.clientY) / 2 + }; } // Export on |window| such that scripts injected from pdf_extension_test.cc can
diff --git a/chrome/browser/resources/pdf/metrics.js b/chrome/browser/resources/pdf/metrics.js index 949adcfb..83f8fa5 100644 --- a/chrome/browser/resources/pdf/metrics.js +++ b/chrome/browser/resources/pdf/metrics.js
@@ -47,8 +47,8 @@ if (!chrome.metricsPrivate) { return; } - if (!PDFMetrics.actionsMetric_) { - PDFMetrics.actionsMetric_ = { + if (!actionsMetric) { + actionsMetric = { 'metricName': 'PDF.Actions', 'type': chrome.metricsPrivate.MetricTypeType.HISTOGRAM_LOG, 'min': 1, @@ -56,28 +56,27 @@ 'buckets': UserAction.NUMBER_OF_ACTIONS + 1 }; } - chrome.metricsPrivate.recordValue(PDFMetrics.actionsMetric_, action); - if (PDFMetrics.firstMap_.has(action)) { - const firstAction = PDFMetrics.firstMap_.get(action); - if (!PDFMetrics.firstActionRecorded_.has(firstAction)) { - chrome.metricsPrivate.recordValue( - PDFMetrics.actionsMetric_, firstAction); - PDFMetrics.firstActionRecorded_.add(firstAction); + chrome.metricsPrivate.recordValue(actionsMetric, action); + if (firstMap.has(action)) { + const firstAction = firstMap.get(action); + if (!firstActionRecorded.has(firstAction)) { + chrome.metricsPrivate.recordValue(actionsMetric, firstAction); + firstActionRecorded.add(firstAction); } } } static resetForTesting() { - PDFMetrics.firstActionRecorded_.clear(); - PDFMetrics.actionsMetric_ = null; + firstActionRecorded.clear(); + actionsMetric = null; } } -/** @private {?chrome.metricsPrivate.MetricType} */ -PDFMetrics.actionsMetric_ = null; +/** @type {?chrome.metricsPrivate.MetricType} */ +let actionsMetric = null; -/** @private {Set} */ -PDFMetrics.firstActionRecorded_ = new Set(); +/** @type {!Set<!UserAction>} */ +const firstActionRecorded = new Set(); // Keep in sync with enums.xml. // Do not change the numeric values or reuse them since these numbers are @@ -218,8 +217,8 @@ // Map from UserAction to the 'FIRST' action. These metrics are recorded // by PDFMetrics.log the first time each corresponding action occurs. -/** @private Map<number, number> */ -PDFMetrics.firstMap_ = new Map([ +/** @type {!Map<!UserAction, !UserAction>} */ +const firstMap = new Map([ [ UserAction.ROTATE, UserAction.ROTATE_FIRST,
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 4f98df83..a047a3a 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -315,7 +315,6 @@ "chromeos/internet_page/esim_remove_profile_dialog.m.js", "chromeos/internet_page/esim_rename_dialog.m.js", "chromeos/internet_page/cellular_networks_list.m.js", - "chromeos/internet_page/cellular_eid_popup.m.js", "chromeos/internet_page/cellular_setup_dialog.m.js", "chromeos/internet_page/cellular_setup_settings_delegate.m.js", "chromeos/internet_page/internet_config.m.js", @@ -603,8 +602,6 @@ "chromeos/internet_page/esim_rename_dialog.html", "chromeos/internet_page/cellular_networks_list.js", "chromeos/internet_page/cellular_networks_list.html", - "chromeos/internet_page/cellular_eid_popup.html", - "chromeos/internet_page/cellular_eid_popup.js", "chromeos/internet_page/cellular_setup_dialog.html", "chromeos/internet_page/cellular_setup_dialog.js", "chromeos/internet_page/cellular_setup_settings_delegate.html",
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn index 028b257..168fadf 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
@@ -8,7 +8,6 @@ js_type_check("closure_compile") { deps = [ - ":cellular_eid_popup", ":cellular_networks_list", ":cellular_setup_dialog", ":esim_remove_profile_dialog", @@ -129,7 +128,6 @@ js_library("internet_subpage") { deps = [ - ":cellular_eid_popup", ":cellular_networks_list", ":internet_page_browser_proxy", "..:deep_linking_behavior", @@ -211,8 +209,9 @@ js_library("cellular_networks_list") { deps = [ - ":cellular_eid_popup", + "//ui/webui/resources/cr_components/chromeos/cellular_setup:cellular_eid_popup", "//ui/webui/resources/cr_components/chromeos/cellular_setup:cellular_types", + "//ui/webui/resources/cr_components/chromeos/cellular_setup:esim_manager_listener_behavior", "//ui/webui/resources/cr_components/chromeos/cellular_setup:esim_manager_utils", "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider", "//ui/webui/resources/cr_components/chromeos/network:network_list_types", @@ -222,10 +221,6 @@ ] } -js_library("cellular_eid_popup") { - deps = [ "//ui/webui/resources/js:i18n_behavior" ] -} - js_library("esim_rename_dialog") { deps = [ "//ui/webui/resources/cr_components/chromeos/cellular_setup:mojo_interface_provider", @@ -250,7 +245,6 @@ js_type_check("closure_compile_module") { is_polymer3 = true deps = [ - ":cellular_eid_popup.m", ":cellular_networks_list.m", ":cellular_setup_dialog.m", ":cellular_setup_settings_delegate.m", @@ -536,6 +530,7 @@ "//chrome/browser/resources/settings/chromeos/localized_link:localized_link.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_components/chromeos/cellular_setup:cellular_types.m", + "//ui/webui/resources/cr_components/chromeos/cellular_setup:esim_manager_listener_behavior.m", "//ui/webui/resources/cr_components/chromeos/cellular_setup:esim_manager_utils.m", "//ui/webui/resources/cr_components/chromeos/network:network_list_types.m", "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m", @@ -544,12 +539,6 @@ extra_deps = [ ":cellular_networks_list_module" ] } -js_library("cellular_eid_popup.m") { - sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/internet_page/cellular_eid_popup.m.js" ] - deps = [ "//ui/webui/resources/js:i18n_behavior.m" ] - extra_deps = [ ":cellular_eid_popup_module" ] -} - js_library("esim_rename_dialog.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/internet_page/esim_rename_dialog.m.js" ] deps = [ @@ -578,7 +567,6 @@ group("polymer3_elements") { public_deps = [ - ":cellular_eid_popup_module", ":cellular_networks_list_module", ":cellular_setup_dialog_module", ":esim_remove_profile_dialog_module", @@ -701,14 +689,6 @@ namespace_rewrites = os_settings_namespace_rewrites } -polymer_modulizer("cellular_eid_popup") { - js_file = "cellular_eid_popup.js" - html_file = "cellular_eid_popup.html" - html_type = "dom-module" - auto_imports = os_settings_auto_imports - namespace_rewrites = os_settings_namespace_rewrites -} - polymer_modulizer("esim_rename_dialog") { js_file = "esim_rename_dialog.js" html_file = "esim_rename_dialog.html"
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.html b/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.html index 9fc2dfd..8386804 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.html
@@ -1,7 +1,9 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.html"> +<link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/esim_manager_utils.html"> +<link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/network/network_list_types.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/network/onc_mojo.html"> <link rel="import" href="chrome://resources/cr_components/chromeos/network/mojo_interface_provider.html"> @@ -13,7 +15,6 @@ <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="../../chromeos/os_settings_icons_css.html"> -<link rel="import" href="./cellular_eid_popup.html"> <dom-module id="cellular-networks-list"> <template> @@ -67,43 +68,45 @@ } </style> - <div class="cellular-network-list-header esim-list-header flex"> - <div class="esim-list-title">$i18n{cellularNetworkEsimLabel}</div> - <div class="flex-column"> - <cr-icon-button - id="eidPopupButton" - iron-icon="cr:info-outline" - title="$i18n{showEidPopupButtonLabel}" - aria-label="$i18n{showEidPopupButtonLabel}" - on-click="toggleEidPopup_"> - </cr-icon-button> - <template is="dom-if" if="[[shouldShowEidPopup_]]" restamp> - <cellular-eid-popup class="eid-popup"> - </cellular-eid-popup> - </template> + <template is="dom-if" if="[[!!euicc_]]" restamp> + <div class="cellular-network-list-header esim-list-header flex"> + <div class="esim-list-title">$i18n{cellularNetworkEsimLabel}</div> + <div class="flex-column"> + <cr-icon-button + id="eidPopupButton" + iron-icon="cr:info-outline" + title="$i18n{showEidPopupButtonLabel}" + aria-label="$i18n{showEidPopupButtonLabel}" + on-click="toggleEidPopup_"> + </cr-icon-button> + <template is="dom-if" if="[[shouldShowEidPopup_]]" restamp> + <cellular-eid-popup class="eid-popup"> + </cellular-eid-popup> + </template> + </div> </div> - </div> - <template is="dom-if" - if="[[shouldShowNetworkSublist_(eSimNetworks_, eSimPendingProfiles_)]]" restamp> - <div class="cellular-network-content"> - <network-list id="esimNetworkList" show-buttons - show-technology-badge="[[showTechnologyBadge]]" - networks="[[eSimNetworks_]]" - custom-items="[[eSimPendingProfiles_]]" - device-state="[[deviceState]]"> - </network-list> - </div> - </template> - <template - is="dom-if" - if="[[!shouldShowNetworkSublist_(eSimNetworks_, eSimPendingProfiles_)]]" restamp> - <div id="eSimNoNetworkFound" - class="cellular-network-content cellular-not-setup"> - <settings-localized-link - on-link-clicked="onEsimLearnMoreClicked_" - localized-string="$i18n{eSimNetworkNotSetup}"> - </settings-localized-link> - </div> + <template is="dom-if" + if="[[shouldShowNetworkSublist_(eSimNetworks_, eSimPendingProfileItems_)]]" restamp> + <div class="cellular-network-content"> + <network-list id="esimNetworkList" show-buttons + show-technology-badge="[[showTechnologyBadge]]" + networks="[[eSimNetworks_]]" + custom-items="[[eSimPendingProfileItems_]]" + device-state="[[deviceState]]"> + </network-list> + </div> + </template> + <template + is="dom-if" + if="[[!shouldShowNetworkSublist_(eSimNetworks_, eSimPendingProfileItems_)]]" restamp> + <div id="eSimNoNetworkFound" + class="cellular-network-content cellular-not-setup"> + <settings-localized-link + on-link-clicked="onEsimLearnMoreClicked_" + localized-string="$i18n{eSimNetworkNotSetup}"> + </settings-localized-link> + </div> + </template> </template> <div class="cellular-network-list-header"> $i18n{cellularNetworkPsimLabel}
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.js b/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.js index c0636dd..48c7799 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/cellular_networks_list.js
@@ -11,6 +11,7 @@ is: 'cellular-networks-list', behaviors: [ + ESimManagerListenerBehavior, I18nBehavior, ], @@ -51,11 +52,24 @@ }, /** + * Dictionary mapping pending eSIM profile iccids to pending eSIM profiles. + * @type {!Map<string, chromeos.cellularSetup.mojom.ESimProfileRemote>} + * @private + */ + profilesMap_: { + type: Object, + value() { + return new Map(); + }, + }, + + /** * The list of pending eSIM profiles to display after the list of eSIM * networks. * @type {!Array<NetworkList.CustomItemState>} + * @private */ - eSimPendingProfiles_: { + eSimPendingProfileItems_: { type: Array, value() { return []; @@ -90,11 +104,21 @@ shouldShowEidPopup_: { type: Boolean, value: false, + }, + + /** + * Euicc object representing the active euicc_ module on the device + * @private {?chromeos.cellularSetup.mojom.EuiccRemote} + */ + euicc_: { + type: Object, + value: null, } }, listeners: { 'close-eid-popup': 'toggleEidPopup_', + 'install-profile': 'installProfile_', }, /** @private {?chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */ @@ -107,43 +131,105 @@ this.fetchESimPendingProfileList_(); }, + /** + * @param {!chromeos.cellularSetup.mojom.EuiccRemote} euicc + * ESimManagerListenerBehavior override + */ + onProfileListChanged(euicc) { + this.fetchESimPendingProfileListForEuicc_(euicc); + }, + + /** + * @param {!chromeos.cellularSetup.mojom.ESimProfileRemote} profile + * ESimManagerListenerBehavior override + */ + onProfileChanged(profile) { + profile.getProperties().then(response => { + const eSimPendingProfileItem = + this.eSimPendingProfileItems_.find(item => { + return item.customData.iccid === response.properties.iccid; + }); + if (!eSimPendingProfileItem) { + return; + } + eSimPendingProfileItem.customItemType = response.properties.state === + chromeos.cellularSetup.mojom.ProfileState.kInstalling ? + NetworkList.CustomItemType.ESIM_INSTALLING_PROFILE : + NetworkList.CustomItemType.ESIM_PENDING_PROFILE; + }); + }, + /** @private */ fetchESimPendingProfileList_() { cellular_setup.getESimManagerRemote() .getAvailableEuiccs() .then(response => { if (response.euiccs.length > 0) { - return cellular_setup.getPendingESimProfiles(response.euiccs[0]); + // Use first available euicc as current. Only single Euicc modules are + // currently supported. + this.euicc_ = response.euiccs[0]; + return this.fetchESimPendingProfileListForEuicc_(this.euicc_); } - throw new Error('No EUICCs available.'); - }) - .then(profiles => { - const pendingProfilePromises = profiles.map(profile => { - return profile.getProperties().then(response => { - return { - customItemType: NetworkList.CustomItemType.ESIM_PENDING_PROFILE, - customItemName: - String.fromCharCode(...response.properties.name.data), - customItemSubtitle: String.fromCharCode( - ...response.properties.serviceProvider.data), - polymerIcon: 'network:cellular-0', - showBeforeNetworksList: false, - customData: { - iccid: response.properties.iccid, - }, - }; - }); - }); - Promise.all(pendingProfilePromises).then(profiles => { - this.eSimPendingProfiles_ = profiles; - }); - }) - .catch(error => { - console.error(error); + this.euicc_ = null; }); }, /** + * @param {!chromeos.cellularSetup.mojom.EuiccRemote} euicc + * @private + */ + fetchESimPendingProfileListForEuicc_(euicc) { + cellular_setup.getPendingESimProfiles(euicc).then( + this.processESimPendingProfiles_.bind(this)); + }, + + /** + * @param {Array<!chromeos.cellularSetup.mojom.ESimProfileRemote>} profiles + * @private + */ + processESimPendingProfiles_(profiles) { + this.profilesMap_ = new Map(); + const eSimPendingProfilePromises = + profiles.map(this.createESimPendingProfilePromise_.bind(this)); + Promise.all(eSimPendingProfilePromises).then(eSimPendingProfileItems => { + this.eSimPendingProfileItems_ = eSimPendingProfileItems; + }); + }, + + /** + * @param {!chromeos.cellularSetup.mojom.ESimProfileRemote} profile + * @return {!Promise<NetworkList.CustomItemState>} + * @private + */ + createESimPendingProfilePromise_(profile) { + return profile.getProperties().then(response => { + this.profilesMap_.set(response.properties.iccid, profile); + return this.createESimPendingProfileItem_(response.properties); + }); + }, + + /** + * @param {!chromeos.cellularSetup.mojom.ESimProfileProperties} properties + * @return {NetworkList.CustomItemState} + */ + createESimPendingProfileItem_(properties) { + return { + customItemType: properties.state === + chromeos.cellularSetup.mojom.ProfileState.kInstalling ? + NetworkList.CustomItemType.ESIM_INSTALLING_PROFILE : + NetworkList.CustomItemType.ESIM_PENDING_PROFILE, + customItemName: String.fromCharCode(...properties.name.data), + customItemSubtitle: + String.fromCharCode(...properties.serviceProvider.data), + polymerIcon: 'network:cellular-0', + showBeforeNetworksList: false, + customData: { + iccid: properties.iccid, + }, + }; + }, + + /** * @private */ async onNetworksListChanged_() { @@ -227,5 +313,19 @@ this.$$('.eid-popup').focus(); }); } - } + }, + + /** + * @param {Event} event + * @private + */ + installProfile_(event) { + const profileIccid = event.detail.iccid; + const profile = this.profilesMap_.get(profileIccid); + profile.installProfile('').then( + () => { + // TODO(crbug.com/1093185) Show error if install fails. + // Show confirmation code page if required. + }); + }, });
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html index 8b1cebd04..0e04f47 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
@@ -137,7 +137,7 @@ <template is="dom-repeat" items="[[languages.inputMethods.enabled]]"> <div class$="list-item [[getInputMethodItemClass_( - item.id, languages.inputMethods.currentId)]] no-outline" + item.id, languages.inputMethods.currentId)]]" actionable on-click="onInputMethodClick_" on-keypress="onInputMethodKeyPress_" tabindex$="[[getInputMethodTabIndex_(
diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc index 4c45c40..fd2058df 100644 --- a/chrome/browser/search_engines/template_url_service_unittest.cc +++ b/chrome/browser/search_engines/template_url_service_unittest.cc
@@ -1967,41 +1967,6 @@ EXPECT_EQ(user5, model()->GetTemplateURLForHost("test5")); } -TEST_F(TemplateURLServiceTest, CleanUpLegacyUniquifiedKeywords) { - test_util()->VerifyLoad(); - - // 1. Add a "better" replaceable engine with keyword = "test1_". - // Expect that the keyword is reset to "test1". - const TemplateURL* replaceable1 = AddKeywordWithDate( - "replaceable1", "test1", "https://test1", std::string(), std::string(), - std::string(), true, "UTF-8", base::Time::FromTimeT(20)); - ASSERT_TRUE(replaceable1); - EXPECT_EQ(replaceable1, - model()->GetTemplateURLForKeyword(base::ASCIIToUTF16("test1"))); - EXPECT_FALSE(model()->GetTemplateURLForKeyword(base::ASCIIToUTF16("test1_"))); - - // 2. Add a "worse" replaceable engine with keyword = "test1_". - // Expect that it is silently collapsed with the above engine. - EXPECT_FALSE(AddKeywordWithDate("replaceable2", "test1_", "https://test1", - std::string(), std::string(), std::string(), - true)); - EXPECT_EQ(replaceable1, - model()->GetTemplateURLForKeyword(base::ASCIIToUTF16("test1"))); - EXPECT_FALSE(model()->GetTemplateURLForKeyword(base::ASCIIToUTF16("test1_"))); - - // 3. But for user engines (non-replaceable ones), do not reset keywords - // ending with underscores. Expect that it gets successfully added with - // "test1_" keyword, and that replaceable1 still exists with "test1" keyword. - const TemplateURL* user1 = - AddKeywordWithDate("user1", "test1_", "https://test1", std::string(), - std::string(), std::string(), false); - ASSERT_TRUE(user1); - EXPECT_EQ(replaceable1, - model()->GetTemplateURLForKeyword(base::ASCIIToUTF16("test1"))); - EXPECT_EQ(user1, - model()->GetTemplateURLForKeyword(base::ASCIIToUTF16("test1_"))); -} - // Check that two extensions with the same engine are handled correctly. TEST_F(TemplateURLServiceTest, ExtensionsWithSameKeywords) { test_util()->VerifyLoad();
diff --git a/chrome/browser/serial/chrome_serial_browsertest.cc b/chrome/browser/serial/chrome_serial_browsertest.cc index eb1a78d..efda58b2 100644 --- a/chrome/browser/serial/chrome_serial_browsertest.cc +++ b/chrome/browser/serial/chrome_serial_browsertest.cc
@@ -3,8 +3,10 @@ // found in the LICENSE file. #include "base/command_line.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/serial/serial_blocklist.h" #include "chrome/browser/serial/serial_chooser_context.h" #include "chrome/browser/serial/serial_chooser_context_factory.h" #include "chrome/browser/ui/browser.h" @@ -45,10 +47,29 @@ ui_test_utils::NavigateToURL(browser(), url); } + void TearDown() override { + // Because SerialBlocklist is a singleton it must be cleared after tests run + // to prevent leakage between tests. + feature_list_.Reset(); + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + } + + void SetDynamicBlocklist(base::StringPiece value) { + feature_list_.Reset(); + + std::map<std::string, std::string> parameters; + parameters[kWebSerialBlocklistAdditions.name] = std::string(value); + feature_list_.InitWithFeaturesAndParameters( + {{kWebSerialBlocklist, parameters}}, {}); + + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + } + device::FakeSerialPortManager& port_manager() { return port_manager_; } SerialChooserContext* context() { return context_; } private: + base::test::ScopedFeatureList feature_list_; device::FakeSerialPortManager port_manager_; SerialChooserContext* context_; }; @@ -108,4 +129,53 @@ EXPECT_EQ(true, content::EvalJs(web_contents, "removedPromise")); } +class SerialBlocklistTest : public SerialTest { + public: + void SetUp() override { + // Add a single device to the blocklist. This has to happen before + // BrowserTestBase::SetUp() is run. + std::map<std::string, std::string> parameters; + parameters[kWebSerialBlocklistAdditions.name] = "usb:18D1:58F0"; + feature_list_.InitWithFeaturesAndParameters( + {{kWebSerialBlocklist, parameters}}, {}); + + SerialTest::SetUp(); + } + + void TearDown() override { + // Because SerialBlocklist is a singleton it must be cleared after tests run + // to prevent leakage between tests. + feature_list_.Reset(); + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + + SerialTest::TearDown(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(SerialBlocklistTest, Blocklist) { + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Create port and grant permission to it. + auto port = device::mojom::SerialPortInfo::New(); + port->token = base::UnguessableToken::Create(); + port->has_vendor_id = true; + port->vendor_id = 0x18D1; + port->has_product_id = true; + port->product_id = 0x58F0; + url::Origin origin = web_contents->GetMainFrame()->GetLastCommittedOrigin(); + context()->GrantPortPermission(origin, origin, *port); + port_manager().AddPort(port.Clone()); + + // Adding a USB device to the blocklist overrides any previously granted + // permissions. + EXPECT_EQ(0, content::EvalJs(web_contents, R"((async () => { + let ports = await navigator.serial.getPorts(); + return ports.length; + })())")); +} + } // namespace
diff --git a/chrome/browser/serial/serial_blocklist.cc b/chrome/browser/serial/serial_blocklist.cc new file mode 100644 index 0000000..e9fddbc --- /dev/null +++ b/chrome/browser/serial/serial_blocklist.cc
@@ -0,0 +1,123 @@ +// Copyright 2021 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/serial/serial_blocklist.h" + +#include <algorithm> +#include <string> +#include <tuple> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "services/device/public/mojom/serial.mojom.h" + +namespace { + +// Returns true if the passed string is exactly 4 digits long and only contains +// valid hexadecimal characters (no leading 0x). +bool IsHexComponent(base::StringPiece string) { + if (string.length() != 4) + return false; + + // This is necessary because base::HexStringToUInt allows whitespace and the + // "0x" prefix in its input. + for (char c : string) { + if (c >= '0' && c <= '9') + continue; + if (c >= 'a' && c <= 'f') + continue; + if (c >= 'A' && c <= 'F') + continue; + return false; + } + return true; +} + +bool CompareEntry(const SerialBlocklist::Entry& a, + const SerialBlocklist::Entry& b) { + return std::tie(a.usb_vendor_id, a.usb_product_id) < + std::tie(b.usb_vendor_id, b.usb_product_id); +} + +// Returns true if an entry in [begin, end) matches the vendor and product IDs +// of |entry| and has a device version greater than or equal to |entry|. +template <class Iterator> +bool EntryMatches(Iterator begin, + Iterator end, + const SerialBlocklist::Entry& entry) { + auto it = std::lower_bound(begin, end, entry, CompareEntry); + return it != end && it->usb_vendor_id == entry.usb_vendor_id && + it->usb_product_id == entry.usb_product_id; +} + +// This list must be sorted according to CompareEntry. +constexpr SerialBlocklist::Entry kStaticEntries[] = { + {0x18D1, 0x58F3}, // Test entry: GOOGLE_HID_ECHO_GADGET +}; + +} // namespace + +constexpr base::Feature kWebSerialBlocklist{"WebSerialBlocklist", + base::FEATURE_ENABLED_BY_DEFAULT}; + +constexpr base::FeatureParam<std::string> kWebSerialBlocklistAdditions{ + &kWebSerialBlocklist, "BlocklistAdditions", /*default_value=*/""}; + +SerialBlocklist::~SerialBlocklist() = default; + +// static +SerialBlocklist& SerialBlocklist::Get() { + static base::NoDestructor<SerialBlocklist> blocklist; + return *blocklist; +} + +bool SerialBlocklist::IsExcluded( + const device::mojom::SerialPortInfo& port_info) const { + // Only USB devices can be matched. + if (!port_info.has_vendor_id || !port_info.has_product_id) { + return false; + } + + Entry entry(port_info.vendor_id, port_info.product_id); + return EntryMatches(std::begin(kStaticEntries), std::end(kStaticEntries), + entry) || + EntryMatches(dynamic_entries_.begin(), dynamic_entries_.end(), entry); +} + +void SerialBlocklist::ResetToDefaultValuesForTesting() { + dynamic_entries_.clear(); + PopulateWithServerProvidedValues(); +} + +SerialBlocklist::SerialBlocklist() { + DCHECK(std::is_sorted(std::begin(kStaticEntries), std::end(kStaticEntries), + CompareEntry)); + PopulateWithServerProvidedValues(); +} + +void SerialBlocklist::PopulateWithServerProvidedValues() { + std::string blocklist_string = kWebSerialBlocklistAdditions.Get(); + + for (const auto& entry : + base::SplitStringPiece(blocklist_string, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + std::vector<base::StringPiece> components = base::SplitStringPiece( + entry, ":", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); + if (components.size() != 3 || components[0] != "usb" || + !IsHexComponent(components[1]) || !IsHexComponent(components[2])) { + continue; + } + + uint32_t vendor_id; + uint32_t product_id; + if (!base::HexStringToUInt(components[1], &vendor_id) || + !base::HexStringToUInt(components[2], &product_id)) { + continue; + } + + dynamic_entries_.emplace_back(vendor_id, product_id); + } + + std::sort(dynamic_entries_.begin(), dynamic_entries_.end(), CompareEntry); +}
diff --git a/chrome/browser/serial/serial_blocklist.h b/chrome/browser/serial/serial_blocklist.h new file mode 100644 index 0000000..324d5a4 --- /dev/null +++ b/chrome/browser/serial/serial_blocklist.h
@@ -0,0 +1,88 @@ +// Copyright 2021 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_SERIAL_SERIAL_BLOCKLIST_H_ +#define CHROME_BROWSER_SERIAL_SERIAL_BLOCKLIST_H_ + +#include <stdint.h> + +#include <string> +#include <vector> + +#include "base/feature_list.h" +#include "base/metrics/field_trial_params.h" +#include "base/no_destructor.h" +#include "services/device/public/mojom/serial.mojom-forward.h" + +// Feature used to configure entries in the Web Serial API blocklist which can +// be deployed using a server configuration. +extern const base::Feature kWebSerialBlocklist; + +// Dynamic additions to the Web Serial API device blocklist. +// +// The string must be a comma-separated list of entries which start with a type +// identifier. The only currently supported type identifier is "usb:". Entries +// may be separated by an arbitrary amount of whitespace. +// +// A USB entry provides a vendor ID and product ID, each a 16-bit integer +// written as exactly 4 hexadecimal digits. For example, the entry +// "usb:1000:001C" matches a device with a vendor ID of 0x1000 and a product +// ID of 0x001C. +// +// Invalid entries in the list will be ignored. +extern const base::FeatureParam<std::string> kWebSerialBlocklistAdditions; + +class SerialBlocklist final { + public: + // An entry in the blocklist. Represents a device that should not be + // accessible using the Web Serial API. Currently only USB devices can be + // matched by an entry but this could be expanded in the future to support a + // more expressive ruleset. + struct Entry { + constexpr Entry(uint16_t usb_vendor_id, uint16_t usb_product_id) + : usb_vendor_id(usb_vendor_id), usb_product_id(usb_product_id) {} + + // Matched against the idVendor field of the USB Device Descriptor. + uint16_t usb_vendor_id; + + // Matched against the idProduct field of the USB Device Descriptor. + uint16_t usb_product_id; + }; + + SerialBlocklist(const SerialBlocklist&) = delete; + SerialBlocklist& operator=(const SerialBlocklist&) = delete; + ~SerialBlocklist(); + + // Returns a singleton instance of the blocklist. + static SerialBlocklist& Get(); + + // Returns if a device is excluded from access. + bool IsExcluded(const device::mojom::SerialPortInfo& port_info) const; + + // Size of the blocklist. + size_t GetDynamicEntryCountForTesting() const { + return dynamic_entries_.size(); + } + + // Reload the blocklist for testing purposes. + void ResetToDefaultValuesForTesting(); + + private: + // Friend NoDestructor to permit access to private constructor. + friend class base::NoDestructor<SerialBlocklist>; + + SerialBlocklist(); + + // Populates the blocklist with values set via a Finch experiment which allows + // the set of blocked devices to be updated without shipping new executable + // versions. + // + // See kWebSerialBlocklistAdditions for the format of this parameter. + void PopulateWithServerProvidedValues(); + + // Set of blocklist entries. + std::vector<Entry> dynamic_entries_; +}; + +#endif // CHROME_BROWSER_SERIAL_SERIAL_BLOCKLIST_H_
diff --git a/chrome/browser/serial/serial_blocklist_unittest.cc b/chrome/browser/serial/serial_blocklist_unittest.cc new file mode 100644 index 0000000..60bfcd4 --- /dev/null +++ b/chrome/browser/serial/serial_blocklist_unittest.cc
@@ -0,0 +1,132 @@ +// Copyright 2021 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/serial/serial_blocklist.h" + +#include "base/strings/string_piece.h" +#include "base/test/scoped_feature_list.h" +#include "services/device/public/mojom/serial.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +class SerialBlocklistTest : public testing::Test { + public: + void SetDynamicBlocklist(base::StringPiece value) { + feature_list_.Reset(); + + std::map<std::string, std::string> parameters; + parameters[kWebSerialBlocklistAdditions.name] = std::string(value); + feature_list_.InitWithFeaturesAndParameters( + {{kWebSerialBlocklist, parameters}}, {}); + + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + } + + device::mojom::SerialPortInfoPtr CreateInfo(uint16_t usb_vendor_id, + uint16_t usb_product_id) { + auto info = device::mojom::SerialPortInfo::New(); + info->has_vendor_id = true; + info->vendor_id = usb_vendor_id; + info->has_product_id = true; + info->product_id = usb_product_id; + return info; + } + + private: + void TearDown() override { + // Because SerialBlocklist is a singleton it must be cleared after tests run + // to prevent leakage between tests. + feature_list_.Reset(); + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + } + + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(SerialBlocklistTest, BasicExclusions) { + SetDynamicBlocklist("usb:18D1:58F0"); + EXPECT_TRUE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F0))); + // Devices with nearby vendor and product IDs are not blocked. + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F1))); + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58EF))); + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D0, 0x58F0))); + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D2, 0x58F0))); +} + +TEST_F(SerialBlocklistTest, NonUsbDevice) { + auto info = device::mojom::SerialPortInfo::New(); + info->has_vendor_id = false; + info->has_product_id = false; + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*info)); +} + +TEST_F(SerialBlocklistTest, StringsWithNoValidEntries) { + SetDynamicBlocklist(""); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("~!@#$%^&*()-_=+[]{}/*-"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist(":"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("::"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist(","); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist(",,"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist(",::,"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("usb:2:3"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("usb:18D1:2"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("usb:0000:0x00"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("usb:0000: 0"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("usb:000g:0000"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("bluetooth:0000:0000"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + + SetDynamicBlocklist("☯"); + EXPECT_EQ(0u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); +} + +TEST_F(SerialBlocklistTest, StringsWithOneValidEntry) { + SetDynamicBlocklist("usb:18D1:58F0"); + EXPECT_EQ(1u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + EXPECT_TRUE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F0))); + + SetDynamicBlocklist(" usb:18D1:58F0 "); + EXPECT_EQ(1u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + EXPECT_TRUE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F0))); + + SetDynamicBlocklist(", usb:18D1:58F0, "); + EXPECT_EQ(1u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + EXPECT_TRUE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F0))); + + SetDynamicBlocklist("usb:18D1:58F0, bluetooth:18D1:58F1"); + EXPECT_EQ(1u, SerialBlocklist::Get().GetDynamicEntryCountForTesting()); + EXPECT_TRUE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F0))); +} + +TEST_F(SerialBlocklistTest, StaticEntries) { + EXPECT_TRUE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F3))); + // Devices with nearby vendor and product IDs are not blocked. + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F4))); + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D1, 0x58F2))); + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D0, 0x58F3))); + EXPECT_FALSE(SerialBlocklist::Get().IsExcluded(*CreateInfo(0x18D2, 0x58F3))); +}
diff --git a/chrome/browser/serial/serial_chooser_context.cc b/chrome/browser/serial/serial_chooser_context.cc index d3079bfb..6130db6 100644 --- a/chrome/browser/serial/serial_chooser_context.cc +++ b/chrome/browser/serial/serial_chooser_context.cc
@@ -13,6 +13,7 @@ #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/serial/serial_blocklist.h" #include "chrome/browser/serial/serial_chooser_histograms.h" #include "content/public/browser/device_service.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -226,6 +227,10 @@ const url::Origin& requesting_origin, const url::Origin& embedding_origin, const device::mojom::SerialPortInfo& port) { + if (SerialBlocklist::Get().IsExcluded(port)) { + return false; + } + if (!CanRequestObjectPermission(requesting_origin, embedding_origin)) { return false; }
diff --git a/chrome/browser/serial/serial_chooser_context_unittest.cc b/chrome/browser/serial/serial_chooser_context_unittest.cc index 5180ec4..3201abe 100644 --- a/chrome/browser/serial/serial_chooser_context_unittest.cc +++ b/chrome/browser/serial/serial_chooser_context_unittest.cc
@@ -8,8 +8,10 @@ #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/test/metrics/histogram_tester.h" +#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/serial/serial_blocklist.h" #include "chrome/browser/serial/serial_chooser_context_factory.h" #include "chrome/browser/serial/serial_chooser_histograms.h" #include "chrome/test/base/testing_profile.h" @@ -79,6 +81,24 @@ SerialChooserContextTest(SerialChooserContextTest&) = delete; SerialChooserContextTest& operator=(SerialChooserContextTest&) = delete; + void TearDown() override { + // Because SerialBlocklist is a singleton it must be cleared after tests run + // to prevent leakage between tests. + feature_list_.Reset(); + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + } + + void SetDynamicBlocklist(base::StringPiece value) { + feature_list_.Reset(); + + std::map<std::string, std::string> parameters; + parameters[kWebSerialBlocklistAdditions.name] = std::string(value); + feature_list_.InitWithFeaturesAndParameters( + {{kWebSerialBlocklist, parameters}}, {}); + + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + } + device::FakeSerialPortManager& port_manager() { return port_manager_; } TestingProfile* profile() { return &profile_; } SerialChooserContext* context() { return context_; } @@ -89,6 +109,7 @@ private: content::BrowserTaskEnvironment task_environment_; + base::test::ScopedFeatureList feature_list_; device::FakeSerialPortManager port_manager_; TestingProfile profile_; SerialChooserContext* context_; @@ -439,3 +460,33 @@ all_origin_objects = context()->GetAllGrantedObjects(); EXPECT_EQ(1u, all_origin_objects.size()); } + +TEST_F(SerialChooserContextTest, Blocklist) { + const auto origin = url::Origin::Create(GURL("https://google.com")); + + auto port = device::mojom::SerialPortInfo::New(); + port->token = base::UnguessableToken::Create(); + port->has_vendor_id = true; + port->vendor_id = 0x18D1; + port->has_product_id = true; + port->product_id = 0x58F0; + context()->GrantPortPermission(origin, origin, *port); + EXPECT_TRUE(context()->HasPortPermission(origin, origin, *port)); + + // Adding a USB device to the blocklist overrides any previously granted + // permissions. + SetDynamicBlocklist("usb:18D1:58F0"); + EXPECT_FALSE(context()->HasPortPermission(origin, origin, *port)); + + // The lists of granted permissions will still include the entry because + // permission storage does not include the USB vendor and product IDs on all + // platforms and users should still be made aware of permissions they've + // granted even if they are being blocked from taking effect. + std::vector<std::unique_ptr<permissions::ChooserContextBase::Object>> + objects = context()->GetGrantedObjects(origin, origin); + EXPECT_EQ(1u, objects.size()); + + std::vector<std::unique_ptr<permissions::ChooserContextBase::Object>> + all_origin_objects = context()->GetAllGrantedObjects(); + EXPECT_EQ(1u, all_origin_objects.size()); +}
diff --git a/chrome/browser/sync_file_system/sync_file_system_service.cc b/chrome/browser/sync_file_system/sync_file_system_service.cc index 3ed800f..ec2889d 100644 --- a/chrome/browser/sync_file_system/sync_file_system_service.cc +++ b/chrome/browser/sync_file_system/sync_file_system_service.cc
@@ -114,7 +114,7 @@ void DidGetFileSyncStatusForDump( base::ListValue* files, size_t* num_results, - const SyncFileSystemService::DumpFilesCallback& callback, + base::RepeatingCallback<void(const base::ListValue&)> callback, base::DictionaryValue* file, SyncStatusCode sync_status_code, SyncFileStatus sync_file_status) { @@ -129,7 +129,10 @@ if (++*num_results < files->GetSize()) return; - callback.Run(*files); + // |callback| is backed by a DumpFilesCallback, which should only be called + // once. Move |callback| here to force repeated calls to crash instead of + // silently failing. + std::move(callback).Run(*files); } // We need this indirection because WeakPtr can only be bound to methods @@ -300,13 +303,13 @@ void SyncFileSystemService::GetExtensionStatusMap( ExtensionStatusMapCallback callback) { - remote_service_->GetOriginStatusMap(base::AdaptCallbackForRepeating( + remote_service_->GetOriginStatusMap( base::BindOnce(&SyncFileSystemService::DidGetExtensionStatusMap, - AsWeakPtr(), std::move(callback)))); + AsWeakPtr(), std::move(callback))); } void SyncFileSystemService::DumpFiles(const GURL& origin, - const DumpFilesCallback& callback) { + DumpFilesCallback callback) { DCHECK(!origin.is_empty()); content::StoragePartition* storage_partition = @@ -315,14 +318,14 @@ storage_partition->GetFileSystemContext(); local_service_->MaybeInitializeFileSystemContext( origin, file_system_context, - base::Bind(&SyncFileSystemService::DidInitializeFileSystemForDump, - AsWeakPtr(), origin, callback)); + base::BindOnce(&SyncFileSystemService::DidInitializeFileSystemForDump, + AsWeakPtr(), origin, std::move(callback))); } -void SyncFileSystemService::DumpDatabase(const DumpFilesCallback& callback) { +void SyncFileSystemService::DumpDatabase(DumpFilesCallback callback) { remote_service_->DumpDatabase( - base::Bind(&SyncFileSystemService::DidDumpDatabase, - AsWeakPtr(), callback)); + base::BindOnce(&SyncFileSystemService::DidDumpDatabase, AsWeakPtr(), + std::move(callback))); } void SyncFileSystemService::GetFileSyncStatus(const FileSystemURL& url, @@ -538,47 +541,40 @@ void SyncFileSystemService::DidInitializeFileSystemForDump( const GURL& origin, - const DumpFilesCallback& callback, + DumpFilesCallback callback, SyncStatusCode status) { DCHECK(!origin.is_empty()); - if (status != SYNC_STATUS_OK) { - callback.Run(base::ListValue()); - return; - } - - if (!remote_service_) { - callback.Run(base::ListValue()); + if (status != SYNC_STATUS_OK || !remote_service_) { + std::move(callback).Run(base::ListValue()); return; } remote_service_->DumpFiles( - origin, - base::Bind( - &SyncFileSystemService::DidDumpFiles, - AsWeakPtr(), - origin, - callback)); + origin, base::BindOnce(&SyncFileSystemService::DidDumpFiles, AsWeakPtr(), + origin, std::move(callback))); } void SyncFileSystemService::DidDumpFiles( const GURL& origin, - const DumpFilesCallback& callback, + DumpFilesCallback callback, std::unique_ptr<base::ListValue> dump_files) { if (!dump_files || !dump_files->GetSize() || !local_service_ || !remote_service_) { - callback.Run(base::ListValue()); + std::move(callback).Run(base::ListValue()); return; } base::ListValue* files = dump_files.get(); - base::Callback<void(base::DictionaryValue*, - SyncStatusCode, - SyncFileStatus)> completion_callback = - base::Bind(&DidGetFileSyncStatusForDump, - base::Owned(dump_files.release()), - base::Owned(new size_t(0)), - callback); + + using AccumulateFileSyncStatusCallback = base::RepeatingCallback<void( + base::DictionaryValue*, SyncStatusCode, SyncFileStatus)>; + + // |accumulate_callback| should only call |callback| once. + AccumulateFileSyncStatusCallback accumulate_callback = base::BindRepeating( + &DidGetFileSyncStatusForDump, base::Owned(dump_files.release()), + base::Owned(new size_t(0)), + base::AdaptCallbackForRepeating(std::move(callback))); // After all metadata loaded, sync status can be added to each entry. for (size_t i = 0; i < files->GetSize(); ++i) { @@ -587,30 +583,30 @@ if (!files->GetDictionary(i, &file) || !file->GetString("path", &path_string)) { NOTREACHED(); - completion_callback.Run( - nullptr, SYNC_FILE_ERROR_FAILED, SYNC_FILE_STATUS_UNKNOWN); + accumulate_callback.Run(nullptr, SYNC_FILE_ERROR_FAILED, + SYNC_FILE_STATUS_UNKNOWN); continue; } base::FilePath file_path = base::FilePath::FromUTF8Unsafe(path_string); FileSystemURL url = CreateSyncableFileSystemURL(origin, file_path); - GetFileSyncStatus(url, base::Bind(completion_callback, file)); + GetFileSyncStatus(url, base::BindOnce(accumulate_callback, file)); } } void SyncFileSystemService::DidDumpDatabase( - const DumpFilesCallback& callback, + DumpFilesCallback callback, std::unique_ptr<base::ListValue> list) { if (!list) - list = base::WrapUnique(new base::ListValue); - callback.Run(*list); + list = std::make_unique<base::ListValue>(); + std::move(callback).Run(*list); } void SyncFileSystemService::DidGetExtensionStatusMap( ExtensionStatusMapCallback callback, std::unique_ptr<RemoteFileSyncService::OriginStatusMap> status_map) { if (!status_map) - status_map = base::WrapUnique(new RemoteFileSyncService::OriginStatusMap); + status_map = std::make_unique<RemoteFileSyncService::OriginStatusMap>(); std::move(callback).Run(*status_map); }
diff --git a/chrome/browser/sync_file_system/sync_file_system_service.h b/chrome/browser/sync_file_system/sync_file_system_service.h index 897fc7e..fb4a9d58 100644 --- a/chrome/browser/sync_file_system/sync_file_system_service.h +++ b/chrome/browser/sync_file_system/sync_file_system_service.h
@@ -51,10 +51,9 @@ public extensions::ExtensionRegistryObserver, public base::SupportsWeakPtr<SyncFileSystemService> { public: - typedef base::Callback<void(const base::ListValue&)> DumpFilesCallback; - typedef base::OnceCallback<void( - const RemoteFileSyncService::OriginStatusMap&)> - ExtensionStatusMapCallback; + using DumpFilesCallback = base::OnceCallback<void(const base::ListValue&)>; + using ExtensionStatusMapCallback = + base::OnceCallback<void(const RemoteFileSyncService::OriginStatusMap&)>; // KeyedService implementation. void Shutdown() override; @@ -64,8 +63,8 @@ SyncStatusCallback callback); void GetExtensionStatusMap(ExtensionStatusMapCallback callback); - void DumpFiles(const GURL& origin, const DumpFilesCallback& callback); - void DumpDatabase(const DumpFilesCallback& callback); + void DumpFiles(const GURL& origin, DumpFilesCallback callback); + void DumpDatabase(DumpFilesCallback callback); // Returns the file |url|'s sync status. void GetFileSyncStatus(const storage::FileSystemURL& url, @@ -111,13 +110,13 @@ SyncStatusCode status); void DidInitializeFileSystemForDump(const GURL& app_origin, - const DumpFilesCallback& callback, + DumpFilesCallback callback, SyncStatusCode status); void DidDumpFiles(const GURL& app_origin, - const DumpFilesCallback& callback, + DumpFilesCallback callback, std::unique_ptr<base::ListValue> files); - void DidDumpDatabase(const DumpFilesCallback& callback, + void DidDumpDatabase(DumpFilesCallback callback, std::unique_ptr<base::ListValue> list); void DidGetExtensionStatusMap(
diff --git a/chrome/browser/sync_file_system/sync_file_system_test_util.cc b/chrome/browser/sync_file_system/sync_file_system_test_util.cc index 898810f..044d98b 100644 --- a/chrome/browser/sync_file_system/sync_file_system_test_util.cc +++ b/chrome/browser/sync_file_system/sync_file_system_test_util.cc
@@ -29,9 +29,10 @@ run_loop->Quit(); } -template <typename R> base::Callback<void(R)> -AssignAndQuitCallback(base::RunLoop* run_loop, R* result) { - return base::Bind(&AssignAndQuit<R>, run_loop, base::Unretained(result)); +template <typename R> +base::OnceCallback<void(R)> AssignAndQuitCallback(base::RunLoop* run_loop, + R* result) { + return base::BindOnce(&AssignAndQuit<R>, run_loop, base::Unretained(result)); } template <typename Arg, typename Param> @@ -42,19 +43,20 @@ } template <typename Arg> -base::Callback<void(typename TypeTraits<Arg>::ParamType)> +base::OnceCallback<void(typename TypeTraits<Arg>::ParamType)> CreateResultReceiver(Arg* arg_out) { - typedef typename TypeTraits<Arg>::ParamType Param; - return base::Bind(&ReceiveResult1<Arg, Param>, - base::Owned(new bool(false)), arg_out); + using Param = typename TypeTraits<Arg>::ParamType; + return base::BindOnce(&ReceiveResult1<Arg, Param>, + base::Owned(new bool(false)), arg_out); } // Instantiate versions we know callers will need. -template base::Callback<void(SyncStatusCode)> -AssignAndQuitCallback(base::RunLoop*, SyncStatusCode*); +template base::OnceCallback<void(SyncStatusCode)> AssignAndQuitCallback( + base::RunLoop*, + SyncStatusCode*); #define INSTANTIATE_RECEIVER(type) \ - template base::Callback<void(type)> CreateResultReceiver(type*) + template base::OnceCallback<void(type)> CreateResultReceiver(type*) INSTANTIATE_RECEIVER(SyncStatusCode); INSTANTIATE_RECEIVER(google_apis::DriveApiErrorCode); INSTANTIATE_RECEIVER(std::unique_ptr<RemoteFileSyncService::OriginStatusMap>);
diff --git a/chrome/browser/sync_file_system/sync_file_system_test_util.h b/chrome/browser/sync_file_system/sync_file_system_test_util.h index 26bafaa..f2a421fa 100644 --- a/chrome/browser/sync_file_system/sync_file_system_test_util.h +++ b/chrome/browser/sync_file_system/sync_file_system_test_util.h
@@ -52,23 +52,22 @@ template <typename R> void AssignAndQuit(base::RunLoop* run_loop, R* result_out, R result); -template <typename R> base::Callback<void(R)> -AssignAndQuitCallback(base::RunLoop* run_loop, R* result); +template <typename R> +base::OnceCallback<void(R)> AssignAndQuitCallback(base::RunLoop* run_loop, + R* result); template <typename Arg> -base::Callback<void(typename TypeTraits<Arg>::ParamType)> +base::OnceCallback<void(typename TypeTraits<Arg>::ParamType)> CreateResultReceiver(Arg* arg_out); template <typename Arg1, typename Arg2> -base::Callback<void(typename TypeTraits<Arg1>::ParamType, - typename TypeTraits<Arg2>::ParamType)> -CreateResultReceiver(Arg1* arg1_out, - Arg2* arg2_out) { - typedef typename TypeTraits<Arg1>::ParamType Param1; - typedef typename TypeTraits<Arg2>::ParamType Param2; - return base::Bind(&ReceiveResult2<Arg1, Arg2, Param1, Param2>, - base::Owned(new bool(false)), - arg1_out, arg2_out); +base::OnceCallback<void(typename TypeTraits<Arg1>::ParamType, + typename TypeTraits<Arg2>::ParamType)> +CreateResultReceiver(Arg1* arg1_out, Arg2* arg2_out) { + using Param1 = typename TypeTraits<Arg1>::ParamType; + using Param2 = typename TypeTraits<Arg2>::ParamType; + return base::BindOnce(&ReceiveResult2<Arg1, Arg2, Param1, Param2>, + base::Owned(new bool(false)), arg1_out, arg2_out); } } // namespace sync_file_system
diff --git a/chrome/browser/thumbnail/cc/BUILD.gn b/chrome/browser/thumbnail/cc/BUILD.gn index 9c709a7..e543ef4 100644 --- a/chrome/browser/thumbnail/cc/BUILD.gn +++ b/chrome/browser/thumbnail/cc/BUILD.gn
@@ -19,6 +19,7 @@ "//content/public/browser", "//media", "//mojo/public/cpp/bindings", + "//net", "//skia", "//ui/gfx", ] @@ -45,6 +46,7 @@ deps = [ ":cc", "//base", + "//net", "//testing/gmock", "//testing/gtest", ]
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 998d8d4..b9be6cf 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3094,6 +3094,13 @@ "cocoa/rosetta_required_infobar_delegate.mm", "cocoa/scoped_menu_bar_lock.h", "cocoa/scoped_menu_bar_lock.mm", + "cocoa/screentime/fake_webpage_controller.h", + "cocoa/screentime/fake_webpage_controller.mm", + "cocoa/screentime/tab_helper.h", + "cocoa/screentime/tab_helper.mm", + "cocoa/screentime/webpage_controller.h", + "cocoa/screentime/webpage_controller_impl.h", + "cocoa/screentime/webpage_controller_impl.mm", "cocoa/share_menu_controller.h", "cocoa/share_menu_controller.mm", "cocoa/simple_message_box_cocoa.h", @@ -3161,6 +3168,7 @@ "Carbon.framework", "Quartz.framework", ] + weak_frameworks = [ "ScreenTime.framework" ] if (enable_chromium_updater) { deps += [
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index b77a584..82d307b 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -3096,6 +3096,9 @@ <message name="IDS_READING_LIST_TITLE" desc="The title for the reading list page in main bookmark UI."> Reading list </message> + <message name="IDS_READING_LIST_TITLE_NEW" desc="The title for the reading list with a new text."> + Reading list <ph name="BEGIN_NEW"><new></ph>New<ph name="END_NEW"></new></ph> + </message> <message name="IDS_READING_LIST_READ" desc="The header for the read section in the reading list UI."> Read </message> @@ -3134,7 +3137,7 @@ Save this page for later and get a reminder </message> <message name="IDS_READING_LIST_SAVE_PAGES_FOR_LATER" desc="The text on the reading list in product help bubble to introduce the feature to the user."> - Save pages for later and get a reminder + Add pages to your Reading List to get a reminder </message> <message name="IDS_READING_LIST_FIND_IN_BOOKMARKS" desc="The text to inform the user to find the reading list in bookmarks UI."> Find your reading list in Bookmarks
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READING_LIST_SAVE_PAGES_FOR_LATER.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READING_LIST_SAVE_PAGES_FOR_LATER.png.sha1 index 1dc0c56..202456aa 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READING_LIST_SAVE_PAGES_FOR_LATER.png.sha1 +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READING_LIST_SAVE_PAGES_FOR_LATER.png.sha1
@@ -1 +1 @@ -26c8ba78ec652819da6c707f067832da8c37de89 \ No newline at end of file +89c19bdab51f56cc41109a57ca8c2227ceea5f5a \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READING_LIST_TITLE_NEW.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READING_LIST_TITLE_NEW.png.sha1 new file mode 100644 index 0000000..e7b8b92 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READING_LIST_TITLE_NEW.png.sha1
@@ -0,0 +1 @@ +50889cf3fbf93573b8531e5d2ef95907c0b57f11 \ No newline at end of file
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc index 10c313a..ff324f88b 100644 --- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc +++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.cc
@@ -120,7 +120,7 @@ void OnWidgetBoundsChanged(views::Widget* widget, const gfx::Rect& bounds) override { - owner_->OnWidgetBoundsChanged(widget, bounds); + owner_->UpdateAnchorPosition(); } private: @@ -488,11 +488,6 @@ } } -void SharesheetBubbleView::OnWidgetBoundsChanged(views::Widget* widget, - const gfx::Rect& new_bounds) { - UpdateAnchorPosition(); -} - void SharesheetBubbleView::CreateBubble() { set_close_on_deactivate(false); SetButtons(ui::DIALOG_BUTTON_NONE);
diff --git a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h index c81d9de1..b522443 100644 --- a/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h +++ b/chrome/browser/ui/ash/sharesheet/sharesheet_bubble_view.h
@@ -44,10 +44,6 @@ void ResizeBubble(const int& width, const int& height); void CloseBubble(); - // views::BubbleDialogDelegateView: - void OnWidgetBoundsChanged(views::Widget* widget, - const gfx::Rect& new_bounds) override; - private: class SharesheetParentWidgetObserver;
diff --git a/chrome/browser/ui/ash/tab_scrubber.cc b/chrome/browser/ui/ash/tab_scrubber.cc index 8c19f25..1557711 100644 --- a/chrome/browser/ui/ash/tab_scrubber.cc +++ b/chrome/browser/ui/ash/tab_scrubber.cc
@@ -293,14 +293,14 @@ // one fourth of |x_offset| as the minimum (i.e. we need 38 tabs to reach // that minimum reduction). swipe_x_ += base::ClampToRange( - x_offset - (tab_strip_->tab_count() * 0.02f * x_offset), 0.25f * x_offset, - x_offset); + x_offset - (tab_strip_->GetTabCount() * 0.02f * x_offset), + 0.25f * x_offset, x_offset); // In an RTL layout, everything is mirrored, i.e. the index of the first tab // (with the smallest X mirrored co-ordinates) is actually the index of the // last tab. Same for the index of the last tab. - int first_tab_index = base::i18n::IsRTL() ? tab_strip_->tab_count() - 1 : 0; - int last_tab_index = base::i18n::IsRTL() ? 0 : tab_strip_->tab_count() - 1; + int first_tab_index = base::i18n::IsRTL() ? tab_strip_->GetTabCount() - 1 : 0; + int last_tab_index = base::i18n::IsRTL() ? 0 : tab_strip_->GetTabCount() - 1; Tab* first_tab = tab_strip_->tab_at(first_tab_index); int first_tab_center = first_tab->GetMirroredBounds().CenterPoint().x();
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 3d854e68b..62b62d2 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -246,6 +246,11 @@ bool is_session_restore = false; +#if BUILDFLAG(IS_CHROMEOS_ASH) + // The id from the restore data to restore the browser window. + int32_t restore_id = 0; +#endif + bool is_focus_mode = false; // Whether this browser was created by a user gesture. We track this
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index b3d0dabb..ec7b2a36 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -690,6 +690,9 @@ case IDC_SEND_TO_DESK_8: SendToDeskAtIndex(browser_, id - IDC_SEND_TO_DESK_1); break; + case IDC_TOGGLE_ASSIGN_TO_ALL_DESKS: + ToggleAssignedToAllDesks(browser_); + break; #endif #if BUILDFLAG(GOOGLE_CHROME_BRANDING) case IDC_FEEDBACK: @@ -988,6 +991,7 @@ "IDC_SEND_TO_DESK_* commands must be in order."); auto* desks_helper = ash::DesksHelper::Get(); UpdateCommandsForDesks(desks_helper ? desks_helper->GetNumberOfDesks() : 1); + command_updater_.UpdateCommandEnabled(IDC_TOGGLE_ASSIGN_TO_ALL_DESKS, true); #endif // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete.
diff --git a/chrome/browser/ui/browser_commands_chromeos.cc b/chrome/browser/ui/browser_commands_chromeos.cc index 58a1be5..3ffe91d 100644 --- a/chrome/browser/ui/browser_commands_chromeos.cc +++ b/chrome/browser/ui/browser_commands_chromeos.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/ash/chrome_screenshot_grabber.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "ui/views/widget/widget.h" using base::UserMetricsAction; @@ -24,3 +25,10 @@ if (grabber->CanTakeScreenshot()) grabber->HandleTakeScreenshotForAllRootWindows(); } + +void ToggleAssignedToAllDesks(Browser* browser) { + auto* widget = views::Widget::GetWidgetForNativeWindow( + browser->window()->GetNativeWindow()); + DCHECK(widget); + widget->SetVisibleOnAllWorkspaces(!widget->IsVisibleOnAllWorkspaces()); +}
diff --git a/chrome/browser/ui/browser_commands_chromeos.h b/chrome/browser/ui/browser_commands_chromeos.h index 15d8d97..f859254 100644 --- a/chrome/browser/ui/browser_commands_chromeos.h +++ b/chrome/browser/ui/browser_commands_chromeos.h
@@ -13,4 +13,7 @@ // Takes a screenshot of the entire desktop (not just the browser window). void TakeScreenshot(); +// Toggles whether |browser| is assigned to all desks. +void ToggleAssignedToAllDesks(Browser* browser); + #endif // CHROME_BROWSER_UI_BROWSER_COMMANDS_CHROMEOS_H_
diff --git a/chrome/browser/ui/cocoa/screentime/README.md b/chrome/browser/ui/cocoa/screentime/README.md new file mode 100644 index 0000000..c918773 --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/README.md
@@ -0,0 +1,23 @@ +This directory contains the integration between Chromium and the macOS +ScreenTime system, which is a digital wellbeing tool allowing users to restrict +their own use of apps and websites by category. + +The ScreenTime system API is documented [on +apple.com](https://developer.apple.com/documentation/screentime?language=objc). +The most pertinent class is `STWebpageController`, which is an +`NSViewController` subclass. Clients of ScreenTime construct a single +`STWebpageController` per tab and splice its corresponding NSView into their +view tree in such a way that it covers the web contents. The NSView becomes +opaque when screen time for that tab or website has been used up. + +The public interface to ScreenTime within Chromium is the +`screentime::TabHelper` class, which is a +[TabHelper](../../../../../docs/tab_helpers.md) that binds an +STWebpageController to a WebContents. + +## Testing + +So that tests can avoid depending on the real ScreenTime system, +STWebpageController is wrapped by a C++ class called +screentime::WebpageController, which has a testing fake called +screentime::FakeWebpageController.
diff --git a/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h b/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h new file mode 100644 index 0000000..ebe2872 --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.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 CHROME_BROWSER_UI_COCOA_SCREENTIME_FAKE_WEBPAGE_CONTROLLER_H_ +#define CHROME_BROWSER_UI_COCOA_SCREENTIME_FAKE_WEBPAGE_CONTROLLER_H_ + +#include "base/mac/scoped_nsobject.h" +#include "chrome/browser/ui/cocoa/screentime/webpage_controller.h" + +namespace screentime { + +// An implementation of WebpageController that is not backed by the real +// ScreenTime framework. This is used for testing and development on pre-11.0 +// devices that don't have the real ScreenTime API available. +// +// FakeWebpageController implements the following behavior: +// 1. The ScreenTime "shield" view is a flat blue layer +// 2. Every navigation causes it to toggle blocking / not blocking state +// +// Further testing hooks may be added to this class in future. +class FakeWebpageController : public WebpageController { + public: + FakeWebpageController(const BlockedChangedCallback& callback); + ~FakeWebpageController() override; + + NSView* GetView() override; + void PageURLChangedTo(const GURL& url) override; + + private: + bool enabled_ = false; + base::scoped_nsobject<NSView> view_; + BlockedChangedCallback blocked_changed_callback_; +}; + +} // namespace screentime + +#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_FAKE_WEBPAGE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.mm b/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.mm new file mode 100644 index 0000000..488cf1a --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/fake_webpage_controller.mm
@@ -0,0 +1,39 @@ +// 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/ui/cocoa/screentime/fake_webpage_controller.h" + +#import <Cocoa/Cocoa.h> + +namespace { + +NSView* MakeView(bool enabled) { + NSView* view = [[NSView alloc] init]; + view.wantsLayer = YES; + view.layer.backgroundColor = NSColor.blueColor.CGColor; + view.hidden = !enabled; + return view; +} + +} // namespace + +namespace screentime { + +FakeWebpageController::FakeWebpageController( + const BlockedChangedCallback& blocked_changed_callback) + : view_(MakeView(enabled_)), + blocked_changed_callback_(blocked_changed_callback) {} +FakeWebpageController::~FakeWebpageController() = default; + +NSView* FakeWebpageController::GetView() { + return view_.get(); +} + +void FakeWebpageController::PageURLChangedTo(const GURL& url) { + enabled_ = !enabled_; + [view_ setHidden:!enabled_]; + blocked_changed_callback_.Run(enabled_); +} + +} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/tab_helper.h b/chrome/browser/ui/cocoa/screentime/tab_helper.h new file mode 100644 index 0000000..9bed147 --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/tab_helper.h
@@ -0,0 +1,50 @@ +// 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_UI_COCOA_SCREENTIME_TAB_HELPER_H_ +#define CHROME_BROWSER_UI_COCOA_SCREENTIME_TAB_HELPER_H_ + +#include <memory> + +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace content { +class WebContents; +} + +namespace screentime { + +class WebpageController; + +// A TabHelper connects a content::WebContents to a WebpageController, +// passing state updates from the WebContents to the WebpageController and +// from the WebpageController to the WebContents or other parts of the browser. +class TabHelper : public content::WebContentsObserver, + public content::WebContentsUserData<TabHelper> { + public: + static void UseFakeWebpageControllerForTesting(); + static bool IsScreentimeEnabled(); + + TabHelper(content::WebContents* contents); + ~TabHelper() override; + + // WebContentsObserver: + void DidFinishNavigation(content::NavigationHandle* handle) override; + + private: + friend class content::WebContentsUserData<TabHelper>; + + std::unique_ptr<WebpageController> MakeWebpageController(); + + void OnBlockedChanged(bool blocked); + + WEB_CONTENTS_USER_DATA_KEY_DECL(); + + std::unique_ptr<WebpageController> page_controller_; +}; + +} // namespace screentime + +#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_TAB_HELPER_H_
diff --git a/chrome/browser/ui/cocoa/screentime/tab_helper.mm b/chrome/browser/ui/cocoa/screentime/tab_helper.mm new file mode 100644 index 0000000..8876b44 --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/tab_helper.mm
@@ -0,0 +1,77 @@ +// 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 <Cocoa/Cocoa.h> + +#include "base/command_line.h" +#include "chrome/browser/ui/cocoa/screentime/fake_webpage_controller.h" +#include "chrome/browser/ui/cocoa/screentime/tab_helper.h" +#include "chrome/browser/ui/cocoa/screentime/webpage_controller.h" +#include "chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/web_contents.h" + +namespace screentime { + +namespace { +bool g_use_fake_webpage_controller = false; +} + +// static +void TabHelper::UseFakeWebpageControllerForTesting() { + g_use_fake_webpage_controller = true; +} + +// static +bool TabHelper::IsScreentimeEnabled() { + static constexpr base::Feature kScreenTime{ + "ScreenTime", + base::FEATURE_DISABLED_BY_DEFAULT, + }; + return base::FeatureList::IsEnabled(kScreenTime); +} + +TabHelper::TabHelper(content::WebContents* contents) + : WebContentsObserver(contents), page_controller_(MakeWebpageController()) { + NSView* contents_view = contents->GetNativeView().GetNativeNSView(); + [contents_view addSubview:page_controller_->GetView()]; +} + +TabHelper::~TabHelper() = default; + +void TabHelper::DidFinishNavigation(content::NavigationHandle* handle) { + // TODO(ellyjones): Some defensive programming around chrome:// URLs would + // probably be a good idea here. It's not unimaginable that ScreenTime would + // misbehave and end up occluding those URLs, which would be very bad. + if (handle->IsInMainFrame() && handle->HasCommitted()) + page_controller_->PageURLChangedTo(handle->GetURL()); +} + +std::unique_ptr<WebpageController> TabHelper::MakeWebpageController() { + const bool use_fake = + g_use_fake_webpage_controller || + base::CommandLine::ForCurrentProcess()->HasSwitch("fake-screentime"); + + // The callback is owned by the WebpageController instance, which is in turn + // owned by this object, so it can't outlive us. + auto callback = + base::BindRepeating(&TabHelper::OnBlockedChanged, base::Unretained(this)); + std::unique_ptr<WebpageController> controller; + if (use_fake) + controller = std::make_unique<FakeWebpageController>(callback); + else + controller = std::make_unique<WebpageControllerImpl>(callback); + return controller; +} + +void TabHelper::OnBlockedChanged(bool blocked) { + // TODO: Pause/resume playing media, update occlusion state on the + // WebContents, and so on. Getting this behavior right will probably require + // some care. + NOTIMPLEMENTED(); +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(TabHelper) + +} // namespace screentime
diff --git a/chrome/browser/ui/cocoa/screentime/webpage_controller.h b/chrome/browser/ui/cocoa/screentime/webpage_controller.h new file mode 100644 index 0000000..ad9f2809f --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/webpage_controller.h
@@ -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. + +#ifndef CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_H_ +#define CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_H_ + +#include "base/callback.h" +#include "url/gurl.h" + +@class NSView; + +namespace screentime { + +// The interface for the per-page controller. This interface exists to allow for +// abstracting away the concrete STWebpageController class, which is only +// available on some platforms and ties into a systemwide API that makes unit +// testing difficult. As little logic as possible should happen in +// implementations of WebpageController. +class WebpageController { + public: + using BlockedChangedCallback = base::RepeatingCallback<void(bool)>; + + WebpageController() = default; + virtual ~WebpageController() = default; + + virtual NSView* GetView() = 0; + + // Called when the WebContents that this WebpageController is attached to + // changes its committed URL to |url|, to update ScreenTime's notion of the + // "page URL" (in Chrome parlance, the top-level frame URL). + virtual void PageURLChangedTo(const GURL& url) = 0; +}; + +} // namespace screentime + +#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h b/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h new file mode 100644 index 0000000..8f02dac --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.h
@@ -0,0 +1,34 @@ +// 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_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_IMPL_H_ + +#include "base/mac/scoped_nsobject.h" +#include "chrome/browser/ui/cocoa/screentime/webpage_controller.h" + +@class STWebpageController; + +namespace screentime { + +// This class wraps the STWebpageController screentime class, to allow for tests +// to use a fake controller. +class WebpageControllerImpl : public WebpageController { + public: + WebpageControllerImpl(const BlockedChangedCallback& callback); + ~WebpageControllerImpl() override; + + NSView* GetView() override; + void PageURLChangedTo(const GURL& url) override; + + void OnBlockedChanged(bool blocked); + + private: + base::scoped_nsobject<STWebpageController> platform_controller_; + BlockedChangedCallback blocked_changed_callback_; +}; + +} // namespace screentime + +#endif // CHROME_BROWSER_UI_COCOA_SCREENTIME_WEBPAGE_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.mm b/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.mm new file mode 100644 index 0000000..0cbab2c --- /dev/null +++ b/chrome/browser/ui/cocoa/screentime/webpage_controller_impl.mm
@@ -0,0 +1,69 @@ +// 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/ui/cocoa/screentime/webpage_controller_impl.h" + +#include "net/base/mac/url_conversions.h" + +#include <ScreenTime/ScreenTime.h> + +@interface BlockedObserver : NSObject +@end + +NS_AVAILABLE_MAC(11.0) +@implementation BlockedObserver { + screentime::WebpageControllerImpl* _controller; + STWebpageController* _nativeController; +} + +- (instancetype)initWithController: + (screentime::WebpageControllerImpl*)controller + nativeController:(STWebpageController*)nativeController { + if (self = [super init]) { + _controller = controller; + _nativeController = nativeController; + [_nativeController addObserver:self + forKeyPath:@"URLIsBlocked" + options:0 + context:nullptr]; + } + return self; +} + +- (void)dealloc { + [_nativeController removeObserver:self forKeyPath:@"URLIsBlocked"]; + [super dealloc]; +} + +- (void)observeValueForKeyPath:(NSString*)forKeyPath + ofObject:(id)object + change:(NSDictionary*)change + context:(void*)context { + DCHECK([forKeyPath isEqualToString:@"URLIsBlocked"]); + _controller->OnBlockedChanged(_nativeController.URLIsBlocked); +} + +@end + +namespace screentime { + +WebpageControllerImpl::WebpageControllerImpl( + const BlockedChangedCallback& blocked_changed_callback) + : platform_controller_([[STWebpageController alloc] init]), + blocked_changed_callback_(blocked_changed_callback) {} +WebpageControllerImpl::~WebpageControllerImpl() = default; + +NSView* WebpageControllerImpl::GetView() { + return [platform_controller_ view]; +} + +void WebpageControllerImpl::PageURLChangedTo(const GURL& url) { + [platform_controller_ setURL:net::NSURLWithGURL(url)]; +} + +void WebpageControllerImpl::OnBlockedChanged(bool blocked) { + blocked_changed_callback_.Run(blocked); +} + +} // namespace screentime
diff --git a/chrome/browser/ui/serial/serial_chooser_controller.cc b/chrome/browser/ui/serial/serial_chooser_controller.cc index 362fd032..d6d8c30b 100644 --- a/chrome/browser/ui/serial/serial_chooser_controller.cc +++ b/chrome/browser/ui/serial/serial_chooser_controller.cc
@@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/unguessable_token.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/serial/serial_blocklist.h" #include "chrome/browser/serial/serial_chooser_context_factory.h" #include "chrome/browser/serial/serial_chooser_histograms.h" #include "chrome/grit/generated_resources.h" @@ -114,7 +115,7 @@ void SerialChooserController::OnPortAdded( const device::mojom::SerialPortInfo& port) { - if (!FilterMatchesAny(port)) + if (!DisplayDevice(port)) return; ports_.push_back(port.Clone()); @@ -148,7 +149,7 @@ }); for (auto& port : ports) { - if (FilterMatchesAny(*port)) + if (DisplayDevice(*port)) ports_.push_back(std::move(port)); } @@ -156,8 +157,11 @@ view()->OnOptionsInitialized(); } -bool SerialChooserController::FilterMatchesAny( +bool SerialChooserController::DisplayDevice( const device::mojom::SerialPortInfo& port) const { + if (SerialBlocklist::Get().IsExcluded(port)) + return false; + if (filters_.empty()) return true;
diff --git a/chrome/browser/ui/serial/serial_chooser_controller.h b/chrome/browser/ui/serial/serial_chooser_controller.h index 21ec2bab..4d9a2df 100644 --- a/chrome/browser/ui/serial/serial_chooser_controller.h +++ b/chrome/browser/ui/serial/serial_chooser_controller.h
@@ -52,7 +52,7 @@ private: void OnGetDevices(std::vector<device::mojom::SerialPortInfoPtr> ports); - bool FilterMatchesAny(const device::mojom::SerialPortInfo& port) const; + bool DisplayDevice(const device::mojom::SerialPortInfo& port) const; void RunCallback(device::mojom::SerialPortInfoPtr port); std::vector<blink::mojom::SerialPortFilterPtr> filters_;
diff --git a/chrome/browser/ui/serial/serial_chooser_controller_unittest.cc b/chrome/browser/ui/serial/serial_chooser_controller_unittest.cc index 065be5a..18ec27a 100644 --- a/chrome/browser/ui/serial/serial_chooser_controller_unittest.cc +++ b/chrome/browser/ui/serial/serial_chooser_controller_unittest.cc
@@ -13,6 +13,7 @@ #include "base/test/mock_callback.h" #include "build/build_config.h" #include "chrome/browser/chooser_controller/mock_chooser_controller_view.h" +#include "chrome/browser/serial/serial_blocklist.h" #include "chrome/browser/serial/serial_chooser_context.h" #include "chrome/browser/serial/serial_chooser_context_factory.h" #include "chrome/browser/serial/serial_chooser_histograms.h" @@ -39,6 +40,15 @@ ->SetPortManagerForTesting(std::move(port_manager)); } + void TearDown() override { + // Because SerialBlocklist is a singleton it must be cleared after tests run + // to prevent leakage between tests. + feature_list_.Reset(); + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + + ChromeRenderViewHostTestHarness::TearDown(); + } + base::UnguessableToken AddPort( const std::string& display_name, const base::FilePath& path, @@ -61,9 +71,21 @@ return port_token; } + void SetDynamicBlocklist(base::StringPiece value) { + feature_list_.Reset(); + + std::map<std::string, std::string> parameters; + parameters[kWebSerialBlocklistAdditions.name] = std::string(value); + feature_list_.InitWithFeaturesAndParameters( + {{kWebSerialBlocklist, parameters}}, {}); + + SerialBlocklist::Get().ResetToDefaultValuesForTesting(); + } + device::FakeSerialPortManager& port_manager() { return port_manager_; } private: + base::test::ScopedFeatureList feature_list_; device::FakeSerialPortManager port_manager_; }; @@ -268,3 +290,60 @@ run_loop.Run(); } } + +TEST_F(SerialChooserControllerTest, Blocklist) { + base::HistogramTester histogram_tester; + + // Create two ports from the same vendor with different product IDs. + base::UnguessableToken port_1 = + AddPort("Test Port 1", base::FilePath(FILE_PATH_LITERAL("/dev/ttyS0")), + 0x1234, 0x0001); + base::UnguessableToken port_2 = + AddPort("Test Port 2", base::FilePath(FILE_PATH_LITERAL("/dev/ttyS1")), + 0x1234, 0x0002); + + // Add the second port to the blocklist. + SetDynamicBlocklist("usb:1234:0002"); + + std::vector<blink::mojom::SerialPortFilterPtr> filters; + auto controller = std::make_unique<SerialChooserController>( + main_rfh(), std::move(filters), base::DoNothing()); + + MockChooserControllerView view; + controller->set_view(&view); + + { + base::RunLoop run_loop; + EXPECT_CALL(view, OnOptionsInitialized).WillOnce(Invoke([&] { + // Expect that only the first port is shown thanks to the filter. + EXPECT_EQ(1u, controller->NumOptions()); + EXPECT_EQ(base::ASCIIToUTF16("Test Port 1 (ttyS0)"), + controller->GetOption(0)); + run_loop.Quit(); + })); + run_loop.Run(); + } + + // Removing the second port should be a no-op since it is filtered out. + EXPECT_CALL(view, OnOptionRemoved).Times(0); + port_manager().RemovePort(port_2); + base::RunLoop().RunUntilIdle(); + + // Adding it back should be a no-op as well. + EXPECT_CALL(view, OnOptionAdded).Times(0); + AddPort("Test Port 2", base::FilePath(FILE_PATH_LITERAL("/dev/ttyS1")), + 0x1234, 0x0002); + base::RunLoop().RunUntilIdle(); + + // Removing the first port should trigger a change in the UI. This also acts + // as a synchronization point to make sure that the changes above were + // processed. + { + base::RunLoop run_loop; + EXPECT_CALL(view, OnOptionRemoved(0)).WillOnce(Invoke([&]() { + run_loop.Quit(); + })); + port_manager().RemovePort(port_1); + run_loop.Run(); + } +}
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 3291c31..6df56ea 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -156,6 +156,10 @@ #include "chrome/browser/ui/hats/hats_helper.h" #endif +#if defined(OS_MAC) +#include "chrome/browser/ui/cocoa/screentime/tab_helper.h" +#endif + #if !defined(OS_ANDROID) #include "chrome/browser/media/feeds/media_feeds_contents_observer.h" #include "chrome/browser/media/feeds/media_feeds_service.h" @@ -403,6 +407,11 @@ web_modal::WebContentsModalDialogManager::CreateForWebContents(web_contents); #endif +#if defined(OS_MAC) + if (screentime::TabHelper::IsScreentimeEnabled()) + screentime::TabHelper::CreateForWebContents(web_contents); +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) app_list::CrOSActionRecorderTabTracker::CreateForWebContents(web_contents); chromeos::app_time::WebTimeNavigationObserver::MaybeCreateForWebContents(
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index ad3f9931..f90422b9 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -2018,25 +2018,34 @@ group_model_->AddTabGroup(new_group, base::nullopt); - // Find a destination for the first tab that's not inside another group. We - // will stack the rest of the tabs up to its right. + // Find a destination for the first tab that's not pinned or inside another + // group. We will stack the rest of the tabs up to its right. int destination_index = -1; for (int i = indices[0]; i < count(); i++) { const int destination_candidate = i + 1; - const bool end_of_strip = !ContainsIndex(destination_candidate); - if (end_of_strip || !GetTabGroupForTab(destination_candidate).has_value() || - GetTabGroupForTab(destination_candidate) != - GetTabGroupForTab(indices[0])) { + + // Grouping at the end of the tabstrip is always valid. + if (!ContainsIndex(destination_candidate)) { + destination_index = destination_candidate; + break; + } + + // Grouping in the middle of pinned tabs is never valid. + if (IsTabPinned(destination_candidate)) + continue; + + // Otherwise, grouping is valid if the destination is not in the middle of a + // different group. + base::Optional<tab_groups::TabGroupId> destination_group = + GetTabGroupForTab(destination_candidate); + if (!destination_group.has_value() || + destination_group != GetTabGroupForTab(indices[0])) { destination_index = destination_candidate; break; } } - // Unpin tabs when grouping -- the states should be mutually exclusive. - std::vector<int> new_indices = indices; - new_indices = SetTabsPinned(new_indices, false); - - MoveTabsAndSetGroupImpl(new_indices, destination_index, new_group); + MoveTabsAndSetGroupImpl(indices, destination_index, new_group); } void TabStripModel::AddToExistingGroupImpl( @@ -2053,9 +2062,6 @@ if (!group_model_->ContainsTabGroup(group)) return; - // Unpin tabs when grouping -- the states should be mutually exclusive. - std::vector<int> new_indices = SetTabsPinned(indices, false); - const TabGroup* group_object = group_model_->GetTabGroup(group); int first_tab_in_group = group_object->GetFirstTab().value(); int last_tab_in_group = group_object->GetLastTab().value(); @@ -2065,13 +2071,13 @@ // that are inside the group. std::vector<int> tabs_left_of_group; std::vector<int> tabs_right_of_group; - for (int new_index : new_indices) { - if (new_index >= first_tab_in_group && new_index <= last_tab_in_group) { - GroupTab(new_index, group); - } else if (new_index < first_tab_in_group) { - tabs_left_of_group.push_back(new_index); + for (int index : indices) { + if (index >= first_tab_in_group && index <= last_tab_in_group) { + GroupTab(index, group); + } else if (index < first_tab_in_group) { + tabs_left_of_group.push_back(index); } else { - tabs_right_of_group.push_back(new_index); + tabs_right_of_group.push_back(index); } } @@ -2111,12 +2117,22 @@ int index, int new_index, base::Optional<tab_groups::TabGroupId> new_group) { - DCHECK(!IsTabPinned(index)); + if (new_group.has_value()) { + // Unpin tabs when grouping -- the states should be mutually exclusive. + // Here we manually unpin the tab to avoid moving the tab twice, which can + // potentially cause race conditions. + if (IsTabPinned(index)) { + contents_data_[index]->set_pinned(false); + for (auto& observer : observers_) { + observer.TabPinnedStateChanged( + this, contents_data_[index]->web_contents(), index); + } + } - if (new_group.has_value()) GroupTab(index, new_group.value()); - else + } else { UngroupTab(index); + } if (index != new_index) MoveWebContentsAtImpl(index, new_index, false);
diff --git a/chrome/browser/ui/tabs/tab_style.h b/chrome/browser/ui/tabs/tab_style.h index 37538b5..0ac1166 100644 --- a/chrome/browser/ui/tabs/tab_style.h +++ b/chrome/browser/ui/tabs/tab_style.h
@@ -5,7 +5,10 @@ #ifndef CHROME_BROWSER_UI_TABS_TAB_STYLE_H_ #define CHROME_BROWSER_UI_TABS_TAB_STYLE_H_ +#include <tuple> + #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect_f.h" @@ -74,8 +77,17 @@ // Colors for various parts of the tab derived by TabStyle. struct TabColors { - SkColor foreground_color; - SkColor background_color; + SkColor foreground_color = gfx::kPlaceholderColor; + SkColor background_color = gfx::kPlaceholderColor; + + TabColors() = default; + TabColors(SkColor foreground_color, SkColor background_color) + : foreground_color(foreground_color), + background_color(background_color) {} + bool operator==(const TabColors& other) const { + return std::tie(foreground_color, background_color) == + std::tie(other.foreground_color, other.background_color); + } }; TabStyle(const TabStyle&) = delete;
diff --git a/chrome/browser/ui/toolbar/assign_to_desks_menu_model.cc b/chrome/browser/ui/toolbar/assign_to_desks_menu_model.cc index 5d6d1d2f..b319331 100644 --- a/chrome/browser/ui/toolbar/assign_to_desks_menu_model.cc +++ b/chrome/browser/ui/toolbar/assign_to_desks_menu_model.cc
@@ -6,23 +6,55 @@ #include "ash/public/cpp/desks_helper.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/views/widget/widget.h" AssignToDesksMenuModel::AssignToDesksMenuModel( - ui::SimpleMenuModel::Delegate* delegate) - : SimpleMenuModel(delegate), desks_helper_(ash::DesksHelper::Get()) { + ui::SimpleMenuModel::Delegate* delegate, + views::Widget* browser_widget) + : SimpleMenuModel(delegate), + desks_helper_(ash::DesksHelper::Get()), + browser_widget_(browser_widget) { constexpr int kMaxNumberOfDesks = IDC_SEND_TO_DESK_8 - IDC_SEND_TO_DESK_1 + 1; + AddCheckItem(IDC_TOGGLE_ASSIGN_TO_ALL_DESKS, + l10n_util::GetStringUTF16(IDS_ASSIGN_TO_ALL_DESKS)); + assign_to_all_desks_item_index_ = GetItemCount() - 1; + AddSeparator(ui::NORMAL_SEPARATOR); + + // Store the number of items that occur before the group of send to desk items + // so we can retrieve the send to desk items' indices properly. + send_to_desk_group_offset_ = GetItemCount(); for (int i = 0; i < kMaxNumberOfDesks; ++i) AddCheckItem(IDC_SEND_TO_DESK_1 + i, base::string16()); } bool AssignToDesksMenuModel::IsVisibleAt(int index) const { - return index < desks_helper_->GetNumberOfDesks(); + if (index == assign_to_all_desks_item_index_) + return true; + return OffsetIndexForSendToDeskGroup(index) < + desks_helper_->GetNumberOfDesks(); } base::string16 AssignToDesksMenuModel::GetLabelAt(int index) const { - return desks_helper_->GetDeskName(index); + if (index == assign_to_all_desks_item_index_) + return l10n_util::GetStringUTF16(IDS_ASSIGN_TO_ALL_DESKS); + return desks_helper_->GetDeskName(OffsetIndexForSendToDeskGroup(index)); } bool AssignToDesksMenuModel::IsItemCheckedAt(int index) const { - return index == desks_helper_->GetActiveDeskIndex(); + const bool is_assigned_to_all_desks = + browser_widget_ && browser_widget_->IsVisibleOnAllWorkspaces(); + + if (index == assign_to_all_desks_item_index_) + return is_assigned_to_all_desks; + + return !is_assigned_to_all_desks && OffsetIndexForSendToDeskGroup(index) == + desks_helper_->GetActiveDeskIndex(); +} + +int AssignToDesksMenuModel::OffsetIndexForSendToDeskGroup(int index) const { + const int send_to_desk_group_index = index - send_to_desk_group_offset_; + DCHECK_GE(send_to_desk_group_index, 0); + return send_to_desk_group_index; }
diff --git a/chrome/browser/ui/toolbar/assign_to_desks_menu_model.h b/chrome/browser/ui/toolbar/assign_to_desks_menu_model.h index d6ae9ca..7598878 100644 --- a/chrome/browser/ui/toolbar/assign_to_desks_menu_model.h +++ b/chrome/browser/ui/toolbar/assign_to_desks_menu_model.h
@@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Chromium Authors. All rights reserved. +// 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. @@ -11,10 +11,15 @@ class DesksHelper; } +namespace views { +class Widget; +} + // A menu model that builds the contents of the assign to desks menu. class AssignToDesksMenuModel : public ui::SimpleMenuModel { public: - explicit AssignToDesksMenuModel(ui::SimpleMenuModel::Delegate* delegate); + AssignToDesksMenuModel(ui::SimpleMenuModel::Delegate* delegate, + views::Widget* browser_widget); ~AssignToDesksMenuModel() override = default; // SimpleMenuModel: @@ -23,7 +28,20 @@ bool IsItemCheckedAt(int index) const override; private: + // Returns |index| - |send_to_desk_group_offset_|. This value is the relative + // index within the group of send to desk items. This value must be greater + // than or equal to 0. + int OffsetIndexForSendToDeskGroup(int index) const; + const ash::DesksHelper* const desks_helper_; + const views::Widget* const browser_widget_; + + // This is the index of the assign to all desks item in the menu model. + int assign_to_all_desks_item_index_; + + // This is the number of items in the menu model that occurs before the group + // of send to desk items. + int send_to_desk_group_offset_; }; #endif // CHROME_BROWSER_UI_TOOLBAR_ASSIGN_TO_DESKS_MENU_MODEL_H_
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc index e31d4e6..5c03f25 100644 --- a/chrome/browser/ui/views/frame/browser_frame.cc +++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -85,6 +85,9 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) params.init_properties_container.SetProperty( full_restore::kWindowIdKey, browser_view_->browser()->session_id().id()); + params.init_properties_container.SetProperty( + full_restore::kRestoreWindowIdKey, + browser_view_->browser()->create_params().restore_id); #endif if (browser_view_->browser()->is_type_normal() || browser_view_->browser()->is_type_devtools() ||
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder.cc b/chrome/browser/ui/views/frame/system_menu_model_builder.cc index 5dc3bcd..c837c74 100644 --- a/chrome/browser/ui/views/frame/system_menu_model_builder.cc +++ b/chrome/browser/ui/views/frame/system_menu_model_builder.cc
@@ -33,6 +33,7 @@ #include "components/user_manager/user_info.h" #include "components/user_manager/user_manager.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/views/widget/widget.h" #endif SystemMenuModelBuilder::SystemMenuModelBuilder( @@ -133,6 +134,9 @@ model->AddSeparator(ui::NORMAL_SEPARATOR); model->AddItemWithStringId(IDC_CLOSE_WINDOW, IDS_CLOSE); #endif +#if BUILDFLAG(IS_CHROMEOS_ASH) + AppendAssignToDesksMenu(model); +#endif AppendTeleportMenu(model); } @@ -150,8 +154,10 @@ ui::SimpleMenuModel* model) { if (ash::features::IsBentoEnabled()) { model->AddSeparator(ui::NORMAL_SEPARATOR); - assign_to_desks_model_ = - std::make_unique<AssignToDesksMenuModel>(&menu_delegate_); + assign_to_desks_model_ = std::make_unique<AssignToDesksMenuModel>( + &menu_delegate_, + views::Widget::GetWidgetForNativeWindow( + menu_delegate_.browser()->window()->GetNativeWindow())); model->AddSubMenuWithStringId(IDC_ASSIGN_TO_DESKS_MENU, IDS_ASSIGN_TO_DESKS_MENU, assign_to_desks_model_.get());
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc index 17a61cf7..14b129d 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -137,13 +137,6 @@ views::BubbleFrameView* frame = GetBubbleFrameView(); if (frame) frame->SetCornerRadius(corner_radius); - if (!base::FeatureList::IsEnabled( - views::features::kEnableMDRoundedCornersOnDialogs)) { - SetPaintToLayer(); - layer()->SetRoundedCornerRadius(gfx::RoundedCornersF(corner_radius)); - if (base::FeatureList::IsEnabled(media::kLiveCaption)) - layer()->SetFillsBoundsOpaquely(false); - } service_->SetDialogDelegate(this); speech::SodaInstaller::GetInstance()->AddObserver(this); } @@ -217,6 +210,9 @@ profile_(profile->GetOriginalProfile()), active_sessions_view_( AddChildView(std::make_unique<MediaNotificationListView>())) { + // Enable layer based clipping to ensure children using layers are clipped + // appropriately. + SetPaintClientToLayer(true); SetButtons(ui::DIALOG_BUTTON_NONE); DCHECK(service_); } @@ -245,13 +241,6 @@ gfx::Insets(kLiveCaptionHorizontalMarginDip, kLiveCaptionVerticalMarginDip), kLiveCaptionBetweenChildSpacing)); - if (!base::FeatureList::IsEnabled( - views::features::kEnableMDRoundedCornersOnDialogs)) { - SkColor native_theme_bg_color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_BubbleBackground); - live_caption_container->SetBackground( - views::CreateSolidBackground(native_theme_bg_color)); - } auto live_caption_image = std::make_unique<views::ImageView>(); live_caption_image->SetImage(gfx::CreateVectorIcon(
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 4532bdc8..824acb2c 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -776,7 +776,7 @@ is_active); // Try to show tab groups IPH if needed. - if (tabstrip_->tab_count() >= 6) { + if (tabstrip_->GetTabCount() >= 6) { feature_engagement_tracker_->NotifyEvent( feature_engagement::events::kSixthTabOpened);
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc index b02ee99e1..875798f5 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.cc +++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -28,6 +28,7 @@ #include "ui/views/animation/ink_drop_impl.h" #include "ui/views/animation/ink_drop_mask.h" #include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/metadata/metadata_impl_macros.h" #include "ui/views/widget/widget.h" #if defined(OS_WIN) @@ -36,9 +37,6 @@ #endif // static -constexpr char NewTabButton::kClassName[]; - -// static const gfx::Size NewTabButton::kButtonSize{28, 28}; class NewTabButton::HighlightPathGenerator @@ -91,10 +89,6 @@ GetInkDrop()->AnimateToState(state); } -const char* NewTabButton::GetClassName() const { - return kClassName; -} - void NewTabButton::AddLayerBeneathView(ui::Layer* new_layer) { ink_drop_container_->AddLayerBeneathView(new_layer); } @@ -273,3 +267,6 @@ SetInkDropBaseColor( color_utils::GetColorWithMaxContrast(GetButtonFillColor())); } + +BEGIN_METADATA(NewTabButton, views::ImageButton) +END_METADATA
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.h b/chrome/browser/ui/views/tabs/new_tab_button.h index da8fdf3..036774a 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.h +++ b/chrome/browser/ui/views/tabs/new_tab_button.h
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "ui/views/controls/button/image_button.h" +#include "ui/views/metadata/metadata_header_macros.h" #include "ui/views/view.h" namespace views { @@ -26,7 +27,7 @@ class NewTabButton : public views::ImageButton, public views::MaskedTargeterDelegate { public: - static constexpr char kClassName[] = "NewTabButton"; + METADATA_HEADER(NewTabButton); static const gfx::Size kButtonSize; @@ -43,7 +44,6 @@ void AnimateInkDropToStateForTesting(views::InkDropState state); // views::ImageButton: - const char* GetClassName() const override; void AddLayerBeneathView(ui::Layer* new_layer) override; void RemoveLayerBeneathView(ui::Layer* old_layer) override;
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 3e13de28..815d0de 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -1021,8 +1021,7 @@ title_->SetEnabledColor(colors.foreground_color); - close_button_->SetIconColors(colors.foreground_color, - colors.background_color); + close_button_->SetColors(colors); if (foreground_color_ != colors.foreground_color) { foreground_color_ = colors.foreground_color;
diff --git a/chrome/browser/ui/views/tabs/tab_close_button.cc b/chrome/browser/ui/views/tabs/tab_close_button.cc index e65e991..7dc2270 100644 --- a/chrome/browser/ui/views/tabs/tab_close_button.cc +++ b/chrome/browser/ui/views/tabs/tab_close_button.cc
@@ -26,6 +26,7 @@ #include "ui/views/animation/ink_drop.h" #include "ui/views/controls/highlight_path_generator.h" #include "ui/views/layout/layout_provider.h" +#include "ui/views/metadata/metadata_impl_macros.h" #include "ui/views/rect_based_targeting_utils.h" #include "ui/views/view_class_properties.h" @@ -88,20 +89,23 @@ : kGlyphSize; } -void TabCloseButton::SetIconColors(SkColor foreground_color, - SkColor background_color) { - icon_color_ = foreground_color; - SetInkDropBaseColor(color_utils::GetColorWithMaxContrast(background_color)); +TabStyle::TabColors TabCloseButton::GetColors() const { + return colors_; +} + +void TabCloseButton::SetColors(TabStyle::TabColors colors) { + if (colors == colors_) + return; + colors_ = std::move(colors); + SetInkDropBaseColor( + color_utils::GetColorWithMaxContrast(colors_.background_color)); + OnPropertyChanged(&colors_, views::kPropertyEffectsPaint); } void TabCloseButton::SetButtonPadding(const gfx::Insets& padding) { *GetProperty(views::kInternalPaddingKey) = padding; } -const char* TabCloseButton::GetClassName() const { - return "TabCloseButton"; -} - views::View* TabCloseButton::GetTooltipHandlerForPoint( const gfx::Point& point) { // Tab close button has no children, so tooltip handler should be the same @@ -157,7 +161,7 @@ flags.setAntiAlias(true); flags.setStrokeWidth(kStrokeWidth); flags.setStrokeCap(cc::PaintFlags::kRound_Cap); - flags.setColor(icon_color_); + flags.setColor(colors_.foreground_color); canvas->DrawLine(glyph_bounds.origin(), glyph_bounds.bottom_right(), flags); canvas->DrawLine(glyph_bounds.bottom_left(), glyph_bounds.top_right(), flags); } @@ -194,3 +198,7 @@ mask->addRect(gfx::RectToSkRect(GetMirroredRect(GetContentsBounds()))); return true; } + +BEGIN_METADATA(TabCloseButton, views::ImageButton) +ADD_PROPERTY_METADATA(TabStyle::TabColors, Colors) +END_METADATA
diff --git a/chrome/browser/ui/views/tabs/tab_close_button.h b/chrome/browser/ui/views/tabs/tab_close_button.h index 6f59db7..dce4685f 100644 --- a/chrome/browser/ui/views/tabs/tab_close_button.h +++ b/chrome/browser/ui/views/tabs/tab_close_button.h
@@ -6,9 +6,10 @@ #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_CLOSE_BUTTON_H_ #include "base/callback_forward.h" -#include "ui/gfx/color_palette.h" +#include "chrome/browser/ui/views/tabs/tab_style_views.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/masked_targeter_delegate.h" +#include "ui/views/metadata/metadata_header_macros.h" // This is a Button subclass that shows the tab closed icon. // @@ -17,6 +18,8 @@ class TabCloseButton : public views::ImageButton, public views::MaskedTargeterDelegate { public: + METADATA_HEADER(TabCloseButton); + using MouseEventCallback = base::RepeatingCallback<void(views::View*, const ui::MouseEvent&)>; @@ -33,11 +36,12 @@ // Returns the width/height of the tab close button, sans insets/padding. static int GetGlyphSize(); + TabStyle::TabColors GetColors() const; // This function must be called before the tab is painted so it knows what // colors to use. It must also be called when the background color of the tab // changes (this class does not track tab activation state), and when the // theme changes. - void SetIconColors(SkColor foreground_color, SkColor background_color); + void SetColors(TabStyle::TabColors colors); // Sets the desired padding around the icon. Only the icon is a target for // mouse clicks, but the entire button is a target for touch events, since the @@ -47,7 +51,6 @@ void SetButtonPadding(const gfx::Insets& padding); // views::ImageButton: - const char* GetClassName() const override; View* GetTooltipHandlerForPoint(const gfx::Point& point) override; bool OnMousePressed(const ui::MouseEvent& event) override; void OnMouseReleased(const ui::MouseEvent& event) override; @@ -67,7 +70,7 @@ MouseEventCallback mouse_event_callback_; - SkColor icon_color_ = gfx::kPlaceholderColor; + TabStyle::TabColors colors_; }; #endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_CLOSE_BUTTON_H_
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 0ff04054..7c623cc 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -3914,8 +3914,8 @@ displays.first.id(), screen->GetDisplayNearestWindow(browser()->window()->GetNativeWindow()) .id()); - EXPECT_EQ(2, tab_strip->tab_count()); - EXPECT_EQ(1, tab_strip2->tab_count()); + EXPECT_EQ(2, tab_strip->GetTabCount()); + EXPECT_EQ(1, tab_strip2->GetTabCount()); // Move to the first tab and drag it enough so that it detaches, but not // enough that it attaches to browser2. @@ -3932,8 +3932,8 @@ ASSERT_TRUE(ReleaseInput()); // tab should have moved - EXPECT_EQ(1, tab_strip->tab_count()); - EXPECT_EQ(2, tab_strip2->tab_count()); + EXPECT_EQ(1, tab_strip->GetTabCount()); + EXPECT_EQ(2, tab_strip2->GetTabCount()); ASSERT_FALSE(tab_strip2->GetDragContext()->IsDragSessionActive()); ASSERT_FALSE(tab_strip->GetDragContext()->IsDragSessionActive());
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 64ec699..6358ef8 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -89,6 +89,7 @@ #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/controls/image_view.h" #include "ui/views/masked_targeter_delegate.h" +#include "ui/views/metadata/metadata_impl_macros.h" #include "ui/views/mouse_watcher_view_host.h" #include "ui/views/rect_based_targeting_utils.h" #include "ui/views/view_model_utils.h" @@ -487,7 +488,7 @@ return tab_strip_->GetModelIndexOf(view); } - int GetTabCount() const override { return tab_strip_->tab_count(); } + int GetTabCount() const override { return tab_strip_->GetTabCount(); } bool IsTabPinned(const Tab* tab) const override { return tab_strip_->IsTabPinned(tab); @@ -1160,17 +1161,17 @@ } void TabStrip::FrameColorsChanged() { - for (int i = 0; i < tab_count(); ++i) + for (int i = 0; i < GetTabCount(); ++i) tab_at(i)->FrameColorsChanged(); UpdateContrastRatioValues(); SchedulePaint(); } void TabStrip::SetBackgroundOffset(int background_offset) { - if (background_offset != background_offset_) { - background_offset_ = background_offset; - SchedulePaint(); - } + if (background_offset == background_offset_) + return; + background_offset_ = background_offset; + OnPropertyChanged(&background_offset_, views::kPropertyEffectsPaint); } bool TabStrip::IsRectInWindowCaption(const gfx::Rect& rect) { @@ -1231,7 +1232,7 @@ } void TabStrip::UpdateLoadingAnimations(const base::TimeDelta& elapsed_time) { - for (int i = 0; i < tab_count(); i++) + for (int i = 0; i < GetTabCount(); i++) tab_at(i)->StepLoadingAnimation(elapsed_time); } @@ -1250,7 +1251,7 @@ AnimateToIdealBounds(); } - for (int i = 0; i < tab_count(); ++i) + for (int i = 0; i < GetTabCount(); ++i) tab_at(i)->Layout(); } @@ -1280,7 +1281,7 @@ // Don't animate the first tab, it looks weird, and don't animate anything // if the containing window isn't visible yet. - if (tab_count() > 1 && GetWidget() && GetWidget()->IsVisible()) { + if (GetTabCount() > 1 && GetWidget() && GetWidget()->IsVisible()) { StartInsertTabAnimation(model_index, pinned ? TabPinned::kPinned : TabPinned::kUnpinned); } else { @@ -1310,9 +1311,9 @@ Profile* profile = controller()->GetProfile(); if (profile) { if (profile->IsGuestSession() || profile->IsEphemeralGuestProfile()) - base::UmaHistogramCounts100("Tab.Count.Guest", tab_count()); + base::UmaHistogramCounts100("Tab.Count.Guest", GetTabCount()); else if (profile->IsIncognitoProfile()) - base::UmaHistogramCounts100("Tab.Count.Incognito", tab_count()); + base::UmaHistogramCounts100("Tab.Count.Incognito", GetTabCount()); } } @@ -1727,6 +1728,10 @@ return tabs_.GetIndexOfView(view); } +int TabStrip::GetTabCount() const { + return tabs_.view_size(); +} + int TabStrip::GetModelCount() const { return controller_->GetCount(); } @@ -1766,7 +1771,7 @@ } views::View* TabStrip::GetTabViewForPromoAnchor(int index_hint) { - return tab_at(base::ClampToRange(index_hint, 0, tab_count() - 1)); + return tab_at(base::ClampToRange(index_hint, 0, GetTabCount() - 1)); } views::View* TabStrip::GetDefaultFocusableChild() { @@ -1905,11 +1910,11 @@ int target_index; if (controller_->IsTabPinned(start_index)) { int temp_index = start_index + 1; - while (temp_index < tab_count() && controller_->IsTabPinned(temp_index)) + while (temp_index < GetTabCount() && controller_->IsTabPinned(temp_index)) ++temp_index; target_index = temp_index - 1; } else { - target_index = tab_count() - 1; + target_index = GetTabCount() - 1; } if (!IsValidModelIndex(target_index)) @@ -2390,11 +2395,6 @@ base::TimeDelta::FromMicroseconds(10000), 50); } -const char* TabStrip::GetClassName() const { - static const char kViewClassName[] = "TabStrip"; - return kViewClassName; -} - gfx::Size TabStrip::GetMinimumSize() const { // If tabs can be stacked, our minimum width is the smallest width of the // stacked tabstrip. @@ -2464,7 +2464,7 @@ // coordinates since we calculate the drop index based on the // original (and therefore non-mirrored) positions of the tabs. const int x = GetMirroredXInView(event.x()); - for (int i = 0; i < tab_count(); ++i) { + for (int i = 0; i < GetTabCount(); ++i) { Tab* tab = tab_at(i); const int tab_max_x = tab->x() + tab->width(); @@ -2480,7 +2480,7 @@ } // The drop isn't over a tab, add it to the end. - return {tab_count(), true}; + return {GetTabCount(), true}; } views::View* TabStrip::GetViewForDrop() { @@ -2572,7 +2572,7 @@ if (model_index > 0) { // If we have a tab to our left, start at its right edge. bounds.set_x(tab_at(model_index - 1)->bounds().right() - tab_overlap); - } else if (model_index + 1 < tab_count()) { + } else if (model_index + 1 < GetTabCount()) { // Otherwise, if we have a tab to our right, start at its left edge. bounds.set_x(tab_at(model_index + 1)->bounds().x()); } else { @@ -2686,7 +2686,7 @@ void TabStrip::AnimateToIdealBounds() { UpdateHoverCard(nullptr); - for (int i = 0; i < tab_count(); ++i) { + for (int i = 0; i < GetTabCount(); ++i) { // If the tab is being dragged manually, skip it. Tab* tab = tab_at(i); if (tab->dragging() && !bounds_animator_.IsAnimating(tab)) @@ -2736,7 +2736,7 @@ } void TabStrip::SnapToIdealBounds() { - for (int i = 0; i < tab_count(); ++i) + for (int i = 0; i < GetTabCount(); ++i) tab_at(i)->SetBoundsRect(ideal_bounds(i)); for (const auto& header_pair : group_views_) { @@ -2810,7 +2810,7 @@ } void TabStrip::UpdateAccessibleTabIndices() { - const int num_tabs = tab_count(); + const int num_tabs = GetTabCount(); for (int i = 0; i < num_tabs; ++i) tab_at(i)->GetViewAccessibility().OverridePosInSet(i + 1, num_tabs); } @@ -2824,7 +2824,7 @@ } const Tab* TabStrip::GetLastVisibleTab() const { - for (int i = tab_count() - 1; i >= 0; --i) { + for (int i = GetTabCount() - 1; i >= 0; --i) { const Tab* tab = tab_at(i); // The tab is marked not visible in a collapsed group, but is "visible" in @@ -2851,14 +2851,14 @@ // If to_model_index is beyond the end of the tab strip, then the tab is newly // added to the end of the tab strip. In that case we can just return one // beyond the view index of the last existing tab. - if (to_model_index >= tab_count()) - return (tab_count() ? GetIndexOf(tab_at(tab_count() - 1)) + 1 : 0); + if (to_model_index >= GetTabCount()) + return (GetTabCount() ? GetIndexOf(tab_at(GetTabCount() - 1)) + 1 : 0); // If there is no from_model_index, then the tab is newly added in the middle // of the tab strip. In that case we treat it as coming from the end of the // tab strip, since new views are ordered at the end by default. if (!from_model_index.has_value()) - from_model_index = tab_count(); + from_model_index = GetTabCount(); DCHECK_NE(to_model_index, from_model_index.value()); @@ -3207,7 +3207,7 @@ // We've been called back after the TabStrip has been emptied out (probably // just prior to the window being destroyed). We need to do nothing here or // else GetTabAt below will crash. - if (tab_count() == 0) + if (GetTabCount() == 0) return; // It is critically important that this is unhooked here, otherwise we will @@ -3216,7 +3216,7 @@ ExitTabClosingMode(); int pinned_tab_count = GetPinnedTabCount(); - if (pinned_tab_count == tab_count()) { + if (pinned_tab_count == GetTabCount()) { // Only pinned tabs, we know the tab widths won't have changed (all // pinned tabs have the same width), so there is nothing to do. return; @@ -3265,11 +3265,11 @@ bool* is_beneath) { DCHECK_NE(drop_index, -1); - Tab* tab = tab_at(std::min(drop_index, tab_count() - 1)); + Tab* tab = tab_at(std::min(drop_index, GetTabCount() - 1)); int center_x = tab->x(); const int width = tab->width(); const int overlap = TabStyle::GetTabOverlap(); - if (drop_index < tab_count()) + if (drop_index < GetTabCount()) center_x += drop_before ? (overlap / 2) : (width / 2); else center_x += width - (overlap / 2); @@ -3400,13 +3400,13 @@ void TabStrip::PrepareForAnimation() { if (!drag_context_->IsDragSessionActive() && !TabDragController::IsAttachedTo(GetDragContext())) { - for (int i = 0; i < tab_count(); ++i) + for (int i = 0; i < GetTabCount(); ++i) tab_at(i)->set_dragging(false); } } void TabStrip::UpdateIdealBounds() { - if (tab_count() == 0) + if (GetTabCount() == 0) return; // Should only happen during creation/destruction, ignore. // Update |last_available_width_| in case there is a different amount of @@ -3470,10 +3470,10 @@ Tab* TabStrip::FindTabForEventFrom(const gfx::Point& point, int start, int delta) { - // |start| equals tab_count() when there are only pinned tabs. - if (start == tab_count()) + // |start| equals GetTabCount() when there are only pinned tabs. + if (start == GetTabCount()) start += delta; - for (int i = start; i >= 0 && i < tab_count(); i += delta) { + for (int i = start; i >= 0 && i < GetTabCount(); i += delta) { if (IsPointInTab(tab_at(i), point)) return tab_at(i); } @@ -3560,7 +3560,7 @@ return false; const int pinned_tab_count = GetPinnedTabCount(); - const int normal_count = tab_count() - pinned_tab_count; + const int normal_count = GetTabCount() - pinned_tab_count; if (normal_count <= 1) return false; @@ -3779,3 +3779,18 @@ IDS_TAB_AX_ANNOUNCE_TAB_REMOVED_FROM_NAMED_GROUP, group_title, contents_string)); } + +BEGIN_METADATA(TabStrip, views::View) +ADD_PROPERTY_METADATA(int, BackgroundOffset) +ADD_READONLY_PROPERTY_METADATA(int, TabCount) +ADD_READONLY_PROPERTY_METADATA(int, ModelCount) +ADD_READONLY_PROPERTY_METADATA(int, PinnedTabCount) +ADD_READONLY_PROPERTY_METADATA(base::Optional<int>, FocusedTabIndex) +ADD_READONLY_PROPERTY_METADATA(int, StrokeThickness) +ADD_READONLY_PROPERTY_METADATA(SkColor, ToolbarTopSeparatorColor) +ADD_READONLY_PROPERTY_METADATA(SkColor, TabSeparatorColor) +ADD_READONLY_PROPERTY_METADATA(float, HoverOpacityForRadialHighlight) +ADD_READONLY_PROPERTY_METADATA(int, ActiveTabWidth) +ADD_READONLY_PROPERTY_METADATA(int, InactiveTabWidth) +ADD_READONLY_PROPERTY_METADATA(int, AvailableWidthForTabStrip) +END_METADATA
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 6a13ef8..55d4485b 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -34,6 +34,7 @@ #include "ui/gfx/geometry/rect.h" #include "ui/views/animation/bounds_animator.h" #include "ui/views/controls/button/image_button.h" +#include "ui/views/metadata/metadata_header_macros.h" #include "ui/views/mouse_watcher.h" #include "ui/views/view.h" #include "ui/views/view_model.h" @@ -80,6 +81,7 @@ public TabController, public BrowserRootView::DropTarget { public: + METADATA_HEADER(TabStrip); explicit TabStrip(std::unique_ptr<TabStripController> controller); TabStrip(const TabStrip&) = delete; TabStrip& operator=(const TabStrip&) = delete; @@ -238,7 +240,7 @@ int GetModelIndexOf(const TabSlotView* view) const; // Gets the number of Tabs in the tab strip. - int tab_count() const { return tabs_.view_size(); } + int GetTabCount() const; // Cover method for TabStripController::GetCount. int GetModelCount() const; @@ -337,7 +339,6 @@ // views::View: void Layout() override; void PaintChildren(const views::PaintInfo& paint_info) override; - const char* GetClassName() const override; gfx::Size GetMinimumSize() const override; gfx::Size CalculatePreferredSize() const override; views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override; @@ -471,14 +472,6 @@ // differ from this width slightly due to rounding. int GetInactiveTabWidth() const; - // Returns the width of the area that contains tabs not including the new tab - // button. - int GetTabAreaWidth() const; - - // Returns the width of the area right of the tabs reserved for the new tab - // button and the frame grab area. - int GetRightSideReservedWidth() const; - // Returns the last tab in the strip that's actually visible. This will be // the actual last tab unless the strip is in the overflow node_data. const Tab* GetLastVisibleTab() const; @@ -680,9 +673,9 @@ views::BoundsAnimator bounds_animator_{this}; // If this value is defined, it is used as the width to lay out tabs - // (instead of GetTabAreaWidth()). It is defined when closing tabs with the - // mouse, and is used to control which tab will end up under the cursor - // after the close animation completes. + // (instead of GetAvailableWidthForTabStrip()). It is defined when closing + // tabs with the mouse, and is used to control which tab will end up under the + // cursor after the close animation completes. base::Optional<int> override_available_width_for_tabs_; // The background offset used by inactive tabs to match the frame image.
diff --git a/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc b/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc index 2c1fb83..c43a14c 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc
@@ -47,7 +47,7 @@ std::vector<content::WebContents*> GetWebContentses() { std::vector<content::WebContents*> contentses; - for (int i = 0; i < tab_strip()->tab_count(); ++i) + for (int i = 0; i < tab_strip()->GetTabCount(); ++i) contentses.push_back(tab_strip_model()->GetWebContentsAt(i)); return contentses; } @@ -55,7 +55,7 @@ std::vector<content::WebContents*> GetWebContentsesInOrder( const std::vector<int>& order) { std::vector<content::WebContents*> contentses; - for (int i = 0; i < tab_strip()->tab_count(); ++i) + for (int i = 0; i < tab_strip()->GetTabCount(); ++i) contentses.push_back(tab_strip_model()->GetWebContentsAt(order[i])); return contentses; }
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index 2d69d78..a6a4cc4c 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -193,14 +193,14 @@ // Makes sure that all tabs have the correct AX indices. void VerifyTabIndices() { - for (int i = 0; i < tab_strip_->tab_count(); ++i) { + for (int i = 0; i < tab_strip_->GetTabCount(); ++i) { ui::AXNodeData ax_node_data; tab_strip_->tab_at(i)->GetViewAccessibility().GetAccessibleNodeData( &ax_node_data); EXPECT_EQ(i + 1, ax_node_data.GetIntAttribute( ax::mojom::IntAttribute::kPosInSet)); EXPECT_EQ( - tab_strip_->tab_count(), + tab_strip_->GetTabCount(), ax_node_data.GetIntAttribute(ax::mojom::IntAttribute::kSetSize)); } } @@ -218,7 +218,7 @@ views::View::Views all_children = tab_strip_->children(); const int num_tab_slot_views = - tab_strip_->tab_count() + tab_strip_->group_views_.size(); + tab_strip_->GetTabCount() + tab_strip_->group_views_.size(); return views::View::Views(all_children.begin(), all_children.begin() + num_tab_slot_views); @@ -231,7 +231,7 @@ base::Optional<tab_groups::TabGroupId> prev_group = base::nullopt; - for (int i = 0; i < tab_strip_->tab_count(); ++i) { + for (int i = 0; i < tab_strip_->GetTabCount(); ++i) { Tab* tab = tab_strip_->tab_at(i); // If the current Tab is the first one in a group, first add the @@ -312,13 +312,13 @@ } TEST_P(TabStripTest, tab_count) { - EXPECT_EQ(0, tab_strip_->tab_count()); + EXPECT_EQ(0, tab_strip_->GetTabCount()); } TEST_P(TabStripTest, AddTabAt) { TestTabStripObserver observer(tab_strip_); controller_->AddTab(0, false); - ASSERT_EQ(1, tab_strip_->tab_count()); + ASSERT_EQ(1, tab_strip_->GetTabCount()); EXPECT_EQ(0, observer.last_tab_added()); Tab* tab = tab_strip_->tab_at(0); EXPECT_FALSE(tab == NULL); @@ -329,7 +329,7 @@ controller_->AddTab(0, false); controller_->AddTab(1, false); controller_->AddTab(2, false); - ASSERT_EQ(3, tab_strip_->tab_count()); + ASSERT_EQ(3, tab_strip_->GetTabCount()); EXPECT_EQ(2, observer.last_tab_added()); Tab* tab = tab_strip_->tab_at(0); controller_->MoveTab(0, 1); @@ -344,11 +344,11 @@ controller_->AddTab(0, false); controller_->AddTab(1, false); const size_t num_children = tab_strip_->children().size(); - EXPECT_EQ(2, tab_strip_->tab_count()); + EXPECT_EQ(2, tab_strip_->GetTabCount()); controller_->RemoveTab(0); EXPECT_EQ(0, observer.last_tab_removed()); // When removing a tab the tabcount should immediately decrement. - EXPECT_EQ(1, tab_strip_->tab_count()); + EXPECT_EQ(1, tab_strip_->GetTabCount()); // But the number of views should remain the same (it's animatining closed). EXPECT_EQ(num_children, tab_strip_->children().size()); @@ -453,12 +453,12 @@ ASSERT_GT(i, 0); EXPECT_LT(i, invisible_tab_index); invisible_tab_index = i; - for (int i = invisible_tab_index + 1; i < tab_strip_->tab_count(); ++i) + for (int i = invisible_tab_index + 1; i < tab_strip_->GetTabCount(); ++i) EXPECT_FALSE(tab_strip_->tab_at(i)->GetVisible()); // When we're already in overflow, adding tabs at the beginning or end of // the strip should not change how many tabs are visible. - controller_->AddTab(tab_strip_->tab_count(), false); + controller_->AddTab(tab_strip_->GetTabCount(), false); CompleteAnimationAndLayout(); EXPECT_TRUE(tab_strip_->tab_at(invisible_tab_index - 1)->GetVisible()); EXPECT_FALSE(tab_strip_->tab_at(invisible_tab_index)->GetVisible()); @@ -468,10 +468,10 @@ EXPECT_FALSE(tab_strip_->tab_at(invisible_tab_index)->GetVisible()); // If we remove enough tabs, all the tabs should be visible. - for (int i = tab_strip_->tab_count() - 1; i >= invisible_tab_index; --i) + for (int i = tab_strip_->GetTabCount() - 1; i >= invisible_tab_index; --i) controller_->RemoveTab(i); CompleteAnimationAndLayout(); - EXPECT_TRUE(tab_strip_->tab_at(tab_strip_->tab_count() - 1)->GetVisible()); + EXPECT_TRUE(tab_strip_->tab_at(tab_strip_->GetTabCount() - 1)->GetVisible()); } TEST_P(TabStripTest, GroupedTabSlotVisibility) { @@ -529,7 +529,7 @@ controller_->AddTab(1, true); controller_->AddTab(2, false); controller_->AddTab(3, false); - ASSERT_EQ(4, tab_strip_->tab_count()); + ASSERT_EQ(4, tab_strip_->GetTabCount()); // Switch to stacked layout mode and force a layout to ensure tabs stack. tab_strip_->SetStackedLayout(true); @@ -544,7 +544,7 @@ int tab = tab_strip_->GetModelIndexOf(FindTabForEvent(p)); if (tab == previous_tab) continue; - if ((tab != -1) || (previous_tab != tab_strip_->tab_count() - 1)) + if ((tab != -1) || (previous_tab != tab_strip_->GetTabCount() - 1)) EXPECT_EQ(previous_tab + 1, tab) << "p = " << p.ToString(); previous_tab = tab; } @@ -559,7 +559,7 @@ controller_->AddTab(1, true); controller_->AddTab(2, false); controller_->AddTab(3, false); - ASSERT_EQ(4, tab_strip_->tab_count()); + ASSERT_EQ(4, tab_strip_->GetTabCount()); // Switch to stacked layout mode and force a layout to ensure tabs stack. tab_strip_->SetStackedLayout(true); @@ -588,7 +588,7 @@ controller_->AddTab(0, false); controller_->AddTab(1, true); controller_->AddTab(2, false); - ASSERT_EQ(3, tab_strip_->tab_count()); + ASSERT_EQ(3, tab_strip_->GetTabCount()); Tab* tab0 = tab_strip_->tab_at(0); Tab* tab1 = tab_strip_->tab_at(1); @@ -661,7 +661,7 @@ controller_->AddTab(0, false); controller_->AddTab(1, true); controller_->AddTab(2, false); - ASSERT_EQ(3, tab_strip_->tab_count()); + ASSERT_EQ(3, tab_strip_->GetTabCount()); Tab* tab0 = tab_strip_->tab_at(0); ASSERT_FALSE(tab0->IsActive()); @@ -738,7 +738,7 @@ controller_->AddTab(2, false); controller_->AddTab(3, false); CompleteAnimationAndLayout(); - ASSERT_EQ(4, tab_strip_->tab_count()); + ASSERT_EQ(4, tab_strip_->GetTabCount()); // Verify that the active tab will be a tooltip handler for points that hit // it. @@ -802,7 +802,7 @@ controller_->AddTab(2, false); controller_->AddTab(3, false); CompleteAnimationAndLayout(); - ASSERT_EQ(4, tab_strip_->tab_count()); + ASSERT_EQ(4, tab_strip_->GetTabCount()); // Verify that the active tab will be a tooltip handler for points that hit // it. @@ -903,17 +903,17 @@ CompleteAnimationAndLayout(); } - EXPECT_GT(tab_strip_->tab_count(), 1); + EXPECT_GT(tab_strip_->GetTabCount(), 1); const int active_index = controller_->GetActiveIndex(); - EXPECT_EQ(tab_strip_->tab_count() - 1, active_index); + EXPECT_EQ(tab_strip_->GetTabCount() - 1, active_index); EXPECT_LT(tab_strip_->ideal_bounds(0).width(), tab_strip_->ideal_bounds(active_index).width()); // During mouse-based tab closure, the active tab should remain at least as // wide as it's minimum width. controller_->SelectTab(0, dummy_event_); - while (tab_strip_->tab_count() > 0) { + while (tab_strip_->GetTabCount() > 0) { const int active_index = controller_->GetActiveIndex(); EXPECT_GE(tab_strip_->ideal_bounds(active_index).width(), TabStyleViews::GetMinimumActiveWidth()); @@ -943,7 +943,7 @@ // If there are only two tabs in the strip, then after closing one the // remaining one will be active and there will be no inactive tabs, // so we stop at 2. - while (tab_strip_->tab_count() > 2) { + while (tab_strip_->GetTabCount() > 2) { const int last_inactive_width = GetInactiveTabWidth(); tab_strip_->CloseTab(tab_strip_->tab_at(controller_->GetActiveIndex()), CLOSE_TAB_FROM_MOUSE); @@ -963,23 +963,24 @@ } // The test closes two tabs, we need at least one left over after that. - ASSERT_GE(tab_strip_->tab_count(), 3); + ASSERT_GE(tab_strip_->GetTabCount(), 3); // Close the second-to-last tab to enter tab closing mode. - tab_strip_->CloseTab(tab_strip_->tab_at(tab_strip_->tab_count() - 2), + tab_strip_->CloseTab(tab_strip_->tab_at(tab_strip_->GetTabCount() - 2), CLOSE_TAB_FROM_MOUSE); CompleteAnimationAndLayout(); ASSERT_LT(GetActiveTabWidth(), standard_width); // Close the last tab; tabs should reach standard width. - tab_strip_->CloseTab(tab_strip_->tab_at(tab_strip_->tab_count() - 1), + tab_strip_->CloseTab(tab_strip_->tab_at(tab_strip_->GetTabCount() - 1), CLOSE_TAB_FROM_MOUSE); CompleteAnimationAndLayout(); EXPECT_EQ(GetActiveTabWidth(), standard_width); // The tabstrip width should match the rightmost tab's right edge. - EXPECT_EQ(tab_strip_->bounds().width(), - tab_strip_->tab_at(tab_strip_->tab_count() - 1)->bounds().right()); + EXPECT_EQ( + tab_strip_->bounds().width(), + tab_strip_->tab_at(tab_strip_->GetTabCount() - 1)->bounds().right()); } // When dragged tabs are moving back to their position, changes to ideal bounds @@ -1332,7 +1333,7 @@ controller_->MoveTabIntoGroup(2, group_id); CompleteAnimationAndLayout(); - ASSERT_EQ(3, tab_strip_->tab_count()); + ASSERT_EQ(3, tab_strip_->GetTabCount()); ASSERT_EQ(3, tab_strip_->GetModelCount()); EXPECT_EQ(base::nullopt, tab_strip_->tab_at(0)->group()); EXPECT_EQ(group_id, tab_strip_->tab_at(1)->group()); @@ -1362,7 +1363,7 @@ // After finishing animations, there should be exactly 1 tab in no // group. - EXPECT_EQ(1, tab_strip_->tab_count()); + EXPECT_EQ(1, tab_strip_->GetTabCount()); EXPECT_EQ(base::nullopt, tab_strip_->tab_at(0)->group()); EXPECT_EQ(1, tab_strip_->GetModelCount()); }
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc index 950c967..1e57de5 100644 --- a/chrome/browser/ui/views/tabs/tab_style_views.cc +++ b/chrome/browser/ui/views/tabs/tab_style_views.cc
@@ -9,6 +9,7 @@ #include "base/numerics/ranges.h" #include "base/numerics/safe_conversions.h" +#include "base/strings/stringprintf.h" #include "cc/paint/paint_record.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/layout_constants.h" @@ -945,6 +946,31 @@ } // namespace +// static +base::string16 views::metadata::TypeConverter<TabStyle::TabColors>::ToString( + views::metadata::ArgType<TabStyle::TabColors> source_value) { + return base::ASCIIToUTF16(base::StringPrintf( + "{%s,%s}", + color_utils::SkColorToRgbaString(source_value.foreground_color).c_str(), + color_utils::SkColorToRgbaString(source_value.background_color).c_str())); +} + +// static +base::Optional<TabStyle::TabColors> views::metadata::TypeConverter< + TabStyle::TabColors>::FromString(const base::string16& source_value) { + base::string16 pruned_string; + base::RemoveChars(source_value, base::ASCIIToUTF16("()rgba"), &pruned_string); + const auto values = + base::SplitStringPiece(pruned_string, base::ASCIIToUTF16("{,}"), + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + const auto foreground_color = RgbaPiecesToSkColor(values, 0); + const auto background_color = RgbaPiecesToSkColor(values, 4); + return (foreground_color.has_value() && background_color.has_value()) + ? base::make_optional<TabStyle::TabColors>( + foreground_color.value(), background_color.value()) + : base::nullopt; +} + // TabStyle -------------------------------------------------------------------- TabStyleViews::~TabStyleViews() = default;
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.h b/chrome/browser/ui/views/tabs/tab_style_views.h index ea5b9f6c..0a09ef6 100644 --- a/chrome/browser/ui/views/tabs/tab_style_views.h +++ b/chrome/browser/ui/views/tabs/tab_style_views.h
@@ -10,6 +10,17 @@ #include "chrome/browser/ui/tabs/tab_style.h" #include "chrome/browser/ui/views/tabs/glow_hover_controller.h" #include "ui/gfx/geometry/rect_f.h" +#include "ui/views/metadata/type_conversion.h" + +template <> +struct views::metadata::TypeConverter<TabStyle::TabColors> { + static constexpr bool is_serializable = true; + static bool IsSerializable() { return is_serializable; } + static base::string16 ToString( + views::metadata::ArgType<TabStyle::TabColors> source_value); + static base::Optional<TabStyle::TabColors> FromString( + const base::string16& source_value); +}; class Tab;
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc index b3d8d79b..a3f18586 100644 --- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc +++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
@@ -241,8 +241,9 @@ content::WebContents* web_contents = nullptr; if (!browser) { - browser = CreateWebApplicationWindow(profile_for_launch, params->app_id, - params->disposition); + browser = + CreateWebApplicationWindow(profile_for_launch, params->app_id, + params->disposition, params->restore_id); } // Navigate application window to application's |url| if necessary.
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc index ffa4fd98..8084c50e 100644 --- a/chrome/browser/ui/web_applications/web_app_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -1212,7 +1212,7 @@ const AppId app_id = InstallPWA(app_url); Browser* const popup_browser = web_app::CreateWebApplicationWindow( - profile(), app_id, WindowOpenDisposition::NEW_POPUP); + profile(), app_id, WindowOpenDisposition::NEW_POPUP, /*restore_id=*/0); EXPECT_TRUE( popup_browser->CanSupportWindowFeature(Browser::FEATURE_LOCATIONBAR));
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.cc b/chrome/browser/ui/web_applications/web_app_launch_manager.cc index b51cdfe..312b269 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_manager.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
@@ -104,7 +104,8 @@ Browser* CreateWebApplicationWindow(Profile* profile, const std::string& app_id, - WindowOpenDisposition disposition) { + WindowOpenDisposition disposition, + int32_t restore_id) { std::string app_name = GenerateApplicationNameFromAppId(app_id); gfx::Rect initial_bounds; Browser::CreateParams browser_params = @@ -116,6 +117,9 @@ app_name, /*trusted_source=*/true, initial_bounds, profile, /*user_gesture=*/true); browser_params.initial_show_state = DetermineWindowShowState(); +#if BUILDFLAG(IS_CHROMEOS_ASH) + browser_params.restore_id = restore_id; +#endif return Browser::Create(browser_params); } @@ -192,8 +196,8 @@ } } if (!browser) { - browser = CreateWebApplicationWindow(profile_, params.app_id, - params.disposition); + browser = CreateWebApplicationWindow( + profile_, params.app_id, params.disposition, params.restore_id); } }
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.h b/chrome/browser/ui/web_applications/web_app_launch_manager.h index 90d947d..2f2b809 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_manager.h +++ b/chrome/browser/ui/web_applications/web_app_launch_manager.h
@@ -74,7 +74,8 @@ Browser* CreateWebApplicationWindow(Profile* profile, const std::string& app_id, - WindowOpenDisposition disposition); + WindowOpenDisposition disposition, + int32_t restore_id); content::WebContents* NavigateWebApplicationWindow( Browser* browser,
diff --git a/chrome/browser/ui/web_applications/web_app_menu_model.cc b/chrome/browser/ui/web_applications/web_app_menu_model.cc index b6bdc13..979a42cd 100644 --- a/chrome/browser/ui/web_applications/web_app_menu_model.cc +++ b/chrome/browser/ui/web_applications/web_app_menu_model.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/media/router/media_router_feature.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" @@ -23,6 +24,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/public/cpp/ash_features.h" #include "chrome/browser/ui/toolbar/assign_to_desks_menu_model.h" +#include "ui/views/widget/widget.h" #endif constexpr int WebAppMenuModel::kUninstallAppCommandId; @@ -74,7 +76,9 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) if (ash::features::IsBentoEnabled()) { AddSeparator(ui::NORMAL_SEPARATOR); - assign_to_desks_submenu_ = std::make_unique<AssignToDesksMenuModel>(this); + assign_to_desks_submenu_ = std::make_unique<AssignToDesksMenuModel>( + this, views::Widget::GetWidgetForNativeWindow( + browser()->window()->GetNativeWindow())); AddSubMenuWithStringId(IDC_ASSIGN_TO_DESKS_MENU, IDS_ASSIGN_TO_DESKS_MENU, assign_to_desks_submenu_.get()); }
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc index 6e4fda6a..88650430 100644 --- a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
@@ -65,7 +65,11 @@ {"scanQRCodeSuccess", IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_SUCCESS}, {"qrCodeRetry", IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_RETRY}, {"scanQrCodeInvalid", IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_INVALID}, - {"profileListPageMessage", IDS_CELLULAR_SETUP_PROFILE_LIST_PAGE_MESSAGE}}; + {"profileListPageMessage", IDS_CELLULAR_SETUP_PROFILE_LIST_PAGE_MESSAGE}, + {"eidPopupTitle", IDS_CELLULAR_SETUP_EID_POPUP_TITLE}, + {"eidPopupDescription", IDS_CELLULAR_SETUP_EID_POPUP_DESCRIPTION}, + {"closeEidPopupButtonLabel", + IDS_CELLULAR_SETUP_CLOSE_EID_POPUP_BUTTON_LABEL}}; struct NamedBoolean { const char* name;
diff --git a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc index 4a7c13c..7ebcf2a 100644 --- a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
@@ -82,6 +82,10 @@ IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE}, {"networkListItemLabelESimPendingProfileWithProviderName", IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_WITH_PROVIDER_NAME}, + {"networkListItemLabelESimPendingProfileInstalling", + IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_INSTALLING}, + {"networkListItemLabelESimPendingProfileWithProviderNameInstalling", + IDS_NETWORK_LIST_ITEM_LABEL_ESIM_PENDING_PROFILE_WITH_PROVIDER_NAME_INSTALLING}, {"wifiNetworkStatusSecured", IDS_WIFI_NETWORK_STATUS_SECURED}, {"wifiNetworkStatusUnsecured", IDS_WIFI_NETWORK_STATUS_UNSECURED}, {"networkListItemNotAvailable", IDS_NETWORK_LIST_NOT_AVAILABLE}, @@ -90,6 +94,7 @@ {"networkListItemNotConnected", IDS_NETWORK_LIST_NOT_CONNECTED}, {"networkListItemNoNetwork", IDS_NETWORK_LIST_NO_NETWORK}, {"networkListItemDownload", IDS_NETWORK_LIST_ITEM_DOWNLOAD}, + {"networkListItemAddingProfile", IDS_NETWORK_LIST_ITEM_ADDING_PROFILE}, {"vpnNameTemplate", IDS_NETWORK_LIST_THIRD_PARTY_VPN_NAME_TEMPLATE}, {"networkIconLabelEthernet", IDS_NETWORK_ICON_LABEL_ETHERNET}, {"networkIconLabelVpn", IDS_NETWORK_ICON_LABEL_VPN},
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_section.cc b/chrome/browser/ui/webui/settings/chromeos/internet_section.cc index 6fb832d..437b3c29 100644 --- a/chrome/browser/ui/webui/settings/chromeos/internet_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/internet_section.cc
@@ -702,12 +702,8 @@ {"eSimNetworkNotSetup", IDS_SETTINGS_INTERNET_ESIM_NOT_SETUP_WITH_SETUP_LINK}, {"cellularNetworkTetherLabel", IDS_SETTINGS_INTERNET_TETHER_LABEL}, - {"eidPopupTitle", IDS_SETTINGS_INTERNET_EID_POPUP_TITLE}, {"showEidPopupButtonLabel", IDS_SETTINGS_INTERNET_SHOW_EID_POPUP_BUTTON_LABEL}, - {"eidPopupDescription", IDS_SETTINGS_INTERNET_EID_POPUP_DESCRIPTION}, - {"closeEidPopupButtonLabel", - IDS_SETTINGS_INTERNET_CLOSE_EID_POPUP_BUTTON_LABEL}, {"eSimRenameProfileDialogLabel", IDS_SETTINGS_INTERNET_NETWORK_RENAME_DIALOG_RENAME_PROFILE}, {"eSimRenameProfileDialogDone",
diff --git a/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_end.xml b/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_end.xml index 8268a6e..babf2e8 100644 --- a/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_end.xml +++ b/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_end.xml
@@ -12,6 +12,6 @@ android:viewportHeight="10" android:autoMirrored="true"> <path - android:fillColor="@android:color/white" + android:fillColor="@color/default_bg_color" android:pathData="M 10,0 A 10,10 0 0 1 0,10 L 10,10 Z" /> </vector>
diff --git a/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_start.xml b/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_start.xml index fda3be5..62aee05 100644 --- a/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_start.xml +++ b/chrome/browser/video_tutorials/android/java/res/drawable/corner_bottom_start.xml
@@ -12,6 +12,6 @@ android:viewportHeight="10" android:autoMirrored="true"> <path - android:fillColor="@android:color/white" + android:fillColor="@color/default_bg_color" android:pathData="M 0,0 A 10,10 0 0 0 10,10 L 0,10 Z" /> </vector>
diff --git a/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_end.xml b/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_end.xml index e58fc39..6d8bf7b 100644 --- a/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_end.xml +++ b/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_end.xml
@@ -12,6 +12,6 @@ android:viewportHeight="10" android:autoMirrored="true"> <path - android:fillColor="@android:color/white" + android:fillColor="@color/default_bg_color" android:pathData="M 0,0 A 10,10 0 0 1 10,10 L 10,0 Z" /> </vector>
diff --git a/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_start.xml b/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_start.xml index 088f3fd6..61bc86b 100644 --- a/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_start.xml +++ b/chrome/browser/video_tutorials/android/java/res/drawable/corner_top_start.xml
@@ -12,6 +12,6 @@ android:viewportHeight="10" android:autoMirrored="true"> <path - android:fillColor="@android:color/white" + android:fillColor="@color/default_bg_color" android:pathData="M 0,10 A 10,10 0 0 1 10,0 L 0,0 Z" /> </vector>
diff --git a/chrome/browser/video_tutorials/android/java/src/org/chromium/chrome/browser/video_tutorials/test/TestVideoTutorialService.java b/chrome/browser/video_tutorials/android/java/src/org/chromium/chrome/browser/video_tutorials/test/TestVideoTutorialService.java index d23093d..96aa9977 100644 --- a/chrome/browser/video_tutorials/android/java/src/org/chromium/chrome/browser/video_tutorials/test/TestVideoTutorialService.java +++ b/chrome/browser/video_tutorials/android/java/src/org/chromium/chrome/browser/video_tutorials/test/TestVideoTutorialService.java
@@ -78,7 +78,7 @@ private void initializeTutorialList() { mTutorials.add(new Tutorial(FeatureType.CHROME_INTRO, "Introduction to chrome", - "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.mp4", + "https://www.gstatic.com/chrome/video-tutorials/webm/1_Search_english.mp4", "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.png", "https://www.gstatic.com/chrome/video-tutorials/gif/sample_anim.gif", "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.png", @@ -86,7 +86,7 @@ mTutorials.add(new Tutorial(FeatureType.DOWNLOAD, "How to use Google Chrome's download functionality", - "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.mp4", + "https://www.gstatic.com/chrome/video-tutorials/webm/1_Search_english.mp4", "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.png", "https://www.gstatic.com/chrome/video-tutorials/gif/sample_anim.gif", "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.png", @@ -94,7 +94,7 @@ mTutorials.add(new Tutorial(FeatureType.SEARCH, "How to efficiently search with Google Chrome", - "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.mp4", + "https://www.gstatic.com/chrome/video-tutorials/webm/1_Search_english.mp4", "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.png", "https://www.gstatic.com/chrome/video-tutorials/gif/sample_anim.gif", "https://www.gstatic.com/chrome/video-tutorials/images/1_Search_english.png",
diff --git a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHCoordinatorImpl.java b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHCoordinatorImpl.java index 99332d1..e0dfcd3e 100644 --- a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHCoordinatorImpl.java +++ b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHCoordinatorImpl.java
@@ -78,7 +78,7 @@ private void fetchImage( Callback<Drawable> consumer, int widthPx, int heightPx, Tutorial tutorial) { boolean useAnimatedGifUrl = ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( - ChromeFeatureList.VIDEO_TUTORIALS, VARIATION_USE_ANIMATED_GIF_URL, false); + ChromeFeatureList.VIDEO_TUTORIALS, VARIATION_USE_ANIMATED_GIF_URL, true); ImageFetcher.Params params = ImageFetcher.Params.create( useAnimatedGifUrl ? tutorial.animatedGifUrl : tutorial.thumbnailUrl, ImageFetcher.VIDEO_TUTORIALS_IPH_UMA_CLIENT_NAME, widthPx, heightPx);
diff --git a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerMediatorUnitTest.java b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerMediatorUnitTest.java index 5a533065..ceb35cb1 100644 --- a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerMediatorUnitTest.java +++ b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerMediatorUnitTest.java
@@ -227,4 +227,22 @@ Assert.assertTrue(VideoTutorialUtils.shouldShowTryNow(FeatureType.VOICE_SEARCH)); Assert.assertFalse(VideoTutorialUtils.shouldShowTryNow(99)); } + + @Test + public void testVideoPlayerURL() { + String videoUrl = "https://example/video.mp4"; + String posterUrl = "https://example/poster.png"; + String animationUrl = "https://example/anim.gif"; + String thumbnailUrl = "https://example/thumb.png"; + String captionUrl = "https://example/caption.vtt"; + String shareUrl = "https://example/share.mp4"; + Tutorial testTutorial = new Tutorial(FeatureType.CHROME_INTRO, "title", videoUrl, posterUrl, + animationUrl, thumbnailUrl, captionUrl, shareUrl, 25); + + assertThat(VideoPlayerURLBuilder.buildFromTutorial(testTutorial), + equalTo("chrome-untrusted://video-tutorials/" + + "?video_url=https://example/video.mp4" + + "&poster_url=https://example/poster.png" + + "&caption_url=https://example/caption.vtt")); + } }
diff --git a/chrome/browser/vr/animation.cc b/chrome/browser/vr/animation.cc index 0c6fbb7..3e44f2d8 100644 --- a/chrome/browser/vr/animation.cc +++ b/chrome/browser/vr/animation.cc
@@ -167,7 +167,7 @@ base::EraseIf(keyframe_models_, [target_property]( const std::unique_ptr<cc::KeyframeModel>& keyframe_model) { - return keyframe_model->target_property_id() == + return keyframe_model->target_property_type() == target_property; }); } @@ -255,7 +255,7 @@ bool Animation::IsAnimatingProperty(int property) const { for (auto& keyframe_model : keyframe_models_) { - if (keyframe_model->target_property_id() == property) + if (keyframe_model->target_property_type() == property) return true; } return false; @@ -293,17 +293,17 @@ continue; if (keyframe_model->run_state() == cc::KeyframeModel::RUNNING || keyframe_model->run_state() == cc::KeyframeModel::PAUSED) { - animated_properties[keyframe_model->target_property_id()] = true; + animated_properties[keyframe_model->target_property_type()] = true; } } for (auto& keyframe_model : keyframe_models_) { if (!include_infinite_animations && keyframe_model->iterations() == std::numeric_limits<double>::infinity()) continue; - if (!animated_properties[keyframe_model->target_property_id()] && + if (!animated_properties[keyframe_model->target_property_type()] && keyframe_model->run_state() == cc::KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY) { - animated_properties[keyframe_model->target_property_id()] = true; + animated_properties[keyframe_model->target_property_type()] = true; keyframe_model->SetRunState(cc::KeyframeModel::RUNNING, monotonic_time); keyframe_model->set_start_time(monotonic_time); } @@ -361,9 +361,9 @@ curve->AddKeyframe(AnimationTraits<ValueType>::KeyframeType::Create( transition_.duration, target, CreateTransitionTimingFunction())); - AddKeyframeModel( - cc::KeyframeModel::Create(std::move(curve), GetNextKeyframeModelId(), - GetNextGroupId(), target_property)); + AddKeyframeModel(cc::KeyframeModel::Create( + std::move(curve), GetNextKeyframeModelId(), GetNextGroupId(), + cc::KeyframeModel::TargetPropertyId(target_property))); } cc::KeyframeModel* Animation::GetRunningKeyframeModelForProperty( @@ -371,7 +371,7 @@ for (auto& keyframe_model : keyframe_models_) { if ((keyframe_model->run_state() == cc::KeyframeModel::RUNNING || keyframe_model->run_state() == cc::KeyframeModel::PAUSED) && - keyframe_model->target_property_id() == target_property) { + keyframe_model->target_property_type() == target_property) { return keyframe_model.get(); } } @@ -381,7 +381,7 @@ cc::KeyframeModel* Animation::GetKeyframeModelForProperty( int target_property) const { for (auto& keyframe_model : keyframe_models_) { - if (keyframe_model->target_property_id() == target_property) { + if (keyframe_model->target_property_type() == target_property) { return keyframe_model.get(); } }
diff --git a/chrome/browser/vr/animation_unittest.cc b/chrome/browser/vr/animation_unittest.cc index 9794ee2..b792532 100644 --- a/chrome/browser/vr/animation_unittest.cc +++ b/chrome/browser/vr/animation_unittest.cc
@@ -87,7 +87,7 @@ gfx::SizeF(20, 200), MicrosecondsToDelta(10000))); EXPECT_EQ(1ul, animation.keyframe_models().size()); - EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_id()); + EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_type()); cc::TransformOperations from_operations; from_operations.AppendTranslate(10, 100, 1000); @@ -97,16 +97,16 @@ 2, 2, from_operations, to_operations, MicrosecondsToDelta(10000))); EXPECT_EQ(2ul, animation.keyframe_models().size()); - EXPECT_EQ(TRANSFORM, animation.keyframe_models()[1]->target_property_id()); + EXPECT_EQ(TRANSFORM, animation.keyframe_models()[1]->target_property_type()); animation.AddKeyframeModel(CreateTransformAnimation( 3, 3, from_operations, to_operations, MicrosecondsToDelta(10000))); EXPECT_EQ(3ul, animation.keyframe_models().size()); - EXPECT_EQ(TRANSFORM, animation.keyframe_models()[2]->target_property_id()); + EXPECT_EQ(TRANSFORM, animation.keyframe_models()[2]->target_property_type()); animation.RemoveKeyframeModels(TRANSFORM); EXPECT_EQ(1ul, animation.keyframe_models().size()); - EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_id()); + EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_type()); animation.RemoveKeyframeModel(animation.keyframe_models()[0]->id()); EXPECT_TRUE(animation.keyframe_models().empty()); @@ -121,7 +121,7 @@ gfx::SizeF(20, 200), MicrosecondsToDelta(10000))); EXPECT_EQ(1ul, animation.keyframe_models().size()); - EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_id()); + EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_type()); EXPECT_EQ(cc::KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY, animation.keyframe_models()[0]->run_state()); @@ -150,7 +150,7 @@ gfx::SizeF(20, 200), MicrosecondsToDelta(10000))); EXPECT_EQ(1ul, animation.keyframe_models().size()); - EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_id()); + EXPECT_EQ(BOUNDS, animation.keyframe_models()[0]->target_property_type()); EXPECT_EQ(cc::KeyframeModel::WAITING_FOR_TARGET_AVAILABILITY, animation.keyframe_models()[0]->run_state()); @@ -172,8 +172,8 @@ 3, 2, from_operations, to_operations, MicrosecondsToDelta(10000))); EXPECT_EQ(3ul, animation.keyframe_models().size()); - EXPECT_EQ(BOUNDS, animation.keyframe_models()[1]->target_property_id()); - EXPECT_EQ(TRANSFORM, animation.keyframe_models()[2]->target_property_id()); + EXPECT_EQ(BOUNDS, animation.keyframe_models()[1]->target_property_type()); + EXPECT_EQ(TRANSFORM, animation.keyframe_models()[2]->target_property_type()); int id1 = animation.keyframe_models()[1]->id(); animation.Tick(start_time + MicrosecondsToDelta(1));
diff --git a/chrome/browser/vr/elements/spinner.cc b/chrome/browser/vr/elements/spinner.cc index 784fad2c..f6fc9f0 100644 --- a/chrome/browser/vr/elements/spinner.cc +++ b/chrome/browser/vr/elements/spinner.cc
@@ -76,7 +76,8 @@ std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( std::move(curve), Animation::GetNextKeyframeModelId(), - Animation::GetNextGroupId(), SPINNER_ROTATION)); + Animation::GetNextGroupId(), + cc::KeyframeModel::TargetPropertyId(SPINNER_ROTATION))); keyframe_model->set_iterations(std::numeric_limits<double>::infinity()); AddKeyframeModel(std::move(keyframe_model)); @@ -91,7 +92,8 @@ keyframe_model = cc::KeyframeModel::Create( std::move(curve), Animation::GetNextKeyframeModelId(), - Animation::GetNextGroupId(), SPINNER_ANGLE_SWEEP); + Animation::GetNextGroupId(), + cc::KeyframeModel::TargetPropertyId(SPINNER_ANGLE_SWEEP)); keyframe_model->set_iterations(std::numeric_limits<double>::infinity()); AddKeyframeModel(std::move(keyframe_model)); @@ -105,7 +107,8 @@ keyframe_model = cc::KeyframeModel::Create( std::move(curve), Animation::GetNextKeyframeModelId(), - Animation::GetNextGroupId(), SPINNER_ANGLE_START); + Animation::GetNextGroupId(), + cc::KeyframeModel::TargetPropertyId(SPINNER_ANGLE_START)); keyframe_model->set_iterations(std::numeric_limits<double>::infinity()); AddKeyframeModel(std::move(keyframe_model));
diff --git a/chrome/browser/vr/elements/throbber.cc b/chrome/browser/vr/elements/throbber.cc index 5414aa77..def9258 100644 --- a/chrome/browser/vr/elements/throbber.cc +++ b/chrome/browser/vr/elements/throbber.cc
@@ -65,7 +65,8 @@ std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( std::move(curve), Animation::GetNextKeyframeModelId(), - Animation::GetNextGroupId(), CIRCLE_GROW)); + Animation::GetNextGroupId(), + cc::KeyframeModel::TargetPropertyId(CIRCLE_GROW))); keyframe_model->set_iterations(std::numeric_limits<double>::infinity()); AddKeyframeModel(std::move(keyframe_model)); }
diff --git a/chrome/browser/vr/test/animation_utils.cc b/chrome/browser/vr/test/animation_utils.cc index e45b631d..d3f4b78 100644 --- a/chrome/browser/vr/test/animation_utils.cc +++ b/chrome/browser/vr/test/animation_utils.cc
@@ -21,7 +21,8 @@ cc::TransformKeyframe::Create(base::TimeDelta(), from, nullptr)); curve->AddKeyframe(cc::TransformKeyframe::Create(duration, to, nullptr)); std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( - std::move(curve), id, group, TargetProperty::TRANSFORM)); + std::move(curve), id, group, + cc::KeyframeModel::TargetPropertyId(TargetProperty::TRANSFORM))); return keyframe_model; } @@ -37,7 +38,8 @@ cc::SizeKeyframe::Create(base::TimeDelta(), from, nullptr)); curve->AddKeyframe(cc::SizeKeyframe::Create(duration, to, nullptr)); std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( - std::move(curve), id, group, TargetProperty::BOUNDS)); + std::move(curve), id, group, + cc::KeyframeModel::TargetPropertyId(TargetProperty::BOUNDS))); return keyframe_model; } @@ -53,7 +55,8 @@ cc::FloatKeyframe::Create(base::TimeDelta(), from, nullptr)); curve->AddKeyframe(cc::FloatKeyframe::Create(duration, to, nullptr)); std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( - std::move(curve), id, group, TargetProperty::OPACITY)); + std::move(curve), id, group, + cc::KeyframeModel::TargetPropertyId(TargetProperty::OPACITY))); return keyframe_model; } @@ -69,7 +72,8 @@ cc::ColorKeyframe::Create(base::TimeDelta(), from, nullptr)); curve->AddKeyframe(cc::ColorKeyframe::Create(duration, to, nullptr)); std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( - std::move(curve), id, group, TargetProperty::BACKGROUND_COLOR)); + std::move(curve), id, group, + cc::KeyframeModel::TargetPropertyId(TargetProperty::BACKGROUND_COLOR))); return keyframe_model; }
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc index 71f8023..48bd2b5 100644 --- a/chrome/browser/vr/ui_scene_creator.cc +++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -1005,7 +1005,8 @@ e->AddKeyframeModel(cc::KeyframeModel::Create( std::move(curve), Animation::GetNextKeyframeModelId(), - Animation::GetNextGroupId(), TRANSFORM)); + Animation::GetNextGroupId(), + cc::KeyframeModel::TargetPropertyId(TRANSFORM))); } #else @@ -1090,7 +1091,8 @@ e->AddKeyframeModel(cc::KeyframeModel::Create( std::move(curve), Animation::GetNextKeyframeModelId(), - Animation::GetNextGroupId(), TRANSFORM)); + Animation::GetNextGroupId(), + cc::KeyframeModel::TargetPropertyId(TRANSFORM))); } #endif
diff --git a/chrome/browser/web_applications/web_app_mover_browsertest.cc b/chrome/browser/web_applications/web_app_mover_browsertest.cc index 9a317d8..2548acf 100644 --- a/chrome/browser/web_applications/web_app_mover_browsertest.cc +++ b/chrome/browser/web_applications/web_app_mover_browsertest.cc
@@ -30,7 +30,7 @@ https_server_.AddDefaultHandlers(GetChromeTestDataDir()); // Since the port is a part of the start_url, this needs to stay consistent // between the tests below. - CHECK(https_server_.Start(44221)); + CHECK(https_server_.Start(16247)); scoped_feature_list_.InitWithFeaturesAndParameters( {{features::kMoveWebApp, {{features::kMoveWebAppUninstallStartUrlPrefix.name,
diff --git a/chrome/browser/webshare/BUILD.gn b/chrome/browser/webshare/BUILD.gn index c97e71b..72725dd9 100644 --- a/chrome/browser/webshare/BUILD.gn +++ b/chrome/browser/webshare/BUILD.gn
@@ -4,10 +4,36 @@ import("//build/config/chromeos/ui_mode.gni") +static_library("storage") { + if (is_chromeos || is_mac) { + sources = [ + "prepare_directory_task.cc", + "prepare_directory_task.h", + "store_file_task.cc", + "store_file_task.h", + "store_files_task.cc", + "store_files_task.h", + ] + deps = [ + "//content/public/browser", + "//mojo/public/cpp/bindings", + ] + public_deps = [ + "//base", + "//third_party/blink/public/common", + ] + } +} + source_set("unit_tests") { testonly = true sources = [ "share_service_unittest.cc" ] + + if (is_chromeos || is_mac) { + sources += [ "prepare_directory_task_unittest.cc" ] + } + deps = [ "//base/test:test_support", "//build:chromeos_buildflags", @@ -23,4 +49,8 @@ if (is_chromeos_ash) { deps += [ "//chrome/browser/webshare/chromeos:unit_tests" ] } + + if (is_chromeos || is_mac) { + deps += [ "//chrome/browser/webshare:storage" ] + } }
diff --git a/chrome/browser/webshare/OWNERS b/chrome/browser/webshare/OWNERS index f19bd69..083fd1f 100644 --- a/chrome/browser/webshare/OWNERS +++ b/chrome/browser/webshare/OWNERS
@@ -1,2 +1,4 @@ +cmp@chromium.org +dmurph@chromium.org ericwilligers@chromium.org mgiuca@chromium.org
diff --git a/chrome/browser/webshare/chromeos/BUILD.gn b/chrome/browser/webshare/chromeos/BUILD.gn index 94921943..d16fd28 100644 --- a/chrome/browser/webshare/chromeos/BUILD.gn +++ b/chrome/browser/webshare/chromeos/BUILD.gn
@@ -2,39 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -static_library("storage") { - sources = [ - "prepare_directory_task.cc", - "prepare_directory_task.h", - "store_file_task.cc", - "store_file_task.h", - "store_files_task.cc", - "store_files_task.h", - ] - deps = [ - "//content/public/browser", - "//mojo/public/cpp/bindings", - ] - public_deps = [ - "//base", - "//third_party/blink/public/common", - ] -} - source_set("unit_tests") { testonly = true - sources = [ - "prepare_directory_task_unittest.cc", - "sharesheet_client_unittest.cc", - ] + sources = [ "sharesheet_client_unittest.cc" ] deps = [ - ":storage", "//base/test:test_support", "//build:chromeos_buildflags", "//chrome/browser", "//chrome/browser/chromeos:chromeos", + "//chrome/browser/webshare:storage", "//chrome/common", "//chrome/test:test_support", "//content/public/browser",
diff --git a/chrome/browser/webshare/chromeos/sharesheet_client.cc b/chrome/browser/webshare/chromeos/sharesheet_client.cc index 03e314c..c7b40ed 100644 --- a/chrome/browser/webshare/chromeos/sharesheet_client.cc +++ b/chrome/browser/webshare/chromeos/sharesheet_client.cc
@@ -20,9 +20,9 @@ #include "chrome/browser/sharesheet/sharesheet_service.h" #include "chrome/browser/sharesheet/sharesheet_service_factory.h" #include "chrome/browser/visibility_timer_tab_helper.h" -#include "chrome/browser/webshare/chromeos/prepare_directory_task.h" -#include "chrome/browser/webshare/chromeos/store_files_task.h" +#include "chrome/browser/webshare/prepare_directory_task.h" #include "chrome/browser/webshare/share_service_impl.h" +#include "chrome/browser/webshare/store_files_task.h" #include "chrome/common/chrome_features.h" #include "components/services/app_service/public/cpp/intent_util.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/webshare/chromeos/sharesheet_client_unittest.cc b/chrome/browser/webshare/chromeos/sharesheet_client_unittest.cc index 3c1bf01..4414fee 100644 --- a/chrome/browser/webshare/chromeos/sharesheet_client_unittest.cc +++ b/chrome/browser/webshare/chromeos/sharesheet_client_unittest.cc
@@ -17,8 +17,8 @@ #include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sharesheet/sharesheet_types.h" -#include "chrome/browser/webshare/chromeos/prepare_directory_task.h" -#include "chrome/browser/webshare/chromeos/store_file_task.h" +#include "chrome/browser/webshare/prepare_directory_task.h" +#include "chrome/browser/webshare/store_file_task.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "content/public/browser/site_instance.h" #include "content/public/test/web_contents_tester.h"
diff --git a/chrome/browser/webshare/chromeos/prepare_directory_task.cc b/chrome/browser/webshare/prepare_directory_task.cc similarity index 95% rename from chrome/browser/webshare/chromeos/prepare_directory_task.cc rename to chrome/browser/webshare/prepare_directory_task.cc index ca5276e..7f148d7e 100644 --- a/chrome/browser/webshare/chromeos/prepare_directory_task.cc +++ b/chrome/browser/webshare/prepare_directory_task.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/webshare/chromeos/prepare_directory_task.h" +#include "chrome/browser/webshare/prepare_directory_task.h" #include "base/files/file.h" #include "base/files/file_enumerator.h" @@ -10,8 +10,12 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" +#include "build/build_config.h" #include "content/public/browser/browser_thread.h" + +#if defined(OS_CHROMEOS) #include "third_party/cros_system_api/constants/cryptohome.h" +#endif using content::BrowserThread; @@ -80,12 +84,14 @@ } } +#if defined(OS_CHROMEOS) if (base::SysInfo::AmountOfFreeDiskSpace(directory) < static_cast<int64_t>(cryptohome::kMinFreeSpaceInBytes + required_space)) { result = base::File::FILE_ERROR_NO_SPACE; VLOG(1) << "Insufficient space for sharing files"; } +#endif } else { DCHECK(result != base::File::FILE_OK); VLOG(1) << "Could not create directory for shared files";
diff --git a/chrome/browser/webshare/chromeos/prepare_directory_task.h b/chrome/browser/webshare/prepare_directory_task.h similarity index 89% rename from chrome/browser/webshare/chromeos/prepare_directory_task.h rename to chrome/browser/webshare/prepare_directory_task.h index 95c280a..c2c880f 100644 --- a/chrome/browser/webshare/chromeos/prepare_directory_task.h +++ b/chrome/browser/webshare/prepare_directory_task.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_WEBSHARE_CHROMEOS_PREPARE_DIRECTORY_TASK_H_ -#define CHROME_BROWSER_WEBSHARE_CHROMEOS_PREPARE_DIRECTORY_TASK_H_ +#ifndef CHROME_BROWSER_WEBSHARE_PREPARE_DIRECTORY_TASK_H_ +#define CHROME_BROWSER_WEBSHARE_PREPARE_DIRECTORY_TASK_H_ #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -51,4 +51,4 @@ } // namespace webshare -#endif // CHROME_BROWSER_WEBSHARE_CHROMEOS_PREPARE_DIRECTORY_TASK_H_ +#endif // CHROME_BROWSER_WEBSHARE_PREPARE_DIRECTORY_TASK_H_
diff --git a/chrome/browser/webshare/chromeos/prepare_directory_task_unittest.cc b/chrome/browser/webshare/prepare_directory_task_unittest.cc similarity index 96% rename from chrome/browser/webshare/chromeos/prepare_directory_task_unittest.cc rename to chrome/browser/webshare/prepare_directory_task_unittest.cc index 0000684..3397f00 100644 --- a/chrome/browser/webshare/chromeos/prepare_directory_task_unittest.cc +++ b/chrome/browser/webshare/prepare_directory_task_unittest.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/webshare/chromeos/prepare_directory_task.h" +#include "chrome/browser/webshare/prepare_directory_task.h" #include <string>
diff --git a/chrome/browser/webshare/chromeos/store_file_task.cc b/chrome/browser/webshare/store_file_task.cc similarity index 98% rename from chrome/browser/webshare/chromeos/store_file_task.cc rename to chrome/browser/webshare/store_file_task.cc index a2aaa66..a8f6865 100644 --- a/chrome/browser/webshare/chromeos/store_file_task.cc +++ b/chrome/browser/webshare/store_file_task.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/webshare/chromeos/store_file_task.h" +#include "chrome/browser/webshare/store_file_task.h" #include "base/strings/string_util.h" #include "base/threading/scoped_blocking_call.h"
diff --git a/chrome/browser/webshare/chromeos/store_file_task.h b/chrome/browser/webshare/store_file_task.h similarity index 91% rename from chrome/browser/webshare/chromeos/store_file_task.h rename to chrome/browser/webshare/store_file_task.h index 31a6e2f..39b0fb2 100644 --- a/chrome/browser/webshare/chromeos/store_file_task.h +++ b/chrome/browser/webshare/store_file_task.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_WEBSHARE_CHROMEOS_STORE_FILE_TASK_H_ -#define CHROME_BROWSER_WEBSHARE_CHROMEOS_STORE_FILE_TASK_H_ +#ifndef CHROME_BROWSER_WEBSHARE_STORE_FILE_TASK_H_ +#define CHROME_BROWSER_WEBSHARE_STORE_FILE_TASK_H_ #include "base/files/file.h" #include "base/files/file_path.h" @@ -63,4 +63,4 @@ } // namespace webshare -#endif // CHROME_BROWSER_WEBSHARE_CHROMEOS_STORE_FILE_TASK_H_ +#endif // CHROME_BROWSER_WEBSHARE_STORE_FILE_TASK_H_
diff --git a/chrome/browser/webshare/chromeos/store_files_task.cc b/chrome/browser/webshare/store_files_task.cc similarity index 96% rename from chrome/browser/webshare/chromeos/store_files_task.cc rename to chrome/browser/webshare/store_files_task.cc index f053a9d4..4ad6dad 100644 --- a/chrome/browser/webshare/chromeos/store_files_task.cc +++ b/chrome/browser/webshare/store_files_task.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/webshare/chromeos/store_files_task.h" +#include "chrome/browser/webshare/store_files_task.h" #include "base/bind.h" #include "base/task/thread_pool.h"
diff --git a/chrome/browser/webshare/chromeos/store_files_task.h b/chrome/browser/webshare/store_files_task.h similarity index 84% rename from chrome/browser/webshare/chromeos/store_files_task.h rename to chrome/browser/webshare/store_files_task.h index 819043de..19ab698b 100644 --- a/chrome/browser/webshare/chromeos/store_files_task.h +++ b/chrome/browser/webshare/store_files_task.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_WEBSHARE_CHROMEOS_STORE_FILES_TASK_H_ -#define CHROME_BROWSER_WEBSHARE_CHROMEOS_STORE_FILES_TASK_H_ +#ifndef CHROME_BROWSER_WEBSHARE_STORE_FILES_TASK_H_ +#define CHROME_BROWSER_WEBSHARE_STORE_FILES_TASK_H_ #include <memory> #include <vector> #include "base/files/file_path.h" #include "base/sequenced_task_runner.h" -#include "chrome/browser/webshare/chromeos/store_file_task.h" +#include "chrome/browser/webshare/store_file_task.h" #include "third_party/blink/public/mojom/webshare/webshare.mojom.h" namespace webshare { @@ -45,4 +45,4 @@ } // namespace webshare -#endif // CHROME_BROWSER_WEBSHARE_CHROMEOS_STORE_FILES_TASK_H_ +#endif // CHROME_BROWSER_WEBSHARE_STORE_FILES_TASK_H_
diff --git a/chrome/browser/xsurface/BUILD.gn b/chrome/browser/xsurface/BUILD.gn index 63826464..ddc8791e 100644 --- a/chrome/browser/xsurface/BUILD.gn +++ b/chrome/browser/xsurface/BUILD.gn
@@ -12,7 +12,6 @@ "android/java/src/org/chromium/chrome/browser/xsurface/ImagePrefetcher.java", "android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java", "android/java/src/org/chromium/chrome/browser/xsurface/ListContentManagerObserver.java", - "android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java", "android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java", "android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java", "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java",
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java deleted file mode 100644 index 154d8b6..0000000 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java +++ /dev/null
@@ -1,47 +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. - -package org.chromium.chrome.browser.xsurface; - -import androidx.annotation.Nullable; - -/** A simple key-value cache that is persisting all data on disk. Automatically evicts old data. */ -public interface PersistentKeyValueCache { - /** Consumes the result of PersistentKeyValueCache.lookup(). */ - public interface ValueConsumer { - /** - * Called when a lookup is complete. - * - * @param value The value found. null if no value was present. - */ - void run(@Nullable byte[] value); - } - - /** - * Retrieves and returns the value associated with the given key if it exists. - * This does not affect the key/value's age for automatic eviction. - * - * @param key The key to look up. - * @param consumer The consumer called when the lookup is complete. - */ - default void lookup(byte[] key, ValueConsumer consumer) {} - - /** - * Inserts the given entry into the cache, overwriting any entry that might already exist - * against the given key. - * - * @param key The key to insert. - * @param value The value to insert. - * @param onComplete Called after the key/value was inserted. - */ - default void put(byte[] key, byte[] value, @Nullable Runnable onComplete) {} - - /** - * Evicts an entry from the cache by the specified key. - * - * @param key The key whose entry must be evicted. - * @param onComplete Called after the operation completes. - */ - default void evict(byte[] key, @Nullable Runnable onComplete) {} -}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java index 75fc160..68e13eb 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScopeDependencyProvider.java
@@ -58,11 +58,6 @@ return null; } - @Nullable - default PersistentKeyValueCache getPersistentKeyValueCache() { - return null; - } - // Posts task to the UI thread. int TASK_TYPE_UI_THREAD = 1; // Posts to a background thread. The task may block.
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 18f5097..3f5ab7e 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1610042255-43b4d84a21124c058546cf1e621ecfbb55dbe4e7.profdata +chrome-linux-master-1610063718-75764fb6f7cc7a2d4d8119e0952784a5ac3fa72a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index c95bdbd..498932ef 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1610009713-66490881217dda72de1fa905fa3f863deeda7cfb.profdata +chrome-win32-master-1610052964-246b43420c64aac53ecf14d1b97c19dc58b69e86.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index b37d1b5d..10b0b39b 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1610042255-9fb87833d682e7ab89f65b59b49fe1c3c9960d61.profdata +chrome-win64-master-1610052964-a33bb7f09ef1aa4be028cda8573fe902d004ec4a.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 298bf428..5660057 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -923,7 +923,7 @@ #endif // defined(OS_WIN) const base::Feature kWindowNaming{"WindowNaming", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; // Enables writing basic system profile to the persistent histograms files // earlier.
diff --git a/chrome/services/printing/print_backend_service_impl.cc b/chrome/services/printing/print_backend_service_impl.cc index e19ad94..3b3ba3f 100644 --- a/chrome/services/printing/print_backend_service_impl.cc +++ b/chrome/services/printing/print_backend_service_impl.cc
@@ -10,10 +10,16 @@ #include "base/logging.h" #include "base/notreached.h" #include "base/optional.h" +#include "build/build_config.h" #include "chrome/services/printing/public/mojom/print_backend_service.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "printing/backend/print_backend.h" +#if defined(OS_MAC) +#include "base/threading/thread_restrictions.h" +#include "chrome/common/printing/printer_capabilities_mac.h" +#endif + namespace printing { PrintBackendServiceImpl::PrintBackendServiceImpl( @@ -58,4 +64,52 @@ std::move(callback).Run(std::move(printer_caps)); } +void PrintBackendServiceImpl::FetchCapabilities( + const std::string& printer_name, + mojom::PrintBackendService::FetchCapabilitiesCallback callback) { + if (!print_backend_) { + std::move(callback).Run(base::nullopt, base::nullopt, base::nullopt); + return; + } + + PrinterSemanticCapsAndDefaults::Papers user_defined_papers; +#if defined(OS_MAC) + { + // Blocking is needed here for when macOS reads paper sizes from file. + // + // Fetching capabilities in the browser process happens from the thread + // pool with the MayBlock() trait for macOS. However this call can also + // run from a utility process's main thread where blocking is not + // implicitly allowed. In order to preserve ordering, the utility process + // must process this synchronously by blocking. + // + // TODO(crbug.com/1163635): Investigate whether utility process main + // thread should be allowed to block like in-process workers are. + base::ScopedAllowBlocking allow_blocking; + user_defined_papers = GetMacCustomPaperSizes(); + } +#endif + + PrinterBasicInfo printer_info; + bool result = + print_backend_->GetPrinterBasicInfo(printer_name, &printer_info); + if (!result) { + DLOG(ERROR) << "GetPrinterBasicInfo failed, last error is " + << logging::GetLastSystemErrorCode(); + std::move(callback).Run(base::nullopt, base::nullopt, base::nullopt); + return; + } + PrinterSemanticCapsAndDefaults caps; + result = + print_backend_->GetPrinterSemanticCapsAndDefaults(printer_name, &caps); + if (!result) { + DLOG(ERROR) << "GetPrinterSemanticCapsAndDefaults failed, last error is " + << logging::GetLastSystemErrorCode(); + std::move(callback).Run(base::nullopt, base::nullopt, base::nullopt); + return; + } + std::move(callback).Run(std::move(printer_info), + std::move(user_defined_papers), std::move(caps)); +} + } // namespace printing
diff --git a/chrome/services/printing/print_backend_service_impl.h b/chrome/services/printing/print_backend_service_impl.h index 21fba2f9..820e4c9 100644 --- a/chrome/services/printing/print_backend_service_impl.h +++ b/chrome/services/printing/print_backend_service_impl.h
@@ -32,6 +32,10 @@ base::OnceCallback<void(const base::Optional<std::string>& printer_name)>; using GetPrinterSemanticCapsAndDefaultsCallback = base::OnceCallback<void( base::Optional<PrinterSemanticCapsAndDefaults> printer_caps)>; + using FetchCapabilitiesCallback = base::OnceCallback<void( + base::Optional<PrinterBasicInfo>, + base::Optional<PrinterSemanticCapsAndDefaults::Papers>, + base::Optional<PrinterSemanticCapsAndDefaults>)>; // mojom::PrintBackendService implementation: void Init(const std::string& locale) override; @@ -42,6 +46,9 @@ const std::string& printer_name, mojom::PrintBackendService::GetPrinterSemanticCapsAndDefaultsCallback callback) override; + void FetchCapabilities( + const std::string& printer_name, + mojom::PrintBackendService::FetchCapabilitiesCallback callback) override; scoped_refptr<PrintBackend> print_backend_;
diff --git a/chrome/services/printing/public/mojom/print_backend_service.mojom b/chrome/services/printing/public/mojom/print_backend_service.mojom index 85f41aa..36588eaf 100644 --- a/chrome/services/printing/public/mojom/print_backend_service.mojom +++ b/chrome/services/printing/public/mojom/print_backend_service.mojom
@@ -23,4 +23,13 @@ // No value provided for `printer_caps` if there is a failure. GetPrinterSemanticCapsAndDefaults(string printer_name) => (PrinterSemanticCapsAndDefaults? printer_caps); + + // Gets the basic info, paper sizes, and semantic capabilities and defaults + // for a specific printer. + // No value for `printer_info`, `user_defined_papers`, and `printer_caps` if + // there is a failure. + FetchCapabilities(string printer_name) + => (PrinterBasicInfo? printer_info, + array<Paper>? user_defined_papers, + PrinterSemanticCapsAndDefaults? printer_caps); };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 06da1dbc..4d91fff3 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3238,6 +3238,7 @@ "../browser/lacros/browser_test_util.cc", "../browser/lacros/browser_test_util.h", "../browser/lacros/clipboard_lacros_browsertest.cc", + "../browser/lacros/crosapi_pref_observer_lacros_browsertest.cc", "../browser/lacros/file_manager_lacros_browsertest.cc", "../browser/lacros/keystore_service_lacros_browsertest.cc", "../browser/lacros/media_session_lacros_browsertest.cc", @@ -3575,11 +3576,9 @@ "../browser/optimization_guide/optimization_guide_hints_manager_unittest.cc", "../browser/optimization_guide/optimization_guide_navigation_data_unittest.cc", "../browser/optimization_guide/optimization_guide_permissions_util_unittest.cc", - "../browser/optimization_guide/optimization_guide_session_statistic_unittest.cc", "../browser/optimization_guide/optimization_guide_top_host_provider_unittest.cc", "../browser/optimization_guide/prediction/prediction_manager_unittest.cc", "../browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc", - "../browser/optimization_guide/prediction/prediction_model_fetcher_unittest.cc", "../browser/page_load_metrics/metrics_web_contents_observer_unittest.cc", "../browser/page_load_metrics/observers/aborts_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc", @@ -4572,6 +4571,7 @@ "../browser/send_tab_to_self/send_tab_to_self_client_service_unittest.cc", "../browser/send_tab_to_self/send_tab_to_self_desktop_util_unittest.cc", "../browser/send_tab_to_self/send_tab_to_self_util_unittest.cc", + "../browser/serial/serial_blocklist_unittest.cc", "../browser/serial/serial_chooser_context_unittest.cc", "../browser/sessions/tab_restore_service_unittest.cc", "../browser/signin/signin_promo_unittest.cc",
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js index fc1af81..e8b367d 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js +++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js
@@ -36,6 +36,11 @@ Polymer.dom.flush(); }); + function assertSelectedPage(pageName, page) { + assertTrue(eSimPage.selectedESimPageName_ === pageName); + assertTrue(eSimPage.selectedESimPageName_ === page.id); + } + test('No eSIM profile flow invalid activation code', async function() { eSimManagerRemote.addEuiccForTest(0); const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs(); @@ -52,18 +57,14 @@ assertTrue(!!finalPage); // Loading page should be showing. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_LOADING && - eSimPage.selectedESimPageName_ === profileLoadingPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); await flushAsync(); // Should now be at the activation code page. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.ACTIVATION_CODE && - eSimPage.selectedESimPageName_ === activationCodePage.id); + assertSelectedPage( + cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage); // Insert an activation code. activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE'; @@ -77,10 +78,8 @@ await flushAsync(); // Install should fail and still be at activation code page. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.ACTIVATION_CODE && - eSimPage.selectedESimPageName_ === activationCodePage.id); + assertSelectedPage( + cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage); assertTrue(activationCodePage.$$('#scanSuccessContainer').hidden); assertFalse(activationCodePage.$$('#scanFailureContainer').hidden); }); @@ -97,18 +96,14 @@ assertTrue(!!finalPage); // Loading page should be showing. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_LOADING && - eSimPage.selectedESimPageName_ === profileLoadingPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); await flushAsync(); // Should now be at the activation code page. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.ACTIVATION_CODE && - eSimPage.selectedESimPageName_ === activationCodePage.id); + assertSelectedPage( + cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage); // Insert an activation code. activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE'; @@ -122,9 +117,7 @@ await flushAsync(); // Should go to final page. - assertTrue( - eSimPage.selectedESimPageName_ === cellular_setup.ESimPageName.FINAL && - eSimPage.selectedESimPageName_ === finalPage.id); + assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage); }); test('Single eSIM profile flow successful install', async function() { @@ -137,17 +130,13 @@ assertTrue(!!finalPage); // Loading page should be showing. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_LOADING && - eSimPage.selectedESimPageName_ === profileLoadingPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); await flushAsync(); // Should go directly to final page. - assertTrue( - eSimPage.selectedESimPageName_ === cellular_setup.ESimPageName.FINAL && - eSimPage.selectedESimPageName_ === finalPage.id); + assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage); assertFalse(!!finalPage.$$('.error')); }); @@ -165,20 +154,41 @@ assertTrue(!!finalPage); // Loading page should be showing. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_LOADING && - eSimPage.selectedESimPageName_ === profileLoadingPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); await flushAsync(); // Should go directly to final page. - assertTrue( - eSimPage.selectedESimPageName_ === cellular_setup.ESimPageName.FINAL && - eSimPage.selectedESimPageName_ === finalPage.id); + assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage); assertTrue(!!finalPage.$$('.error')); }); + test('Single eSIM profile flow confirmation code required', async function() { + eSimManagerRemote.addEuiccForTest(1); + const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs(); + const profileList = await availableEuiccs.euiccs[0].getProfileList(); + profileList.profiles[0].setProfileInstallResultForTest( + chromeos.cellularSetup.mojom.ProfileInstallResult + .kErrorNeedsConfirmationCode); + + const profileLoadingPage = eSimPage.$$('#profileLoadingPage'); + const confirmationCodePage = eSimPage.$$('#confirmationCodePage'); + + assertTrue(!!profileLoadingPage); + assertTrue(!!confirmationCodePage); + + // Loading page should be showing. + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); + + await flushAsync(); + + // Confirmation code page should be showing. + assertSelectedPage( + cellular_setup.ESimPageName.CONFIRMATION_CODE, confirmationCodePage); + }); + test('Multiple eSIM profiles skip discovery flow', async function() { eSimManagerRemote.addEuiccForTest(2); @@ -193,18 +203,14 @@ assertTrue(!!finalPage); // Loading page should be showing. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_LOADING && - eSimPage.selectedESimPageName_ === profileLoadingPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); await flushAsync(); // Should go to profile discovery page. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_DISCOVERY && - eSimPage.selectedESimPageName_ === profileDiscoveryPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_DISCOVERY, profileDiscoveryPage); // Simulate pressing 'Skip'. assertTrue( @@ -214,10 +220,8 @@ Polymer.dom.flush(); // Should now be at the activation code page. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.ACTIVATION_CODE && - eSimPage.selectedESimPageName_ === activationCodePage.id); + assertSelectedPage( + cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage); // Insert an activation code. activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE'; @@ -230,9 +234,7 @@ await flushAsync(); // Should now be at the final page. - assertTrue( - eSimPage.selectedESimPageName_ === cellular_setup.ESimPageName.FINAL && - eSimPage.selectedESimPageName_ === finalPage.id); + assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage); }); test('Multiple eSIM profiles select flow', async function() { @@ -249,18 +251,14 @@ assertTrue(!!finalPage); // Loading page should be showing. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_LOADING && - eSimPage.selectedESimPageName_ === profileLoadingPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); await flushAsync(); // Should go to profile discovery page. - assertTrue( - eSimPage.selectedESimPageName_ === - cellular_setup.ESimPageName.PROFILE_DISCOVERY && - eSimPage.selectedESimPageName_ === profileDiscoveryPage.id); + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_DISCOVERY, profileDiscoveryPage); // Select the first profile on the list. const profileList = profileDiscoveryPage.$$('#profileList'); @@ -280,9 +278,59 @@ await flushAsync(); // Should now be at the final page. - assertTrue( - eSimPage.selectedESimPageName_ === cellular_setup.ESimPageName.FINAL && - eSimPage.selectedESimPageName_ === finalPage.id); + assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage); assertFalse(!!finalPage.$$('.error')); }); + + test( + 'Multiple eSIM profiles select flow confirmation code required', + async function() { + eSimManagerRemote.addEuiccForTest(2); + const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs(); + const profileList = await availableEuiccs.euiccs[0].getProfileList(); + profileList.profiles[0].setProfileInstallResultForTest( + chromeos.cellularSetup.mojom.ProfileInstallResult + .kErrorNeedsConfirmationCode); + + const profileLoadingPage = eSimPage.$$('#profileLoadingPage'); + const profileDiscoveryPage = eSimPage.$$('#profileDiscoveryPage'); + const confirmationCodePage = eSimPage.$$('#confirmationCodePage'); + + assertTrue(!!profileLoadingPage); + assertTrue(!!profileDiscoveryPage); + assertTrue(!!confirmationCodePage); + + // Loading page should be showing. + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage); + + await flushAsync(); + + // Should go to profile discovery page. + assertSelectedPage( + cellular_setup.ESimPageName.PROFILE_DISCOVERY, + profileDiscoveryPage); + + // Select the first profile on the list. + const profileListUI = profileDiscoveryPage.$$('#profileList'); + profileListUI.selectItem(profileListUI.items[0]); + Polymer.dom.flush(); + + // The 'Next' button should now be enabled. + assertTrue( + eSimPage.buttonState.next === + cellularSetup.ButtonState.SHOWN_AND_ENABLED); + assertTrue( + eSimPage.buttonState.skipDiscovery === + cellularSetup.ButtonState.HIDDEN); + + // Simulate pressing 'Next'. + eSimPage.navigateForward(); + await flushAsync(); + + // Confirmation code page should be showing. + assertSelectedPage( + cellular_setup.ESimPageName.CONFIRMATION_CODE, + confirmationCodePage); + }); });
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/fake_esim_manager_remote.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/fake_esim_manager_remote.js index cae2dc30..62864ab2 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/fake_esim_manager_remote.js +++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/fake_esim_manager_remote.js
@@ -44,6 +44,10 @@ * chromeos.cellularSetup.mojom.ProfileInstallResult},}>} */ installProfile(confirmationCode) { + this.properties_.state = + chromeos.cellularSetup.mojom.ProfileState.kActive; + this.fakeEuicc_.notifyProfileChangedForTest(this); + this.fakeEuicc_.notifyProfileListChangedForTest(); return Promise.resolve({ result: this.profileInstallResult_ ? this.profileInstallResult_ : @@ -119,6 +123,7 @@ /** @override */ uninstallProfile() { + this.fakeEuicc_.notifyProfileChangedForTest(this); this.defferedUninstallProfilePromise_ = this.deferredPromise_(); return this.defferedUninstallProfilePromise_.promise; } @@ -144,7 +149,8 @@ /** @implements {chromeos.cellularSetup.mojom.Euicc} */ class FakeEuicc { - constructor(numProfiles) { + constructor(numProfiles, fakeESimManager) { + this.fakeESimManager_ = fakeESimManager; this.profiles_ = []; for (let i = 0; i < numProfiles; i++) { this.addProfileForTest_(); @@ -180,6 +186,7 @@ * chromeos.cellularSetup.mojom.ProfileInstallResult},}>} */ installProfileFromActivationCode(activationCode, confirmationCode) { + this.notifyProfileListChangedForTest(); return Promise.resolve({ result: this.profileInstallResult_ ? this.profileInstallResult_ : @@ -218,6 +225,7 @@ this.profiles_ = result; if (profileRemoved) { + this.notifyProfileListChangedForTest(); return { result: chromeos.cellularSetup.mojom.ESimOperationResult.kSuccess }; @@ -226,12 +234,24 @@ result: chromeos.cellularSetup.mojom.ESimOperationResult.kFailure }; } + + /** + * @param {FakeProfile} profile + */ + notifyProfileChangedForTest(profile) { + this.fakeESimManager_.notifyProfileChangedForTest(profile); + } + + notifyProfileListChangedForTest() { + this.fakeESimManager_.notifyProfileListChangedForTest(this); + } } /** @implements {chromeos.cellularSetup.mojom.ESimManagerInterface} */ /* #export */ class FakeESimManagerRemote { constructor() { this.euiccs_ = []; + this.observers_ = []; } /** @@ -248,9 +268,35 @@ * @param {number} numProfiles The number of profiles the EUICC has. */ addEuiccForTest(numProfiles) { - const euicc = new FakeEuicc(numProfiles); + const euicc = new FakeEuicc(numProfiles, this); this.euiccs_.push(euicc); } + + /** + * @param {!chromeos.cellularSetup.mojom.ESimManagerObserverInterface} + * observer + */ + addObserver(observer) { + this.observers_.push(observer); + } + + /** + * @param {FakeEuicc} euicc + */ + notifyProfileListChangedForTest(euicc) { + for (const observer of this.observers_) { + observer.onProfileListChanged(euicc); + } + } + + /** + * @param {FakeProfile} profile + */ + notifyProfileChangedForTest(profile) { + for (const observer of this.observers_) { + observer.onProfileChanged(profile); + } + } } // #cr_define_end
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js index 4ff7ff8b..675a1407 100644 --- a/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js +++ b/chrome/test/data/webui/cr_components/chromeos/network/network_list_item_test.js
@@ -94,7 +94,7 @@ }); test( - 'Pending eSIM profile name, provider, download button visibilty', + 'Pending eSIM profile name, provider, install button visibilty', async () => { const itemName = 'Item Name'; const itemSubtitle = 'Item Subtitle'; @@ -118,7 +118,44 @@ assertTrue(!!subtitle); assertEquals(itemSubtitle, subtitle.textContent.trim()); - let downloadButton = listItem.$$('#downloadButton'); - assertTrue(!!downloadButton); + let installButton = listItem.$$('#installButton'); + assertTrue(!!installButton); + + let installProfileEventIccid = null; + listItem.addEventListener('install-profile', (event) => { + installProfileEventIccid = event.detail.iccid; + }); + installButton.click(); + + await flushAsync(); + assertEquals(installProfileEventIccid, 'iccid'); + }); + + test( + 'Installing eSIM profile name, provider, spinner visibilty', async () => { + const itemName = 'Item Name'; + const itemSubtitle = 'Item Subtitle'; + listItem.item = { + customItemType: NetworkList.CustomItemType.ESIM_INSTALLING_PROFILE, + customItemName: itemName, + customItemSubtitle: itemSubtitle, + polymerIcon: 'network:cellular-0', + showBeforeNetworksList: false, + customData: { + iccid: 'iccid', + }, + }; + await flushAsync(); + + let networkName = listItem.$$('#networkName'); + assertTrue(!!networkName); + assertEquals(itemName, networkName.textContent.trim()); + + let subtitle = listItem.$$('#subtitle'); + assertTrue(!!subtitle); + assertEquals(itemSubtitle, subtitle.textContent.trim()); + + let spinner = listItem.$$('paper-spinner-lite'); + assertTrue(!!spinner); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js b/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js index e5fd658..459fbd3 100644 --- a/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js +++ b/chrome/test/data/webui/settings/chromeos/cellular_networks_list_test.js
@@ -32,7 +32,9 @@ eSimManagerRemote = new cellular_setup.FakeESimManagerRemote(); cellular_setup.setESimManagerRemoteForTesting(eSimManagerRemote); + }); + function init() { cellularNetworkList = document.createElement('cellular-networks-list'); // iron-list will not create list items if the container of the list is of // size zero. @@ -40,7 +42,7 @@ cellularNetworkList.style.width = '100%'; document.body.appendChild(cellularNetworkList); Polymer.dom.flush(); - }); + } function setNetworksForTest(type, networks) { mojoApi_.resetForTest(); @@ -57,6 +59,8 @@ } test('Tether, cellular and eSIM profiles', async () => { + init(); + const eSimNetwork1 = OncMojo.getDefaultNetworkState( mojom.NetworkType.kCellular, 'cellular_esim1'); const eSimNetwork2 = OncMojo.getDefaultNetworkState( @@ -102,10 +106,12 @@ test( 'Fire show cellular setup event on eSim/psim no network link click', async () => { + eSimManagerRemote.addEuiccForTest(0); + init(); + setNetworksForTest(mojom.NetworkType.kCellular, [ OncMojo.getDefaultNetworkState(mojom.NetworkType.kTether, 'tether1'), ]); - eSimManagerRemote.addEuiccForTest(0); Polymer.dom.flush(); await flushAsync(); @@ -139,8 +145,8 @@ }); test('Show EID and QR code popup', async () => { - eSimManagerRemote.addEuiccForTest(0); - + eSimManagerRemote.addEuiccForTest(1); + init(); let eidPopup = cellularNetworkList.$$('.eid-popup'); assertFalse(!!eidPopup); const eidPopupBtn = cellularNetworkList.$$('#eidPopupButton'); @@ -152,4 +158,42 @@ eidPopup = cellularNetworkList.$$('.eid-popup'); assertTrue(!!eidPopup); }); + + test('Install pending eSIM profile', async () => { + eSimManagerRemote.addEuiccForTest(1); + init(); + await flushAsync(); + + let eSimNetworkList = cellularNetworkList.$$('#esimNetworkList'); + assertTrue(!!eSimNetworkList); + assertEquals(1, cellularNetworkList.eSimPendingProfileItems_.length); + + const listItem = eSimNetworkList.$$('network-list-item'); + assertTrue(!!listItem); + const installButton = listItem.$$('#installButton'); + assertTrue(!!installButton); + installButton.click(); + + await flushAsync(); + + // eSIM network list should now be hidden and link showing. + eSimNetworkList = cellularNetworkList.$$('#esimNetworkList'); + assertFalse(!!eSimNetworkList); + const esimNoNetworkAnchor = cellularNetworkList.$$('#eSimNoNetworkFound') + .querySelector('settings-localized-link') + .shadowRoot.querySelector('a'); + assertTrue(!!esimNoNetworkAnchor); + }); + test('Hide esim section when no EUICC is found', async () => { + setNetworksForTest(mojom.NetworkType.kCellular, [ + OncMojo.getDefaultNetworkState(mojom.NetworkType.kTether, 'tether1'), + ]); + init(); + Polymer.dom.flush(); + await flushAsync(); + const esimNetworkList = cellularNetworkList.$$('#esimNetworkList'); + + assertFalse(!!esimNetworkList); + }); + });
diff --git a/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc b/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc index 3de040e2..1097c67 100644 --- a/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc +++ b/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc
@@ -166,7 +166,10 @@ int frames_remaining = status.ringing_time_frames; int frames_to_process = std::min(frames_remaining, kNumFrames); while (frames_remaining > 0) { + // Make sure |frames_to_process| is an even multiple of 8. frames_to_process = std::min(frames_to_process, frames_remaining); + frames_to_process = (frames_to_process + 7); + frames_to_process -= frames_to_process % 8; data.assign(frames_to_process * num_input_channels, 0); pp->ProcessFrames(data.data(), frames_to_process, &metadata); frames_remaining -= frames_to_process;
diff --git a/chromecast/media/cma/decoder/cast_audio_decoder.cc b/chromecast/media/cma/decoder/cast_audio_decoder.cc index 90f370f..51d1e0f 100644 --- a/chromecast/media/cma/decoder/cast_audio_decoder.cc +++ b/chromecast/media/cma/decoder/cast_audio_decoder.cc
@@ -266,8 +266,8 @@ auto result = base::MakeRefCounted<::media::DecoderBuffer>(size); if (output_format_ == kOutputSigned16) { - bus->ToInterleaved(num_frames, OutputFormatSizeInBytes(output_format_), - result->writable_data()); + bus->ToInterleaved<::media::SignedInt16SampleTypeTraits>( + num_frames, reinterpret_cast<int16_t*>(result->writable_data())); } else if (output_format_ == kOutputPlanarFloat) { // Data in an AudioBus is already in planar float format; just copy each // channel into the result buffer in order.
diff --git a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc index f977aff..8afa66b 100644 --- a/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc +++ b/chromeos/components/cdm_factory_daemon/chromeos_cdm_factory.cc
@@ -227,11 +227,14 @@ &GetOutputProtectionOnTaskRunner, output_protection_remote.InitWithNewPipeAndPassReceiver())); + url::Origin cdm_origin; + frame_interfaces_->GetCdmOrigin(&cdm_origin); + // Now create the remote CDM instance that links everything up. - remote_factory_->CreateCdm(cdm->GetClientInterface(), - std::move(storage_remote), - std::move(cros_cdm_pending_receiver), - std::move(output_protection_remote)); + remote_factory_->CreateCdm( + cdm->GetClientInterface(), std::move(storage_remote), + std::move(output_protection_remote), cdm_origin.host(), + std::move(cros_cdm_pending_receiver)); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(cdm_created_cb), std::move(cdm), ""));
diff --git a/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom b/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom index 86a834e..281f92a 100644 --- a/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom +++ b/chromeos/components/cdm_factory_daemon/mojom/cdm_factory_daemon.mojom
@@ -9,7 +9,7 @@ // interface can also be used to connect directly to the OEMCrypto // implementation for ARC. -// Next MinVersion: 3 +// Next MinVersion: 4 module chromeos.cdm.mojom; @@ -22,20 +22,23 @@ // Next Method ID: 2 interface CdmFactory { // Deprecated, do not use. - CreateCdmDeprecated@0( - pending_associated_remote<ContentDecryptionModuleClient> client, - pending_associated_remote<CdmStorage> storage, - pending_associated_receiver<ContentDecryptionModule> cdm); - - // Creates a new ContentDecryptionModule instance with the corresponding - // client, remote storage implementation and output protection. Use an - // associated interface to ensure ordering and that all become invalidated at - // the same time. [MinVersion=1] - CreateCdm@1(pending_associated_remote<ContentDecryptionModuleClient> client, + CreateCdmDeprecated@1( + pending_associated_remote<ContentDecryptionModuleClient> client, pending_associated_remote<CdmStorage> storage, pending_associated_receiver<ContentDecryptionModule> cdm, pending_remote<OutputProtection> output_protection); + + // Creates a new ContentDecryptionModule instance for a |host| with the + // corresponding |client|, remote |storage| implementation and + // |output_protection|. Use an associated interface to ensure ordering and + // that all become invalidated at the same time. + [MinVersion=3] + CreateCdm@2(pending_associated_remote<ContentDecryptionModuleClient> client, + pending_associated_remote<CdmStorage> storage, + pending_remote<OutputProtection> output_protection, + string host, + pending_associated_receiver<ContentDecryptionModule> cdm); }; // Next Method ID: 5
diff --git a/chromeos/components/help_app_ui/resources/browser_proxy.js b/chromeos/components/help_app_ui/resources/browser_proxy.js index 3db70b1..ca0b96b 100644 --- a/chromeos/components/help_app_ui/resources/browser_proxy.js +++ b/chromeos/components/help_app_ui/resources/browser_proxy.js
@@ -102,7 +102,7 @@ locale: searchable_item.locale, }; }); - indexRemote.addOrUpdate(data_to_send); + return indexRemote.addOrUpdate(data_to_send); }); guestMessagePipe.registerHandler(Message.CLEAR_SEARCH_INDEX, async () => {
diff --git a/chromeos/components/proximity_auth/proximity_auth_profile_pref_manager.cc b/chromeos/components/proximity_auth/proximity_auth_profile_pref_manager.cc index d8cd04f..9f9bcce 100644 --- a/chromeos/components/proximity_auth/proximity_auth_profile_pref_manager.cc +++ b/chromeos/components/proximity_auth/proximity_auth_profile_pref_manager.cc
@@ -175,7 +175,10 @@ bool has_shown) { // This is persisted within SyncPrefsToLocalState() instead, since the local // state must act as the source of truth for this pref. - NOTREACHED(); + + // TODO(crbug.com/1152491): Add a NOTREACHED() to ensure this method is not + // called. It is currently incorrectly, though harmlessly, called by virtual + // Chrome OS on Linux. } bool ProximityAuthProfilePrefManager::HasShownLoginDisabledMessage() const {
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn index 562e6b9..446dd77 100644 --- a/chromeos/crosapi/mojom/BUILD.gn +++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -17,6 +17,7 @@ "message_center.mojom", "metrics_reporting.mojom", "notification.mojom", + "prefs.mojom", "screen_manager.mojom", "select_file.mojom", "test_controller.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index d6586d4c5..ebdb116 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -12,6 +12,7 @@ import "chromeos/crosapi/mojom/keystore_service.mojom"; import "chromeos/crosapi/mojom/message_center.mojom"; import "chromeos/crosapi/mojom/metrics_reporting.mojom"; +import "chromeos/crosapi/mojom/prefs.mojom"; import "chromeos/crosapi/mojom/screen_manager.mojom"; import "chromeos/crosapi/mojom/select_file.mojom"; import "chromeos/crosapi/mojom/test_controller.mojom"; @@ -43,8 +44,8 @@ // milestone when you added it, to help us reason about compatibility between // lacros-chrome and older ash-chrome binaries. // -// Next version: 11 -// Next method id: 16 +// Next version: 12 +// Next method id: 17 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e"] interface AshChromeService { // Binds Chrome OS Account Manager for Identity management. @@ -79,6 +80,10 @@ [MinVersion=8] BindMetricsReporting@13(pending_receiver<MetricsReporting> receiver); + // Binds the prefs service which allows get, set, and notify update of prefs. + // Added in M89. + [MinVersion=11] BindPrefs@16(pending_receiver<Prefs> receiver); + // Binds the ScreenManager interface for interacting with windows, screens and // displays. // Added in M86.
diff --git a/chromeos/crosapi/mojom/prefs.mojom b/chromeos/crosapi/mojom/prefs.mojom new file mode 100644 index 0000000..66c8e95 --- /dev/null +++ b/chromeos/crosapi/mojom/prefs.mojom
@@ -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. + +module crosapi.mojom; + +import "mojo/public/mojom/base/values.mojom"; + +// Pref paths. +[Stable, Extensible] +enum PrefPath { + kUnknown = 0, + // M89: metrics::prefs::kMetricsReportingEnabled (local state). + kMetricsReportingEnabled = 1, + // M89: ash::prefs::kAccessibilitySpokenFeedbackEnabled (profile). + kAccessibilitySpokenFeedbackEnabled = 2, +}; + +// Interface for pref observers. Implemented by lacros-chrome. Used by +// ash-chrome to send pref updates. +[Stable, Uuid="07d804d1-3d8d-4da1-b9b9-05f8a6bfe4c4"] +interface PrefObserver { + // Called when an observed pref changes. + OnPrefChanged@0(mojo_base.mojom.Value value); +}; + +// Interface for prefs. Implemented by ash-chrome. +// Next version: 1 +// Next method id: 3 +[Stable, Uuid="815df607-0596-46f7-9ed9-14683b4826a3"] +interface Prefs { + // Gets the specified ash pref. Returns empty if ash-chrome does not have path + // registered, or if the pref is not found. + GetPref@0(PrefPath path) => (mojo_base.mojom.Value? value); + + // Sets the specified ash pref. Does nothing if ash-chrome does not have path + // registered. + SetPref@1(PrefPath path, mojo_base.mojom.Value value) => (); + + // Adds an observer for ash pref. The observer is fired immediately with the + // current value. Multiple observers may be registered for any given pref. + // Does nothing if ash-chrome does not have path registered. + AddObserver@2(PrefPath path, pending_remote<PrefObserver> observer); +};
diff --git a/chromeos/lacros/lacros_chrome_service_impl.cc b/chromeos/lacros/lacros_chrome_service_impl.cc index dbc677f..1bebf67 100644 --- a/chromeos/lacros/lacros_chrome_service_impl.cc +++ b/chromeos/lacros/lacros_chrome_service_impl.cc
@@ -244,6 +244,12 @@ ash_chrome_service_->BindMetricsReporting(std::move(receiver)); } + void BindPrefsReceiver( + mojo::PendingReceiver<crosapi::mojom::Prefs> pending_receiver) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + ash_chrome_service_->BindPrefs(std::move(pending_receiver)); + } + void BindTestControllerReceiver( mojo::PendingReceiver<crosapi::mojom::TestController> pending_receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -454,6 +460,16 @@ &LacrosChromeServiceNeverBlockingState::BindClipboardReceiver, weak_sequenced_state_, std::move(pending_receiver))); } + + if (IsPrefsAvailable()) { + mojo::PendingReceiver<crosapi::mojom::Prefs> pending_receiver = + prefs_remote_.BindNewPipeAndPassReceiver(); + never_blocking_sequence_->PostTask( + FROM_HERE, + base::BindOnce( + &LacrosChromeServiceNeverBlockingState::BindPrefsReceiver, + weak_sequenced_state_, std::move(pending_receiver))); + } } // static @@ -625,6 +641,13 @@ AshChromeService::MethodMinVersions::kBindCertDatabaseMinVersion; } +bool LacrosChromeServiceImpl::IsPrefsAvailable() { + base::Optional<uint32_t> version = AshChromeServiceVersion(); + return version && + version.value() >= + AshChromeService::MethodMinVersions::kBindPrefsMinVersion; +} + bool LacrosChromeServiceImpl::IsOnLacrosStartupAvailable() { base::Optional<uint32_t> version = AshChromeServiceVersion(); return version &&
diff --git a/chromeos/lacros/lacros_chrome_service_impl.h b/chromeos/lacros/lacros_chrome_service_impl.h index 71082ad..3160829 100644 --- a/chromeos/lacros/lacros_chrome_service_impl.h +++ b/chromeos/lacros/lacros_chrome_service_impl.h
@@ -20,6 +20,7 @@ #include "chromeos/crosapi/mojom/keystore_service.mojom.h" #include "chromeos/crosapi/mojom/message_center.mojom.h" #include "chromeos/crosapi/mojom/metrics_reporting.mojom.h" +#include "chromeos/crosapi/mojom/prefs.mojom.h" #include "chromeos/crosapi/mojom/screen_manager.mojom.h" #include "chromeos/crosapi/mojom/select_file.mojom.h" #include "chromeos/crosapi/mojom/test_controller.mojom.h" @@ -213,6 +214,17 @@ return clipboard_remote_; } + // Whether the Prefs API is available. + bool IsPrefsAvailable(); + + // This must be called on the affine sequence. It exposes a remote that can + // be used to interface with Prefs. + mojo::Remote<crosapi::mojom::Prefs>& prefs_remote() { + DCHECK_CALLED_ON_VALID_SEQUENCE(affine_sequence_checker_); + DCHECK(IsPrefsAvailable()); + return prefs_remote_; + } + // -------------------------------------------------------------------------- // Some clients will want to use mojo::Remotes on arbitrary sequences (e.g. // background threads). The following methods allow the client to construct a @@ -307,6 +319,7 @@ mojo::Remote<crosapi::mojom::FileManager> file_manager_remote_; mojo::Remote<crosapi::mojom::TestController> test_controller_remote_; mojo::Remote<crosapi::mojom::Clipboard> clipboard_remote_; + mojo::Remote<crosapi::mojom::Prefs> prefs_remote_; // This member is instantiated on the affine sequence alongside the // constructor. All subsequent invocations of this member, including
diff --git a/chromeos/services/assistant/BUILD.gn b/chromeos/services/assistant/BUILD.gn index 9d0afbaa56..6b9c2d5 100644 --- a/chromeos/services/assistant/BUILD.gn +++ b/chromeos/services/assistant/BUILD.gn
@@ -82,8 +82,8 @@ "media_session/assistant_media_session.h", "platform/audio_device_owner.cc", "platform/audio_device_owner.h", - "platform/audio_input_host.cc", - "platform/audio_input_host.h", + "platform/audio_input_host_impl.cc", + "platform/audio_input_host_impl.h", "platform/audio_input_impl.cc", "platform/audio_input_impl.h", "platform/audio_input_provider_impl.cc",
diff --git a/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc b/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc index a4a82b9..6f6a5ec 100644 --- a/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_delegate_impl.cc
@@ -9,6 +9,7 @@ #include <utility> #include "ash/public/cpp/assistant/assistant_state_base.h" +#include "chromeos/services/assistant/platform/audio_input_host_impl.h" #include "chromeos/services/assistant/platform_api_impl.h" #include "chromeos/services/assistant/service_context.h" #include "libassistant/shared/internal_api/assistant_manager_internal.h" @@ -20,21 +21,26 @@ AssistantManagerServiceDelegateImpl::AssistantManagerServiceDelegateImpl( mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor, ServiceContext* context) - : battery_monitor_(std::move(battery_monitor)), - context_(context) {} + : battery_monitor_(std::move(battery_monitor)), context_(context) {} AssistantManagerServiceDelegateImpl::~AssistantManagerServiceDelegateImpl() = default; +std::unique_ptr<AudioInputHost> +AssistantManagerServiceDelegateImpl::CreateAudioInputHost() { + return std::make_unique<AudioInputHostImpl>( + context_->cras_audio_handler(), context_->power_manager_client(), + context_->assistant_state()->locale().value()); +} + std::unique_ptr<CrosPlatformApi> AssistantManagerServiceDelegateImpl::CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner> background_thread_task_runner) { return std::make_unique<PlatformApiImpl>( media_session, context_->power_manager_client(), - context_->cras_audio_handler(), std::move(battery_monitor_), - context_->main_task_runner(), background_thread_task_runner, - context_->assistant_state()->locale().value()); + std::move(battery_monitor_), context_->main_task_runner(), + background_thread_task_runner); } std::unique_ptr<assistant_client::AssistantManager>
diff --git a/chromeos/services/assistant/assistant_manager_service_delegate_impl.h b/chromeos/services/assistant/assistant_manager_service_delegate_impl.h index 1d0eb8586..82836437 100644 --- a/chromeos/services/assistant/assistant_manager_service_delegate_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_delegate_impl.h
@@ -25,15 +25,15 @@ ServiceContext* context); ~AssistantManagerServiceDelegateImpl() override; + // AssistantManagerServiceDelegate implementation: + std::unique_ptr<AudioInputHost> CreateAudioInputHost() override; std::unique_ptr<CrosPlatformApi> CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner> background_thread_task_runner) override; - std::unique_ptr<assistant_client::AssistantManager> CreateAssistantManager( assistant_client::PlatformApi* platform_api, const std::string& lib_assistant_config) override; - assistant_client::AssistantManagerInternal* UnwrapAssistantManagerInternal( assistant_client::AssistantManager* assistant_manager) override;
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index 413dd9d..d4df871 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -40,6 +40,7 @@ #include "chromeos/services/assistant/public/cpp/device_actions.h" #include "chromeos/services/assistant/public/cpp/features.h" #include "chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h" +#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" #include "chromeos/services/assistant/public/cpp/migration/libassistant_v1_api.h" #include "chromeos/services/assistant/public/shared/utils.h" #include "chromeos/services/assistant/service_context.h" @@ -198,6 +199,10 @@ // To solve this chicken-and-egg problem, we need a separe Initialize() call. assistant_proxy_->Initialize(libassistant_service_host_.get()); + audio_input_host_ = delegate_->CreateAudioInputHost(); + + platform_api_->InitializeAudioInputHost(*audio_input_host_); + settings_delegate_ = std::make_unique<AssistantDeviceSettingsDelegate>(context); @@ -361,7 +366,7 @@ } void AssistantManagerServiceImpl::EnableHotword(bool enable) { - platform_api_->OnHotwordEnabled(enable); + audio_input_host_->OnHotwordEnabled(enable); } void AssistantManagerServiceImpl::SetArcPlayStoreEnabled(bool enable) { @@ -449,14 +454,14 @@ DCHECK(assistant_manager()); DVLOG(1) << __func__; - platform_api_->SetMicState(true); + audio_input_host_->SetMicState(true); assistant_manager()->StartAssistantInteraction(); } void AssistantManagerServiceImpl::StopActiveInteraction( bool cancel_conversation) { DVLOG(1) << __func__; - platform_api_->SetMicState(false); + audio_input_host_->SetMicState(false); if (!assistant_manager_internal()) { VLOG(1) << "Stopping interaction without assistant manager."; @@ -578,7 +583,7 @@ &AssistantManagerServiceImpl::OnConversationTurnStartedInternal, metadata); - platform_api_->OnConversationTurnStarted(); + audio_input_host_->OnConversationTurnStarted(); // Retrieve the cached interaction metadata associated with this conversation // turn or construct a new instance if there's no match in the cache. @@ -607,10 +612,10 @@ if (resolution != Resolution::NORMAL_WITH_FOLLOW_ON && resolution != Resolution::CANCELLED && resolution != Resolution::BARGE_IN) { - platform_api_->SetMicState(false); + audio_input_host_->SetMicState(false); } - platform_api_->OnConversationTurnFinished(); + audio_input_host_->OnConversationTurnFinished(); switch (resolution) { // Interaction ended normally. @@ -1396,6 +1401,11 @@ return api ? api->assistant_manager_internal() : nullptr; } +void AssistantManagerServiceImpl::SetMicState(bool mic_open) { + DCHECK(audio_input_host_); + audio_input_host_->SetMicState(mic_open); +} + ServiceControllerProxy& AssistantManagerServiceImpl::service_controller() { return assistant_proxy_->service_controller(); }
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h index 26a3d96..cff59765 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -63,6 +63,7 @@ class AssistantDeviceSettingsDelegate; class AssistantManagerServiceDelegate; class AssistantProxy; +class AudioInputHost; class CrosPlatformApi; class ServiceContext; class ServiceControllerProxy; @@ -220,7 +221,7 @@ assistant_client::AssistantManager* assistant_manager(); assistant_client::AssistantManagerInternal* assistant_manager_internal(); - CrosPlatformApi* platform_api() { return platform_api_.get(); } + void SetMicState(bool mic_open); // assistant_client::MediaManager::Listener overrides: void OnPlaybackStateChange( @@ -313,6 +314,7 @@ std::unique_ptr<AssistantSettingsImpl> assistant_settings_; std::unique_ptr<AssistantProxy> assistant_proxy_; + std::unique_ptr<AudioInputHost> audio_input_host_; base::ObserverList<AssistantInteractionSubscriber> interaction_subscribers_; mojo::Remote<media_session::mojom::MediaController> media_controller_;
diff --git a/chromeos/services/assistant/assistant_settings_impl.cc b/chromeos/services/assistant/assistant_settings_impl.cc index e68eb8f1..f064b87 100644 --- a/chromeos/services/assistant/assistant_settings_impl.cc +++ b/chromeos/services/assistant/assistant_settings_impl.cc
@@ -13,7 +13,6 @@ #include "chromeos/dbus/util/version_loader.h" #include "chromeos/services/assistant/assistant_manager_service_impl.h" #include "chromeos/services/assistant/public/cpp/features.h" -#include "chromeos/services/assistant/public/cpp/migration/cros_platform_api.h" #include "chromeos/services/assistant/public/proto/assistant_device_settings_ui.pb.h" #include "chromeos/services/assistant/public/proto/settings_ui.pb.h" #include "chromeos/services/assistant/service_context.h" @@ -124,7 +123,7 @@ DCHECK(main_task_runner()->RunsTasksInCurrentSequence()); DCHECK(!speaker_id_enrollment_client_); - assistant_manager_service_->platform_api()->SetMicState(true); + assistant_manager_service_->SetMicState(true); if (!assistant_manager_service_->assistant_manager_internal()) return; @@ -153,7 +152,7 @@ DCHECK(HasStarted(assistant_manager_service_)); DCHECK(main_task_runner()->RunsTasksInCurrentSequence()); - assistant_manager_service_->platform_api()->SetMicState(false); + assistant_manager_service_->SetMicState(false); if (!assistant_manager_service_->assistant_manager_internal()) return;
diff --git a/chromeos/services/assistant/platform/audio_input_host.h b/chromeos/services/assistant/platform/audio_input_host.h deleted file mode 100644 index 528af7a9..0000000 --- a/chromeos/services/assistant/platform/audio_input_host.h +++ /dev/null
@@ -1,80 +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 CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_ -#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_ - -#include <string> - -#include "base/component_export.h" -#include "base/memory/weak_ptr.h" -#include "base/scoped_observation.h" -#include "chromeos/dbus/power/power_manager_client.h" -#include "chromeos/services/assistant/platform/audio_devices.h" - -namespace chromeos { -namespace assistant { - -class AudioInputImpl; - -// Class that provides the bridge between the ChromeOS UI thread and the -// Libassistant audio input class. -// The goal is that |AudioInputImpl| no longer depends on any external events. -// This will allow us to move it to the Libassistant mojom service (at which -// point this class will talk to the Libassistant mojom service). -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioInputHost - : private chromeos::PowerManagerClient::Observer, - private AudioDevices::Observer - -{ - public: - AudioInputHost(AudioInputImpl* audio_input, - CrasAudioHandler* cras_audio_handler, - chromeos::PowerManagerClient* power_manager_client, - const std::string& locale); - AudioInputHost(AudioInputHost&) = delete; - AudioInputHost& operator=(AudioInputHost&) = delete; - ~AudioInputHost() override; - - // Called when the mic state associated with the interaction is changed. - void SetMicState(bool mic_open); - - // Called when hotword enabled status changed. - void OnHotwordEnabled(bool enable); - - void OnConversationTurnStarted(); - void OnConversationTurnFinished(); - - // AudioDevices::Observer implementation: - void SetDeviceId(const base::Optional<std::string>& device_id) override; - void SetHotwordDeviceId( - const base::Optional<std::string>& device_id) override; - - private: - // chromeos::PowerManagerClient::Observer overrides: - void LidEventReceived(chromeos::PowerManagerClient::LidState state, - base::TimeTicks timestamp) override; - - void OnInitialLidStateReceived( - base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states); - - // Owned by |PlatformApiImpl| which also owns |this|. - AudioInputImpl* const audio_input_; - chromeos::PowerManagerClient* const power_manager_client_; - base::ScopedObservation<chromeos::PowerManagerClient, - chromeos::PowerManagerClient::Observer> - power_manager_client_observer_; - - // Observes available audio devices and will set device-id/hotword-device-id - // accordingly. - AudioDevices audio_devices_; - AudioDevices::ScopedObservation audio_devices_observation_{this}; - - base::WeakPtrFactory<AudioInputHost> weak_factory_{this}; -}; - -} // namespace assistant -} // namespace chromeos - -#endif // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_
diff --git a/chromeos/services/assistant/platform/audio_input_host.cc b/chromeos/services/assistant/platform/audio_input_host_impl.cc similarity index 68% rename from chromeos/services/assistant/platform/audio_input_host.cc rename to chromeos/services/assistant/platform/audio_input_host_impl.cc index 6ace7006..4f6dcd6e 100644 --- a/chromeos/services/assistant/platform/audio_input_host.cc +++ b/chromeos/services/assistant/platform/audio_input_host_impl.cc
@@ -1,8 +1,8 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. +// Copyright 2021 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 "chromeos/services/assistant/platform/audio_input_host.h" +#include "chromeos/services/assistant/platform/audio_input_host_impl.h" #include "base/check.h" #include "base/optional.h" @@ -30,35 +30,38 @@ } // namespace -chromeos::assistant::AudioInputHost::AudioInputHost( - AudioInputImpl* audio_input, +chromeos::assistant::AudioInputHostImpl::AudioInputHostImpl( CrasAudioHandler* cras_audio_handler, chromeos::PowerManagerClient* power_manager_client, const std::string& locale) - : audio_input_(audio_input), - power_manager_client_(power_manager_client), + : power_manager_client_(power_manager_client), power_manager_client_observer_(this), audio_devices_(cras_audio_handler, locale) { - DCHECK(audio_input_); DCHECK(power_manager_client_); - - audio_devices_observation_.Observe(&audio_devices_); - power_manager_client_observer_.Observe(power_manager_client); - power_manager_client->GetSwitchStates(base::BindOnce( - &AudioInputHost::OnInitialLidStateReceived, weak_factory_.GetWeakPtr())); } -AudioInputHost::~AudioInputHost() = default; +AudioInputHostImpl::~AudioInputHostImpl() = default; -void AudioInputHost::SetMicState(bool mic_open) { +void AudioInputHostImpl::Initialize(AudioInputImpl* audio_input) { + DCHECK(audio_input); + audio_input_ = audio_input; + audio_devices_observation_.Observe(&audio_devices_); + power_manager_client_observer_.Observe(power_manager_client_); + power_manager_client_->GetSwitchStates( + base::BindOnce(&AudioInputHostImpl::OnInitialLidStateReceived, + weak_factory_.GetWeakPtr())); +} + +void AudioInputHostImpl::SetMicState(bool mic_open) { audio_input_->SetMicState(mic_open); } -void AudioInputHost::SetDeviceId(const base::Optional<std::string>& device_id) { +void AudioInputHostImpl::SetDeviceId( + const base::Optional<std::string>& device_id) { audio_input_->SetDeviceId(device_id.value_or("")); } -void AudioInputHost::OnConversationTurnStarted() { +void AudioInputHostImpl::OnConversationTurnStarted() { audio_input_->OnConversationTurnStarted(); // Inform power manager of a wake notification when Libassistant // recognized hotword and started a conversation. We intentionally @@ -67,20 +70,20 @@ power_manager_client_->NotifyWakeNotification(); } -void AudioInputHost::OnConversationTurnFinished() { +void AudioInputHostImpl::OnConversationTurnFinished() { audio_input_->OnConversationTurnFinished(); } -void AudioInputHost::OnHotwordEnabled(bool enable) { +void AudioInputHostImpl::OnHotwordEnabled(bool enable) { audio_input_->OnHotwordEnabled(enable); } -void AudioInputHost::SetHotwordDeviceId( +void AudioInputHostImpl::SetHotwordDeviceId( const base::Optional<std::string>& device_id) { audio_input_->SetHotwordDeviceId(device_id.value_or("")); } -void AudioInputHost::LidEventReceived( +void AudioInputHostImpl::LidEventReceived( chromeos::PowerManagerClient::LidState state, base::TimeTicks timestamp) { // Lid switch event still gets fired during system suspend, which enables @@ -89,7 +92,7 @@ audio_input_->OnLidStateChanged(ConvertLidState(state)); } -void AudioInputHost::OnInitialLidStateReceived( +void AudioInputHostImpl::OnInitialLidStateReceived( base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states) { if (switch_states.has_value()) audio_input_->OnLidStateChanged(ConvertLidState(switch_states->lid_state));
diff --git a/chromeos/services/assistant/platform/audio_input_host_impl.h b/chromeos/services/assistant/platform/audio_input_host_impl.h new file mode 100644 index 0000000..fc3583a --- /dev/null +++ b/chromeos/services/assistant/platform/audio_input_host_impl.h
@@ -0,0 +1,73 @@ +// Copyright 2021 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 CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_ +#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_ + +#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" + +#include <string> + +#include "base/component_export.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/scoped_observation.h" +#include "base/time/time.h" +#include "chromeos/dbus/power/power_manager_client.h" +#include "chromeos/services/assistant/platform/audio_devices.h" + +namespace chromeos { +namespace assistant { + +class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioInputHostImpl + : public AudioInputHost, + private chromeos::PowerManagerClient::Observer, + private AudioDevices::Observer { + public: + AudioInputHostImpl(CrasAudioHandler* cras_audio_handler, + chromeos::PowerManagerClient* power_manager_client, + const std::string& locale); + AudioInputHostImpl(const AudioInputHostImpl&) = delete; + AudioInputHostImpl& operator=(const AudioInputHostImpl&) = delete; + ~AudioInputHostImpl() override; + + // AudioInputHost implementation: + void Initialize(AudioInputImpl* audio_input) override; + void SetMicState(bool mic_open) override; + void OnHotwordEnabled(bool enable) override; + void OnConversationTurnStarted() override; + void OnConversationTurnFinished() override; + + // AudioDevices::Observer implementation: + void SetDeviceId(const base::Optional<std::string>& device_id) override; + void SetHotwordDeviceId( + const base::Optional<std::string>& device_id) override; + + private: + // chromeos::PowerManagerClient::Observer overrides: + void LidEventReceived(chromeos::PowerManagerClient::LidState state, + base::TimeTicks timestamp) override; + + void OnInitialLidStateReceived( + base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states); + + // Owned by |PlatformApiImpl| which also owns |this|. + AudioInputImpl* audio_input_ = nullptr; + chromeos::PowerManagerClient* const power_manager_client_; + base::ScopedObservation<chromeos::PowerManagerClient, + chromeos::PowerManagerClient::Observer> + power_manager_client_observer_; + + // Observes available audio devices and will set device-id/hotword-device-id + // accordingly. + AudioDevices audio_devices_; + AudioDevices::ScopedObservation audio_devices_observation_{this}; + + base::WeakPtrFactory<AudioInputHostImpl> weak_factory_{this}; +}; + +} // namespace assistant +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_
diff --git a/chromeos/services/assistant/platform/audio_input_impl_unittest.cc b/chromeos/services/assistant/platform/audio_input_impl_unittest.cc index 21811c7..28b6d5f 100644 --- a/chromeos/services/assistant/platform/audio_input_impl_unittest.cc +++ b/chromeos/services/assistant/platform/audio_input_impl_unittest.cc
@@ -12,7 +12,7 @@ #include "base/test/task_environment.h" #include "chromeos/audio/cras_audio_handler.h" #include "chromeos/dbus/power/fake_power_manager_client.h" -#include "chromeos/services/assistant/platform/audio_input_host.h" +#include "chromeos/services/assistant/platform/audio_input_host_impl.h" #include "chromeos/services/assistant/platform/audio_stream_factory_delegate.h" #include "chromeos/services/assistant/public/cpp/features.h" #include "chromeos/services/assistant/test_support/scoped_assistant_client.h" @@ -101,9 +101,10 @@ audio_input_impl_ = std::make_unique<AudioInputImpl>( &audio_stream_factory_delegate_, "fake-device-id"); - audio_input_host_ = std::make_unique<AudioInputHost>( - audio_input_impl_.get(), cras_audio_handler_.Get(), - FakePowerManagerClient::Get(), "initial-locale"); + audio_input_host_ = std::make_unique<AudioInputHostImpl>( + cras_audio_handler_.Get(), FakePowerManagerClient::Get(), + "initial-locale"); + audio_input_host_->Initialize(audio_input_impl_.get()); audio_input_host_->SetDeviceId("initial-device-id"); audio_input_impl_->AddObserver(this); @@ -152,7 +153,7 @@ DefaultAudioStreamFactoryDelegate audio_stream_factory_delegate_; ScopedCrasAudioHandler cras_audio_handler_; std::unique_ptr<AudioInputImpl> audio_input_impl_; - std::unique_ptr<AudioInputHost> audio_input_host_; + std::unique_ptr<AudioInputHostImpl> audio_input_host_; DISALLOW_COPY_AND_ASSIGN(AudioInputImplTest); };
diff --git a/chromeos/services/assistant/platform_api_impl.cc b/chromeos/services/assistant/platform_api_impl.cc index 84d44577..dc59df3 100644 --- a/chromeos/services/assistant/platform_api_impl.cc +++ b/chromeos/services/assistant/platform_api_impl.cc
@@ -12,6 +12,7 @@ #include "chromeos/services/assistant/platform/audio_devices.h" #include "chromeos/services/assistant/platform/power_manager_provider_impl.h" #include "chromeos/services/assistant/public/cpp/features.h" +#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" #include "chromeos/services/assistant/utils.h" #include "libassistant/shared/public/assistant_export.h" #include "libassistant/shared/public/platform_api.h" @@ -78,19 +79,13 @@ PlatformApiImpl::PlatformApiImpl( AssistantMediaSession* media_session, PowerManagerClient* power_manager_client, - CrasAudioHandler* cras_audio_handler, mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor, scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> background_task_runner, - const std::string& pref_locale) + scoped_refptr<base::SingleThreadTaskRunner> background_task_runner) : audio_input_provider_(), audio_output_provider_(media_session, background_task_runner, - media::AudioDeviceDescription::kDefaultDeviceId), - audio_input_host_(&audio_input_provider_.GetAudioInput(), - cras_audio_handler, - power_manager_client, - pref_locale) { + media::AudioDeviceDescription::kDefaultDeviceId) { // Only enable native power features if they are supported by the UI. std::unique_ptr<PowerManagerProviderImpl> provider; if (features::IsPowerManagerEnabled()) { @@ -127,20 +122,8 @@ return *system_provider_; } -void PlatformApiImpl::SetMicState(bool mic_open) { - audio_input_host_.SetMicState(mic_open); -} - -void PlatformApiImpl::OnConversationTurnStarted() { - audio_input_host_.OnConversationTurnStarted(); -} - -void PlatformApiImpl::OnConversationTurnFinished() { - audio_input_host_.OnConversationTurnFinished(); -} - -void PlatformApiImpl::OnHotwordEnabled(bool enable) { - audio_input_host_.OnHotwordEnabled(enable); +void PlatformApiImpl::InitializeAudioInputHost(AudioInputHost& host) { + host.Initialize(&audio_input_provider_.GetAudioInput()); } } // namespace assistant
diff --git a/chromeos/services/assistant/platform_api_impl.h b/chromeos/services/assistant/platform_api_impl.h index 2ba1b1f..782ddc8 100644 --- a/chromeos/services/assistant/platform_api_impl.h +++ b/chromeos/services/assistant/platform_api_impl.h
@@ -10,7 +10,6 @@ #include <utility> #include <vector> -#include "chromeos/services/assistant/platform/audio_input_host.h" #include "chromeos/services/assistant/platform/audio_input_provider_impl.h" #include "chromeos/services/assistant/platform/audio_output_provider_impl.h" #include "chromeos/services/assistant/platform/file_provider_impl.h" @@ -23,7 +22,6 @@ #include "services/device/public/mojom/battery_monitor.mojom.h" namespace chromeos { -class CrasAudioHandler; class PowerManagerClient; namespace assistant { @@ -36,11 +34,9 @@ PlatformApiImpl( AssistantMediaSession* media_session, PowerManagerClient* power_manager_client, - CrasAudioHandler* cras_audio_handler, mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor, scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> background_task_runner, - const std::string& pref_locale); + scoped_refptr<base::SingleThreadTaskRunner> background_task_runner); ~PlatformApiImpl() override; // assistant_client::PlatformApi overrides @@ -51,14 +47,7 @@ assistant_client::NetworkProvider& GetNetworkProvider() override; assistant_client::SystemProvider& GetSystemProvider() override; - // Called when the mic state associated with the interaction is changed. - void SetMicState(bool mic_open) override; - - void OnConversationTurnStarted() override; - void OnConversationTurnFinished() override; - - // Called when hotword enabled status changed. - void OnHotwordEnabled(bool enable) override; + void InitializeAudioInputHost(AudioInputHost& host) override; private: // ChromeOS does not use auth manager, so we don't yet need to implement a @@ -98,7 +87,6 @@ FakeAuthProvider auth_provider_; FileProviderImpl file_provider_; NetworkProviderImpl network_provider_; - AudioInputHost audio_input_host_; std::unique_ptr<SystemProviderImpl> system_provider_; DISALLOW_COPY_AND_ASSIGN(PlatformApiImpl);
diff --git a/chromeos/services/assistant/public/cpp/migration/BUILD.gn b/chromeos/services/assistant/public/cpp/migration/BUILD.gn index d901cdc..910c427 100644 --- a/chromeos/services/assistant/public/cpp/migration/BUILD.gn +++ b/chromeos/services/assistant/public/cpp/migration/BUILD.gn
@@ -11,6 +11,7 @@ sources = [ "assistant_manager_service_delegate.h", + "audio_input_host.h", "cros_platform_api.h", "libassistant_v1_api.cc", "libassistant_v1_api.h",
diff --git a/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h b/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h index 446616a5..f92b2f2 100644 --- a/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h +++ b/chromeos/services/assistant/public/cpp/migration/assistant_manager_service_delegate.h
@@ -20,6 +20,7 @@ namespace assistant { class AssistantMediaSession; +class AudioInputHost; class CrosPlatformApi; // Interface class that provides factory methods for assistant internal @@ -29,6 +30,8 @@ AssistantManagerServiceDelegate() = default; virtual ~AssistantManagerServiceDelegate() = default; + virtual std::unique_ptr<AudioInputHost> CreateAudioInputHost() = 0; + virtual std::unique_ptr<CrosPlatformApi> CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/chromeos/services/assistant/public/cpp/migration/audio_input_host.h b/chromeos/services/assistant/public/cpp/migration/audio_input_host.h new file mode 100644 index 0000000..2314831 --- /dev/null +++ b/chromeos/services/assistant/public/cpp/migration/audio_input_host.h
@@ -0,0 +1,41 @@ +// Copyright 2021 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 CHROMEOS_SERVICES_ASSISTANT_PUBLIC_CPP_MIGRATION_AUDIO_INPUT_HOST_H_ +#define CHROMEOS_SERVICES_ASSISTANT_PUBLIC_CPP_MIGRATION_AUDIO_INPUT_HOST_H_ + +#include <string> + +#include "base/component_export.h" + +namespace chromeos { +namespace assistant { + +class AudioInputImpl; + +// Class that provides the bridge between the ChromeOS UI thread and the +// Libassistant audio input class. +class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioInputHost { + public: + virtual ~AudioInputHost() = default; + + // Initialize this class by setting the backend that it's supposed to use. + // TODO(b/171748795): Should be gone when the Libassistant V2 migration is + // completed. + virtual void Initialize(AudioInputImpl* audio_input) = 0; + + // Called when the mic state associated with the interaction is changed. + virtual void SetMicState(bool mic_open) = 0; + + // Called when hotword enabled status changed. + virtual void OnHotwordEnabled(bool enable) = 0; + + virtual void OnConversationTurnStarted() = 0; + virtual void OnConversationTurnFinished() = 0; +}; + +} // namespace assistant +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_ASSISTANT_PUBLIC_CPP_MIGRATION_AUDIO_INPUT_HOST_H_
diff --git a/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h b/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h index 409e7a10..41f4ee12 100644 --- a/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h +++ b/chromeos/services/assistant/public/cpp/migration/cros_platform_api.h
@@ -19,6 +19,8 @@ namespace chromeos { namespace assistant { +class AudioInputHost; + // Platform API required by the voice assistant, extended with some methods used // when ChromeOS needs to make changes to the platform state. // Note that this no longer inherits from |assistant_client::PlatformApi|, @@ -29,14 +31,10 @@ CrosPlatformApi() = default; virtual ~CrosPlatformApi() = default; - // Called when the mic state associated with the interaction is changed. - virtual void SetMicState(bool mic_open) = 0; - - virtual void OnConversationTurnStarted() = 0; - virtual void OnConversationTurnFinished() = 0; - - // Called when hotword enabled status changed. - virtual void OnHotwordEnabled(bool enable) = 0; + // Initialize the AudioInputHost. + // TODO(b/171748795): Should be gone when the Libassistant V2 migration is + // completed. + virtual void InitializeAudioInputHost(AudioInputHost&) = 0; // Returns the platform's audio input provider. virtual assistant_client::AudioInputProvider& GetAudioInputProvider() = 0;
diff --git a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc index 4e0a16e..73c9b52 100644 --- a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc +++ b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.cc
@@ -9,10 +9,30 @@ #include "chromeos/assistant/internal/test_support/fake_assistant_manager.h" #include "chromeos/assistant/internal/test_support/fake_assistant_manager_internal.h" #include "chromeos/services/assistant//public/cpp/migration/fake_platform_api.h" +#include "chromeos/services/assistant/public/cpp/migration/audio_input_host.h" namespace chromeos { namespace assistant { +namespace { + +class FakeAudioInputHost : public AudioInputHost { + public: + FakeAudioInputHost() = default; + FakeAudioInputHost(const FakeAudioInputHost&) = delete; + FakeAudioInputHost& operator=(const FakeAudioInputHost&) = delete; + ~FakeAudioInputHost() override = default; + + // AudioInputHost implementation: + void Initialize(AudioInputImpl* audio_input) override {} + void SetMicState(bool mic_open) override {} + void OnHotwordEnabled(bool enable) override {} + void OnConversationTurnStarted() override {} + void OnConversationTurnFinished() override {} +}; + +} // namespace + FakeAssistantManagerServiceDelegate::FakeAssistantManagerServiceDelegate() { // We start by creating a pending assistant manager, as our unittests // might need to access the assistant manager before it is created through @@ -23,6 +43,11 @@ FakeAssistantManagerServiceDelegate::~FakeAssistantManagerServiceDelegate() = default; +std::unique_ptr<AudioInputHost> +FakeAssistantManagerServiceDelegate::CreateAudioInputHost() { + return std::make_unique<FakeAudioInputHost>(); +} + std::unique_ptr<CrosPlatformApi> FakeAssistantManagerServiceDelegate::CreatePlatformApi( AssistantMediaSession* media_session,
diff --git a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h index 1ba87f1e..1adddb28 100644 --- a/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h +++ b/chromeos/services/assistant/public/cpp/migration/fake_assistant_manager_service_delegate.h
@@ -26,6 +26,7 @@ FakeAssistantManager* assistant_manager(); // AssistantManagerServiceDelegate: + std::unique_ptr<AudioInputHost> CreateAudioInputHost() override; std::unique_ptr<CrosPlatformApi> CreatePlatformApi( AssistantMediaSession* media_session, scoped_refptr<base::SingleThreadTaskRunner> background_thread_task_runner)
diff --git a/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h b/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h index 49fde32a..b730a4c 100644 --- a/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h +++ b/chromeos/services/assistant/public/cpp/migration/fake_platform_api.h
@@ -28,10 +28,7 @@ assistant_client::FileProvider& GetFileProvider() override; assistant_client::NetworkProvider& GetNetworkProvider() override; assistant_client::SystemProvider& GetSystemProvider() override; - void SetMicState(bool mic_open) override {} - void OnHotwordEnabled(bool enable) override {} - void OnConversationTurnStarted() override {} - void OnConversationTurnFinished() override {} + void InitializeAudioInputHost(AudioInputHost&) override {} private: DISALLOW_COPY_AND_ASSIGN(FakePlatformApi);
diff --git a/components/crash/content/browser/error_reporting/mock_crash_endpoint.cc b/components/crash/content/browser/error_reporting/mock_crash_endpoint.cc index 64f4490..c9575b2 100644 --- a/components/crash/content/browser/error_reporting/mock_crash_endpoint.cc +++ b/components/crash/content/browser/error_reporting/mock_crash_endpoint.cc
@@ -89,8 +89,8 @@ ++report_count_; last_report_ = Report(absolute_url.query(), request.content); auto http_response = std::make_unique<net::test_server::BasicHttpResponse>(); - http_response->set_code(net::HTTP_OK); - http_response->set_content("123"); + http_response->set_code(response_code_); + http_response->set_content(response_content_); http_response->set_content_type("text/plain"); if (on_report_) { on_report_.Run();
diff --git a/components/crash/content/browser/error_reporting/mock_crash_endpoint.h b/components/crash/content/browser/error_reporting/mock_crash_endpoint.h index 7d0fb98..7f6f85fc 100644 --- a/components/crash/content/browser/error_reporting/mock_crash_endpoint.h +++ b/components/crash/content/browser/error_reporting/mock_crash_endpoint.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/optional.h" +#include "net/http/http_status_code.h" #include "url/gurl.h" namespace net { @@ -51,6 +52,12 @@ // submitting crash reports. void set_consented(bool consented) { consented_ = consented; } + // Set the response that the server will return. + void set_response(net::HttpStatusCode code, const std::string& content) { + response_code_ = code; + response_content_ = content; + } + // Returns the URL that tests should send crash reports to. std::string GetCrashEndpointURL() const; @@ -66,6 +73,8 @@ int report_count_ = 0; bool consented_ = true; base::RepeatingClosure on_report_; + net::HttpStatusCode response_code_ = net::HTTP_OK; + std::string response_content_ = "123"; }; #endif // COMPONENTS_CRASH_CONTENT_BROWSER_ERROR_REPORTING_MOCK_CRASH_ENDPOINT_H_
diff --git a/components/dom_distiller/ios/BUILD.gn b/components/dom_distiller/ios/BUILD.gn index 0bfc6a6c..29c300e 100644 --- a/components/dom_distiller/ios/BUILD.gn +++ b/components/dom_distiller/ios/BUILD.gn
@@ -17,7 +17,6 @@ "//components/dom_distiller/core/proto", "//components/favicon/ios", "//ios/web/public", - "//ios/web/public/deprecated", "//url", ] }
diff --git a/components/dom_distiller/ios/distiller_page_ios.h b/components/dom_distiller/ios/distiller_page_ios.h index c7cfa77..2e28b36 100644 --- a/components/dom_distiller/ios/distiller_page_ios.h +++ b/components/dom_distiller/ios/distiller_page_ios.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_DOM_DISTILLER_IOS_DISTILLER_PAGE_IOS_H_ #define COMPONENTS_DOM_DISTILLER_IOS_DISTILLER_PAGE_IOS_H_ -#include <objc/objc.h> #include <memory> #include <string> @@ -52,7 +51,7 @@ private: // Called once the |script_| has been evaluated on the page. - void HandleJavaScriptResult(id result); + void HandleJavaScriptResult(const base::Value* result); // web::WebStateObserver implementation. void PageLoaded(
diff --git a/components/dom_distiller/ios/distiller_page_ios.mm b/components/dom_distiller/ios/distiller_page_ios.mm index b53503a..4c58f7f 100644 --- a/components/dom_distiller/ios/distiller_page_ios.mm +++ b/components/dom_distiller/ios/distiller_page_ios.mm
@@ -13,12 +13,9 @@ #include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/strings/string_split.h" -#include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "ios/web/public/browser_state.h" -#import "ios/web/public/deprecated/crw_js_injection_manager.h" -#import "ios/web/public/deprecated/crw_js_injection_receiver.h" #import "ios/web/public/navigation/navigation_manager.h" #import "ios/web/public/navigation/web_state_policy_decider.h" #import "ios/web/public/web_state.h" @@ -40,11 +37,13 @@ int const kMaximumParsingRecursionDepth = 6; -// Converts result of WKWebView script evaluation to base::Value, parsing -// |wk_result| up to a depth of |max_depth|. -base::Value ValueResultFromScriptResult(id wk_result, int max_depth) { +// Returns a clone of |value| where double values are converted to integers if +// the numbers has no fraction. |value| is only processed up to |max_depth|. +base::Value ConvertedResultFromScriptResult(const base::Value* value, + int max_depth) { base::Value result; - if (!wk_result) { + if (!value || value->is_none()) { + DCHECK_EQ(result.type(), base::Value::Type::NONE); return result; } @@ -53,52 +52,48 @@ return result; } - CFTypeID result_type = CFGetTypeID(reinterpret_cast<CFTypeRef>(wk_result)); - if (result_type == CFStringGetTypeID()) { - result = base::Value(base::SysNSStringToUTF8(wk_result)); + if (value->is_string()) { + result = base::Value(value->GetString()); DCHECK_EQ(result.type(), base::Value::Type::STRING); - } else if (result_type == CFNumberGetTypeID()) { + } else if (value->is_double()) { // Different implementation is here. - if ([wk_result intValue] != [wk_result doubleValue]) { - result = base::Value([wk_result doubleValue]); - DCHECK_EQ(result.type(), base::Value::Type::DOUBLE); - } else { - result = base::Value([wk_result intValue]); + double double_value = value->GetDouble(); + int int_value = round(double_value); + if (double_value == int_value) { + result = base::Value(int_value); DCHECK_EQ(result.type(), base::Value::Type::INTEGER); + } else { + result = base::Value(double_value); + DCHECK_EQ(result.type(), base::Value::Type::DOUBLE); } // End of different implementation. - } else if (result_type == CFBooleanGetTypeID()) { - result = base::Value(static_cast<bool>([wk_result boolValue])); + } else if (value->is_bool()) { + result = base::Value(value); DCHECK_EQ(result.type(), base::Value::Type::BOOLEAN); - } else if (result_type == CFNullGetTypeID()) { - DCHECK_EQ(result.type(), base::Value::Type::NONE); - } else if (result_type == CFDictionaryGetTypeID()) { + } else if (value->is_dict()) { base::Value dictionary(base::Value::Type::DICTIONARY); - for (id key in wk_result) { - NSString* obj_c_string = base::mac::ObjCCast<NSString>(key); - base::Value value = - ValueResultFromScriptResult(wk_result[obj_c_string], max_depth - 1); + for (const auto kv : value->DictItems()) { + base::Value item_value = + ConvertedResultFromScriptResult(&kv.second, max_depth - 1); - if (value.type() == base::Value::Type::NONE) { + if (item_value.type() == base::Value::Type::NONE) { return result; } - - std::string combined_path = base::SysNSStringToUTF8(obj_c_string); - std::vector<base::StringPiece> path = base::SplitStringPiece( - combined_path, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); - dictionary.SetPath(path, std::move(value)); + dictionary.SetPath(kv.first, std::move(item_value)); } result = std::move(dictionary); DCHECK_EQ(result.type(), base::Value::Type::DICTIONARY); - } else if (result_type == CFArrayGetTypeID()) { + + } else if (value->is_list()) { std::vector<base::Value> list; - for (id list_item in wk_result) { - base::Value value = ValueResultFromScriptResult(list_item, max_depth - 1); - if (value.type() == base::Value::Type::NONE) { + for (const base::Value& list_item : value->GetList()) { + base::Value converted_item = + ConvertedResultFromScriptResult(&list_item, max_depth - 1); + if (converted_item.type() == base::Value::Type::NONE) { return result; } - list.push_back(std::move(value)); + list.push_back(std::move(converted_item)); } result = base::Value(list); DCHECK_EQ(result.type(), base::Value::Type::LIST); @@ -214,19 +209,14 @@ } // Inject the script. base::WeakPtr<DistillerPageIOS> weak_this = weak_ptr_factory_.GetWeakPtr(); - [[web_state_->GetJSInjectionReceiver() - instanceOfClass:[CRWJSInjectionManager class]] - executeJavaScript:base::SysUTF8ToNSString(script_) - completionHandler:^(id result, NSError* error) { - DistillerPageIOS* distiller_page = weak_this.get(); - if (distiller_page) - distiller_page->HandleJavaScriptResult(result); - }]; + web_state_->ExecuteJavaScript( + base::UTF8ToUTF16(script_), + base::BindOnce(&DistillerPageIOS::HandleJavaScriptResult, weak_this)); } -void DistillerPageIOS::HandleJavaScriptResult(id result) { +void DistillerPageIOS::HandleJavaScriptResult(const base::Value* result) { base::Value result_as_value = - ValueResultFromScriptResult(result, kMaximumParsingRecursionDepth); + ConvertedResultFromScriptResult(result, kMaximumParsingRecursionDepth); OnDistillationDone(url_, &result_as_value); }
diff --git a/components/domain_reliability/quic_error_mapping.cc b/components/domain_reliability/quic_error_mapping.cc index bff8a2e4..57ff62e 100644 --- a/components/domain_reliability/quic_error_mapping.cc +++ b/components/domain_reliability/quic_error_mapping.cc
@@ -434,6 +434,8 @@ {quic::QUIC_INVALID_0RTT_PACKET_NUMBER_OUT_OF_ORDER, "quic.quic_invalid_0rtt_packet_number_out_of_order"}, {quic::QUIC_INVALID_PRIORITY_UPDATE, "quic::quic_invalid_priority_update"}, + {quic::QUIC_PEER_PORT_CHANGE_HANDSHAKE_UNCONFIRMED, + "quic.peer_port_change_handshake_unconfirmed"}, // No error. Used as bound while iterating. {quic::QUIC_LAST_ERROR, "quic.last_error"}};
diff --git a/components/embedder_support/android/metrics/android_metrics_service_client.cc b/components/embedder_support/android/metrics/android_metrics_service_client.cc index 1b108cbe6..ce00e9f 100644 --- a/components/embedder_support/android/metrics/android_metrics_service_client.cc +++ b/components/embedder_support/android/metrics/android_metrics_service_client.cc
@@ -464,7 +464,7 @@ } std::string AndroidMetricsServiceClient::GetVersionString() { - return version_info::GetVersionNumber(); + return metrics::GetVersionString(); } void AndroidMetricsServiceClient::CollectFinalMetricsForLog(
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java index 34e01d6..bf7134d 100644 --- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java +++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
@@ -67,6 +67,7 @@ String READ_LATER_CONTEXT_MENU_FEATURE = "IPH_ReadLaterContextMenu"; String READ_LATER_APP_MENU_BOOKMARK_THIS_PAGE_FEATURE = "IPH_ReadLaterAppMenuBookmarkThisPage"; String READ_LATER_APP_MENU_BOOKMARKS_FEATURE = "IPH_ReadLaterAppMenuBookmarks"; + String READ_LATER_BOTTOM_SHEET_FEATURE = "IPH_ReadLaterBottomSheet"; /** * An IPH feature that encourages users to get better translations by enabling access to page
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc index 9050024..fde7586 100644 --- a/components/feature_engagement/public/feature_constants.cc +++ b/components/feature_engagement/public/feature_constants.cc
@@ -81,6 +81,8 @@ "IPH_ReadLaterAppMenuBookmarkThisPage", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHReadLaterAppMenuBookmarksFeature{ "IPH_ReadLaterAppMenuBookmarks", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kIPHReadLaterBottomSheetFeature{ + "IPH_ReadLaterBottomSheet", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kIPHEphemeralTabFeature{"IPH_EphemeralTab", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kIPHFeedCardMenuFeature{"IPH_FeedCardMenu",
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h index 139b5dc7..c6bc56f2 100644 --- a/components/feature_engagement/public/feature_constants.h +++ b/components/feature_engagement/public/feature_constants.h
@@ -68,6 +68,7 @@ extern const base::Feature kIPHReadLaterContextMenuFeature; extern const base::Feature kIPHReadLaterAppMenuBookmarkThisPageFeature; extern const base::Feature kIPHReadLaterAppMenuBookmarksFeature; +extern const base::Feature kIPHReadLaterBottomSheetFeature; extern const base::Feature kIPHTabGroupsQuicklyComparePagesFeature; extern const base::Feature kIPHTabGroupsTapToSeeAnotherTabFeature; extern const base::Feature kIPHTabGroupsYourTabsAreTogetherFeature;
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc index 5580aeb..7b2f29d 100644 --- a/components/feature_engagement/public/feature_list.cc +++ b/components/feature_engagement/public/feature_list.cc
@@ -52,6 +52,7 @@ &kIPHReadLaterContextMenuFeature, &kIPHReadLaterAppMenuBookmarkThisPageFeature, &kIPHReadLaterAppMenuBookmarksFeature, + &kIPHReadLaterBottomSheetFeature, &kIPHTabGroupsQuicklyComparePagesFeature, &kIPHTabGroupsTapToSeeAnotherTabFeature, &kIPHTabGroupsYourTabsAreTogetherFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h index bc3e77f9..38fb616 100644 --- a/components/feature_engagement/public/feature_list.h +++ b/components/feature_engagement/public/feature_list.h
@@ -105,6 +105,8 @@ "IPH_ReadLaterAppMenuBookmarkThisPage"); DEFINE_VARIATION_PARAM(kIPHReadLaterAppMenuBookmarksFeature, "IPH_ReadLaterAppMenuBookmarks"); +DEFINE_VARIATION_PARAM(kIPHReadLaterBottomSheetFeature, + "IPH_ReadLaterBottomSheet"); DEFINE_VARIATION_PARAM(kIPHTabGroupsQuicklyComparePagesFeature, "IPH_TabGroupsQuicklyComparePages"); DEFINE_VARIATION_PARAM(kIPHTabGroupsTapToSeeAnotherTabFeature, @@ -201,6 +203,7 @@ VARIATION_ENTRY(kIPHReadLaterContextMenuFeature), VARIATION_ENTRY(kIPHReadLaterAppMenuBookmarkThisPageFeature), VARIATION_ENTRY(kIPHReadLaterAppMenuBookmarksFeature), + VARIATION_ENTRY(kIPHReadLaterBottomSheetFeature), VARIATION_ENTRY(kIPHTabGroupsQuicklyComparePagesFeature), VARIATION_ENTRY(kIPHTabGroupsTapToSeeAnotherTabFeature), VARIATION_ENTRY(kIPHTabGroupsYourTabsAreTogetherFeature),
diff --git a/components/feed/core/proto/BUILD.gn b/components/feed/core/proto/BUILD.gn index 3221e2c..9244b9ae 100644 --- a/components/feed/core/proto/BUILD.gn +++ b/components/feed/core/proto/BUILD.gn
@@ -23,7 +23,6 @@ #UNUSED_IN_CHROME "v2/wire/in_place_update_handle.proto", #UNUSED_IN_CHROME "v2/wire/response_status_code.proto", #UNUSED_IN_CHROME "v2/wire/templates.proto", - "v2/keyvalue_store.proto", "v2/packing.proto", "v2/store.proto", "v2/ui.proto",
diff --git a/components/feed/core/proto/v2/keyvalue_store.proto b/components/feed/core/proto/v2/keyvalue_store.proto deleted file mode 100644 index 7bdfbe4..0000000 --- a/components/feed/core/proto/v2/keyvalue_store.proto +++ /dev/null
@@ -1,15 +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. - -syntax = "proto3"; - -package feedkvstore; - -option optimize_for = LITE_RUNTIME; - -message Entry { - bytes value = 1; - // Unix timetamp in milliseconds. - int64 modification_time = 2; -}
diff --git a/components/feed/core/v2/BUILD.gn b/components/feed/core/v2/BUILD.gn index d8bde6d..9fb5329a 100644 --- a/components/feed/core/v2/BUILD.gn +++ b/components/feed/core/v2/BUILD.gn
@@ -31,8 +31,6 @@ "notice_card_tracker.h", "offline_page_spy.cc", "offline_page_spy.h", - "persistent_key_value_store_impl.cc", - "persistent_key_value_store_impl.h", "prefs.cc", "prefs.h", "proto_util.cc", @@ -43,8 +41,6 @@ "public/feed_service.h", "public/feed_stream_api.cc", "public/feed_stream_api.h", - "public/persistent_key_value_store.cc", - "public/persistent_key_value_store.h", "public/types.h", "refresh_task_scheduler.h", "request_throttler.cc", @@ -121,14 +117,12 @@ "image_fetcher_unittest.cc", "metrics_reporter_unittest.cc", "notice_card_tracker_unittest.cc", - "persistent_key_value_store_impl_unittest.cc", "proto_util_unittest.cc", "protocol_translator_unittest.cc", "public/feed_service_unittest.cc", "request_throttler_unittest.cc", "scheduling_unittest.cc", "stream_model_unittest.cc", - "test/callback_receiver.cc", "test/callback_receiver.h", "test/callback_receiver_unittest.cc", "test/proto_printer.cc",
diff --git a/components/feed/core/v2/config.h b/components/feed/core/v2/config.h index 025b287..1eb0d61 100644 --- a/components/feed/core/v2/config.h +++ b/components/feed/core/v2/config.h
@@ -44,14 +44,6 @@ base::TimeDelta session_id_max_age = base::TimeDelta::FromDays(30); // Maximum number of images prefetched per refresh. int max_prefetch_image_requests_per_refresh = 50; - - // Configuration for `PersistentKeyValueStore`. - - // Maximum total database size before items are evicted. - int64_t persistent_kv_store_maximum_size_before_eviction = 1000000; - // Eviction task is performed after this many bytes are written. - int persistent_kv_store_cleanup_interval_in_written_bytes = 1000000; - // Set of optional capabilities included in requests. See // CreateFeedQueryRequest() for required capabilities. base::flat_set<feedwire::Capability> experimental_capabilities = {
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc index cc73904..15e3d41 100644 --- a/components/feed/core/v2/feed_stream.cc +++ b/components/feed/core/v2/feed_stream.cc
@@ -168,7 +168,6 @@ FeedNetwork* feed_network, ImageFetcher* image_fetcher, FeedStore* feed_store, - PersistentKeyValueStoreImpl* persistent_key_value_store, offline_pages::PrefetchService* prefetch_service, offline_pages::OfflinePageModel* offline_page_model, const ChromeInfo& chrome_info) @@ -180,7 +179,6 @@ feed_network_(feed_network), image_fetcher_(image_fetcher), store_(feed_store), - persistent_key_value_store_(persistent_key_value_store), chrome_info_(chrome_info), task_queue_(this), request_throttler_(profile_prefs), @@ -729,10 +727,6 @@ return image_fetcher_->Fetch(url, std::move(callback)); } -PersistentKeyValueStoreImpl* FeedStream::GetPersistentKeyValueStore() { - return persistent_key_value_store_; -} - void FeedStream::CancelImageFetch(ImageFetchId id) { image_fetcher_->Cancel(id); }
diff --git a/components/feed/core/v2/feed_stream.h b/components/feed/core/v2/feed_stream.h index e40d7a9..1a269812 100644 --- a/components/feed/core/v2/feed_stream.h +++ b/components/feed/core/v2/feed_stream.h
@@ -20,7 +20,6 @@ #include "components/feed/core/proto/v2/wire/response.pb.h" #include "components/feed/core/v2/enums.h" #include "components/feed/core/v2/notice_card_tracker.h" -#include "components/feed/core/v2/persistent_key_value_store_impl.h" #include "components/feed/core/v2/protocol_translator.h" #include "components/feed/core/v2/public/feed_stream_api.h" #include "components/feed/core/v2/request_throttler.h" @@ -45,7 +44,6 @@ class MetricsReporter; class OfflinePageSpy; class RefreshTaskScheduler; -class PersistentKeyValueStoreImpl; class StreamModel; class SurfaceUpdater; struct StreamModelUpdateRequest; @@ -112,7 +110,6 @@ FeedNetwork* feed_network, ImageFetcher* image_fetcher, FeedStore* feed_store, - PersistentKeyValueStoreImpl* persistent_key_value_store, offline_pages::PrefetchService* prefetch_service, offline_pages::OfflinePageModel* offline_page_model, const ChromeInfo& chrome_info); @@ -138,7 +135,6 @@ const GURL& url, base::OnceCallback<void(NetworkResponse)> callback) override; void CancelImageFetch(ImageFetchId id) override; - PersistentKeyValueStoreImpl* GetPersistentKeyValueStore() override; void LoadMore(SurfaceId surface_id, base::OnceCallback<void(bool)> callback) override; void ExecuteOperations( @@ -331,7 +327,6 @@ FeedNetwork* feed_network_; ImageFetcher* image_fetcher_; FeedStore* store_; - PersistentKeyValueStoreImpl* persistent_key_value_store_; const WireResponseTranslator* wire_response_translator_; ChromeInfo chrome_info_;
diff --git a/components/feed/core/v2/feed_stream_unittest.cc b/components/feed/core/v2/feed_stream_unittest.cc index ccb9683a..78cbb826 100644 --- a/components/feed/core/v2/feed_stream_unittest.cc +++ b/components/feed/core/v2/feed_stream_unittest.cc
@@ -26,7 +26,6 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/clock.h" #include "components/feed/core/common/pref_names.h" -#include "components/feed/core/proto/v2/keyvalue_store.pb.h" #include "components/feed/core/proto/v2/store.pb.h" #include "components/feed/core/proto/v2/ui.pb.h" #include "components/feed/core/proto/v2/wire/chrome_client_info.pb.h" @@ -38,10 +37,8 @@ #include "components/feed/core/v2/feed_network.h" #include "components/feed/core/v2/image_fetcher.h" #include "components/feed/core/v2/metrics_reporter.h" -#include "components/feed/core/v2/persistent_key_value_store_impl.h" #include "components/feed/core/v2/prefs.h" #include "components/feed/core/v2/protocol_translator.h" -#include "components/feed/core/v2/public/persistent_key_value_store.h" #include "components/feed/core/v2/refresh_task_scheduler.h" #include "components/feed/core/v2/scheduling.h" #include "components/feed/core/v2/stream_model.h" @@ -596,9 +593,8 @@ // Ensure the task queue can return to idle. Failure to do so may be due // to a stuck task that never called |TaskComplete()|. WaitForIdleTaskQueue(); - // ProtoDatabase requires PostTask to clean up. + // Store requires PostTask to clean up. store_.reset(); - persistent_key_value_store_.reset(); task_environment_.RunUntilIdle(); } @@ -629,8 +625,7 @@ chrome_info.version = base::Version({99, 1, 9911, 2}); stream_ = std::make_unique<FeedStream>( &refresh_scheduler_, metrics_reporter_.get(), this, &profile_prefs_, - &network_, image_fetcher_.get(), store_.get(), - persistent_key_value_store_.get(), &prefetch_service_, + &network_, image_fetcher_.get(), store_.get(), &prefetch_service_, &offline_page_model_, chrome_info); WaitForIdleTaskQueue(); // Wait for any initialization. @@ -699,16 +694,8 @@ std::unique_ptr<FeedStore> store_ = std::make_unique<FeedStore>( leveldb_proto::ProtoDatabaseProvider::GetUniqueDB<feedstore::Record>( leveldb_proto::ProtoDbType::FEED_STREAM_DATABASE, - /*db_dir=*/{}, + /*file_path=*/{}, task_environment_.GetMainThreadTaskRunner())); - - std::unique_ptr<PersistentKeyValueStoreImpl> persistent_key_value_store_ = - std::make_unique<PersistentKeyValueStoreImpl>( - leveldb_proto::ProtoDatabaseProvider::GetUniqueDB<feedkvstore::Entry>( - leveldb_proto::ProtoDbType::FEED_KEY_VALUE_DATABASE, - /*db_dir=*/{}, - task_environment_.GetMainThreadTaskRunner())); - FakeRefreshTaskScheduler refresh_scheduler_; TestPrefetchService prefetch_service_; TestOfflinePageModel offline_page_model_; @@ -2802,22 +2789,5 @@ EXPECT_TIME_EQ(kExpiryTime, stream_->GetMetadata()->GetSessionIdExpiryTime()); } -TEST_F(FeedStreamTest, PersistentKeyValueStoreIsClearedOnClearAll) { - // Store some data and verify it exists. - PersistentKeyValueStore* store = stream_->GetPersistentKeyValueStore(); - store->Put("x", "y", base::DoNothing()); - CallbackReceiver<PersistentKeyValueStore::Result> get_result; - store->Get("x", get_result.Bind()); - ASSERT_EQ("y", *get_result.RunAndGetResult().get_result); - - stream_->OnCacheDataCleared(); // triggers ClearAll(). - WaitForIdleTaskQueue(); - - // Verify ClearAll() deleted the data. - get_result.Clear(); - store->Get("x", get_result.Bind()); - EXPECT_FALSE(get_result.RunAndGetResult().get_result); -} - } // namespace } // namespace feed
diff --git a/components/feed/core/v2/persistent_key_value_store_impl.cc b/components/feed/core/v2/persistent_key_value_store_impl.cc deleted file mode 100644 index 7be37daf..0000000 --- a/components/feed/core/v2/persistent_key_value_store_impl.cc +++ /dev/null
@@ -1,325 +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/feed/core/v2/persistent_key_value_store_impl.h" - -#include <vector> - -#include "base/bind.h" -#include "base/rand_util.h" -#include "base/time/time.h" -#include "components/feed/core/proto/v2/keyvalue_store.pb.h" -#include "components/feed/core/v2/config.h" -#include "components/offline_pages/task/task.h" - -namespace feed { -namespace { -using ::feed::internal::kMaxEntriesInMemory; -using feedkvstore::Entry; -} // namespace - -// Eviction task functionality. -class EvictTask { - public: - static void Start(base::WeakPtr<PersistentKeyValueStoreImpl> store, - base::OnceCallback<void(bool)> done_callback) { - auto state = std::make_unique<State>(); - state->store = store; - state->done_callback = std::move(done_callback); - - auto* db = GetDbOrFinish(state); - if (!db) - return; - db->LoadKeys(base::BindOnce(&EvictTask::LoadKeysDone, std::move(state))); - } - - private: - struct EntryMetadata { - std::string key; - int64_t size_bytes; - int64_t modification_time; - }; - - struct State { - base::WeakPtr<PersistentKeyValueStoreImpl> store; - base::OnceCallback<void(bool)> done_callback; - - std::vector<std::string> all_keys; - size_t next_key_index = 0; - std::vector<EntryMetadata> metadata; - }; - - static void Finish(std::unique_ptr<State> state) { - std::move(state->done_callback).Run(true); - } - - static leveldb_proto::ProtoDatabase<Entry>* GetDbOrFinish( - std::unique_ptr<State>& state) { - if (state->store) { - return state->store->GetDatabase(); - } - Finish(std::move(state)); - return nullptr; - } - - static void IndexMore(std::unique_ptr<State> state) { - auto* db = GetDbOrFinish(state); - if (!db) - return; - if (state->next_key_index >= state->all_keys.size()) { - IndexingDone(std::move(state)); - return; - } - const size_t first_index = state->next_key_index; - std::string last_key; - state->next_key_index = std::min( - state->next_key_index + kMaxEntriesInMemory, state->all_keys.size()); - - std::string lower_bound = state->all_keys[first_index], - upper_bound = state->all_keys[state->next_key_index - 1]; - db->LoadKeysAndEntriesInRange( - lower_bound, upper_bound, - base::BindOnce(&EvictTask::IndexMore_LoadChunkDone, std::move(state))); - } - - static void IndexMore_LoadChunkDone( - std::unique_ptr<State> state, - bool ok, - std::unique_ptr<std::map<std::string, feedkvstore::Entry>> entries) { - const int64_t now = - base::Time::Now().ToDeltaSinceWindowsEpoch().InMilliseconds(); - for (auto& entry : *entries) { - EntryMetadata m; - m.key = entry.first; - m.modification_time = entry.second.modification_time(); - // If modification time is in the future, assume the information is out - // of date. - if (m.modification_time > now) - m.modification_time = 0; - m.size_bytes = entry.second.value().size(); - state->metadata.push_back(m); - } - IndexMore(std::move(state)); - } - - static void LoadKeysDone(std::unique_ptr<State> state, - bool ok, - std::unique_ptr<std::vector<std::string>> keys) { - if (!ok || !keys) { - Finish(std::move(state)); - return; - } - state->all_keys = std::move(*keys); - IndexMore(std::move(state)); - } - - static void IndexingDone(std::unique_ptr<State> state) { - auto* db = GetDbOrFinish(state); - if (!db) - return; - std::sort(state->metadata.begin(), state->metadata.end(), - [&](const EntryMetadata& a, const EntryMetadata& b) { - return a.modification_time > b.modification_time; - }); - - size_t i = 0; - int64_t total_size = 0; - const int64_t max_db_size_bytes = - GetFeedConfig().persistent_kv_store_maximum_size_before_eviction; - for (; i < state->metadata.size(); ++i) { - total_size += state->metadata[i].size_bytes; - if (total_size > max_db_size_bytes) { - break; - } - } - - auto keys_to_remove = std::make_unique<std::vector<std::string>>(); - for (; i < state->metadata.size(); ++i) { - keys_to_remove->push_back(state->metadata[i].key); - } - - db->UpdateEntries( - std::make_unique<std::vector<std::pair<std::string, Entry>>>(), - std::move(keys_to_remove), - base::BindOnce([](std::unique_ptr<State> state, - bool ok) { Finish(std::move(state)); }, - std::move(state))); - } -}; - -PersistentKeyValueStoreImpl::Task::Task() = default; -PersistentKeyValueStoreImpl::Task::Task(TaskType task_type, - ResultCallback callback) - : Task(task_type, std::string(), std::move(callback)) {} -PersistentKeyValueStoreImpl::Task::Task(TaskType task_type, - std::string key, - ResultCallback callback) - : type(task_type), key(key), done_callback(std::move(callback)) {} -PersistentKeyValueStoreImpl::Task::Task(Task&&) noexcept = default; -PersistentKeyValueStoreImpl::Task::~Task() = default; - -PersistentKeyValueStoreImpl::PersistentKeyValueStoreImpl( - std::unique_ptr<leveldb_proto::ProtoDatabase<feedkvstore::Entry>> database) - : database_(std::move(database)) {} - -PersistentKeyValueStoreImpl::~PersistentKeyValueStoreImpl() = default; - -void PersistentKeyValueStoreImpl::OnDatabaseInitialized( - leveldb_proto::Enums::InitStatus status) { - database_status_ = status; - TaskComplete({}, {}); -} - -bool PersistentKeyValueStoreImpl::IsInitialized() const { - return database_status_ == leveldb_proto::Enums::InitStatus::kOK; -} - -void PersistentKeyValueStoreImpl::AddTask(Task task) { - if (!triggered_initialize_) { - triggered_initialize_ = true; - running_task_ = true; - database_->Init(base::BindOnce( - &PersistentKeyValueStoreImpl::OnDatabaseInitialized, GetWeakPtr())); - } - if (!running_task_) { - StartTask(std::move(task)); - } else { - queued_tasks_.push(std::move(task)); - } -} - -void PersistentKeyValueStoreImpl::ClearAll(ResultCallback callback) { - AddTask({TaskType::kClearAll, std::move(callback)}); -} - -void PersistentKeyValueStoreImpl::Put(const std::string& key, - const std::string& value, - ResultCallback callback) { - // Use a random number to trigger EvictOldEntries(). - // The expected number of calls to EvictOldEntries() is =~ - // (sum of bytes written) / `cleanup_interval_in_written_bytes`. - int cleanup_interval_in_written_bytes = - GetFeedConfig().persistent_kv_store_cleanup_interval_in_written_bytes; - int rand_int = base::RandInt(0, cleanup_interval_in_written_bytes); - if (cleanup_interval_in_written_bytes > 0 && - rand_int < static_cast<int>(value.size())) { - EvictOldEntries(base::DoNothing()); - } - Task task(TaskType::kPut, key, std::move(callback)); - task.put_value = value; - AddTask(std::move(task)); -} - -void PersistentKeyValueStoreImpl::Get(const std::string& key, - ResultCallback callback) { - AddTask({TaskType::kGet, key, std::move(callback)}); -} - -void PersistentKeyValueStoreImpl::Delete(const std::string& key, - ResultCallback callback) { - AddTask({TaskType::kDelete, key, std::move(callback)}); -} - -void PersistentKeyValueStoreImpl::EvictOldEntries(ResultCallback callback) { - AddTask({TaskType::kEvictOldEntries, std::move(callback)}); -} - -void PersistentKeyValueStoreImpl::StartTask(Task task) { - if (!IsInitialized()) { - TaskComplete(std::move(task), {}); - return; - } - running_task_ = true; - - switch (task.type) { - case TaskType::kGet: { - std::string key = std::move(task.key); - database_->GetEntry(key, - base::BindOnce(&PersistentKeyValueStoreImpl::GetDone, - GetWeakPtr(), std::move(task))); - break; - } - case TaskType::kPut: { - auto entries_to_save = std::make_unique< - leveldb_proto::ProtoDatabase<feedkvstore::Entry>::KeyEntryVector>(); - { - feedkvstore::Entry new_entry; - new_entry.set_value(std::move(task.put_value)); - new_entry.set_modification_time( - base::Time::Now().ToDeltaSinceWindowsEpoch().InMilliseconds()); - entries_to_save->emplace_back(task.key, std::move(new_entry)); - } - database_->UpdateEntries( - std::move(entries_to_save), - /*keys_to_remove=*/std::make_unique<std::vector<std::string>>(), - base::BindOnce(&PersistentKeyValueStoreImpl::TaskCompleteBool, - GetWeakPtr(), std::move(task))); - break; - } - case TaskType::kDelete: { - auto keys_to_remove = std::make_unique<std::vector<std::string>>(); - keys_to_remove->push_back(task.key); - database_->UpdateEntries( - std::make_unique<std::vector<std::pair<std::string, Entry>>>(), - std::move(keys_to_remove), - base::BindOnce(&PersistentKeyValueStoreImpl::TaskCompleteBool, - GetWeakPtr(), std::move(task))); - break; - } - case TaskType::kClearAll: { - auto filter = [](const std::string& key) { return true; }; - database_->UpdateEntriesWithRemoveFilter( - std::make_unique< - std::vector<std::pair<std::string, feedkvstore::Entry>>>(), - base::BindRepeating(filter), - base::BindOnce(&PersistentKeyValueStoreImpl::TaskCompleteBool, - GetWeakPtr(), std::move(task))); - break; - } - case TaskType::kEvictOldEntries: { - EvictTask::Start( - GetWeakPtr(), - base::BindOnce(&PersistentKeyValueStoreImpl::TaskCompleteBool, - GetWeakPtr(), std::move(task))); - break; - } - } -} - -void PersistentKeyValueStoreImpl::GetDone( - Task task, - bool ok, - std::unique_ptr<feedkvstore::Entry> get_entry) { - Result result; - if (ok && get_entry) { - result.success = true; - result.get_result = std::move(get_entry->value()); - } else { - result.success = ok; - } - TaskComplete(std::move(task), std::move(result)); -} - -void PersistentKeyValueStoreImpl::TaskComplete(Task complete_task, - Result result) { - if (complete_task.done_callback) { - std::move(complete_task.done_callback).Run(std::move(result)); - } - if (queued_tasks_.empty()) { - running_task_ = false; - return; - } - Task new_task = std::move(queued_tasks_.front()); - queued_tasks_.pop(); - StartTask(std::move(new_task)); -} - -void PersistentKeyValueStoreImpl::TaskCompleteBool(Task complete_task, - bool ok) { - Result result; - result.success = ok; - return TaskComplete(std::move(complete_task), std::move(result)); -} - -} // namespace feed
diff --git a/components/feed/core/v2/persistent_key_value_store_impl.h b/components/feed/core/v2/persistent_key_value_store_impl.h deleted file mode 100644 index 520b760..0000000 --- a/components/feed/core/v2/persistent_key_value_store_impl.h +++ /dev/null
@@ -1,115 +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_FEED_CORE_V2_PERSISTENT_KEY_VALUE_STORE_IMPL_H_ -#define COMPONENTS_FEED_CORE_V2_PERSISTENT_KEY_VALUE_STORE_IMPL_H_ - -#include <list> -#include <memory> -#include <string> - -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "components/feed/core/v2/public/persistent_key_value_store.h" -#include "components/leveldb_proto/public/proto_database.h" -#include "components/leveldb_proto/public/proto_database_provider.h" -#include "components/offline_pages/task/task_queue.h" - -namespace feedkvstore { -class Entry; -} -namespace feed { -namespace internal { -constexpr int kMaxEntriesInMemory = 50; -} // namespace internal - -// A generic persistent key-value cache. Has a maximum size determined by -// `feed::Config`. Once size of all values exceed the maximum, older keys -// are eventually evicted. Key age is determined only by the last call to -// `Put()`. -class PersistentKeyValueStoreImpl : public PersistentKeyValueStore { - public: - using Result = PersistentKeyValueStore::Result; - using ResultCallback = base::OnceCallback<void(Result)>; - - explicit PersistentKeyValueStoreImpl( - std::unique_ptr<leveldb_proto::ProtoDatabase<feedkvstore::Entry>> - database); - ~PersistentKeyValueStoreImpl() override; - PersistentKeyValueStoreImpl(const PersistentKeyValueStoreImpl&) = delete; - PersistentKeyValueStoreImpl& operator=(const PersistentKeyValueStoreImpl&) = - delete; - - // PersistentKeyValueStore methods. - - // Erase all data in the store. - void ClearAll(ResultCallback callback) override; - // Write/overwrite a key/value pair. - void Put(const std::string& key, - const std::string& value, - ResultCallback callback) override; - // Get a value by key. - void Get(const std::string& key, ResultCallback callback) override; - // Delete a value by key. - void Delete(const std::string& key, ResultCallback callback) override; - - // Evict old stored entries until total size of all values in the database - // is less than max_db_size_bytes. - void EvictOldEntries(ResultCallback callback); - - leveldb_proto::ProtoDatabase<feedkvstore::Entry>* GetDatabase() { - return database_.get(); - } - - base::WeakPtr<PersistentKeyValueStoreImpl> GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - bool IsTaskRunningForTesting() const { return running_task_; } - - private: - enum class TaskType { kGet, kPut, kDelete, kClearAll, kEvictOldEntries }; - // Represents any operation on the database. Allows us to easily perform lazy - // initialization, and serialize db operations. - struct Task { - Task(); - Task(TaskType type, ResultCallback callback); - Task(TaskType type, std::string key, ResultCallback callback); - Task(Task&&) noexcept; - Task(const Task&) = delete; - Task& operator=(const Task&) = delete; - ~Task(); - - TaskType type; - // Key for kGet, kPut, and kDelete. - std::string key; - // Value for kPut. - std::string put_value; - ResultCallback done_callback; - }; - - void AddTask(Task task); - // Implementation functions for potentially queueable actions. - void StartTask(Task task); - - void GetDone(Task task, bool ok, std::unique_ptr<feedkvstore::Entry> entry); - void OnDatabaseInitialized(leveldb_proto::Enums::InitStatus status); - void TaskComplete(Task task, Result result); - void TaskCompleteBool(Task task, bool ok); - - bool IsInitialized() const; - - bool running_task_ = false; - base::queue<Task> queued_tasks_; - bool triggered_initialize_ = false; - leveldb_proto::Enums::InitStatus database_status_ = - leveldb_proto::Enums::InitStatus::kNotInitialized; - std::unique_ptr<leveldb_proto::ProtoDatabase<feedkvstore::Entry>> database_; - base::WeakPtrFactory<PersistentKeyValueStoreImpl> weak_ptr_factory_{this}; -}; - -} // namespace feed - -#endif // COMPONENTS_FEED_CORE_V2_PERSISTENT_KEY_VALUE_STORE_IMPL_H_
diff --git a/components/feed/core/v2/persistent_key_value_store_impl_unittest.cc b/components/feed/core/v2/persistent_key_value_store_impl_unittest.cc deleted file mode 100644 index 2f9b3a4..0000000 --- a/components/feed/core/v2/persistent_key_value_store_impl_unittest.cc +++ /dev/null
@@ -1,411 +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/feed/core/v2/persistent_key_value_store_impl.h" - -#include <map> -#include <set> -#include <utility> - -#include "base/hash/hash.h" -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/test/bind.h" -#include "base/test/task_environment.h" -#include "components/feed/core/proto/v2/keyvalue_store.pb.h" -#include "components/feed/core/v2/config.h" -#include "components/feed/core/v2/public/persistent_key_value_store.h" -#include "components/feed/core/v2/test/callback_receiver.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace feed { -namespace { -using ::feed::internal::kMaxEntriesInMemory; - -int hash_int(int v) { - return static_cast<int>(base::PersistentHash(base::NumberToString(v))); -} - -class PersistentKeyValueStoreTest : public testing::Test { - public: - void SetUp() override { - // Disable automatic cleanup for deterministic testing. - Config config = GetFeedConfig(); - config.persistent_kv_store_cleanup_interval_in_written_bytes = 0; - SetFeedConfigForTesting(config); - MakeStore(); - } - - void TearDown() override { - if (store_) { - ASSERT_FALSE(store_->IsTaskRunningForTesting()); - } - // ProtoDatabase requires PostTask to clean up. - store_.reset(); - base::RunLoop().RunUntilIdle(); - } - - protected: - void MakeStore() { - store_ = std::make_unique<PersistentKeyValueStoreImpl>( - leveldb_proto::ProtoDatabaseProvider::GetUniqueDB<feedkvstore::Entry>( - leveldb_proto::ProtoDbType::FEED_STREAM_DATABASE, - /*db_dir=*/{}, task_environment_.GetMainThreadTaskRunner())); - } - - void SetMaxSizeBeforeEviction(int size_in_bytes) { - Config config = GetFeedConfig(); - config.persistent_kv_store_maximum_size_before_eviction = size_in_bytes; - SetFeedConfigForTesting(config); - } - - void Put(const std::string& key, const std::string& value) { - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Put(key, value, callback.Bind()); - ASSERT_TRUE(callback.RunAndGetResult().success); - } - - std::string Get(const std::string& key) { - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Get(key, callback.Bind()); - return callback.RunAndGetResult().get_result.value_or("<not-found>"); - } - - std::map<std::string, std::string> GetAllEntries() { - // Make sure any queued tasks are complete. - base::RunLoop().RunUntilIdle(); - std::map<std::string, std::string> result; - auto callback = - [&](bool ok, - std::unique_ptr<std::map<std::string, feedkvstore::Entry>> data) { - CHECK(ok); - for (auto& entry : *data) { - result.emplace(entry.first, entry.second.value()); - } - }; - store_->GetDatabase()->LoadKeysAndEntries( - base::BindLambdaForTesting(callback)); - - base::RunLoop().RunUntilIdle(); - return result; - } - - base::test::TaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - std::unique_ptr<PersistentKeyValueStoreImpl> store_; -}; - -TEST_F(PersistentKeyValueStoreTest, Put) { - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Put("x", "y", callback.Bind()); - - ASSERT_TRUE(callback.RunAndGetResult().success); - EXPECT_EQ((std::map<std::string, std::string>{{"x", "y"}}), GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, GetEmptyKey) { - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Get("", callback.Bind()); - - EXPECT_TRUE(callback.RunAndGetResult().success); - EXPECT_FALSE(callback.GetResult()->get_result); -} - -TEST_F(PersistentKeyValueStoreTest, GetKeyNotPresent) { - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Get("x", callback.Bind()); - - EXPECT_TRUE(callback.RunAndGetResult().success); - EXPECT_FALSE(callback.GetResult()->get_result); -} - -TEST_F(PersistentKeyValueStoreTest, GetKeyPresent) { - Put("x", "y"); - - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Get("x", callback.Bind()); - EXPECT_TRUE(callback.RunAndGetResult().success); - EXPECT_EQ("y", callback.RunAndGetResult().get_result); -} - -TEST_F(PersistentKeyValueStoreTest, Delete) { - Put("x", "y"); - - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Delete("x", callback.Bind()); - EXPECT_TRUE(callback.RunAndGetResult().success); - EXPECT_EQ("<not-found>", Get("x")); -} - -TEST_F(PersistentKeyValueStoreTest, DeleteNotPresent) { - Put("x", "y"); - - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->Delete("y", callback.Bind()); - EXPECT_TRUE(callback.RunAndGetResult().success); - EXPECT_EQ("y", Get("x")); -} - -TEST_F(PersistentKeyValueStoreTest, ClearAll) { - Put("x", "y"); - Put("a", "b"); - - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->ClearAll(callback.Bind()); - EXPECT_TRUE(callback.RunAndGetResult().success); - - EXPECT_EQ((std::map<std::string, std::string>{}), GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesOnEmptyDatabaseDoesntCrash) { - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->EvictOldEntries(callback.Bind()); - EXPECT_TRUE(callback.RunAndGetResult().success); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesBelowSizeLimit) { - Put("x", "12345"); - - // Set config db size limit to equal size of 'x'. - SetMaxSizeBeforeEviction(5); - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->EvictOldEntries(callback.Bind()); - EXPECT_TRUE(callback.RunAndGetResult().success); - - EXPECT_EQ((std::map<std::string, std::string>{{"x", "12345"}}), - GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesAboveSizeLimit) { - Put("x", "12345"); - - // Set config db size limit to just below size of 'x'. - SetMaxSizeBeforeEviction(4); - CallbackReceiver<PersistentKeyValueStore::Result> callback; - store_->EvictOldEntries(callback.Bind()); - EXPECT_TRUE(callback.RunAndGetResult().success); - - EXPECT_EQ((std::map<std::string, std::string>{}), GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, PutAndGetAreQueuedWhileEvicting) { - SetMaxSizeBeforeEviction(0); - std::vector<std::string> calls; - auto record_call = base::BindLambdaForTesting( - [&](std::string label, PersistentKeyValueStore::Result) { - calls.push_back(label); - }); - store_->Put("x", "12345", base::BindOnce(record_call, "put1")); - store_->EvictOldEntries(base::BindOnce(record_call, "evict")); - store_->Put("y", "123456", base::BindOnce(record_call, "put2")); - std::string get_result = Get("y"); - - EXPECT_EQ(std::vector<std::string>({"put1", "evict", "put2"}), calls); - EXPECT_EQ((std::map<std::string, std::string>{ - {"y", "123456"}, - }), - GetAllEntries()); - EXPECT_EQ("123456", get_result); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesDeletesOldEntriesFirst) { - Put("1", "x"); - task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); - Put("2", "x"); - - SetMaxSizeBeforeEviction(1); - store_->EvictOldEntries(base::DoNothing()); - - EXPECT_EQ((std::map<std::string, std::string>{{"2", "x"}}), GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, - EvictOldEntriesDeletesOldEntriesFirstReverseKeys) { - Put("2", "x"); - task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); - Put("1", "x"); - - SetMaxSizeBeforeEviction(1); - store_->EvictOldEntries(base::DoNothing()); - - EXPECT_EQ((std::map<std::string, std::string>{{"1", "x"}}), GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesDeleteFutureEntriesFirst) { - // Insert two entries manually. The second entry has a modification time in - // the future, so it will be evicted preferentially. - { - // Trigger and wait for db initialization. - Get("foo"); - - auto entries_to_save = std::make_unique< - leveldb_proto::ProtoDatabase<feedkvstore::Entry>::KeyEntryVector>(); - { - feedkvstore::Entry new_entry; - new_entry.set_value("1"); - new_entry.set_modification_time( - (base::Time::Now().ToDeltaSinceWindowsEpoch()).InMilliseconds()); - entries_to_save->emplace_back("key1", std::move(new_entry)); - } - { - feedkvstore::Entry new_entry; - new_entry.set_value("2"); - new_entry.set_modification_time( - (base::Time::Now().ToDeltaSinceWindowsEpoch() + - base::TimeDelta::FromMinutes(1)) - .InMilliseconds()); - entries_to_save->emplace_back("key2", std::move(new_entry)); - } - - CallbackReceiver<bool> callback; - store_->GetDatabase()->UpdateEntries( - std::move(entries_to_save), - /*keys_to_remove=*/std::make_unique<std::vector<std::string>>(), - callback.Bind()); - ASSERT_TRUE(callback.RunAndGetResult()); - } - - SetMaxSizeBeforeEviction(1); - store_->EvictOldEntries(base::DoNothing()); - - EXPECT_EQ((std::map<std::string, std::string>{{"key1", "1"}}), - GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesManyEntries) { - const int kFinalEntryCount = kMaxEntriesInMemory * 2; - const int kInitialEntryCount = kFinalEntryCount + kMaxEntriesInMemory / 2; - - for (int i = 0; i < kInitialEntryCount; ++i) { - // Make key order different than insertion order. - int key = hash_int(i); - Put(base::NumberToString(key), "x"); - task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); - } - - SetMaxSizeBeforeEviction(kFinalEntryCount); - store_->EvictOldEntries(base::DoNothing()); - - std::map<std::string, std::string> want_entries; - for (int i = kInitialEntryCount - kFinalEntryCount; i < kInitialEntryCount; - ++i) { - want_entries[base::NumberToString(hash_int(i))] = "x"; - } - EXPECT_EQ(want_entries, GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesExactlyMaxEntriesInMemory) { - for (int i = 0; i < kMaxEntriesInMemory; ++i) { - // Make key order different than insertion order. - int key = hash_int(i); - Put(base::NumberToString(key), "x"); - task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); - } - - SetMaxSizeBeforeEviction(kMaxEntriesInMemory - 1); - store_->EvictOldEntries(base::DoNothing()); - - std::map<std::string, std::string> want_entries; - for (int i = 1; i < kMaxEntriesInMemory; ++i) { - want_entries[base::NumberToString(hash_int(i))] = "x"; - } - EXPECT_EQ(want_entries, GetAllEntries()); -} - -TEST_F(PersistentKeyValueStoreTest, EvictOldEntriesMaxEntriesInMemoryPlusOne) { - for (int i = 0; i < kMaxEntriesInMemory + 1; ++i) { - // Make key order different than insertion order. - int key = hash_int(i); - Put(base::NumberToString(key), "x"); - task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); - } - - SetMaxSizeBeforeEviction(kMaxEntriesInMemory + 1 - 1); - store_->EvictOldEntries(base::DoNothing()); - - std::map<std::string, std::string> want_entries; - for (int i = 1; i < kMaxEntriesInMemory + 1; ++i) { - want_entries[base::NumberToString(hash_int(i))] = "x"; - } - EXPECT_EQ(want_entries, GetAllEntries()); -} - -void CallAfterNPostTasks(int post_task_count, base::OnceClosure done) { - if (post_task_count == 0) { - std::move(done).Run(); - } else { - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(base::BindOnce(&CallAfterNPostTasks, post_task_count - 1, - std::move(done)))); - } -} - -// Test that `EvictOldEntries()` completes without crashing, even when the -// store is deleted between posted tasks. -TEST_F(PersistentKeyValueStoreTest, DeleteStoreWhileEvictOldEntriesIsRunning) { - SetMaxSizeBeforeEviction(kMaxEntriesInMemory + 1); - - constexpr int kMaxPostTasks = 32; // Today, must be at least 16. - for (int post_tasks_before_delete = 0; - post_tasks_before_delete < kMaxPostTasks; ++post_tasks_before_delete) { - MakeStore(); - for (int i = 0; i < kMaxEntriesInMemory + 1; ++i) { - Put(base::NumberToString(i), "x"); - task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); - } - // Call EvictOldEntries(), and then eventually delete the store while - // EvictOldEntries() is running. If EvictOldEntries() completes first, - // then exit the loop because we've tried all possible orderings. - base::RunLoop run_loop; - bool evict_complete = false, delete_complete = false; - bool evict_complete_first = false; - auto complete_func = [&](bool is_evict_call) { - evict_complete |= is_evict_call; - delete_complete |= !is_evict_call; - if (evict_complete && delete_complete) { - evict_complete_first = !is_evict_call; - run_loop.QuitClosure().Run(); - } - }; - store_->EvictOldEntries(base::BindLambdaForTesting( - [&](PersistentKeyValueStore::Result) { complete_func(true); })); - CallAfterNPostTasks(post_tasks_before_delete, - base::BindLambdaForTesting([&]() { - store_.reset(); - complete_func(false); - })); - run_loop.RunUntilIdle(); - if (evict_complete_first) { - ASSERT_GT(post_tasks_before_delete, 2) - << "EvictOldEntries completed with fewer post tasks than expected"; - return; - } - } - ASSERT_TRUE(false) - << "EvictOldEntries didn't complete after kMaxPostTasks post tasks?"; -} - -TEST_F(PersistentKeyValueStoreTest, DataStoreCleansOldDataAutomatically) { - // Simulate use of the store by inserting 10 byte entries. On average, we - // should perform eviction on every 10 Put() calls -- with a 1/10 chance on - // each call. We have a negligible probability of ~1.0e-46 of failing to run - // eviction after 1000 iterations. - Config config = GetFeedConfig(); - config.persistent_kv_store_cleanup_interval_in_written_bytes = 100; - config.persistent_kv_store_maximum_size_before_eviction = 10; - SetFeedConfigForTesting(config); - MakeStore(); - - for (int i = 0;; ++i) { - ASSERT_LT(i, 1000); - Put(base::NumberToString(i), "1234567890"); - task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1)); - if (Get("0") == "<not-found>") - break; - } -} - -} // namespace -} // namespace feed
diff --git a/components/feed/core/v2/public/feed_service.cc b/components/feed/core/v2/public/feed_service.cc index 4c14bfd..135f2313 100644 --- a/components/feed/core/v2/public/feed_service.cc +++ b/components/feed/core/v2/public/feed_service.cc
@@ -15,7 +15,6 @@ #include "components/feed/core/v2/feed_stream.h" #include "components/feed/core/v2/image_fetcher.h" #include "components/feed/core/v2/metrics_reporter.h" -#include "components/feed/core/v2/persistent_key_value_store_impl.h" #include "components/feed/core/v2/refresh_task_scheduler.h" #include "components/feed/feed_feature_list.h" #include "components/history/core/browser/history_service.h" @@ -182,8 +181,6 @@ PrefService* profile_prefs, PrefService* local_state, std::unique_ptr<leveldb_proto::ProtoDatabase<feedstore::Record>> database, - std::unique_ptr<leveldb_proto::ProtoDatabase<feedkvstore::Entry>> - key_value_store_database, signin::IdentityManager* identity_manager, history::HistoryService* history_service, offline_pages::PrefetchService* prefetch_service, @@ -203,14 +200,12 @@ profile_prefs); image_fetcher_ = std::make_unique<ImageFetcher>(url_loader_factory); store_ = std::make_unique<FeedStore>(std::move(database)); - persistent_key_value_store_ = std::make_unique<PersistentKeyValueStoreImpl>( - std::move(key_value_store_database)); stream_ = std::make_unique<FeedStream>( refresh_task_scheduler_.get(), metrics_reporter_.get(), stream_delegate_.get(), profile_prefs, feed_network_.get(), - image_fetcher_.get(), store_.get(), persistent_key_value_store_.get(), - prefetch_service, offline_page_model, chrome_info); + image_fetcher_.get(), store_.get(), prefetch_service, offline_page_model, + chrome_info); history_observer_ = std::make_unique<HistoryObserverImpl>( history_service, static_cast<FeedStream*>(stream_.get()),
diff --git a/components/feed/core/v2/public/feed_service.h b/components/feed/core/v2/public/feed_service.h index 2890d65..d8c1f2a 100644 --- a/components/feed/core/v2/public/feed_service.h +++ b/components/feed/core/v2/public/feed_service.h
@@ -31,9 +31,6 @@ namespace feedstore { class Record; } // namespace feedstore -namespace feedkvstore { -class Entry; -} // namespace feedkvstore namespace network { class SharedURLLoaderFactory; } // namespace network @@ -51,7 +48,6 @@ class FeedNetwork; class FeedStore; class FeedStream; -class PersistentKeyValueStoreImpl; class ImageFetcher; namespace internal { @@ -86,8 +82,6 @@ PrefService* profile_prefs, PrefService* local_state, std::unique_ptr<leveldb_proto::ProtoDatabase<feedstore::Record>> database, - std::unique_ptr<leveldb_proto::ProtoDatabase<feedkvstore::Entry>> - key_value_store_database, signin::IdentityManager* identity_manager, history::HistoryService* history_service, offline_pages::PrefetchService* prefetch_service, @@ -129,7 +123,6 @@ std::unique_ptr<FeedNetwork> feed_network_; std::unique_ptr<ImageFetcher> image_fetcher_; std::unique_ptr<FeedStore> store_; - std::unique_ptr<PersistentKeyValueStoreImpl> persistent_key_value_store_; std::unique_ptr<RefreshTaskScheduler> refresh_task_scheduler_; std::unique_ptr<HistoryObserverImpl> history_observer_; std::unique_ptr<IdentityManagerObserverImpl> identity_manager_observer_;
diff --git a/components/feed/core/v2/public/feed_stream_api.h b/components/feed/core/v2/public/feed_stream_api.h index c531bed2..b33d9e8 100644 --- a/components/feed/core/v2/public/feed_stream_api.h +++ b/components/feed/core/v2/public/feed_stream_api.h
@@ -23,7 +23,6 @@ } // namespace feedstore namespace feed { -class PersistentKeyValueStore; // This is the public access point for interacting with the Feed stream // contents. @@ -94,8 +93,6 @@ // |id| doesn't match an active fetch, nothing happens. virtual void CancelImageFetch(ImageFetchId id) = 0; - virtual PersistentKeyValueStore* GetPersistentKeyValueStore() = 0; - // Apply |operations| to the stream model. Does nothing if the model is not // yet loaded. virtual void ExecuteOperations(
diff --git a/components/feed/core/v2/public/persistent_key_value_store.cc b/components/feed/core/v2/public/persistent_key_value_store.cc deleted file mode 100644 index ba15023..0000000 --- a/components/feed/core/v2/public/persistent_key_value_store.cc +++ /dev/null
@@ -1,15 +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/feed/core/v2/public/persistent_key_value_store.h" - -namespace feed { - -PersistentKeyValueStore::Result::Result() = default; -PersistentKeyValueStore::Result::Result(Result&&) = default; -PersistentKeyValueStore::Result& PersistentKeyValueStore::Result::operator=( - Result&&) = default; -PersistentKeyValueStore::Result::~Result() = default; - -} // namespace feed
diff --git a/components/feed/core/v2/public/persistent_key_value_store.h b/components/feed/core/v2/public/persistent_key_value_store.h deleted file mode 100644 index 070d21e8..0000000 --- a/components/feed/core/v2/public/persistent_key_value_store.h +++ /dev/null
@@ -1,57 +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_FEED_CORE_V2_PUBLIC_PERSISTENT_KEY_VALUE_STORE_H_ -#define COMPONENTS_FEED_CORE_V2_PUBLIC_PERSISTENT_KEY_VALUE_STORE_H_ - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "base/optional.h" - -namespace feed { - -// A generic persistent key-value cache. Has a maximum size determined by -// `feed::Config`. Once size of all values exceed the maximum, older keys -// are eventually evicted. Key age is determined only by the last call to -// `Put()`. -class PersistentKeyValueStore { - public: - struct Result { - Result(); - Result(Result&&); - Result& operator=(Result&&); - ~Result(); - // Whether the operation succeeded. Failure may be due to a low level - // database error, or a missing key/value pair. - bool success = false; - // For `Get()` operations, the value of the key if it exists. - base::Optional<std::string> get_result; - }; - - using ResultCallback = base::OnceCallback<void(Result)>; - - PersistentKeyValueStore() = default; - virtual ~PersistentKeyValueStore() = default; - PersistentKeyValueStore(const PersistentKeyValueStore&) = delete; - PersistentKeyValueStore& operator=(const PersistentKeyValueStore&) = delete; - - // Erase all data in the store. - virtual void ClearAll(ResultCallback callback) = 0; - // Write/overwrite a key/value pair. - virtual void Put(const std::string& key, - const std::string& value, - ResultCallback callback) = 0; - // Get a value by key. - virtual void Get(const std::string& key, ResultCallback callback) = 0; - // Delete a value by key. - virtual void Delete(const std::string& key, ResultCallback callback) = 0; - - private: -}; - -} // namespace feed - -#endif // COMPONENTS_FEED_CORE_V2_PUBLIC_PERSISTENT_KEY_VALUE_STORE_H_
diff --git a/components/feed/core/v2/tasks/clear_all_task.cc b/components/feed/core/v2/tasks/clear_all_task.cc index 45fb2c7..ddcf65d1 100644 --- a/components/feed/core/v2/tasks/clear_all_task.cc +++ b/components/feed/core/v2/tasks/clear_all_task.cc
@@ -9,7 +9,6 @@ #include "components/feed/core/v2/feed_store.h" #include "components/feed/core/v2/feed_stream.h" -#include "components/feed/core/v2/public/persistent_key_value_store.h" namespace feed { @@ -18,7 +17,6 @@ void ClearAllTask::Run() { stream_->UnloadModel(); - stream_->GetPersistentKeyValueStore()->ClearAll(base::DoNothing()); stream_->GetStore()->ClearAll( base::BindOnce(&ClearAllTask::StoreClearComplete, GetWeakPtr())); }
diff --git a/components/feed/core/v2/test/callback_receiver.cc b/components/feed/core/v2/test/callback_receiver.cc deleted file mode 100644 index a9621ee..0000000 --- a/components/feed/core/v2/test/callback_receiver.cc +++ /dev/null
@@ -1,28 +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/feed/core/v2/test/callback_receiver.h" - -namespace feed { -namespace internal { -void CallbackReceiverBase::RunUntilCalled() { - if (called_) - return; - if (run_loop_) { - run_loop_->Run(); - } else { - base::RunLoop run_loop; - run_loop_ = &run_loop; - run_loop.Run(); - run_loop_ = nullptr; - } -} -void CallbackReceiverBase::Done() { - called_ = true; - if (run_loop_) - run_loop_->Quit(); -} - -} // namespace internal -} // namespace feed
diff --git a/components/feed/core/v2/test/callback_receiver.h b/components/feed/core/v2/test/callback_receiver.h index 3b2c4549..1cd9fc6 100644 --- a/components/feed/core/v2/test/callback_receiver.h +++ b/components/feed/core/v2/test/callback_receiver.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_FEED_CORE_V2_TEST_CALLBACK_RECEIVER_H_ #define COMPONENTS_FEED_CORE_V2_TEST_CALLBACK_RECEIVER_H_ -#include <memory> #include <tuple> #include <utility> @@ -22,41 +21,23 @@ return base::nullopt; } -class CallbackReceiverBase { - public: - explicit CallbackReceiverBase(base::RunLoop* run_loop = nullptr) - : run_loop_(run_loop) {} - - void Clear() { called_ = false; } - bool called() const { return called_; } - void RunUntilCalled(); - void Done(); - - private: - bool called_ = false; - base::RunLoop* run_loop_; -}; - } // namespace internal template <typename... T> -class CallbackReceiver : public internal::CallbackReceiverBase { +class CallbackReceiver { public: explicit CallbackReceiver(base::RunLoop* run_loop = nullptr) - : CallbackReceiverBase(run_loop) {} - + : run_loop_(run_loop) {} void Done(T... results) { results_ = std::make_tuple(std::move(results)...); - CallbackReceiverBase::Done(); + if (run_loop_) + run_loop_->Quit(); } base::OnceCallback<void(T...)> Bind() { return base::BindOnce(&CallbackReceiver::Done, base::Unretained(this)); } - void Clear() { - CallbackReceiverBase::Clear(); - results_ = std::make_tuple(internal::Nullopt<T>()...); - } + void Clear() { results_ = std::make_tuple(internal::Nullopt<T>()...); } // Get a result by its position in the arguments to Done(). // Call GetResult() for the first argument or GetResult<I>(). @@ -66,12 +47,6 @@ return std::get<I>(results_); } - template <size_t I = 0> - typename std::tuple_element<I, std::tuple<T...>>::type& RunAndGetResult() { - RunUntilCalled(); - return std::get<I>(results_).value(); - } - // Get a result by its type. Won't compile if there is more than one matching // type. template <class C> @@ -81,17 +56,7 @@ private: std::tuple<base::Optional<T>...> results_; -}; - -template <> -class CallbackReceiver<> : public internal::CallbackReceiverBase { - public: - explicit CallbackReceiver(base::RunLoop* run_loop = nullptr) - : CallbackReceiverBase(run_loop) {} - - base::OnceClosure Bind() { - return base::BindOnce(&CallbackReceiverBase::Done, base::Unretained(this)); - } + base::RunLoop* run_loop_; }; } // namespace feed
diff --git a/components/feed/core/v2/test/callback_receiver_unittest.cc b/components/feed/core/v2/test/callback_receiver_unittest.cc index c3a3e85..301cec7 100644 --- a/components/feed/core/v2/test/callback_receiver_unittest.cc +++ b/components/feed/core/v2/test/callback_receiver_unittest.cc
@@ -5,9 +5,6 @@ #include "components/feed/core/v2/test/callback_receiver.h" #include "base/optional.h" -#include "base/test/bind.h" -#include "base/test/task_environment.h" -#include "base/threading/sequenced_task_runner_handle.h" #include "testing/gtest/include/gtest/gtest.h" namespace feed { @@ -44,25 +41,4 @@ EXPECT_EQ(cr.GetResult<1>(), base::nullopt); } -TEST(CallbackReceiverTest, RunAndGetResult) { - base::test::TaskEnvironment task_environment{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - - CallbackReceiver<int> cr1; - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(cr1.Bind(), 42)); - EXPECT_EQ(42, cr1.RunAndGetResult()); -} - -TEST(CallbackReceiverTest, RunAndGetResultExternalRunLoop) { - base::test::TaskEnvironment task_environment{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - - base::RunLoop run_loop; - CallbackReceiver<int> cr1(&run_loop); - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(cr1.Bind(), 42)); - EXPECT_EQ(42, cr1.RunAndGetResult()); -} - } // namespace feed
diff --git a/components/full_restore/full_restore_read_handler.cc b/components/full_restore/full_restore_read_handler.cc index bd1e814..07b49fd70 100644 --- a/components/full_restore/full_restore_read_handler.cc +++ b/components/full_restore/full_restore_read_handler.cc
@@ -41,6 +41,9 @@ const base::FilePath& profile_path, Callback callback, std::unique_ptr<RestoreData> restore_data) { + if (restore_data) + profile_path_to_restore_data_[profile_path] = restore_data->Clone(); + std::move(callback).Run(std::move(restore_data)); }
diff --git a/components/full_restore/full_restore_read_handler.h b/components/full_restore/full_restore_read_handler.h index 57572d7..6104189b 100644 --- a/components/full_restore/full_restore_read_handler.h +++ b/components/full_restore/full_restore_read_handler.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_FULL_RESTORE_FULL_RESTORE_READ_HANDLER_H_ #define COMPONENTS_FULL_RESTORE_FULL_RESTORE_READ_HANDLER_H_ +#include <map> #include <memory> #include "base/callback.h" @@ -49,6 +50,10 @@ Callback callback, std::unique_ptr<RestoreData>); + // The restore data read from the full restore files. + std::map<base::FilePath, std::unique_ptr<RestoreData>> + profile_path_to_restore_data_; + base::WeakPtrFactory<FullRestoreReadHandler> weak_factory_{this}; };
diff --git a/components/full_restore/full_restore_save_handler.cc b/components/full_restore/full_restore_save_handler.cc index 02699ce..f6b2ebcc 100644 --- a/components/full_restore/full_restore_save_handler.cc +++ b/components/full_restore/full_restore_save_handler.cc
@@ -126,6 +126,22 @@ it->second.second, window_id, window_info); } +void FullRestoreSaveHandler::Flush(const base::FilePath& profile_path) { + if (save_running_.find(profile_path) != save_running_.end()) + return; + + save_running_.insert(profile_path); + + BackendTaskRunner(profile_path) + ->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&FullRestoreFileHandler::WriteToFile, + GetFileHandler(profile_path), + profile_path_to_restore_data_[profile_path].Clone()), + base::BindOnce(&FullRestoreSaveHandler::OnSaveFinished, + weak_factory_.GetWeakPtr(), profile_path)); +} + void FullRestoreSaveHandler::MaybeStartSaveTimer() { if (!save_timer_.IsRunning() && save_running_.empty()) { save_timer_.Start(FROM_HERE, kSaveDelay, @@ -138,16 +154,9 @@ if (pending_save_profile_paths_.empty()) return; - for (const auto& file_path : pending_save_profile_paths_) { - save_running_.insert(file_path); - BackendTaskRunner(file_path)->PostTaskAndReply( - FROM_HERE, - base::BindOnce(&FullRestoreFileHandler::WriteToFile, - GetFileHandler(file_path), - profile_path_to_restore_data_[file_path].Clone()), - base::BindOnce(&FullRestoreSaveHandler::OnSaveFinished, - weak_factory_.GetWeakPtr(), file_path)); - } + for (const auto& file_path : pending_save_profile_paths_) + Flush(file_path); + pending_save_profile_paths_.clear(); }
diff --git a/components/full_restore/full_restore_save_handler.h b/components/full_restore/full_restore_save_handler.h index 2b412a5..4e6cc9ff 100644 --- a/components/full_restore/full_restore_save_handler.h +++ b/components/full_restore/full_restore_save_handler.h
@@ -61,6 +61,10 @@ // Save |window_info| to |profile_path_to_restore_data_|. void SaveWindowInfo(const WindowInfo& window_info); + // Flushes the full restore file in |profile_path| with the current restore + // data. + void Flush(const base::FilePath& profile_path); + base::OneShotTimer* GetTimerForTesting() { return &save_timer_; } private:
diff --git a/components/full_restore/full_restore_utils.cc b/components/full_restore/full_restore_utils.cc index a5b017df..ca329658 100644 --- a/components/full_restore/full_restore_utils.cc +++ b/components/full_restore/full_restore_utils.cc
@@ -15,6 +15,7 @@ namespace full_restore { DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kWindowIdKey, 0) +DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kRestoreWindowIdKey, 0) void SaveAppLaunchInfo(const base::FilePath& profile_dir, std::unique_ptr<AppLaunchInfo> app_launch_info) {
diff --git a/components/full_restore/full_restore_utils.h b/components/full_restore/full_restore_utils.h index f92ca52..0fcf698 100644 --- a/components/full_restore/full_restore_utils.h +++ b/components/full_restore/full_restore_utils.h
@@ -29,6 +29,10 @@ COMPONENT_EXPORT(FULL_RESTORE) extern const ui::ClassProperty<int32_t>* const kWindowIdKey; +// A property key to indicate the restore id for the window from RestoreData. +COMPONENT_EXPORT(FULL_RESTORE) +extern const ui::ClassProperty<int32_t>* const kRestoreWindowIdKey; + // Saves the app launch parameters to the full restore file. COMPONENT_EXPORT(FULL_RESTORE) void SaveAppLaunchInfo(const base::FilePath& profile_dir,
diff --git a/components/full_restore/restore_data.cc b/components/full_restore/restore_data.cc index 303ca43..c9b00ac 100644 --- a/components/full_restore/restore_data.cc +++ b/components/full_restore/restore_data.cc
@@ -117,4 +117,8 @@ app_id_to_launch_list_.erase(app_id); } +void RestoreData::RemoveApp(const std::string& app_id) { + app_id_to_launch_list_.erase(app_id); +} + } // namespace full_restore
diff --git a/components/full_restore/restore_data.h b/components/full_restore/restore_data.h index 02f6444..b50a369 100644 --- a/components/full_restore/restore_data.h +++ b/components/full_restore/restore_data.h
@@ -91,6 +91,9 @@ // Remove a AppRestoreData with |window_id| for |app_id|. void RemoveAppRestoreData(const std::string& app_id, int window_id); + // Remove the launch list for |app_id|. + void RemoveApp(const std::string& app_id); + const AppIdToLaunchList& app_id_to_launch_list() const { return app_id_to_launch_list_; }
diff --git a/components/full_restore/restore_data_unittest.cc b/components/full_restore/restore_data_unittest.cc index 7aec532..3c99402 100644 --- a/components/full_restore/restore_data_unittest.cc +++ b/components/full_restore/restore_data_unittest.cc
@@ -271,7 +271,7 @@ ModifyWindowInfos(); VerifyRestoreData(restore_data()); - // Remove kAppId1's kId1. + // Remove kAppId1's kWindowId1. restore_data().RemoveAppRestoreData(kAppId1, kWindowId1); EXPECT_EQ(2u, app_id_to_launch_list().size()); @@ -291,7 +291,7 @@ EXPECT_TRUE(base::Contains(launch_list_it2->second, kWindowId3)); - // Remove kAppId1's kId2. + // Remove kAppId1's kWindowId2. restore_data().RemoveAppRestoreData(kAppId1, kWindowId2); EXPECT_EQ(1u, app_id_to_launch_list().size()); @@ -306,12 +306,35 @@ EXPECT_TRUE(base::Contains(launch_list_it2->second, kWindowId3)); - // Remove kAppId2's kId3. + // Remove kAppId2's kWindowId3. restore_data().RemoveAppRestoreData(kAppId2, kWindowId3); EXPECT_EQ(0u, app_id_to_launch_list().size()); } +TEST_F(RestoreDataTest, RemoveApp) { + AddAppLaunchInfos(); + ModifyWindowInfos(); + VerifyRestoreData(restore_data()); + + // Remove kAppId1. + restore_data().RemoveApp(kAppId1); + + EXPECT_EQ(1u, app_id_to_launch_list().size()); + + // Verify for |kAppId2| + auto launch_list_it2 = app_id_to_launch_list().find(kAppId2); + EXPECT_TRUE(launch_list_it2 != app_id_to_launch_list().end()); + EXPECT_EQ(1u, launch_list_it2->second.size()); + + EXPECT_TRUE(base::Contains(launch_list_it2->second, kWindowId3)); + + // Remove kAppId2. + restore_data().RemoveApp(kAppId2); + + EXPECT_EQ(0u, app_id_to_launch_list().size()); +} + TEST_F(RestoreDataTest, Convert) { AddAppLaunchInfos(); ModifyWindowInfos();
diff --git a/components/leveldb_proto/public/shared_proto_database_client_list.cc b/components/leveldb_proto/public/shared_proto_database_client_list.cc index c2d3f632..eae251d 100644 --- a/components/leveldb_proto/public/shared_proto_database_client_list.cc +++ b/components/leveldb_proto/public/shared_proto_database_client_list.cc
@@ -88,8 +88,6 @@ return "NearbySharePublicCertificateDatabase"; case ProtoDbType::VIDEO_TUTORIALS_DATABASE: return "VideoTutorialsDatabase"; - case ProtoDbType::FEED_KEY_VALUE_DATABASE: - return "FeedKeyValueDatabase"; case ProtoDbType::LAST: NOTREACHED(); return std::string();
diff --git a/components/leveldb_proto/public/shared_proto_database_client_list.h b/components/leveldb_proto/public/shared_proto_database_client_list.h index 55e2f9a77..57d6886 100644 --- a/components/leveldb_proto/public/shared_proto_database_client_list.h +++ b/components/leveldb_proto/public/shared_proto_database_client_list.h
@@ -18,8 +18,7 @@ // The enum values are used to index into the shared database. Do not rearrange // or reuse the integer values. Add new database types at the end of the enum, // and update the string mapping in ProtoDbTypeToString(). Also update the -// suffix LevelDBClients in histogram_suffixes_list.xml to match the strings for -// the types. +// suffix LevelDBClients in histograms.xml to match the strings for the types. enum class ProtoDbType { TEST_DATABASE0 = 0, TEST_DATABASE1 = 1, @@ -54,7 +53,6 @@ UPBOARDING_QUERY_TILE_STORE = 28, NEARBY_SHARE_PUBLIC_CERTIFICATE_DATABASE = 29, VIDEO_TUTORIALS_DATABASE = 30, - FEED_KEY_VALUE_DATABASE = 31, LAST, }; @@ -70,7 +68,6 @@ ProtoDbType::UPBOARDING_QUERY_TILE_STORE, ProtoDbType::NEARBY_SHARE_PUBLIC_CERTIFICATE_DATABASE, ProtoDbType::VIDEO_TUTORIALS_DATABASE, - ProtoDbType::FEED_KEY_VALUE_DATABASE, ProtoDbType::LAST, // Marks the end of list. };
diff --git a/components/optimization_guide/DEPS b/components/optimization_guide/DEPS index 8acabd3..a4bfbd0f 100644 --- a/components/optimization_guide/DEPS +++ b/components/optimization_guide/DEPS
@@ -2,7 +2,6 @@ "+components/leveldb_proto", "+components/prefs", "+components/variations", - "+content/public/browser", "+google_apis", "+net", "+services/network",
diff --git a/components/optimization_guide/core/BUILD.gn b/components/optimization_guide/core/BUILD.gn index 51119dfa..ddd71c2b 100644 --- a/components/optimization_guide/core/BUILD.gn +++ b/components/optimization_guide/core/BUILD.gn
@@ -39,6 +39,8 @@ "optimization_guide_service.cc", "optimization_guide_service.h", "optimization_guide_service_observer.h", + "optimization_guide_session_statistic.cc", + "optimization_guide_session_statistic.h", "optimization_guide_store.cc", "optimization_guide_store.h", "optimization_guide_switches.cc", @@ -50,6 +52,10 @@ "optimization_target_model_observer.h", "prediction_model.cc", "prediction_model.h", + "prediction_model_fetcher.cc", + "prediction_model_fetcher.h", + "prediction_model_file.cc", + "prediction_model_file.h", "store_update_data.cc", "store_update_data.h", "top_host_provider.h", @@ -107,9 +113,11 @@ "optimization_filter_unittest.cc", "optimization_guide_features_unittest.cc", "optimization_guide_service_unittest.cc", + "optimization_guide_session_statistic_unittest.cc", "optimization_guide_store_unittest.cc", "optimization_guide_switches_unittest.cc", "optimization_metadata_unittest.cc", + "prediction_model_fetcher_unittest.cc", "prediction_model_unittest.cc", "store_update_data_unittest.cc", "url_pattern_with_wildcards_unittest.cc",
diff --git a/chrome/browser/optimization_guide/optimization_guide_session_statistic.cc b/components/optimization_guide/core/optimization_guide_session_statistic.cc similarity index 89% rename from chrome/browser/optimization_guide/optimization_guide_session_statistic.cc rename to components/optimization_guide/core/optimization_guide_session_statistic.cc index d7915d1..002085a 100644 --- a/chrome/browser/optimization_guide/optimization_guide_session_statistic.cc +++ b/components/optimization_guide/core/optimization_guide_session_statistic.cc
@@ -2,10 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" +#include "components/optimization_guide/core/optimization_guide_session_statistic.h" #include <cmath> +namespace optimization_guide { + OptimizationGuideSessionStatistic::OptimizationGuideSessionStatistic() : num_samples_(0u), mean_(0.0), variance_sum_(0.0) {} @@ -40,3 +42,5 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return num_samples_; } + +} // namespace optimization_guide
diff --git a/chrome/browser/optimization_guide/optimization_guide_session_statistic.h b/components/optimization_guide/core/optimization_guide_session_statistic.h similarity index 81% rename from chrome/browser/optimization_guide/optimization_guide_session_statistic.h rename to components/optimization_guide/core/optimization_guide_session_statistic.h index 25ce038..da3c76f 100644 --- a/chrome/browser/optimization_guide/optimization_guide_session_statistic.h +++ b/components/optimization_guide/core/optimization_guide_session_statistic.h
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SESSION_STATISTIC_H_ -#define CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SESSION_STATISTIC_H_ +#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_SESSION_STATISTIC_H_ +#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_SESSION_STATISTIC_H_ #include "base/sequence_checker.h" #include "base/values.h" +namespace optimization_guide { + // OptimizationGuideSessionStatistic calculates running statistics, mean and // variance, for real valued inputs one sample at a time. class OptimizationGuideSessionStatistic { @@ -45,4 +47,6 @@ DISALLOW_COPY_AND_ASSIGN(OptimizationGuideSessionStatistic); }; -#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SESSION_STATISTIC_H_ +} // namespace optimization_guide + +#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_SESSION_STATISTIC_H_
diff --git a/chrome/browser/optimization_guide/optimization_guide_session_statistic_unittest.cc b/components/optimization_guide/core/optimization_guide_session_statistic_unittest.cc similarity index 88% rename from chrome/browser/optimization_guide/optimization_guide_session_statistic_unittest.cc rename to components/optimization_guide/core/optimization_guide_session_statistic_unittest.cc index 205cfe9..d0540386 100644 --- a/chrome/browser/optimization_guide/optimization_guide_session_statistic_unittest.cc +++ b/components/optimization_guide/core/optimization_guide_session_statistic_unittest.cc
@@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h" +#include "components/optimization_guide/core/optimization_guide_session_statistic.h" #include <cmath> #include "testing/gtest/include/gtest/gtest.h" +namespace optimization_guide { + TEST(OptimzationGuideSessionStatisticTest, CalculateSessionStatisticsForSamples) { OptimizationGuideSessionStatistic stat; @@ -41,3 +43,5 @@ EXPECT_EQ(0.0, stat.GetVariance()); EXPECT_EQ(0.0, stat.GetStdDev()); } + +} // namespace optimization_guide
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc b/components/optimization_guide/core/prediction_model_fetcher.cc similarity index 93% rename from chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc rename to components/optimization_guide/core/prediction_model_fetcher.cc index d8af38e..e976947b 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc +++ b/components/optimization_guide/core/prediction_model_fetcher.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/optimization_guide/prediction/prediction_model_fetcher.h" +#include "components/optimization_guide/core/prediction_model_fetcher.h" #include <memory> #include <string> @@ -16,13 +16,13 @@ #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/variations/net/variations_http_headers.h" -#include "content/public/browser/network_service_instance.h" #include "net/base/load_flags.h" #include "net/base/url_util.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" @@ -30,14 +30,16 @@ PredictionModelFetcher::PredictionModelFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - GURL optimization_guide_service_get_models_url) + const GURL& optimization_guide_service_get_models_url, + network::NetworkConnectionTracker* network_connection_tracker) : optimization_guide_service_get_models_url_( net::AppendOrReplaceQueryParameter( optimization_guide_service_get_models_url, "key", optimization_guide::features:: - GetOptimizationGuideServiceAPIKey())) { - url_loader_factory_ = std::move(url_loader_factory); + GetOptimizationGuideServiceAPIKey())), + url_loader_factory_(url_loader_factory), + network_connection_tracker_(network_connection_tracker) { CHECK(optimization_guide_service_get_models_url_.SchemeIs(url::kHttpsScheme)); } @@ -51,7 +53,7 @@ ModelsFetchedCallback models_fetched_callback) { SEQUENCE_CHECKER(sequence_checker_); - if (content::GetNetworkConnectionTracker()->IsOffline()) { + if (network_connection_tracker_->IsOffline()) { std::move(models_fetched_callback).Run(base::nullopt); return false; }
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h b/components/optimization_guide/core/prediction_model_fetcher.h similarity index 85% rename from chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h rename to components/optimization_guide/core/prediction_model_fetcher.h index 55728171..ea98064a 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h +++ b/components/optimization_guide/core/prediction_model_fetcher.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_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MODEL_FETCHER_H_ -#define CHROME_BROWSER_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MODEL_FETCHER_H_ +#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_PREDICTION_MODEL_FETCHER_H_ +#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_PREDICTION_MODEL_FETCHER_H_ #include <memory> #include <string> @@ -18,6 +18,7 @@ #include "url/gurl.h" namespace network { +class NetworkConnectionTracker; class SharedURLLoaderFactory; class SimpleURLLoader; } // namespace network @@ -39,7 +40,8 @@ public: PredictionModelFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - GURL optimization_guide_service_get_models_url); + const GURL& optimization_guide_service_get_models_url, + network::NetworkConnectionTracker* network_connection_tracker); virtual ~PredictionModelFetcher(); // Requests PredictionModels and HostModelFeatures from the Optimization Guide @@ -85,6 +87,10 @@ // Used for creating a |url_loader_| when needed for request hints. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + // Listens to changes around the network connection. Not owned. Guaranteed to + // outlive |this|. + network::NetworkConnectionTracker* network_connection_tracker_; + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(PredictionModelFetcher); @@ -92,4 +98,4 @@ } // namespace optimization_guide -#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MODEL_FETCHER_H_ +#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_PREDICTION_MODEL_FETCHER_H_
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher_unittest.cc b/components/optimization_guide/core/prediction_model_fetcher_unittest.cc similarity index 96% rename from chrome/browser/optimization_guide/prediction/prediction_model_fetcher_unittest.cc rename to components/optimization_guide/core/prediction_model_fetcher_unittest.cc index fa3202fa..7b960a1a 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_fetcher_unittest.cc +++ b/components/optimization_guide/core/prediction_model_fetcher_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/optimization_guide/core/prediction_model_fetcher.h" + #include <memory> #include <string> #include <vector> @@ -14,7 +16,6 @@ #include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" -#include "chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h" #include "components/optimization_guide/core/optimization_guide_features.h" #include "components/optimization_guide/proto/models.pb.h" #include "net/base/url_util.h" @@ -35,9 +36,11 @@ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI), shared_url_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &test_url_loader_factory_)) { + &test_url_loader_factory_)), + network_tracker_(network::TestNetworkConnectionTracker::GetInstance()) { prediction_model_fetcher_ = std::make_unique<PredictionModelFetcher>( - shared_url_loader_factory_, GURL(optimization_guide_service_url)); + shared_url_loader_factory_, GURL(optimization_guide_service_url), + network_tracker_); } ~PredictionModelFetcherTest() override {} @@ -51,13 +54,11 @@ bool models_fetched() { return models_fetched_; } void SetConnectionOffline() { - network_tracker_ = network::TestNetworkConnectionTracker::GetInstance(); network_tracker_->SetConnectionType( network::mojom::ConnectionType::CONNECTION_NONE); } void SetConnectionOnline() { - network_tracker_ = network::TestNetworkConnectionTracker::GetInstance(); network_tracker_->SetConnectionType( network::mojom::ConnectionType::CONNECTION_4G); }
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_file.cc b/components/optimization_guide/core/prediction_model_file.cc similarity index 93% rename from chrome/browser/optimization_guide/prediction/prediction_model_file.cc rename to components/optimization_guide/core/prediction_model_file.cc index 690ef7c..f21ec85 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_file.cc +++ b/components/optimization_guide/core/prediction_model_file.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/optimization_guide/prediction/prediction_model_file.h" +#include "components/optimization_guide/core/prediction_model_file.h" #include "base/memory/ptr_util.h" #include "components/optimization_guide/core/optimization_guide_util.h"
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_file.h b/components/optimization_guide/core/prediction_model_file.h similarity index 82% rename from chrome/browser/optimization_guide/prediction/prediction_model_file.h rename to components/optimization_guide/core/prediction_model_file.h index 69a87af..d0489d4 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_model_file.h +++ b/components/optimization_guide/core/prediction_model_file.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_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MODEL_FILE_H_ -#define CHROME_BROWSER_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MODEL_FILE_H_ +#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_PREDICTION_MODEL_FILE_H_ +#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_PREDICTION_MODEL_FILE_H_ #include <memory> @@ -40,4 +40,4 @@ } // namespace optimization_guide -#endif // CHROME_BROWSER_OPTIMIZATION_GUIDE_PREDICTION_PREDICTION_MODEL_FILE_H_ +#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_PREDICTION_MODEL_FILE_H_
diff --git a/components/policy/proto/record.proto b/components/policy/proto/record.proto index 1450db6..d046b39 100644 --- a/components/policy/proto/record.proto +++ b/components/policy/proto/record.proto
@@ -116,7 +116,8 @@ // Public key id (required). // Identifies private key matching |public_asymmetric_key| for the server. - optional uint64 public_key_id = 2; + // Matches Encryptor::PublicKeyId. + optional int32 public_key_id = 2; // Signature of |public_asymmetric_key| (required). // Verified by client against a well-known signature.
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc index 72064b66..124bd48 100644 --- a/components/search_engines/template_url_service.cc +++ b/components/search_engines/template_url_service.cc
@@ -1831,26 +1831,7 @@ template_url->data_.id = ++next_id_; } - bool force_reset_keyword = false; - if (template_url->safe_for_autoreplace() && - base::EndsWith(template_url->keyword(), base::ASCIIToUTF16("_"))) { - // In the past, when we added new engines with a duplicate keyword as an - // existing engine, we uniquified it by adding underscores to the end. - // This was a problem, because it caused an increasing proliferation of - // entries like "example.com_" and "example.com__" in the database. - // - // For engines that are safe_for_autoreplace(), the only way they could have - // keywords ending with underscores is if we uniquified it. Now we detect - // these cases, and reverse it by resetting the keyword. - // - // This migration will be complete once the below-logged UMA goes to zero. - force_reset_keyword = true; - LogSearchTemplateURLEvent( - MIGRATE_SAFE_FOR_AUTOREPLACE_RESET_UNDERSCORE_KEYWORD); - } - - template_url->ResetKeywordIfNecessary(search_terms_data(), - force_reset_keyword); + template_url->ResetKeywordIfNecessary(search_terms_data(), false); // Early exit if the newly added TemplateURL was a replaceable duplicate. // No need to inform either Sync or flag on the model-mutated in that case.
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h index fa2e31d..8f43e43e 100644 --- a/components/search_engines/template_url_service.h +++ b/components/search_engines/template_url_service.h
@@ -114,7 +114,6 @@ SYNC_UPDATE_SUCCESS = 6, SYNC_UPDATE_CONVERTED_TO_ADD = 7, MIGRATE_SAFE_FOR_AUTOREPLACE_PLAY_API_ENGINE = 8, - MIGRATE_SAFE_FOR_AUTOREPLACE_RESET_UNDERSCORE_KEYWORD = 9, SEARCH_TEMPLATE_URL_EVENT_MAX, };
diff --git a/components/translate/core/browser/BUILD.gn b/components/translate/core/browser/BUILD.gn index 1cfd0b7..b3464b3 100644 --- a/components/translate/core/browser/BUILD.gn +++ b/components/translate/core/browser/BUILD.gn
@@ -136,6 +136,10 @@ "//services/network/public/cpp:cpp", "//ui/base", ] + + if (is_ios || is_android) { + sources += [ "translate_infobar_delegate_unittest.cc" ] + } } source_set("test_support") {
diff --git a/components/translate/core/browser/DEPS b/components/translate/core/browser/DEPS index 96e8379..cdef75d 100644 --- a/components/translate/core/browser/DEPS +++ b/components/translate/core/browser/DEPS
@@ -9,5 +9,8 @@ specific_include_rules = { "translate_ranker_impl_unittest\.cc": [ "+components/ukm", + ], + "translate_metrics_logger_impl_unittest\.cc": [ + "+components/ukm", ] }
diff --git a/components/translate/core/browser/mock_translate_client.h b/components/translate/core/browser/mock_translate_client.h index 5e832f8..640535f 100644 --- a/components/translate/core/browser/mock_translate_client.h +++ b/components/translate/core/browser/mock_translate_client.h
@@ -12,6 +12,7 @@ #include "components/infobars/core/infobar.h" #include "components/translate/core/browser/translate_client.h" #include "components/translate/core/browser/translate_driver.h" +#include "components/translate/core/browser/translate_infobar_delegate.h" #include "components/translate/core/browser/translate_prefs.h" #include "components/translate/core/common/language_detection_details.h" #include "testing/gmock/include/gmock/gmock.h" @@ -40,11 +41,9 @@ MOCK_CONST_METHOD0(GetInfobarIconID, int()); #if !defined(USE_AURA) - MOCK_CONST_METHOD1(CreateInfoBarMock, - infobars::InfoBar*(TranslateInfoBarDelegate*)); std::unique_ptr<infobars::InfoBar> CreateInfoBar( std::unique_ptr<TranslateInfoBarDelegate> delegate) const { - return base::WrapUnique(CreateInfoBarMock(delegate.get())); + return std::make_unique<infobars::InfoBar>(std::move(delegate)); } #endif
diff --git a/components/translate/core/browser/mock_translate_metrics_logger.h b/components/translate/core/browser/mock_translate_metrics_logger.h index 8fba1eba..30ca4ada 100644 --- a/components/translate/core/browser/mock_translate_metrics_logger.h +++ b/components/translate/core/browser/mock_translate_metrics_logger.h
@@ -30,6 +30,7 @@ MOCK_METHOD1(OnPageLoadStart, void(bool)); MOCK_METHOD1(OnForegroundChange, void(bool)); MOCK_METHOD1(RecordMetrics, void(bool)); + MOCK_METHOD1(SetUkmSourceId, void(ukm::SourceId)); MOCK_METHOD2(LogRankerMetrics, void(RankerDecision, uint32_t)); MOCK_METHOD1(LogTriggerDecision, void(TriggerDecision)); MOCK_METHOD0(LogAutofillAssistantDeferredTriggerDecision, void());
diff --git a/components/translate/core/browser/translate_infobar_delegate.h b/components/translate/core/browser/translate_infobar_delegate.h index e93cf44c5..2a9d6e4 100644 --- a/components/translate/core/browser/translate_infobar_delegate.h +++ b/components/translate/core/browser/translate_infobar_delegate.h
@@ -248,7 +248,7 @@ bool triggered_from_menu); private: - friend class TranslationInfoBarTest; + friend class TranslateInfoBarDelegateTest; typedef std::pair<std::string, base::string16> LanguageNamePair; bool is_off_the_record_;
diff --git a/components/translate/core/browser/translate_infobar_delegate_unittest.cc b/components/translate/core/browser/translate_infobar_delegate_unittest.cc new file mode 100644 index 0000000..36cebede --- /dev/null +++ b/components/translate/core/browser/translate_infobar_delegate_unittest.cc
@@ -0,0 +1,327 @@ +// 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/translate/core/browser/translate_infobar_delegate.h" + +#include <string> +#include <vector> + +#include "base/test/task_environment.h" +#include "components/infobars/core/confirm_infobar_delegate.h" +#include "components/infobars/core/infobar.h" +#include "components/infobars/core/infobar_manager.h" +#include "components/language/core/browser/language_model.h" +#include "components/language/core/browser/language_prefs.h" +#include "components/language/core/browser/pref_names.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "components/translate/core/browser/mock_translate_client.h" +#include "components/translate/core/browser/mock_translate_driver.h" +#include "components/translate/core/browser/mock_translate_ranker.h" +#include "components/translate/core/browser/translate_accept_languages.h" +#include "components/translate/core/browser/translate_client.h" +#include "components/translate/core/browser/translate_infobar_delegate.h" +#include "components/translate/core/browser/translate_manager.h" +#include "components/translate/core/browser/translate_pref_names.h" +#include "components/translate/core/browser/translate_prefs.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Return; +using testing::Test; +using translate::testing::MockTranslateClient; +using translate::testing::MockTranslateDriver; +using translate::testing::MockTranslateRanker; + +namespace translate { + +const char kOriginalLanguage[] = "fr"; +const char kTargetLanguage[] = "en"; + +namespace { + +class TestInfoBarManager : public infobars::InfoBarManager { + public: + TestInfoBarManager() = default; + // infobars::InfoBarManager: + ~TestInfoBarManager() override {} + + // infobars::InfoBarManager: + std::unique_ptr<infobars::InfoBar> CreateConfirmInfoBar( + std::unique_ptr<ConfirmInfoBarDelegate> delegate) override { + return std::make_unique<infobars::InfoBar>(std::move(delegate)); + } + + // infobars::InfoBarManager: + int GetActiveEntryID() override { return 0; } + + // infobars::InfoBarManager: + void OpenURL(const GURL& url, WindowOpenDisposition disposition) override { + NOTREACHED(); + } +}; + +} // namespace + +class MockObserver : public TranslateInfoBarDelegate::Observer { + public: + MOCK_METHOD(void, + OnTranslateInfoBarDelegateDestroyed, + (TranslateInfoBarDelegate*), + (override)); + MOCK_METHOD(void, + OnTranslateStepChanged, + (translate::TranslateStep, TranslateErrors::Type), + (override)); + MOCK_METHOD(void, OnTargetLanguageChanged, (const std::string&), (override)); + MOCK_METHOD(bool, IsDeclinedByUser, (), (override)); +}; + +class TestLanguageModel : public language::LanguageModel { + std::vector<LanguageDetails> GetLanguages() override { + return {LanguageDetails("en", 1.0)}; + } +}; + +class TranslateInfoBarDelegateTest : public ::testing::Test { + public: + TranslateInfoBarDelegateTest() = default; + + protected: + void SetUp() override { + pref_service_ = + std::make_unique<sync_preferences::TestingPrefServiceSyncable>(); + language::LanguagePrefs::RegisterProfilePrefs(pref_service_->registry()); + pref_service_->SetString(testing::accept_languages_prefs, std::string()); + pref_service_->SetString(language::prefs::kAcceptLanguages, std::string()); +#if BUILDFLAG(IS_CHROMEOS_ASH) + pref_service_->SetString(language::prefs::kPreferredLanguages, + std::string()); +#endif + pref_service_->registry()->RegisterBooleanPref( + prefs::kOfferTranslateEnabled, true); + TranslatePrefs::RegisterProfilePrefs(pref_service_->registry()); + ranker_ = std::make_unique<MockTranslateRanker>(); + client_ = + std::make_unique<MockTranslateClient>(&driver_, pref_service_.get()); + manager_ = std::make_unique<TranslateManager>(client_.get(), ranker_.get(), + language_model_.get()); + manager_->GetLanguageState()->set_translation_declined(false); + infobar_manager_ = std::make_unique<TestInfoBarManager>(); + } + + std::unique_ptr<TranslateInfoBarDelegate> ConstructInfoBarDelegate() { + return std::unique_ptr<TranslateInfoBarDelegate>( + new TranslateInfoBarDelegate( + manager_->GetWeakPtr(), /*is_off_the_record=*/false, + translate::TranslateStep::TRANSLATE_STEP_BEFORE_TRANSLATE, + kOriginalLanguage, kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false)); + } + + MockTranslateDriver driver_; + std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_; + std::unique_ptr<MockTranslateClient> client_; + std::unique_ptr<TestLanguageModel> language_model_; + std::unique_ptr<TranslateManager> manager_; + std::unique_ptr<MockTranslateRanker> ranker_; + std::unique_ptr<TestInfoBarManager> infobar_manager_; +}; + +TEST_F(TranslateInfoBarDelegateTest, CreateTranslateInfobarDelegate) { + EXPECT_EQ(infobar_manager_->infobar_count(), 0u); + + // Create the initial InfoBar + TranslateInfoBarDelegate::Create( + /*replace_existing_infobar=*/false, manager_->GetWeakPtr(), + infobar_manager_.get(), + /*is_off_the_record=*/false, + translate::TranslateStep::TRANSLATE_STEP_TRANSLATING, kOriginalLanguage, + kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false); + + EXPECT_EQ(infobar_manager_->infobar_count(), 1u); + TranslateInfoBarDelegate* delegate = + infobar_manager_->infobar_at(0)->delegate()->AsTranslateInfoBarDelegate(); + EXPECT_FALSE(delegate->is_error()); + EXPECT_EQ(translate::TranslateStep::TRANSLATE_STEP_TRANSLATING, + delegate->translate_step()); + EXPECT_FALSE(delegate->is_off_the_record()); + EXPECT_FALSE(delegate->triggered_from_menu()); + EXPECT_EQ(delegate->target_language_code(), kTargetLanguage); + EXPECT_EQ(delegate->original_language_code(), kOriginalLanguage); + + // Create another one and replace the old one + TranslateInfoBarDelegate::Create( + /*replace_existing_infobar=*/true, manager_->GetWeakPtr(), + infobar_manager_.get(), + /*is_off_the_record=*/true, + translate::TranslateStep::TRANSLATE_STEP_AFTER_TRANSLATE, + kOriginalLanguage, kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false); + + EXPECT_EQ(infobar_manager_->infobar_count(), 1u); + delegate = + infobar_manager_->infobar_at(0)->delegate()->AsTranslateInfoBarDelegate(); + EXPECT_EQ(delegate->translate_step(), + translate::TranslateStep::TRANSLATE_STEP_AFTER_TRANSLATE); + + // Create but don't replace existing one. + TranslateInfoBarDelegate::Create( + /*replace_existing_infobar=*/false, manager_->GetWeakPtr(), + infobar_manager_.get(), + /*is_off_the_record=*/false, + translate::TranslateStep::TRANSLATE_STEP_BEFORE_TRANSLATE, + kOriginalLanguage, kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false); + + EXPECT_EQ(infobar_manager_->infobar_count(), 1u); + delegate = + infobar_manager_->infobar_at(0)->delegate()->AsTranslateInfoBarDelegate(); + ASSERT_EQ(delegate->translate_step(), + translate::TranslateStep::TRANSLATE_STEP_AFTER_TRANSLATE); +} + +TEST_F(TranslateInfoBarDelegateTest, DestructTranslateInfobarDelegate) { + MockObserver mock_observer; + std::unique_ptr<TranslateInfoBarDelegate> delegate = + ConstructInfoBarDelegate(); + EXPECT_CALL(mock_observer, + OnTranslateInfoBarDelegateDestroyed(delegate.get())); + + delegate->AddObserver(&mock_observer); + delegate.reset(); +} + +TEST_F(TranslateInfoBarDelegateTest, IsTranslatableLanguage) { + // A language is translatable if it's not blocked or is not an accept + // language. + std::unique_ptr<TranslateInfoBarDelegate> delegate = + ConstructInfoBarDelegate(); + TranslateAcceptLanguages accept_languages(pref_service_.get(), + testing::accept_languages_prefs); + ON_CALL(*(client_.get()), GetTranslateAcceptLanguages()) + .WillByDefault(Return(&accept_languages)); + ListPrefUpdate update(pref_service_.get(), language::prefs::kFluentLanguages); + update->Append(kOriginalLanguage); + pref_service_->SetString(language::prefs::kAcceptLanguages, + kOriginalLanguage); +#if BUILDFLAG(IS_CHROMEOS_ASH) + pref_service_->SetString(language::prefs::kPreferredLanguages, + kOriginalLanguage); +#endif + + EXPECT_FALSE(delegate->IsTranslatableLanguageByPrefs()); + + // Remove kOriginalLanguage from the blocked languages. + update->EraseListValue(base::Value(kOriginalLanguage)); + EXPECT_TRUE(delegate->IsTranslatableLanguageByPrefs()); +} + +TEST_F(TranslateInfoBarDelegateTest, ShouldAutoAlwaysTranslate) { + DictionaryPrefUpdate update_translate_accepted_count( + pref_service_.get(), TranslatePrefs::kPrefTranslateAcceptedCount); + base::DictionaryValue* update_translate_accepted_dict = + update_translate_accepted_count.Get(); + // 6 = kAutoAlwaysThreshold + 1 + update_translate_accepted_dict->SetInteger(kOriginalLanguage, 6); + + const base::DictionaryValue* dict = pref_service_->GetDictionary( + TranslatePrefs::kPrefTranslateAutoAlwaysCount); + int translate_auto_always_count = 0; + dict->GetInteger(kOriginalLanguage, &translate_auto_always_count); + EXPECT_EQ(0, translate_auto_always_count); + + TranslateInfoBarDelegate::Create( + /*replace_existing_infobar=*/true, manager_->GetWeakPtr(), + infobar_manager_.get(), + /*is_off_the_record=*/false, + translate::TranslateStep::TRANSLATE_STEP_TRANSLATING, kOriginalLanguage, + kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false); + TranslateInfoBarDelegate* delegate = + infobar_manager_->infobar_at(0)->delegate()->AsTranslateInfoBarDelegate(); + EXPECT_TRUE(delegate->ShouldAutoAlwaysTranslate()); + + int count = -1; + update_translate_accepted_dict->GetInteger(kOriginalLanguage, &count); + EXPECT_EQ(0, count); + dict = pref_service_->GetDictionary( + TranslatePrefs::kPrefTranslateAutoAlwaysCount); + translate_auto_always_count = 0; + dict->GetInteger(kOriginalLanguage, &translate_auto_always_count); + EXPECT_EQ(1, translate_auto_always_count); +} + +TEST_F(TranslateInfoBarDelegateTest, ShouldNotAutoAlwaysTranslate) { + // Create an off record info bar. + TranslateInfoBarDelegate::Create( + /*replace_existing_infobar=*/false, manager_->GetWeakPtr(), + infobar_manager_.get(), /*is_off_the_record=*/true, + translate::TranslateStep::TRANSLATE_STEP_TRANSLATING, kOriginalLanguage, + kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false); + + EXPECT_EQ(infobar_manager_->infobar_count(), 1u); + TranslateInfoBarDelegate* delegate = + infobar_manager_->infobar_at(0)->delegate()->AsTranslateInfoBarDelegate(); + EXPECT_FALSE(delegate->ShouldAutoAlwaysTranslate()); +} + +TEST_F(TranslateInfoBarDelegateTest, ShouldAutoNeverTranslate) { + TranslateAcceptLanguages accept_languages(pref_service_.get(), + testing::accept_languages_prefs); + ON_CALL(*(client_.get()), GetTranslateAcceptLanguages()) + .WillByDefault(Return(&accept_languages)); + + DictionaryPrefUpdate update_translate_denied_count( + pref_service_.get(), TranslatePrefs::kPrefTranslateDeniedCount); + base::DictionaryValue* update_translate_denied_dict = + update_translate_denied_count.Get(); + // 21 = kAutoNeverThreshold + 1 + update_translate_denied_dict->SetInteger(kOriginalLanguage, 21); + + const base::DictionaryValue* dict = pref_service_->GetDictionary( + TranslatePrefs::kPrefTranslateAutoNeverCount); + int translate_auto_never_count = 0; + dict->GetInteger(kOriginalLanguage, &translate_auto_never_count); + EXPECT_EQ(0, translate_auto_never_count); + + TranslateInfoBarDelegate::Create( + /*replace_existing_infobar=*/true, manager_->GetWeakPtr(), + infobar_manager_.get(), + /*is_off_the_record=*/false, + translate::TranslateStep::TRANSLATE_STEP_TRANSLATING, kOriginalLanguage, + kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false); + TranslateInfoBarDelegate* delegate = + infobar_manager_->infobar_at(0)->delegate()->AsTranslateInfoBarDelegate(); + EXPECT_TRUE(delegate->ShouldAutoNeverTranslate()); + + int count = -1; + update_translate_denied_dict->GetInteger(kOriginalLanguage, &count); + EXPECT_EQ(0, count); + dict = pref_service_->GetDictionary( + TranslatePrefs::kPrefTranslateAutoNeverCount); + translate_auto_never_count = 0; + dict->GetInteger(kOriginalLanguage, &translate_auto_never_count); + EXPECT_EQ(1, translate_auto_never_count); +} + +TEST_F(TranslateInfoBarDelegateTest, ShouldAutoNeverTranslate_Not) { + // Create an off record info bar. + TranslateInfoBarDelegate::Create( + /*replace_existing_infobar=*/false, manager_->GetWeakPtr(), + infobar_manager_.get(), /*is_off_the_record=*/true, + translate::TranslateStep::TRANSLATE_STEP_TRANSLATING, kOriginalLanguage, + kTargetLanguage, TranslateErrors::Type::NONE, + /*triggered_from_menu=*/false); + + EXPECT_EQ(infobar_manager_->infobar_count(), 1u); + TranslateInfoBarDelegate* delegate = + infobar_manager_->infobar_at(0)->delegate()->AsTranslateInfoBarDelegate(); + EXPECT_FALSE(delegate->ShouldAutoNeverTranslate()); +} + +} // namespace translate
diff --git a/components/translate/core/browser/translate_metrics_logger.h b/components/translate/core/browser/translate_metrics_logger.h index a3c5b904..1782a3c2 100644 --- a/components/translate/core/browser/translate_metrics_logger.h +++ b/components/translate/core/browser/translate_metrics_logger.h
@@ -9,6 +9,7 @@ #include <string> #include "components/translate/core/common/translate_errors.h" +#include "services/metrics/public/cpp/ukm_source_id.h" namespace translate { @@ -57,6 +58,8 @@ kMaxValue = kAutomaticTranslationByPref, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class UIInteraction { kUninitialized = 0, kTranslate = 1, @@ -89,6 +92,9 @@ // won't be called again. virtual void RecordMetrics(bool is_final) = 0; + // Sets the UKM source ID for the current page load. + virtual void SetUkmSourceId(ukm::SourceId ukm_source_id) = 0; + virtual void LogRankerMetrics(RankerDecision ranker_decision, uint32_t ranker_version) = 0;
diff --git a/components/translate/core/browser/translate_metrics_logger_impl.cc b/components/translate/core/browser/translate_metrics_logger_impl.cc index 96460d2..9fcc6825 100644 --- a/components/translate/core/browser/translate_metrics_logger_impl.cc +++ b/components/translate/core/browser/translate_metrics_logger_impl.cc
@@ -8,6 +8,9 @@ #include "base/metrics/metrics_hashes.h" #include "base/time/default_tick_clock.h" #include "components/translate/core/browser/translate_manager.h" +#include "services/metrics/public/cpp/metrics_utils.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_recorder.h" namespace translate { @@ -63,18 +66,74 @@ void TranslateMetricsLoggerImpl::RecordMetrics(bool is_final) { UpdateTimeTranslated(current_state_is_translated_, is_foreground_); + // If a translation is still in progress, then use the previous state. + bool this_initial_state_is_translated = + is_initial_state_dependent_on_in_progress_translation_ + ? previous_state_is_translated_ + : initial_state_is_translated_; + bool this_current_state_is_translated = is_translation_in_progress_ + ? previous_state_is_translated_ + : current_state_is_translated_; + // The first time |RecordMetrics| is called, record all page load frequency // UMA metrcis. if (sequence_no_ == 0) - RecordPageLoadUmaMetrics(); + RecordPageLoadUmaMetrics(this_initial_state_is_translated, + this_current_state_is_translated); - // TODO(curranmax): Log UKM metrics now that the page load is. - // completed. https://crbug.com/1114868. + // Record metrics to UKM. + ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get(); + ukm::builders::TranslatePageLoad(ukm_source_id_) + .SetSequenceNumber(sequence_no_) + .SetTriggerDecision(int(trigger_decision_)) + .SetRankerDecision(int(ranker_decision_)) + .SetRankerVersion(int(ranker_version_)) + .SetInitialState(int(ConvertToTranslateState( + this_initial_state_is_translated, initial_state_is_ui_shown_, + initial_state_is_omnibox_icon_shown_))) + .SetFinalState(int(ConvertToTranslateState( + this_current_state_is_translated, current_state_is_ui_shown_, + current_state_is_omnibox_icon_shown_))) + .SetNumTranslations( + ukm::GetExponentialBucketMinForCounts1000(num_translations_)) + .SetNumReversions( + ukm::GetExponentialBucketMinForCounts1000(num_reversions_)) + .SetInitialSourceLanguage( + int(base::HashMetricName(initial_source_language_))) + .SetFinalSourceLanguage( + int(base::HashMetricName(current_source_language_))) + .SetInitialSourceLanguageInContentLanguages( + int(is_initial_source_language_in_users_content_languages_)) + .SetInitialTargetLanguage( + int(base::HashMetricName(initial_target_language_))) + .SetFinalTargetLanguage( + int(base::HashMetricName(current_target_language_))) + .SetNumTargetLanguageChanges(ukm::GetExponentialBucketMinForCounts1000( + num_target_language_changes_)) + .SetFirstUIInteraction(int(first_ui_interaction_)) + .SetNumUIInteractions( + ukm::GetExponentialBucketMinForCounts1000(num_ui_interactions_)) + .SetFirstTranslateError(int(first_translate_error_type_)) + .SetNumTranslateErrors( + ukm::GetExponentialBucketMinForCounts1000(num_translate_errors_)) + .SetTotalTimeTranslated(ukm::GetExponentialBucketMinForUserTiming( + total_time_translated_.InSeconds())) + .SetTotalTimeNotTranslated(ukm::GetExponentialBucketMinForUserTiming( + total_time_not_translated_.InSeconds())) + .SetMaxTimeToTranslate(ukm::GetExponentialBucketMinForUserTiming( + max_time_to_translate_.InMilliseconds())) + .Record(ukm_recorder); sequence_no_++; } -void TranslateMetricsLoggerImpl::RecordPageLoadUmaMetrics() { +void TranslateMetricsLoggerImpl::SetUkmSourceId(ukm::SourceId ukm_source_id) { + ukm_source_id_ = ukm_source_id; +} + +void TranslateMetricsLoggerImpl::RecordPageLoadUmaMetrics( + bool initial_state_is_translated, + bool current_state_is_translated) { base::UmaHistogramEnumeration(kTranslatePageLoadRankerDecision, ranker_decision_); base::UmaHistogramSparse(kTranslatePageLoadRankerVersion, @@ -85,23 +144,14 @@ kTranslatePageLoadAutofillAssistantDeferredTriggerDecision, autofill_assistant_deferred_trigger_decision_); - // If a translation is still in progress, then use the previous state. - bool this_initial_state_is_translated = - is_initial_state_dependent_on_in_progress_translation_ - ? previous_state_is_translated_ - : initial_state_is_translated_; - bool this_current_state_is_translated = is_translation_in_progress_ - ? previous_state_is_translated_ - : current_state_is_translated_; - base::UmaHistogramEnumeration( kTranslatePageLoadInitialState, - ConvertToTranslateState(this_initial_state_is_translated, + ConvertToTranslateState(initial_state_is_translated, initial_state_is_ui_shown_, initial_state_is_omnibox_icon_shown_)); base::UmaHistogramEnumeration( kTranslatePageLoadFinalState, - ConvertToTranslateState(this_current_state_is_translated, + ConvertToTranslateState(current_state_is_translated, current_state_is_ui_shown_, current_state_is_omnibox_icon_shown_)); base::UmaHistogramCounts10000(kTranslatePageLoadNumTranslations,
diff --git a/components/translate/core/browser/translate_metrics_logger_impl.h b/components/translate/core/browser/translate_metrics_logger_impl.h index 93d1b12..10e4026 100644 --- a/components/translate/core/browser/translate_metrics_logger_impl.h +++ b/components/translate/core/browser/translate_metrics_logger_impl.h
@@ -41,6 +41,7 @@ void OnPageLoadStart(bool is_foreground) override {} void OnForegroundChange(bool is_foreground) override {} void RecordMetrics(bool is_final) override {} + void SetUkmSourceId(ukm::SourceId ukm_source_id) override {} void LogRankerMetrics(RankerDecision ranker_decision, uint32_t ranker_version) override {} void LogTriggerDecision(TriggerDecision trigger_decision) override {} @@ -85,6 +86,7 @@ void OnPageLoadStart(bool is_foreground) override; void OnForegroundChange(bool is_foreground) override; void RecordMetrics(bool is_final) override; + void SetUkmSourceId(ukm::SourceId ukm_source_id) override; void LogRankerMetrics(RankerDecision ranker_decision, uint32_t ranker_version) override; void LogTriggerDecision(TriggerDecision trigger_decision) override; @@ -108,7 +110,8 @@ friend class testing::TranslateMetricsLoggerImplTest; // Logs all page load frequency UMA metrics based on the stored state. - void RecordPageLoadUmaMetrics(); + void RecordPageLoadUmaMetrics(bool initial_state_is_translated, + bool current_stat_is_translated); // Helpter function to get the correct |TranslateState| value based on the // different dimensions we care about. @@ -128,6 +131,9 @@ // recorded UKM protos. unsigned int sequence_no_ = 0; + // The UKM source ID for the current page load. + ukm::SourceId ukm_source_id_ = ukm::kInvalidSourceId; + // Tracks if the associated page is in the foreground (|true|) or the // background (|false|) bool is_foreground_ = false;
diff --git a/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc b/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc index d4c3f44b..546f49f 100644 --- a/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc +++ b/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc
@@ -5,23 +5,54 @@ #include "components/translate/core/browser/translate_metrics_logger_impl.h" #include <memory> +#include <vector> #include "base/logging.h" #include "base/metrics/metrics_hashes.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_tick_clock.h" +#include "base/test/task_environment.h" +#include "components/ukm/test_ukm_recorder.h" +#include "services/metrics/public/cpp/metrics_utils.h" +#include "services/metrics/public/cpp/ukm_builders.h" #include "testing/gtest/include/gtest/gtest.h" namespace translate { namespace testing { +namespace { +const char* kAllUkmMetricNames[] = { + ukm::builders::TranslatePageLoad::kSequenceNumberName, + ukm::builders::TranslatePageLoad::kTriggerDecisionName, + ukm::builders::TranslatePageLoad::kRankerDecisionName, + ukm::builders::TranslatePageLoad::kRankerVersionName, + ukm::builders::TranslatePageLoad::kInitialStateName, + ukm::builders::TranslatePageLoad::kFinalStateName, + ukm::builders::TranslatePageLoad::kNumTranslationsName, + ukm::builders::TranslatePageLoad::kNumReversionsName, + ukm::builders::TranslatePageLoad::kInitialSourceLanguageName, + ukm::builders::TranslatePageLoad::kFinalSourceLanguageName, + ukm::builders::TranslatePageLoad:: + kInitialSourceLanguageInContentLanguagesName, + ukm::builders::TranslatePageLoad::kInitialTargetLanguageName, + ukm::builders::TranslatePageLoad::kFinalTargetLanguageName, + ukm::builders::TranslatePageLoad::kNumTargetLanguageChangesName, + ukm::builders::TranslatePageLoad::kFirstUIInteractionName, + ukm::builders::TranslatePageLoad::kNumUIInteractionsName, + ukm::builders::TranslatePageLoad::kFirstTranslateErrorName, + ukm::builders::TranslatePageLoad::kNumTranslateErrorsName, + ukm::builders::TranslatePageLoad::kTotalTimeTranslatedName, + ukm::builders::TranslatePageLoad::kTotalTimeNotTranslatedName, + ukm::builders::TranslatePageLoad::kMaxTimeToTranslateName}; +} // namespace + class TranslateMetricsLoggerImplTest : public ::testing::Test { public: void ResetTest() { translate_metrics_logger_ = std::make_unique<TranslateMetricsLoggerImpl>( nullptr /*translate_manager*/); - histogram_tester_ = std::make_unique<base::HistogramTester>(); + test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); } void SetUp() override { ResetTest(); } @@ -32,6 +63,10 @@ base::HistogramTester* histogram_tester() { return histogram_tester_.get(); } + ukm::TestAutoSetUkmRecorder* test_ukm_recorder() { + return test_ukm_recorder_.get(); + } + void CheckTranslateStateHistograms(TranslateState expected_initial_state, TranslateState expected_final_state, int expected_num_translations, @@ -75,14 +110,341 @@ expected_num_ui_interactions); } + // Helper functions to check that the metrics in the given UKM entry match + // expectations. + void CheckUkmEntrySequenceNumber( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + int expected_sequence_number) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kSequenceNumberName), + expected_sequence_number); + } + + void CheckUkmEntryTriggerDecision( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + TriggerDecision expected_trigger_decision) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kTriggerDecisionName), + int(expected_trigger_decision)); + } + + void CheckUkmEntryRankerDecision( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + RankerDecision expected_ranker_decision) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kRankerDecisionName), + int(expected_ranker_decision)); + } + + void CheckUkmEntryRankerVersion( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + uint32_t expected_ranker_version) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kRankerVersionName), + int(expected_ranker_version)); + } + + void CheckUkmEntryInitialState( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + TranslateState expected_initial_state) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kInitialStateName), + int(expected_initial_state)); + } + + void CheckUkmEntryFinalState( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + TranslateState expected_final_state) { + EXPECT_EQ( + ukm_entry.metrics.at(ukm::builders::TranslatePageLoad::kFinalStateName), + int(expected_final_state)); + } + + void CheckUkmEntryNumTranslations( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + int expected_num_translations) { + EXPECT_EQ( + ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kNumTranslationsName), + ukm::GetExponentialBucketMinForCounts1000(expected_num_translations)); + } + + void CheckUkmEntryNumReversions( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + int expected_num_reversions) { + EXPECT_EQ( + ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kNumReversionsName), + ukm::GetExponentialBucketMinForCounts1000(expected_num_reversions)); + } + + void CheckUkmEntryInitialSourceLanguage( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + const std::string& expected_initial_source_language) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kInitialSourceLanguageName), + int(base::HashMetricName(expected_initial_source_language))); + } + + void CheckUkmEntryFinalSourceLanguage( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + const std::string& expected_final_source_language) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kFinalSourceLanguageName), + int(base::HashMetricName(expected_final_source_language))); + } + + void CheckUkmEntryInitialSourceLanguageInContentLanguages( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + bool expected_is_initial_source_language_in_content_languages) { + EXPECT_EQ( + ukm_entry.metrics.at(ukm::builders::TranslatePageLoad:: + kInitialSourceLanguageInContentLanguagesName), + int(expected_is_initial_source_language_in_content_languages)); + } + + void CheckUkmEntryInitialTargetLanguage( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + const std::string& expected_initial_target_language) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kInitialTargetLanguageName), + int(base::HashMetricName(expected_initial_target_language))); + } + + void CheckUkmEntryFinalTargetLanguage( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + const std::string& expected_final_target_language) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kFinalTargetLanguageName), + int(base::HashMetricName(expected_final_target_language))); + } + + void CheckUkmEntryNumTargetLanguageChanges( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + int expected_num_target_language_changes) { + EXPECT_EQ( + ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kNumTargetLanguageChangesName), + ukm::GetExponentialBucketMinForCounts1000( + expected_num_target_language_changes)); + } + + void CheckUkmEntryFirstUIInteraction( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + UIInteraction expected_first_ui_interaction) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kFirstUIInteractionName), + int(expected_first_ui_interaction)); + } + + void CheckUkmEntryNumUIInteractions( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + int expected_num_ui_interactions) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kNumUIInteractionsName), + ukm::GetExponentialBucketMinForCounts1000( + expected_num_ui_interactions)); + } + + void CheckUkmEntryFirstTranslateError( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + TranslateErrors::Type expected_first_translate_error) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kFirstTranslateErrorName), + int(expected_first_translate_error)); + } + + void CheckUkmEntryNumTranslateErrors( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + int expected_num_translate_errors) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kNumTranslateErrorsName), + ukm::GetExponentialBucketMinForCounts1000( + expected_num_translate_errors)); + } + + void CheckUkmEntryTotalTimeTranslated( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + const base::TimeDelta& expected_total_time_translated) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kTotalTimeTranslatedName), + ukm::GetExponentialBucketMinForUserTiming( + expected_total_time_translated.InSeconds())); + } + + void CheckUkmEntryTotalTimeNotTranslated( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + const base::TimeDelta& expected_total_time_not_translated) { + EXPECT_EQ( + ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kTotalTimeNotTranslatedName), + ukm::GetExponentialBucketMinForUserTiming( + expected_total_time_not_translated.InSeconds())); + } + + void CheckUkmEntryMaxTimeToTranslate( + const ukm::TestUkmRecorder::HumanReadableUkmEntry& ukm_entry, + const base::TimeDelta& expected_max_time_to_translate) { + EXPECT_EQ(ukm_entry.metrics.at( + ukm::builders::TranslatePageLoad::kMaxTimeToTranslateName), + ukm::GetExponentialBucketMinForUserTiming( + expected_max_time_to_translate.InMilliseconds())); + } + private: + // Needed to set up the test UKM recorder. + base::test::SingleThreadTaskEnvironment task_environment_; + // Test target. std::unique_ptr<TranslateMetricsLoggerImpl> translate_metrics_logger_; // Records the UMA histograms for each test. std::unique_ptr<base::HistogramTester> histogram_tester_; + + // Record the UKM protos for each test. + std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_; }; +TEST_F(TranslateMetricsLoggerImplTest, RecordUkmMetrics) { + // Establish constants for this test. + base::SimpleTestTickClock test_clock; + + constexpr base::TimeDelta delay1 = base::TimeDelta::FromSeconds(100); + constexpr base::TimeDelta delay2 = base::TimeDelta::FromSeconds(200); + constexpr base::TimeDelta delay3 = base::TimeDelta::FromSeconds(300); + constexpr base::TimeDelta delay4 = base::TimeDelta::FromSeconds(400); + constexpr base::TimeDelta delay5 = base::TimeDelta::FromSeconds(500); + + constexpr base::TimeDelta translation_delay1 = + base::TimeDelta::FromSeconds(10); + constexpr base::TimeDelta translation_delay2 = + base::TimeDelta::FromSeconds(30); + constexpr base::TimeDelta translation_delay3 = + base::TimeDelta::FromSeconds(20); + + const ukm::SourceId ukm_source_id = 4321; + + const RankerDecision ranker_decision = RankerDecision::kShowUI; + const uint32_t ranker_model_version = 1234; + + const TriggerDecision trigger_decision = + TriggerDecision::kDisabledNeverTranslateSite; + + const std::string initial_source_language = "es"; + const bool is_initial_source_language_in_users_content_languages = true; + const std::string final_source_language = "it"; + + const std::string initial_target_language = "de"; + const std::string final_target_language = "fr"; + + // Simulate a page load where the following happens: the Ranker decides to + // show the translate UI, the user initiates a manual translation which + // finishes without an error, the user reverts the translations, the user + // changes the source and target language, the user starts another + // translation but this one fails due to a network error, the user tries to + // translate again and this time the translation succeeds, and then finally + // the user closes the translate UI. + translate_metrics_logger()->SetInternalClockForTesting(&test_clock); + translate_metrics_logger()->OnPageLoadStart(true); + translate_metrics_logger()->SetUkmSourceId(ukm_source_id); + + translate_metrics_logger()->LogInitialSourceLanguage( + initial_source_language, + is_initial_source_language_in_users_content_languages); + translate_metrics_logger()->LogTargetLanguage(initial_target_language); + translate_metrics_logger()->LogRankerMetrics(ranker_decision, + ranker_model_version); + translate_metrics_logger()->LogTriggerDecision(trigger_decision); + translate_metrics_logger()->LogUIChange(true); + translate_metrics_logger()->LogInitialState(); + + test_clock.Advance(delay1); + + translate_metrics_logger()->LogUIInteraction(UIInteraction::kTranslate); + + translate_metrics_logger()->LogTranslationStarted(); + test_clock.Advance(translation_delay1); + translate_metrics_logger()->LogTranslationFinished(true, + TranslateErrors::NONE); + + test_clock.Advance(delay2); + + translate_metrics_logger()->LogUIInteraction(UIInteraction::kRevert); + translate_metrics_logger()->LogReversion(); + + test_clock.Advance(delay3); + + translate_metrics_logger()->LogUIInteraction( + UIInteraction::kChangeSourceLanguage); + translate_metrics_logger()->LogSourceLanguage(final_source_language); + translate_metrics_logger()->LogUIInteraction( + UIInteraction::kChangeTargetLanguage); + translate_metrics_logger()->LogTargetLanguage(final_target_language); + translate_metrics_logger()->LogUIInteraction(UIInteraction::kTranslate); + + translate_metrics_logger()->LogTranslationStarted(); + test_clock.Advance(translation_delay2); + translate_metrics_logger()->LogTranslationFinished(false, + TranslateErrors::NETWORK); + + test_clock.Advance(delay4); + + translate_metrics_logger()->LogUIInteraction(UIInteraction::kTranslate); + + translate_metrics_logger()->LogTranslationStarted(); + test_clock.Advance(translation_delay3); + translate_metrics_logger()->LogTranslationFinished(true, + TranslateErrors::NONE); + + test_clock.Advance(delay5); + + translate_metrics_logger()->LogUIInteraction( + UIInteraction::kCloseUIExplicitly); + translate_metrics_logger()->LogUIChange(false); + + // Record stored metrics. + translate_metrics_logger()->RecordMetrics(true); + + // Check that the recorded UKM proto matches expectations. + auto ukm_entries = test_ukm_recorder()->GetEntries( + ukm::builders::TranslatePageLoad::kEntryName, + std::vector<std::string>(std::begin(kAllUkmMetricNames), + std::end(kAllUkmMetricNames))); + + // Expect that ukm_entries has one element. + EXPECT_EQ(ukm_entries.size(), 1u); + + // Only element has a source_id of ukm_source_id + EXPECT_EQ(ukm_entries[0].source_id, ukm_source_id); + + // Check each metric in the UKM entry. + CheckUkmEntrySequenceNumber(ukm_entries[0], 0); + CheckUkmEntryTriggerDecision(ukm_entries[0], trigger_decision); + CheckUkmEntryRankerDecision(ukm_entries[0], ranker_decision); + CheckUkmEntryRankerVersion(ukm_entries[0], ranker_model_version); + CheckUkmEntryInitialState(ukm_entries[0], + TranslateState::kNotTranslatedUIShown); + CheckUkmEntryFinalState(ukm_entries[0], TranslateState::kTranslatedNoUI); + CheckUkmEntryNumTranslations(ukm_entries[0], 2); + CheckUkmEntryNumReversions(ukm_entries[0], 1); + CheckUkmEntryInitialSourceLanguage(ukm_entries[0], initial_source_language); + CheckUkmEntryFinalSourceLanguage(ukm_entries[0], final_source_language); + CheckUkmEntryInitialSourceLanguageInContentLanguages( + ukm_entries[0], is_initial_source_language_in_users_content_languages); + CheckUkmEntryInitialTargetLanguage(ukm_entries[0], initial_target_language); + CheckUkmEntryFinalTargetLanguage(ukm_entries[0], final_target_language); + CheckUkmEntryNumTargetLanguageChanges(ukm_entries[0], 1); + CheckUkmEntryFirstUIInteraction(ukm_entries[0], UIInteraction::kTranslate); + CheckUkmEntryNumUIInteractions(ukm_entries[0], 7); + CheckUkmEntryFirstTranslateError(ukm_entries[0], TranslateErrors::NETWORK); + CheckUkmEntryNumTranslateErrors(ukm_entries[0], 1); + CheckUkmEntryTotalTimeTranslated(ukm_entries[0], delay2 + delay5); + CheckUkmEntryTotalTimeNotTranslated( + ukm_entries[0], delay1 + delay3 + delay4 + translation_delay1 + + translation_delay2 + translation_delay3); + CheckUkmEntryMaxTimeToTranslate(ukm_entries[0], translation_delay3); +} + TEST_F(TranslateMetricsLoggerImplTest, MultipleRecordMetrics) { // Set test constants and log them with the test target. RankerDecision ranker_decision = RankerDecision::kShowUI;
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 6b27692..d6409537 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1705,11 +1705,35 @@ } IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityIframeAriaHidden) { + RunHtmlTest(FILE_PATH_LITERAL("iframe-aria-hidden.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityIframeCreate) { + RunHtmlTest(FILE_PATH_LITERAL("iframe-create.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityIframeCreateEmpty) { + RunHtmlTest(FILE_PATH_LITERAL("iframe-create-empty.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityIframeEmptyPositioned) { + RunHtmlTest(FILE_PATH_LITERAL("iframe-empty-positioned.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityIframeScrollable) { RunHtmlTest(FILE_PATH_LITERAL("iframe-scrollable.html")); } IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityIframeSrcdocChanged) { + RunHtmlTest(FILE_PATH_LITERAL("iframe-srcdoc-changed.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityIframePostEnable) { enable_accessibility_after_navigating_ = true; RunHtmlTest(FILE_PATH_LITERAL("iframe.html"));
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index a5f5b62ac..c94711e 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -1156,6 +1156,8 @@ map->Add<blink::mojom::PeriodicBackgroundSyncService>( BindServiceWorkerReceiver( &RenderProcessHostImpl::CreatePeriodicSyncService, host)); + map->Add<blink::mojom::PushMessaging>(BindServiceWorkerReceiver( + &RenderProcessHostImpl::BindPushMessaging, host)); } void PopulateBinderMapWithContext(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index b3d7f24..85aaafea 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2292,11 +2292,6 @@ {base::TaskPriority::USER_BLOCKING, base::MayBlock()})); #endif - AddUIThreadInterface( - registry.get(), - base::BindRepeating(&RenderProcessHostImpl::BindPushMessagingManager, - weak_factory_.GetWeakPtr())); - file_system_manager_impl_.reset(new FileSystemManagerImpl( GetID(), storage_partition_impl_->GetFileSystemContext(), ChromeBlobStorageContext::GetFor(GetBrowserContext()))); @@ -2533,8 +2528,9 @@ ->CreatePeriodicSyncService(std::move(receiver)); } -void RenderProcessHostImpl::BindPushMessagingManager( +void RenderProcessHostImpl::BindPushMessaging( mojo::PendingReceiver<blink::mojom::PushMessaging> receiver) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); push_messaging_manager_->AddPushMessagingReceiver(std::move(receiver)); }
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index e2b3d5f..cb236a1 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -585,6 +585,11 @@ mojo::PendingReceiver<media::mojom::VideoDecodePerfHistory> receiver) override; + // Binds `receiever` to the `PushMessagingManager` instance owned by the + // render process host, and is used by workers via `BrowserInterfaceBroker`. + void BindPushMessaging( + mojo::PendingReceiver<blink::mojom::PushMessaging> receiver); + // Binds |receiver| to a OneShotBackgroundSyncService instance owned by the // StoragePartition associated with the render process host, and is used by // frames and service workers via BrowserInterfaceBroker. @@ -766,8 +771,6 @@ mojo::PendingReceiver<blink::mojom::WebDatabaseHost> receiver); void BindAecDumpManager( mojo::PendingReceiver<blink::mojom::AecDumpManager> receiver); - void BindPushMessagingManager( - mojo::PendingReceiver<blink::mojom::PushMessaging> receiver); void BindP2PSocketManager( mojo::PendingReceiver<network::mojom::P2PSocketManager> receiver); void CreateMediaLogRecordHost(
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc index ff3bb07..485cfc6c 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -116,14 +116,14 @@ void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader( const network::ResourceRequest& tentative_resource_request, BrowserContext* browser_context, - ServiceWorkerLoaderCallback callback, + NavigationLoaderInterceptor::LoaderCallback loader_callback, NavigationLoaderInterceptor::FallbackCallback fallback_callback) { // InitializeContainerHost() will update the host. This is important to do // before falling back to network below, so service worker APIs still work // even if the service worker is bypassed for request interception. if (!InitializeContainerHost(tentative_resource_request)) { // We can't do anything other than to fall back to network. - std::move(callback).Run({}); + std::move(loader_callback).Run({}); return; } @@ -131,7 +131,7 @@ // request interception, or if the context is gone so we have to bypass // anyway. if (skip_service_worker_ || !context_) { - std::move(callback).Run({}); + std::move(loader_callback).Run({}); return; } @@ -145,7 +145,7 @@ // headers between now and when the request handler passed to // |loader_callback_| is invoked. if (ShouldFallbackToLoadOfflinePage(tentative_resource_request.headers)) { - std::move(callback).Run({}); + std::move(loader_callback).Run({}); return; } #endif // BUILDFLAG(ENABLE_OFFLINE_PAGES) @@ -160,7 +160,7 @@ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "URL", tentative_resource_request.url.spec()); - loader_callback_ = std::move(callback); + loader_callback_ = std::move(loader_callback); fallback_callback_ = std::move(fallback_callback); registration_lookup_start_time_ = base::TimeTicks::Now(); browser_context_ = browser_context; @@ -426,8 +426,9 @@ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "Info", "Forwarded to the ServiceWorker"); std::move(loader_callback_) - .Run(base::BindOnce(&ServiceWorkerMainResourceLoader::StartRequest, - loader_wrapper_->get()->AsWeakPtr())); + .Run(base::MakeRefCounted<SingleRequestURLLoaderFactory>( + base::BindOnce(&ServiceWorkerMainResourceLoader::StartRequest, + loader_wrapper_->get()->AsWeakPtr()))); } void ServiceWorkerControlleeRequestHandler::DidUpdateRegistration(
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.h b/content/browser/service_worker/service_worker_controllee_request_handler.h index 266b397..e9b5c26 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.h +++ b/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -52,12 +52,10 @@ // This could get called multiple times during the lifetime in redirect // cases. (In fallback-to-network cases we basically forward the request // to the request to the next request handler) - using ServiceWorkerLoaderCallback = - base::OnceCallback<void(SingleRequestURLLoaderFactory::RequestHandler)>; void MaybeCreateLoader( const network::ResourceRequest& tentative_request, BrowserContext* browser_context, - ServiceWorkerLoaderCallback callback, + NavigationLoaderInterceptor::LoaderCallback loader_callback, NavigationLoaderInterceptor::FallbackCallback fallback_callback); // Does all initialization of |container_host_| for a request. @@ -113,7 +111,7 @@ bool force_update_started_; base::TimeTicks registration_lookup_start_time_; - ServiceWorkerLoaderCallback loader_callback_; + NavigationLoaderInterceptor::LoaderCallback loader_callback_; NavigationLoaderInterceptor::FallbackCallback fallback_callback_; ServiceWorkerAccessedCallback service_worker_accessed_callback_;
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc index b74404b3..9d31f41 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc
@@ -124,8 +124,7 @@ ServiceWorkerContextCore* context_core = handle_->context_wrapper()->context(); if (!context_core || !browser_context) { - LoaderCallbackWrapper(std::move(loader_callback), - /*handler=*/{}); + std::move(loader_callback).Run(/*handler=*/{}); return; } @@ -198,19 +197,15 @@ // ControllerServiceWorkerInfoPtr and ServiceWorkerObjectHost from the // subresource loader params which is created by the interceptor. if (inherit_container_host_only) { - LoaderCallbackWrapper(std::move(loader_callback), - /*handler=*/{}); + std::move(loader_callback).Run(/*handler=*/{}); return; } } - // Start the inner interceptor. We continue in - // LoaderCallbackWrapper() or the fallback callback is called. + // Start the inner interceptor. It will invoke the loader callback + // or fallback callback. handle_->interceptor()->MaybeCreateLoader( - tentative_resource_request, browser_context, - base::BindOnce( - &ServiceWorkerMainResourceLoaderInterceptor::LoaderCallbackWrapper, - GetWeakPtr(), std::move(loader_callback)), + tentative_resource_request, browser_context, std::move(loader_callback), std::move(fallback_callback)); } @@ -261,28 +256,6 @@ return base::Optional<SubresourceLoaderParams>(std::move(params)); } -void ServiceWorkerMainResourceLoaderInterceptor::LoaderCallbackWrapper( - LoaderCallback loader_callback, - SingleRequestURLLoaderFactory::RequestHandler handler) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - if (!handler) { - std::move(loader_callback).Run({}); - return; - } - - // The inner interceptor wants to handle the request. - std::move(loader_callback) - .Run(base::MakeRefCounted<SingleRequestURLLoaderFactory>( - std::move(handler))); -} - -base::WeakPtr<ServiceWorkerMainResourceLoaderInterceptor> -ServiceWorkerMainResourceLoaderInterceptor::GetWeakPtr() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - return weak_factory_.GetWeakPtr(); -} - ServiceWorkerMainResourceLoaderInterceptor:: ServiceWorkerMainResourceLoaderInterceptor( base::WeakPtr<ServiceWorkerMainResourceHandle> handle,
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h index b35cfb2..8997c46 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h +++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h
@@ -72,12 +72,6 @@ base::Optional<SubresourceLoaderParams> MaybeCreateSubresourceLoaderParams() override; - void LoaderCallbackWrapper( - LoaderCallback loader_callback, - SingleRequestURLLoaderFactory::RequestHandler handler); - - base::WeakPtr<ServiceWorkerMainResourceLoaderInterceptor> GetWeakPtr(); - private: friend class ServiceWorkerMainResourceLoaderInterceptorTest; @@ -132,9 +126,6 @@ const int process_id_; const base::Optional<DedicatedOrSharedWorkerToken> worker_token_; - base::WeakPtrFactory<ServiceWorkerMainResourceLoaderInterceptor> - weak_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(ServiceWorkerMainResourceLoaderInterceptor); };
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index fc894e22..c912ce5f 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -516,22 +516,48 @@ // Internal state ------------------------------------------------------------ - // Indicates whether the WebContents is being captured (e.g., for screenshots - // or mirroring). Increment calls must be balanced with an equivalent number - // of decrement calls. |capture_size| specifies the capturer's video - // resolution, but can be empty to mean "unspecified." The first screen - // capturer that provides a non-empty |capture_size| will override the value - // returned by GetPreferredSize() until all captures have ended. |stay_hidden| - // determines whether to treat the underlying page as user-visible or not. + // Indicates whether the WebContents is being captured (e.g., for screenshots, + // or mirroring video and/or audio). Each IncrementCapturerCount() call must + // be balanced with a corresponding DecrementCapturerCount() call. + // + // Both internal-to-content and embedders must increment the capturer count + // while capturing to ensure "hidden rendering" optimizations are disabled. + // For example, renderers will be configured to produce compositor frames + // regardless of their "backgrounded" or on-screen occlusion state. + // + // Embedders can detect whether a WebContents is being captured (see + // IsBeingCaptured() below) and use this, for example, to provide an + // alternative user interface. So, developers should be careful to understand + // the side-effects from using or changing these APIs, both upstream and + // downstream of this API layer. + // + // |capture_size| is only used in the case of mirroring (i.e., screen capture + // video); otherwise, an empty gfx::Size should be provided. This specifies + // the capturer's target video resolution, but can be empty to mean + // "unspecified." This becomes a temporary override to GetPreferredSize(), + // allowing embedders to size the WebContents on-screen views for optimal + // capture quality. + // + // |stay_hidden| affects the page visibility state of the renderers (i.e., a + // web page can be made aware of whether it is actually user-visible). If + // true, the show/hide state of the WebContents will be passed to the + // renderers, like normal. If false, the renderers will always be told they + // are user-visible while being captured. virtual void IncrementCapturerCount(const gfx::Size& capture_size, bool stay_hidden) = 0; virtual void DecrementCapturerCount(bool stay_hidden) = 0; + + // Returns true if audio/screenshot/video is being captured by the embedder, + // as indicated by calls to IncrementCapturerCount(). virtual bool IsBeingCaptured() = 0; - // Returns true if there is any active capturer that called - // IncrementCaptureCount() with |stay_hidden|==false. + + // Returns true if audio/screenshot/video is being captured by the embedder + // and renderers are being told they are always user-visible, as indicated by + // calls to IncrementCapturerCount(). virtual bool IsBeingVisiblyCaptured() = 0; // Indicates/Sets whether all audio output from this WebContents is muted. + // This does not affect audio capture, just local/system output. virtual bool IsAudioMuted() = 0; virtual void SetAudioMuted(bool mute) = 0;
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index 686cb4b..69ec6c38 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -552,10 +552,6 @@ indirect_child_ids); } - if (src.IsScrollableContainer()) { - SerializeScrollAttributes(src, dst); - } - if (dst->id == image_data_node_id_) { // In general, string attributes should be truncated using // TruncateAndAddStringAttribute, but ImageDataUrl contains a data url @@ -705,30 +701,6 @@ src.ContainerLiveRegionRelevant().Utf8()); } -void BlinkAXTreeSource::SerializeScrollAttributes(WebAXObject src, - ui::AXNodeData* dst) const { - // Only mark as scrollable if user has actual scrollbars to use. - dst->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable, - src.IsUserScrollable()); - // Provide x,y scroll info if scrollable in any way (programmatically or via - // user). - const gfx::Point& scroll_offset = src.GetScrollOffset(); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollX, scroll_offset.x()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollY, scroll_offset.y()); - - const gfx::Point& min_scroll_offset = src.MinimumScrollOffset(); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin, - min_scroll_offset.x()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin, - min_scroll_offset.y()); - - const gfx::Point& max_scroll_offset = src.MaximumScrollOffset(); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax, - max_scroll_offset.x()); - dst->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax, - max_scroll_offset.y()); -} - void BlinkAXTreeSource::SerializeChooserPopupAttributes( WebAXObject src, ui::AXNodeData* dst) const {
diff --git a/content/renderer/accessibility/blink_ax_tree_source.h b/content/renderer/accessibility/blink_ax_tree_source.h index 4a2e02f..ebf3261 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.h +++ b/content/renderer/accessibility/blink_ax_tree_source.h
@@ -144,8 +144,6 @@ ui::AXNodeData* dst) const; void SerializeLiveRegionAttributes(blink::WebAXObject src, ui::AXNodeData* dst) const; - void SerializeScrollAttributes(blink::WebAXObject src, - ui::AXNodeData* dst) const; void SerializeChooserPopupAttributes(blink::WebAXObject src, ui::AXNodeData* dst) const; void SerializeOtherScreenReaderAttributes(blink::WebAXObject src,
diff --git a/content/test/data/accessibility/html/iframe-aria-hidden-expected-android.txt b/content/test/data/accessibility/html/iframe-aria-hidden-expected-android.txt new file mode 100644 index 0000000..32cf95fa --- /dev/null +++ b/content/test/data/accessibility/html/iframe-aria-hidden-expected-android.txt
@@ -0,0 +1,5 @@ +android.webkit.WebView focusable focused scrollable +++android.view.View invisible +++++android.view.View scrollable +++android.view.View invisible +++++android.view.View scrollable
diff --git a/content/test/data/accessibility/html/iframe-aria-hidden-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-aria-hidden-expected-auralinux.txt new file mode 100644 index 0000000..1c48268 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-aria-hidden-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[internal frame] +++++[document web] +++[internal frame] +++++[document web] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-aria-hidden-expected-blink.txt b/content/test/data/accessibility/html/iframe-aria-hidden-expected-blink.txt new file mode 100644 index 0000000..64e3db2 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-aria-hidden-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer ignored +++++++iframe invisible +++++++++rootWebArea +++++++++++genericContainer ignored +++++++++++++genericContainer ignored +++++++iframe invisible +++++++++rootWebArea +++++++++++genericContainer ignored +++++++++++++genericContainer ignored
diff --git a/content/test/data/accessibility/html/iframe-aria-hidden-expected-mac.txt b/content/test/data/accessibility/html/iframe-aria-hidden-expected-mac.txt new file mode 100644 index 0000000..3a9d66f --- /dev/null +++ b/content/test/data/accessibility/html/iframe-aria-hidden-expected-mac.txt
@@ -0,0 +1 @@ +AXWebArea
diff --git a/content/test/data/accessibility/html/iframe-aria-hidden-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-aria-hidden-expected-uia-win.txt new file mode 100644 index 0000000..8190616 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-aria-hidden-expected-uia-win.txt
@@ -0,0 +1,5 @@ +Document +++Document IsControlElement=false +++++Document +++Document IsControlElement=false +++++Document
diff --git a/content/test/data/accessibility/html/iframe-aria-hidden-expected-win.txt b/content/test/data/accessibility/html/iframe-aria-hidden-expected-win.txt new file mode 100644 index 0000000..5b037d3 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-aria-hidden-expected-win.txt
@@ -0,0 +1,5 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1>' +++IA2_ROLE_INTERNAL_FRAME INVISIBLE ia2_hypertext='<obj0>' +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++IA2_ROLE_INTERNAL_FRAME INVISIBLE ia2_hypertext='<obj0>' +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-aria-hidden.html b/content/test/data/accessibility/html/iframe-aria-hidden.html new file mode 100644 index 0000000..e0f6af8 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-aria-hidden.html
@@ -0,0 +1,10 @@ +<!-- +@WIN-ALLOW:ia2_hypertext=* +--> +<iframe tabindex="-1" aria-hidden="true" src="frame/empty.html" + style="position: absolute; width: 9em; height: 9em; top: -99em;"> +</iframe> +<!-- Use a unique @src for code that ensures all iframes are loaded --> +<iframe aria-hidden="true" src="frame/empty.html#2" + style="position: absolute; width: 9em; height: 9em; top: -99em;"> +</iframe>
diff --git a/content/test/data/accessibility/html/iframe-create-empty-expected-android.txt b/content/test/data/accessibility/html/iframe-create-empty-expected-android.txt new file mode 100644 index 0000000..4710ffa --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-empty-expected-android.txt
@@ -0,0 +1,4 @@ +android.webkit.WebView focusable focused scrollable +++android.view.View +++++android.view.View +++++++android.view.View scrollable \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-create-empty-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-create-empty-expected-auralinux.txt new file mode 100644 index 0000000..3e87e98 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-empty-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] +++[section] +++++[internal frame] +++++++[document web] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-create-empty-expected-blink.txt b/content/test/data/accessibility/html/iframe-create-empty-expected-blink.txt new file mode 100644 index 0000000..49582ee --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-empty-expected-blink.txt
@@ -0,0 +1,7 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++iframe +++++++++rootWebArea +++++++++++genericContainer ignored +++++++++++++genericContainer ignored
diff --git a/content/test/data/accessibility/html/iframe-create-empty-expected-mac.txt b/content/test/data/accessibility/html/iframe-create-empty-expected-mac.txt new file mode 100644 index 0000000..92b4eb1 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-empty-expected-mac.txt
@@ -0,0 +1,4 @@ +AXWebArea +++AXGroup +++++AXGroup +++++++AXWebArea \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-create-empty-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-create-empty-expected-uia-win.txt new file mode 100644 index 0000000..a0d01774 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-empty-expected-uia-win.txt
@@ -0,0 +1,4 @@ +Document +++Group IsControlElement=false +++++Document +++++++Document \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-create-empty-expected-win.txt b/content/test/data/accessibility/html/iframe-create-empty-expected-win.txt new file mode 100644 index 0000000..08fba45 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-empty-expected-win.txt
@@ -0,0 +1,4 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0>' +++IA2_ROLE_SECTION ia2_hypertext='<obj0>' +++++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' +++++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-create-empty.html b/content/test/data/accessibility/html/iframe-create-empty.html new file mode 100644 index 0000000..50bb0915 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-empty.html
@@ -0,0 +1,10 @@ +<!-- +@WIN-ALLOW:ia2_hypertext=* +--> +<body> +</body> +<script> + const iframe = document.createElement('iframe'); + iframe.src = 'frame/empty.html'; + document.body.appendChild(iframe); +</script>
diff --git a/content/test/data/accessibility/html/iframe-create-expected-android.txt b/content/test/data/accessibility/html/iframe-create-expected-android.txt new file mode 100644 index 0000000..5d669779 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-expected-android.txt
@@ -0,0 +1,7 @@ +android.webkit.WebView focusable focused scrollable +++android.view.View +++++android.view.View +++++++android.view.View scrollable +++++++++android.view.View +++++++++++android.view.View role_description='link' clickable focusable link name='done' +++++++++++++android.widget.TextView name='done'
diff --git a/content/test/data/accessibility/html/iframe-create-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-create-expected-auralinux.txt new file mode 100644 index 0000000..32d4f91 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] +++[section] +++++[internal frame] +++++++[document web] +++++++++[section] +++++++++++[link] name='done' +++++++++++++[static] name='done' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-create-expected-blink.txt b/content/test/data/accessibility/html/iframe-create-expected-blink.txt new file mode 100644 index 0000000..4add46a --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-expected-blink.txt
@@ -0,0 +1,10 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++iframe +++++++++rootWebArea +++++++++++genericContainer ignored +++++++++++++genericContainer +++++++++++++++link name='done' +++++++++++++++++staticText name='done' +++++++++++++++++++inlineTextBox name='done'
diff --git a/content/test/data/accessibility/html/iframe-create-expected-mac.txt b/content/test/data/accessibility/html/iframe-create-expected-mac.txt new file mode 100644 index 0000000..83dad19 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-expected-mac.txt
@@ -0,0 +1,7 @@ +AXWebArea +++AXGroup +++++AXGroup +++++++AXWebArea +++++++++AXGroup +++++++++++AXLink AXDescription='done' +++++++++++++AXStaticText AXValue='done'
diff --git a/content/test/data/accessibility/html/iframe-create-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-create-expected-uia-win.txt new file mode 100644 index 0000000..abd6efa --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-expected-uia-win.txt
@@ -0,0 +1,7 @@ +Document +++Group IsControlElement=false +++++Document +++++++Document +++++++++Group IsControlElement=false +++++++++++Hyperlink Name='done' +++++++++++++Text Name='done' IsControlElement=false \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-create-expected-win.txt b/content/test/data/accessibility/html/iframe-create-expected-win.txt new file mode 100644 index 0000000..07b8110 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create-expected-win.txt
@@ -0,0 +1,7 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0>' +++IA2_ROLE_SECTION ia2_hypertext='<obj0>' +++++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' +++++++ROLE_SYSTEM_DOCUMENT value='about:srcdoc' READONLY FOCUSABLE ia2_hypertext='<obj0>' +++++++++IA2_ROLE_SECTION ia2_hypertext='<obj0>' +++++++++++ROLE_SYSTEM_LINK name='done' FOCUSABLE ia2_hypertext='done' +++++++++++++ROLE_SYSTEM_STATICTEXT name='done' ia2_hypertext='done'
diff --git a/content/test/data/accessibility/html/iframe-create.html b/content/test/data/accessibility/html/iframe-create.html new file mode 100644 index 0000000..230e51f --- /dev/null +++ b/content/test/data/accessibility/html/iframe-create.html
@@ -0,0 +1,11 @@ +<!-- +@WIN-ALLOW:ia2_hypertext=* +@WAIT-FOR:done +--> +<body> +</body> +<script> + const iframe = document.createElement('iframe'); + iframe.srcdoc = '<a href="/">done</a>'; + document.body.appendChild(iframe); +</script>
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-android.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-android.txt new file mode 100644 index 0000000..4465176 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-android.txt
@@ -0,0 +1,5 @@ +android.webkit.WebView focusable focused scrollable +++android.view.View +++++android.view.View scrollable +++android.view.View +++++android.view.View scrollable
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-auralinux.txt new file mode 100644 index 0000000..1c48268 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-auralinux.txt
@@ -0,0 +1,5 @@ +[document web] +++[internal frame] +++++[document web] +++[internal frame] +++++[document web] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-blink.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-blink.txt new file mode 100644 index 0000000..3e04afa --- /dev/null +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer ignored +++++++iframe +++++++++rootWebArea +++++++++++genericContainer ignored +++++++++++++genericContainer ignored +++++++iframe +++++++++rootWebArea +++++++++++genericContainer ignored +++++++++++++genericContainer ignored
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-mac.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-mac.txt new file mode 100644 index 0000000..ac1b05b --- /dev/null +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-mac.txt
@@ -0,0 +1,5 @@ +AXWebArea +++AXGroup +++++AXWebArea +++AXGroup +++++AXWebArea
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-uia-win.txt new file mode 100644 index 0000000..de016ef --- /dev/null +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-uia-win.txt
@@ -0,0 +1,5 @@ +Document +++Document +++++Document +++Document +++++Document
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-win.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-win.txt new file mode 100644 index 0000000..870cb45 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-win.txt
@@ -0,0 +1,5 @@ +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1>' +++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned.html b/content/test/data/accessibility/html/iframe-empty-positioned.html new file mode 100644 index 0000000..e5936932 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-empty-positioned.html
@@ -0,0 +1,10 @@ +<!-- +@WIN-ALLOW:ia2_hypertext=* +--> +<iframe tabindex="-1" src="frame/empty.html" + style="position: absolute; width: 9em; height: 9em; top: -99em;"> +</iframe> +<!-- Use a unique @src for code that ensures all iframes are loaded --> +<iframe onload="iframeLoaded()" src="frame/empty.html#2" + style="position: absolute; width: 9em; height: 9em; top: -99em;"> +</iframe>
diff --git a/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-android.txt b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-android.txt new file mode 100644 index 0000000..a0d86e77 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-android.txt
@@ -0,0 +1,4 @@ +android.webkit.WebView focusable focused scrollable name='done' +++android.view.View +++++android.view.View +++++++android.view.View scrollable \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-auralinux.txt new file mode 100644 index 0000000..8d28d8c --- /dev/null +++ b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-auralinux.txt
@@ -0,0 +1,4 @@ +[document web] name='done' +++[section] +++++[internal frame] +++++++[document web] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-blink.txt b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-blink.txt new file mode 100644 index 0000000..6c84d3a --- /dev/null +++ b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-blink.txt
@@ -0,0 +1,7 @@ +rootWebArea name='done' +++genericContainer ignored +++++genericContainer +++++++iframe +++++++++rootWebArea +++++++++++genericContainer ignored +++++++++++++genericContainer ignored \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-mac.txt b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-mac.txt new file mode 100644 index 0000000..54f34edc --- /dev/null +++ b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-mac.txt
@@ -0,0 +1,4 @@ +AXWebArea AXTitle='done' +++AXGroup +++++AXGroup +++++++AXWebArea \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-uia-win.txt new file mode 100644 index 0000000..b01fea99 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-uia-win.txt
@@ -0,0 +1,4 @@ +Document Name='done' +++Group IsControlElement=false +++++Document +++++++Document \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-win.txt b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-win.txt new file mode 100644 index 0000000..e35bd84 --- /dev/null +++ b/content/test/data/accessibility/html/iframe-srcdoc-changed-expected-win.txt
@@ -0,0 +1,4 @@ +ROLE_SYSTEM_DOCUMENT name='done' READONLY FOCUSABLE ia2_hypertext='<obj0>' +++IA2_ROLE_SECTION ia2_hypertext='<obj0>' +++++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' +++++++ROLE_SYSTEM_DOCUMENT value='about:srcdoc' READONLY FOCUSABLE \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-srcdoc-changed.html b/content/test/data/accessibility/html/iframe-srcdoc-changed.html new file mode 100644 index 0000000..06175d8f --- /dev/null +++ b/content/test/data/accessibility/html/iframe-srcdoc-changed.html
@@ -0,0 +1,18 @@ +<!-- +@WIN-ALLOW:ia2_hypertext=* +@WAIT-FOR:done +--> +<body> +</body> +<script> + const iframe = document.createElement('iframe'); + iframe.onload = () => { + iframe.onload = () => { + setTimeout(() => { document.title = 'done' }, 99); + }; + iframe.srcdoc = ''; + }; + iframe.srcdoc = '<a href="/">link inside iframe</a>'; + document.body.appendChild(iframe); +</script> +
diff --git a/content/web_test/renderer/web_ax_object_proxy.cc b/content/web_test/renderer/web_ax_object_proxy.cc index 54f563d..b7ab5db 100644 --- a/content/web_test/renderer/web_ax_object_proxy.cc +++ b/content/web_test/renderer/web_ax_object_proxy.cc
@@ -1459,12 +1459,12 @@ int WebAXObjectProxy::ScrollX() { UpdateLayout(); - return accessibility_object_.GetScrollOffset().x(); + return GetAXNodeData().GetIntAttribute(ax::mojom::IntAttribute::kScrollX); } int WebAXObjectProxy::ScrollY() { UpdateLayout(); - return accessibility_object_.GetScrollOffset().y(); + return GetAXNodeData().GetIntAttribute(ax::mojom::IntAttribute::kScrollY); } std::string WebAXObjectProxy::ToString() {
diff --git a/docs/testing/regression-test-selection.md b/docs/testing/regression-test-selection.md new file mode 100644 index 0000000..4f1417b --- /dev/null +++ b/docs/testing/regression-test-selection.md
@@ -0,0 +1,38 @@ +# Regression test selection (RTS) + +Regression Test Selection (RTS) is a technique to intellegently select tests to +run, without spending too many resources on testing, but still detecting bad +code changes. + +[TOC] + +## Current strategy + +The current strategy is to skip files which we deem unaffected by the CL's +changelist. Affectedness is estimated using the heuristic that dependent files +are committed together. We look at git history and measure how often each file +A appears together each file B in the same commit. If A affects B, +and B affects C, we assume A also affects C. We represent these transitive +relationships in a graph where files are the nodes and the probability that the +two files affect each other are the weighted edges. The distance between two +nodes represents the (inverse) probability that these two files affect +each other. Finally, we skip tests in files that are farther than a +certain distance from the files in the CL. + +## Skipping mechanism + +Test skipping happens at the GN level in +[source_set](/build/config/BUILDCONFIG.gn) and [test](/testing/test.gni) +GN targets. + +## Known failure mode + +Consider a test file A that contains unit tests, as well as some variables +used in another file B. When our RTS strategy excludes A, but not B, a +compilation error will occur. + +## Design Docs + +- [File-level RTS](http://doc/1KWG82gNpkaRAchlp3jtENFdlefGvJxMHkAszlu9fo1c) +- [Chrome RTS](http://doc/10RP1XRw8ZSrvgVky1flH7ykAaIaG15RymM4gW7bFURQ) +
diff --git a/extensions/browser/api/BUILD.gn b/extensions/browser/api/BUILD.gn index 30686d6..85f6363 100644 --- a/extensions/browser/api/BUILD.gn +++ b/extensions/browser/api/BUILD.gn
@@ -134,9 +134,9 @@ "media_perception_private/media_perception_private_api.h", ] + # TODO(crbug/1158984): as above, remove these deps. public_deps += [ "//extensions/browser/api/cec_private", - "//extensions/browser/api/clipboard", "//extensions/browser/api/diagnostics", "//extensions/browser/api/virtual_keyboard", "//extensions/browser/api/vpn_provider", @@ -207,6 +207,10 @@ "//extensions/browser/api/virtual_keyboard_private", "//extensions/browser/api/web_request", ] + + if (is_chromeos_ash) { + public_deps += [ "//extensions/browser/api/clipboard" ] + } } function_registration("api_registration") {
diff --git a/extensions/browser/api/automation_internal/automation_internal_api.cc b/extensions/browser/api/automation_internal/automation_internal_api.cc index 091a1be9..c028d84 100644 --- a/extensions/browser/api/automation_internal/automation_internal_api.cc +++ b/extensions/browser/api/automation_internal/automation_internal_api.cc
@@ -282,6 +282,10 @@ ui::AXTreeID ax_tree_id = rfh->GetAXTreeID(); + // The AXTreeID is not yet ready/set. + if (ax_tree_id == ui::AXTreeIDUnknown()) + return RespondNow(Error("Tab is not ready.")); + // This gets removed when the extension process dies. AutomationEventRouter::GetInstance()->RegisterListenerForOneTree( extension_id(), source_process_id(), ax_tree_id);
diff --git a/extensions/browser/api/clipboard/BUILD.gn b/extensions/browser/api/clipboard/BUILD.gn index f4d1009..145361c0 100644 --- a/extensions/browser/api/clipboard/BUILD.gn +++ b/extensions/browser/api/clipboard/BUILD.gn
@@ -13,7 +13,11 @@ "clipboard_api.h", ] - deps = [ "//extensions/common/api" ] + deps = [ + "//extensions/browser/api", + "//extensions/common/api", + "//ui/base/clipboard", + ] public_deps = [ "//extensions/browser:browser_sources" ] }
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc index bd5f486..815efc0 100644 --- a/extensions/browser/guest_view/web_view/web_view_apitest.cc +++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -663,6 +663,13 @@ RunTest("testNavOnSrcAttributeChange", "web_view/apitest"); } +IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestLoadCommitUrlsWithIframe) { + const std::string app_location = "web_view/apitest"; + StartTestServer(app_location); + RunTest("testLoadCommitUrlsWithIframe", app_location); + StopTestServer(); +} + IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestNewWindow) { std::string app_location = "web_view/apitest"; StartTestServer(app_location);
diff --git a/extensions/renderer/resources/guest_view/web_view/web_view_events.js b/extensions/renderer/resources/guest_view/web_view/web_view_events.js index 0110436a..0a04ac1 100644 --- a/extensions/renderer/resources/guest_view/web_view/web_view_events.js +++ b/extensions/renderer/resources/guest_view/web_view/web_view_events.js
@@ -277,12 +277,6 @@ event.processId, event.visibleUrl); - // TODO(1149615): The |url| property of the loadcommit event is documented as - // being set to the committed URL, but was being incorrectly set. This - // preserves the existing incorrect behaviour which we'll defer fixing in - // case existing code relies on this behaviour. - event.url = event.visibleUrl; - var webViewEvent = this.makeDomEvent(event, eventName); this.view.dispatchEvent(webViewEvent); };
diff --git a/extensions/test/data/web_view/apitest/empty_frame.html b/extensions/test/data/web_view/apitest/empty_frame.html new file mode 100644 index 0000000..5582149 --- /dev/null +++ b/extensions/test/data/web_view/apitest/empty_frame.html
@@ -0,0 +1,11 @@ +<!doctype html> +<!-- + * Copyright (c) 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. +--> +<html> +<body> + <p>Hello</p> +</body> +</html>
diff --git a/extensions/test/data/web_view/apitest/main.js b/extensions/test/data/web_view/apitest/main.js index 0394384..8b149a8 100644 --- a/extensions/test/data/web_view/apitest/main.js +++ b/extensions/test/data/web_view/apitest/main.js
@@ -12,6 +12,7 @@ embedder.baseGuestURL = 'http://localhost:' + config.testServer.port; embedder.closeSocketURL = embedder.baseGuestURL + '/close-socket'; embedder.emptyGuestURL = embedder.baseGuestURL + '/empty_guest.html'; + embedder.emptyFrameURL = embedder.baseGuestURL + '/empty_frame.html'; embedder.noReferrerGuestURL = embedder.baseGuestURL + '/guest_noreferrer.html'; embedder.detectUserAgentURL = embedder.baseGuestURL + '/detect-user-agent'; @@ -1305,6 +1306,33 @@ document.body.appendChild(webview); } +// Tests that loadcommit has the correct |url| set when a guest's iframe commits +// a navigation. +function testLoadCommitUrlsWithIframe() { + let webview = document.createElement('webview'); + let loadCommitSeen = 0; + webview.addEventListener('loadcommit', function(e) { + ++loadCommitSeen; + if (loadCommitSeen === 1) { + embedder.test.assertEq(embedder.emptyGuestURL, e.url); + embedder.test.assertEq(true, e.isTopLevel); + embedder.test.assertEq(embedder.emptyGuestURL, webview.src); + webview.executeScript({ + code: "let iframe = document.createElement('iframe'); " + + "iframe.src = '" + embedder.emptyFrameURL + "'; " + + "document.body.appendChild(iframe);" + }); + } else if (loadCommitSeen === 2) { + embedder.test.assertEq(embedder.emptyFrameURL, e.url); + embedder.test.assertEq(false, e.isTopLevel); + embedder.test.assertEq(embedder.emptyGuestURL, webview.src); + embedder.test.succeed(); + } + }); + webview.src = embedder.emptyGuestURL; + document.body.appendChild(webview); +} + // This test verifies that new window attachment functions as expected. // // TODO(crbug.com/594215) Test that opening a new window with a data URL is @@ -1969,6 +1997,7 @@ 'testNavOnConsecutiveSrcAttributeChanges': testNavOnConsecutiveSrcAttributeChanges, 'testNavOnSrcAttributeChange': testNavOnSrcAttributeChange, + 'testLoadCommitUrlsWithIframe': testLoadCommitUrlsWithIframe, 'testNewWindow': testNewWindow, 'testNewWindowNoPreventDefault': testNewWindowNoPreventDefault, 'testNewWindowNoReferrerLink': testNewWindowNoReferrerLink,
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index fad18e8..d8d94921 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -7879,6 +7879,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -7930,6 +7934,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -7981,6 +7989,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -8530,6 +8542,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -9544,6 +9560,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -9593,6 +9613,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -10459,6 +10483,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -12300,6 +12328,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -12553,6 +12585,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -13768,6 +13804,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -13818,6 +13858,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -15497,6 +15541,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -15548,6 +15596,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -16564,6 +16616,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -16615,6 +16671,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -16666,6 +16726,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -16717,6 +16781,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -17533,6 +17601,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -17890,6 +17962,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -17941,6 +18017,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -17992,6 +18072,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18043,6 +18127,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18094,6 +18182,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18145,6 +18237,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18351,6 +18447,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18511,6 +18611,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18564,6 +18668,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18670,6 +18778,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18776,6 +18888,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18829,6 +18945,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18882,6 +19002,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18935,6 +19059,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -18988,6 +19116,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19041,6 +19173,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19398,6 +19534,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19551,6 +19691,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19653,6 +19797,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19704,6 +19852,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19755,6 +19907,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19806,6 +19962,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -19908,6 +20068,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20010,6 +20174,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20061,6 +20229,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20112,6 +20284,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20163,6 +20339,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20214,6 +20394,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20316,6 +20500,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20418,6 +20606,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20723,6 +20915,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20774,6 +20970,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -20825,6 +21025,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -21335,6 +21539,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -21438,6 +21646,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -21490,6 +21702,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -21542,6 +21758,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -22197,6 +22417,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -22247,6 +22471,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -22397,6 +22625,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -22447,6 +22679,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -22497,6 +22733,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -22694,6 +22934,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -23152,6 +23396,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -23407,6 +23655,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -23759,6 +24011,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -23810,6 +24066,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -23861,6 +24121,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -23912,6 +24176,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -23962,6 +24230,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -24011,6 +24283,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -24521,6 +24797,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -24776,6 +25056,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 } @@ -25028,6 +25312,10 @@ value: 100 } experiments { + key: "chromium.resultdb.result_sink.gtests_local" + value: 30 + } + experiments { key: "chromium.resultdb.result_sink.junit_tests" value: 100 }
diff --git a/infra/config/lib/ci.star b/infra/config/lib/ci.star index 15c5b019..f73965f 100644 --- a/infra/config/lib/ci.star +++ b/infra/config/lib/ci.star
@@ -368,6 +368,9 @@ builder_group = "chromium.fyi", execution_timeout = execution_timeout, goma_backend = goma_backend, + experiments = { + "chromium.resultdb.result_sink.gtests_local": 30, + }, **kwargs )
diff --git a/ios/chrome/browser/reading_list/reading_list_distiller_page.h b/ios/chrome/browser/reading_list/reading_list_distiller_page.h index 87849962..c56bcd6 100644 --- a/ios/chrome/browser/reading_list/reading_list_distiller_page.h +++ b/ios/chrome/browser/reading_list/reading_list_distiller_page.h
@@ -5,6 +5,7 @@ #ifndef IOS_CHROME_BROWSER_READING_LIST_READING_LIST_DISTILLER_PAGE_H_ #define IOS_CHROME_BROWSER_READING_LIST_READING_LIST_DISTILLER_PAGE_H_ +#include <objc/objc.h> #include <memory> #include <string>
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 index bef2b038..f0f85075 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -3b26166428e3a19cc62e2e6bbd25c56fa56e0f14 \ No newline at end of file +df0c5af3c01e211e892dfa7202abbd97923f42c8 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 index 15ad719c..eb566b2 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -bade0d034e8d070145cfedc1b11d8cb4912921b9 \ No newline at end of file +479a5cdbe222d03b81f46ad57802cbabe8d85142 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 index 6f2432b7..51f978a2 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -517fece53c63d20775e8f6de18e075f9e9e1839d \ No newline at end of file +8aa76742ce99c2f6bf9abdf6fd8e1ae5d7c8b833 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 index d654c36..cb695ab 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -2f5c59d957fae9d8facd01bfdd33fabb86a6aa4f \ No newline at end of file +0d6c6bcfbf96031da1e97b6ca45ec1b950c947d8 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 index 1d9501af..d96943a 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -ce03b4b4e07bd0a2840c747488029982fdb16968 \ No newline at end of file +6304c71654ccc27f78f770f348c50d9343ecc014 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 index d46d87f..c550be42 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -a2ff48001fa30f443c32e3d419eedf0463e0b5d9 \ No newline at end of file +fd43d9d0bdf5b608a75bde850d771f551137244e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 index 288e848..3e33356 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -28919fcd2b9da2fbc43a0ba8c5212db5b9c6f75c \ No newline at end of file +2f23f78fcdc06953931ecefc1454539aa68c35cb \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 index 76c2772..601bf34 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -9bd7713148eebea17d890d5ffbd4c6c37f872fa3 \ No newline at end of file +2cc660c0e8df8ad03130b81e30dc6cd86ca71d59 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 index 811a3b9d..69ab0b8 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -797902106a902871ac79e59ab66096f3b9419d6e \ No newline at end of file +d1a3948e1471f0d3eafef0d042257fce2406cbe1 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 index 34f4df4..643fca35 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -d8be2afb0bc3d6589c971a84f710f942189430cf \ No newline at end of file +cad27834b77d0b6819db2ecd2a9db07b1c386f06 \ No newline at end of file
diff --git a/ios/web/web_view_only/BUILD.gn b/ios/web/web_view_only/BUILD.gn index c6f6054..e4b06df 100644 --- a/ios/web/web_view_only/BUILD.gn +++ b/ios/web/web_view_only/BUILD.gn
@@ -31,6 +31,7 @@ deps = [ "//base", + "//ios/web/public", "//ios/web/public/web_view_only", "//ios/web/test:test_support",
diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc index e838ced..8dfff90 100644 --- a/media/audio/android/audio_android_unittest.cc +++ b/media/audio/android/audio_android_unittest.cc
@@ -203,7 +203,8 @@ // sufficient data remaining in the file to fill up the complete frame. int frames = max_size / (dest->channels() * kBytesPerSample); if (max_size) { - dest->FromInterleaved(file_->data() + pos_, frames, kBytesPerSample); + auto* source = reinterpret_cast<const int16_t*>(file_->data() + pos_); + dest->FromInterleaved<SignedInt16SampleTypeTraits>(source, frames); pos_ += max_size; }
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc index dba6a55..859181d 100644 --- a/media/audio/audio_low_latency_input_output_unittest.cc +++ b/media/audio/audio_low_latency_input_output_unittest.cc
@@ -210,8 +210,12 @@ EXPECT_EQ(channels_, dest->channels()); size = std::min(dest->frames() * frame_size_, size); EXPECT_EQ(static_cast<size_t>(size) % sizeof(*dest->channel(0)), 0U); - dest->FromInterleaved(source, size / frame_size_, - frame_size_ / channels_); + + // We should only have 16 bits per sample. + DCHECK_EQ(frame_size_ / channels_, 2); + dest->FromInterleaved<SignedInt16SampleTypeTraits>( + reinterpret_cast<const int16_t*>(source), size / channels_); + buffer_->Seek(size); return size / frame_size_; }
diff --git a/media/audio/win/waveout_output_win.cc b/media/audio/win/waveout_output_win.cc index d36d8571..c2c96fc 100644 --- a/media/audio/win/waveout_output_win.cc +++ b/media/audio/win/waveout_output_win.cc
@@ -344,8 +344,10 @@ // Note: If this ever changes to output raw float the data must be clipped // and sanitized since it may come from an untrusted source such as NaCl. audio_bus_->Scale(volume_); - audio_bus_->ToInterleaved( - frames_filled, format_.Format.wBitsPerSample / 8, buffer->lpData); + + DCHECK_EQ(format_.Format.wBitsPerSample, 16); + audio_bus_->ToInterleaved<SignedInt16SampleTypeTraits>( + frames_filled, reinterpret_cast<int16_t*>(buffer->lpData)); buffer->dwBufferLength = used * format_.Format.nChannels / channels_; } else {
diff --git a/media/base/audio_block_fifo.cc b/media/base/audio_block_fifo.cc index 85fa6d27..ad49cff 100644 --- a/media/base/audio_block_fifo.cc +++ b/media/base/audio_block_fifo.cc
@@ -116,13 +116,33 @@ std::min(block_frames_ - write_pos_, frames_to_push); if (source) { - // Deinterleave the content to the FIFO and update the |write_pos_|. - current_block->FromInterleavedPartial(source_ptr, write_pos_, push_frames, - bytes_per_sample); + // Deinterleave the content to the FIFO. + switch (bytes_per_sample) { + case 1: + current_block->FromInterleavedPartial<UnsignedInt8SampleTypeTraits>( + source_ptr, write_pos_, push_frames); + break; + case 2: + current_block->FromInterleavedPartial<SignedInt16SampleTypeTraits>( + reinterpret_cast<const int16_t*>(source_ptr), write_pos_, + push_frames); + break; + case 4: + current_block->FromInterleavedPartial<SignedInt32SampleTypeTraits>( + reinterpret_cast<const int32_t*>(source_ptr), write_pos_, + push_frames); + break; + default: + NOTREACHED() << "Unsupported bytes per sample encountered: " + << bytes_per_sample; + current_block->ZeroFramesPartial(write_pos_, push_frames); + } } else { current_block->ZeroFramesPartial(write_pos_, push_frames); } + write_pos_ = (write_pos_ + push_frames) % block_frames_; + if (!write_pos_) { // The current block is completely filled, increment |write_block_| and // |available_blocks_|.
diff --git a/media/base/audio_bus.cc b/media/base/audio_bus.cc index 694b53e..76ee5c2 100644 --- a/media/base/audio_bus.cc +++ b/media/base/audio_bus.cc
@@ -273,81 +273,6 @@ channel_data_.push_back(data + i * aligned_frames); } -// Forwards to non-deprecated version. -void AudioBus::FromInterleaved(const void* source, - int frames, - int bytes_per_sample) { - DCHECK(!is_bitstream_format_); - switch (bytes_per_sample) { - case 1: - FromInterleaved<UnsignedInt8SampleTypeTraits>( - reinterpret_cast<const uint8_t*>(source), frames); - break; - case 2: - FromInterleaved<SignedInt16SampleTypeTraits>( - reinterpret_cast<const int16_t*>(source), frames); - break; - case 4: - FromInterleaved<SignedInt32SampleTypeTraits>( - reinterpret_cast<const int32_t*>(source), frames); - break; - default: - NOTREACHED() << "Unsupported bytes per sample encountered: " - << bytes_per_sample; - ZeroFrames(frames); - } -} - -// Forwards to non-deprecated version. -void AudioBus::FromInterleavedPartial(const void* source, - int start_frame, - int frames, - int bytes_per_sample) { - DCHECK(!is_bitstream_format_); - switch (bytes_per_sample) { - case 1: - FromInterleavedPartial<UnsignedInt8SampleTypeTraits>( - reinterpret_cast<const uint8_t*>(source), start_frame, frames); - break; - case 2: - FromInterleavedPartial<SignedInt16SampleTypeTraits>( - reinterpret_cast<const int16_t*>(source), start_frame, frames); - break; - case 4: - FromInterleavedPartial<SignedInt32SampleTypeTraits>( - reinterpret_cast<const int32_t*>(source), start_frame, frames); - break; - default: - NOTREACHED() << "Unsupported bytes per sample encountered: " - << bytes_per_sample; - ZeroFramesPartial(start_frame, frames); - } -} - -// Forwards to non-deprecated version. -void AudioBus::ToInterleaved(int frames, - int bytes_per_sample, - void* dest) const { - DCHECK(!is_bitstream_format_); - switch (bytes_per_sample) { - case 1: - ToInterleaved<UnsignedInt8SampleTypeTraits>( - frames, reinterpret_cast<uint8_t*>(dest)); - break; - case 2: - ToInterleaved<SignedInt16SampleTypeTraits>( - frames, reinterpret_cast<int16_t*>(dest)); - break; - case 4: - ToInterleaved<SignedInt32SampleTypeTraits>( - frames, reinterpret_cast<int32_t*>(dest)); - break; - default: - NOTREACHED() << "Unsupported bytes per sample encountered: " - << bytes_per_sample; - } -} - void AudioBus::CopyTo(AudioBus* dest) const { dest->set_is_bitstream_format(is_bitstream_format()); if (is_bitstream_format()) {
diff --git a/media/base/audio_bus.h b/media/base/audio_bus.h index 024fee8..1c520279 100644 --- a/media/base/audio_bus.h +++ b/media/base/audio_bus.h
@@ -104,11 +104,6 @@ const typename SourceSampleTypeTraits::ValueType* source_buffer, int num_frames_to_write); - // DEPRECATED (https://crbug.com/580391) - // Please use the version templated with SourceSampleTypeTraits instead. - // TODO(chfremer): Remove (https://crbug.com/619623) - void FromInterleaved(const void* source, int frames, int bytes_per_sample); - // Similar to FromInterleaved...(), but overwrites the frames starting at a // given offset |write_offset_in_frames| and does not zero out frames that are // not overwritten. @@ -118,12 +113,6 @@ int write_offset_in_frames, int num_frames_to_write); - // DEPRECATED (https://crbug.com/580391) - // Please use the version templated with SourceSampleTypeTraits instead. - // TODO(chfremer): Remove (https://crbug.com/619623) - void FromInterleavedPartial(const void* source, int start_frame, int frames, - int bytes_per_sample); - // Reads the sample values stored in this AudioBus instance and places them // into the given |dest_buffer| in interleaved format using the sample format // specified by TargetSampleTypeTraits. For a list of ready-to-use @@ -134,11 +123,6 @@ int num_frames_to_read, typename TargetSampleTypeTraits::ValueType* dest_buffer) const; - // DEPRECATED (https://crbug.com/580391) - // Please use the version templated with TargetSampleTypeTraits instead. - // TODO(chfremer): Remove (https://crbug.com/619623) - void ToInterleaved(int frames, int bytes_per_sample, void* dest) const; - // Similar to ToInterleaved(), but reads the frames starting at a given // offset |read_offset_in_frames|. template <class TargetSampleTypeTraits>
diff --git a/media/base/audio_bus_unittest.cc b/media/base/audio_bus_unittest.cc index 79bb101..38d5cbd09 100644 --- a/media/base/audio_bus_unittest.cc +++ b/media/base/audio_bus_unittest.cc
@@ -335,40 +335,6 @@ kTestVectorFrameCount * sizeof(*expected->channel(ch))); } - // Test deprecated version that takes |bytes_per_sample| as an input. - { - SCOPED_TRACE("uint8_t"); - bus->Zero(); - bus->FromInterleaved(kTestVectorUint8, kTestVectorFrameCount, - sizeof(*kTestVectorUint8)); - - // Biased uint8_t calculations have poor precision, so the epsilon here is - // slightly more permissive than int16_t and int32_t calculations. - VerifyAreEqualWithEpsilon(bus.get(), expected.get(), - 1.0f / (std::numeric_limits<uint8_t>::max() - 1)); - } - { - SCOPED_TRACE("int16_t"); - bus->Zero(); - bus->FromInterleaved(kTestVectorInt16, kTestVectorFrameCount, - sizeof(*kTestVectorInt16)); - VerifyAreEqualWithEpsilon( - bus.get(), expected.get(), - 1.0f / (std::numeric_limits<uint16_t>::max() + 1.0f)); - } - { - SCOPED_TRACE("int32_t"); - bus->Zero(); - bus->FromInterleaved(kTestVectorInt32, kTestVectorFrameCount, - sizeof(*kTestVectorInt32)); - - VerifyAreEqualWithEpsilon( - bus.get(), expected.get(), - 1.0f / (std::numeric_limits<uint32_t>::max() + 1.0f)); - } - - // Test non-deprecated version that takes SampleTypeTraits as a template - // parameter. { SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); bus->Zero(); @@ -424,18 +390,6 @@ kPartialFrames * sizeof(*expected->channel(ch))); } - // Test deprecated version that takes |bytes_per_sample| as an input. - { - SCOPED_TRACE("int32_t"); - bus->Zero(); - bus->FromInterleavedPartial( - kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart, - kPartialFrames, sizeof(*kTestVectorInt32)); - VerifyAreEqual(bus.get(), expected.get()); - } - - // Test non-deprecated version that takes SampleTypeTraits as a template - // parameter. { SCOPED_TRACE("SignedInt32SampleTypeTraits"); bus->Zero(); @@ -456,43 +410,6 @@ kTestVectorFrameCount * sizeof(*bus->channel(ch))); } - // Test deprecated version that takes |bytes_per_sample| as an input. - { - SCOPED_TRACE("uint8_t"); - uint8_t test_array[base::size(kTestVectorUint8)]; - bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorUint8), test_array); - ASSERT_EQ(0, - memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8))); - } - { - SCOPED_TRACE("int16_t"); - int16_t test_array[base::size(kTestVectorInt16)]; - bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array); - ASSERT_EQ(0, - memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16))); - } - { - SCOPED_TRACE("int32_t"); - int32_t test_array[base::size(kTestVectorInt32)]; - bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt32), test_array); - - // Some compilers get better precision than others on the half-max test, so - // let the test pass with an off by one check on the half-max. - int32_t alternative_acceptable_result[base::size(kTestVectorInt32)]; - memcpy(alternative_acceptable_result, kTestVectorInt32, - sizeof(kTestVectorInt32)); - ASSERT_EQ(alternative_acceptable_result[4], - std::numeric_limits<int32_t>::max() / 2); - alternative_acceptable_result[4]++; - - ASSERT_TRUE( - memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || - memcmp(test_array, alternative_acceptable_result, - sizeof(alternative_acceptable_result)) == 0); - } - - // Test non-deprecated version that takes SampleTypeTraits as a template - // parameter. { SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); uint8_t test_array[base::size(kTestVectorUint8)];
diff --git a/media/filters/audio_file_reader.cc b/media/filters/audio_file_reader.cc index cb81d92..df95bac9 100644 --- a/media/filters/audio_file_reader.cc +++ b/media/filters/audio_file_reader.cc
@@ -276,9 +276,25 @@ sizeof(float) * frames_read); } } else { - audio_bus->FromInterleaved( - frame->data[0], frames_read, - av_get_bytes_per_sample(codec_context_->sample_fmt)); + int bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); + switch (bytes_per_sample) { + case 1: + audio_bus->FromInterleaved<UnsignedInt8SampleTypeTraits>( + reinterpret_cast<const uint8_t*>(frame->data[0]), frames_read); + break; + case 2: + audio_bus->FromInterleaved<SignedInt16SampleTypeTraits>( + reinterpret_cast<const int16_t*>(frame->data[0]), frames_read); + break; + case 4: + audio_bus->FromInterleaved<SignedInt32SampleTypeTraits>( + reinterpret_cast<const int32_t*>(frame->data[0]), frames_read); + break; + default: + NOTREACHED() << "Unsupported bytes per sample encountered: " + << bytes_per_sample; + audio_bus->ZeroFrames(frames_read); + } } (*total_frames) += frames_read;
diff --git a/media/gpu/android/media_codec_video_decoder_unittest.cc b/media/gpu/android/media_codec_video_decoder_unittest.cc index 0fc5de4..e76456ae 100644 --- a/media/gpu/android/media_codec_video_decoder_unittest.cc +++ b/media/gpu/android/media_codec_video_decoder_unittest.cc
@@ -21,6 +21,7 @@ #include "media/base/decoder_buffer.h" #include "media/base/media_util.h" #include "media/base/test_helpers.h" +#include "media/base/video_codecs.h" #include "media/base/video_frame.h" #include "media/gpu/android/android_video_surface_chooser_impl.h" #include "media/gpu/android/fake_codec_allocator.h" @@ -996,6 +997,8 @@ test_codecs.push_back(kCodecVP8); if (MediaCodecUtil::IsVp9DecoderAvailable()) test_codecs.push_back(kCodecVP9); + if (MediaCodecUtil::IsAv1DecoderAvailable()) + test_codecs.push_back(kCodecAV1); return test_codecs; } @@ -1013,6 +1016,12 @@ : std::vector<VideoCodec>(); } +static std::vector<VideoCodec> GetAv1IfAvailable() { + return MediaCodecUtil::IsAv1DecoderAvailable() + ? std::vector<VideoCodec>(1, kCodecAV1) + : std::vector<VideoCodec>(); +} + INSTANTIATE_TEST_SUITE_P(MediaCodecVideoDecoderTest, MediaCodecVideoDecoderTest, testing::ValuesIn(GetTestList())); @@ -1027,4 +1036,8 @@ MediaCodecVideoDecoderVp8Test, testing::ValuesIn(GetVp8IfAvailable())); +INSTANTIATE_TEST_SUITE_P(MediaCodecVideoDecoderAV1Test, + MediaCodecVideoDecoderAV1Test, + testing::ValuesIn(GetAv1IfAvailable())); + } // namespace media
diff --git a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc index 6ac0d7f..6d23197 100644 --- a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc
@@ -369,11 +369,6 @@ bool uses_crypto = false; VAEncryptionParameters crypto_params = {}; if (IsEncryptedSession()) { - // Always indicate full sample since H264 can support that and we don't know - // yet which it is. - // TODO(jkardatzke): Fix full sample encryption, specifying true for it here - // always will cause H264 subsample to fail and we don't know which it is - // yet. const ProtectedSessionState state = SetupDecryptDecode( /*full_sample=*/false, size, &crypto_params, &encryption_segment_info_, subsamples);
diff --git a/media/gpu/vaapi/test/decode.cc b/media/gpu/vaapi/test/decode.cc index 904e491..ae4e596 100644 --- a/media/gpu/vaapi/test/decode.cc +++ b/media/gpu/vaapi/test/decode.cc
@@ -41,6 +41,7 @@ " --video=<video path>\n" " [--frames=<number of frames to decode>]\n" " [--out-prefix=<path prefix of decoded frame PNGs>]\n" + " [--loop]\n" " [--v=<log verbosity>]\n" " [--help]\n"; @@ -59,21 +60,19 @@ " prefix (which may specify a directory) is provided here,\n" " resulting in e.g. frame_0.png, frame_1.png, etc. if passed\n" " \"frame\".\n" + " If specified along with --loop (see below), only saves the first\n" + " iteration of decoded frames.\n" " If omitted, the output of this binary is error or lack thereof.\n" + " --loop\n" + " Optional. If specified, loops decoding until terminated\n" + " externally or until an error occurs, at which point the current\n" + " pass through the video completes and the binary exits.\n" + " If specified with --frames, loops decoding that number of\n" + " leading frames. If specified with --out-prefix, loops decoding,\n" + " but only saves the first iteration of decoded frames.\n" " --help\n" " Display this help message and exit.\n"; -// Creates the appropriate decoder for the given |fourcc|. -std::unique_ptr<VideoDecoder> CreateDecoder( - uint32_t fourcc, - std::unique_ptr<media::IvfParser> ivf_parser, - const VaapiDevice& va_device) { - if (fourcc == fourcc('V', 'P', '9', '0')) - return std::make_unique<Vp9Decoder>(std::move(ivf_parser), va_device); - - return nullptr; -} - // Returns string representation of |fourcc|. std::string FourccStr(uint32_t fourcc) { std::stringstream s; @@ -84,6 +83,30 @@ return s.str(); } +// Creates the appropriate decoder for |stream_data| which is expected to point +// to IVF data of length |stream_len|. The decoder will use |va_device| to issue +// VAAPI calls. Returns nullptr on failure. +std::unique_ptr<VideoDecoder> CreateDecoder(const VaapiDevice& va_device, + const uint8_t* stream_data, + size_t stream_len) { + // Set up video parser. + auto ivf_parser = std::make_unique<media::IvfParser>(); + media::IvfFileHeader file_header{}; + if (!ivf_parser->Initialize(stream_data, stream_len, &file_header)) { + LOG(ERROR) << "Couldn't initialize IVF parser"; + return nullptr; + } + + // Create appropriate decoder for codec. + VLOG(1) << "Creating decoder with codec " << FourccStr(file_header.fourcc); + if (file_header.fourcc == fourcc('V', 'P', '9', '0')) + return std::make_unique<Vp9Decoder>(std::move(ivf_parser), va_device); + + LOG(ERROR) << "Codec " << FourccStr(file_header.fourcc) << " not supported.\n" + << kUsageMsg; + return nullptr; +} + } // namespace int main(int argc, char** argv) { @@ -119,20 +142,6 @@ return EXIT_FAILURE; } - // Set up video stream and parser. - base::MemoryMappedFile stream; - if (!stream.Initialize(video_path)) { - LOG(ERROR) << "Couldn't open file: " << video_path; - return EXIT_FAILURE; - } - - auto ivf_parser = std::make_unique<media::IvfParser>(); - media::IvfFileHeader file_header{}; - if (!ivf_parser->Initialize(stream.data(), stream.length(), &file_header)) { - LOG(ERROR) << "Couldn't initialize IVF parser for file: " << video_path; - return EXIT_FAILURE; - } - // Initialize VA stubs. StubPathMap paths; const std::string va_suffix(base::NumberToString(VA_MAJOR_VERSION + 1)); @@ -146,43 +155,53 @@ return EXIT_FAILURE; } - const VaapiDevice va_device; - std::unique_ptr<VideoDecoder> dec = - CreateDecoder(file_header.fourcc, std::move(ivf_parser), va_device); - if (!dec) { - LOG(ERROR) << "Codec " << FourccStr(file_header.fourcc) - << " not supported.\n" - << kUsageMsg; + // Set up video stream. + base::MemoryMappedFile stream; + if (!stream.Initialize(video_path)) { + LOG(ERROR) << "Couldn't open file: " << video_path; return EXIT_FAILURE; } - VLOG(1) << "Created decoder for codec " << FourccStr(file_header.fourcc); - VideoDecoder::Result res; - int i = 0; + const VaapiDevice va_device; + const bool loop_decode = cmd->HasSwitch("loop"); + bool first_loop = true; bool errored = false; - while (true) { - LOG(INFO) << "Frame " << i << "..."; - res = dec->DecodeNextFrame(); - if (res == VideoDecoder::kEOStream) { - LOG(INFO) << "End of stream."; - break; + do { + const std::unique_ptr<VideoDecoder> dec = + CreateDecoder(va_device, stream.data(), stream.length()); + if (!dec) { + LOG(ERROR) << "Failed to create decoder for file: " << video_path; + return EXIT_FAILURE; + } + int i = 0; + + while (true) { + LOG(INFO) << "Frame " << i << "..."; + const VideoDecoder::Result res = dec->DecodeNextFrame(); + + if (res == VideoDecoder::kEOStream) { + LOG(INFO) << "End of stream."; + break; + } + + if (res == VideoDecoder::kFailed) { + LOG(ERROR) << "Failed to decode."; + errored = true; + continue; + } + + if (!output_prefix.empty() && first_loop) { + dec->LastDecodedFrameToPNG( + base::StringPrintf("%s_%d.png", output_prefix.c_str(), i)); + } + + if (++i == n_frames) + break; } - if (res == VideoDecoder::kFailed) { - LOG(ERROR) << "Failed to decode."; - errored = true; - continue; - } - - if (!output_prefix.empty()) { - dec->LastDecodedFrameToPNG( - base::StringPrintf("%s_%d.png", output_prefix.c_str(), i)); - } - - if (++i == n_frames) - break; - }; + first_loop = false; + } while (loop_decode && !errored); LOG(INFO) << "Done reading.";
diff --git a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc index 6674b1e..fa533e05 100644 --- a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc +++ b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc
@@ -162,6 +162,7 @@ : VideoFrameMapper(format), vaapi_wrapper_(VaapiWrapper::Create(VaapiWrapper::kVideoProcess, VAProfileNone, + EncryptionScheme::kUnencrypted, base::DoNothing())) {} VaapiDmaBufVideoFrameMapper::~VaapiDmaBufVideoFrameMapper() {}
diff --git a/media/gpu/vaapi/vaapi_image_decoder.cc b/media/gpu/vaapi/vaapi_image_decoder.cc index 3c13981..1c92c7b 100644 --- a/media/gpu/vaapi/vaapi_image_decoder.cc +++ b/media/gpu/vaapi/vaapi_image_decoder.cc
@@ -29,7 +29,8 @@ bool VaapiImageDecoder::Initialize(const ReportErrorToUMACB& error_uma_cb) { vaapi_wrapper_ = - VaapiWrapper::Create(VaapiWrapper::kDecode, va_profile_, error_uma_cb); + VaapiWrapper::Create(VaapiWrapper::kDecode, va_profile_, + EncryptionScheme::kUnencrypted, error_uma_cb); return !!vaapi_wrapper_; }
diff --git a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc index d94c070..cce592e9 100644 --- a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc
@@ -500,6 +500,7 @@ client_ = client; scoped_refptr<VaapiWrapper> vaapi_wrapper = VaapiWrapper::Create( VaapiWrapper::kEncode, VAProfileJPEGBaseline, + EncryptionScheme::kUnencrypted, base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiJpegEncodeAccelerator.VAAPIError")); @@ -510,6 +511,7 @@ scoped_refptr<VaapiWrapper> vpp_vaapi_wrapper = VaapiWrapper::Create( VaapiWrapper::kVideoProcess, VAProfileNone, + EncryptionScheme::kUnencrypted, base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiJpegEncodeAccelerator.Vpp.VAAPIError")); if (!vpp_vaapi_wrapper) {
diff --git a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc index 3bbac0d..40ec729 100644 --- a/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_mjpeg_decode_accelerator.cc
@@ -141,6 +141,7 @@ vpp_vaapi_wrapper_ = VaapiWrapper::Create( VaapiWrapper::kVideoProcess, VAProfileNone, + EncryptionScheme::kUnencrypted, base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiMjpegDecodeAccelerator.Vpp.VAAPIError")); if (!vpp_vaapi_wrapper_) {
diff --git a/media/gpu/vaapi/vaapi_unittest.cc b/media/gpu/vaapi/vaapi_unittest.cc index 16a3129..791cbdd0 100644 --- a/media/gpu/vaapi/vaapi_unittest.cc +++ b/media/gpu/vaapi/vaapi_unittest.cc
@@ -279,7 +279,8 @@ for (const auto& profile_and_entrypoints : configurations) { const VAProfile va_profile = profile_and_entrypoints.first; scoped_refptr<VaapiWrapper> wrapper = VaapiWrapper::Create( - VaapiWrapper::kEncode, va_profile, base::DoNothing()); + VaapiWrapper::kEncode, va_profile, EncryptionScheme::kUnencrypted, + base::DoNothing()); // Depending on the GPU Gen, flags and policies, we may or may not utilize // all entrypoints (e.g. we might always want VAEntrypointEncSliceLP if
diff --git a/media/gpu/vaapi/vaapi_utils_unittest.cc b/media/gpu/vaapi/vaapi_utils_unittest.cc index 479ea443..834a2df9 100644 --- a/media/gpu/vaapi/vaapi_utils_unittest.cc +++ b/media/gpu/vaapi/vaapi_utils_unittest.cc
@@ -42,6 +42,7 @@ // Create a VaapiWrapper for testing. vaapi_wrapper_ = VaapiWrapper::Create(VaapiWrapper::kDecode, VAProfileJPEGBaseline, + EncryptionScheme::kUnencrypted, base::BindRepeating([](VaapiFunctions function) { LOG(FATAL) << "Oh noes! Decoder failed"; }));
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc index 7460b84..9d9cb7a 100644 --- a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -205,7 +205,7 @@ VLOGF(2) << "Initializing VAVDA, profile: " << GetProfileName(profile); vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec( - VaapiWrapper::kDecode, profile, + VaapiWrapper::kDecode, profile, EncryptionScheme::kUnencrypted, base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiVideoDecodeAccelerator.VAAPIError")); @@ -620,7 +620,7 @@ if (profile_ != new_profile) { profile_ = new_profile; auto new_vaapi_wrapper = VaapiWrapper::CreateForVideoCodec( - VaapiWrapper::kDecode, profile_, + VaapiWrapper::kDecode, profile_, EncryptionScheme::kUnencrypted, base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiVideoDecodeAccelerator.VAAPIError")); RETURN_AND_NOTIFY_ON_FAILURE(new_vaapi_wrapper.get(), @@ -715,6 +715,7 @@ if (!vpp_vaapi_wrapper_) { vpp_vaapi_wrapper_ = VaapiWrapper::Create( VaapiWrapper::kVideoProcess, VAProfileNone, + EncryptionScheme::kUnencrypted, base::BindRepeating( &ReportVaapiErrorToUMA, "Media.VaapiVideoDecodeAccelerator.Vpp.VAAPIError"));
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc index c0b2328..9d74a48 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.cc +++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -220,7 +220,7 @@ #else VaapiWrapper::kDecode, #endif - profile, + profile, config.encryption_scheme(), base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiVideoDecoder.VAAPIError")); UMA_HISTOGRAM_BOOLEAN("Media.VaapiVideoDecoder.VaapiWrapperCreationSuccess", @@ -554,7 +554,7 @@ #else VaapiWrapper::kDecode, #endif - profile_, + profile_, encryption_scheme_, base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiVideoDecoder.VAAPIError")); if (!new_vaapi_wrapper.get()) {
diff --git a/media/gpu/vaapi/vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/vaapi_video_decoder_delegate.cc index 097fc72..b36cda8 100644 --- a/media/gpu/vaapi/vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/vaapi_video_decoder_delegate.cc
@@ -92,7 +92,6 @@ protected_session_state_ = ProtectedSessionState::kFailed; return protected_session_state_; } - full_sample_ = full_sample; // We need to start the creation of this, first part requires getting the // hw config data from the daemon. chromeos::ChromeOsCdmFactory::GetHwConfigData(BindToCurrentLoop( @@ -106,14 +105,10 @@ if (encryption_scheme_ == EncryptionScheme::kCenc) { crypto_params->encryption_type = - full_sample_ ? VA_ENCRYPTION_TYPE_CENC_CTR : VA_ENCRYPTION_TYPE_CTR_128; + full_sample ? VA_ENCRYPTION_TYPE_CENC_CTR : VA_ENCRYPTION_TYPE_CTR_128; } else { - if (full_sample_) { - LOG(ERROR) << "CBC encryption is not supported for CENCv1"; - protected_session_state_ = ProtectedSessionState::kFailed; - return protected_session_state_; - } - crypto_params->encryption_type = VA_ENCRYPTION_TYPE_CBC; + crypto_params->encryption_type = + full_sample ? VA_ENCRYPTION_TYPE_CENC_CBC : VA_ENCRYPTION_TYPE_CBC; } if (subsamples.empty() || @@ -128,12 +123,6 @@ return protected_session_state_; } - if (full_sample_ != full_sample) { - LOG(ERROR) << "Cannot switch between full/subsample mid session"; - protected_session_state_ = ProtectedSessionState::kFailed; - return protected_session_state_; - } - DCHECK(decrypt_config_); // We also need to make sure we have the key data for the active // DecryptConfig now that the protected session exists. @@ -205,8 +194,8 @@ } hw_identifier_.clear(); - if (!vaapi_wrapper_->CreateProtectedSession(encryption_scheme_, full_sample_, - config_data, &hw_identifier_)) { + if (!vaapi_wrapper_->CreateProtectedSession(encryption_scheme_, config_data, + &hw_identifier_)) { LOG(ERROR) << "Failed to setup protected session"; protected_session_state_ = ProtectedSessionState::kFailed; on_protected_session_update_cb_.Run(false);
diff --git a/media/gpu/vaapi/vaapi_video_decoder_delegate.h b/media/gpu/vaapi/vaapi_video_decoder_delegate.h index fec3845..96ce00f 100644 --- a/media/gpu/vaapi/vaapi_video_decoder_delegate.h +++ b/media/gpu/vaapi/vaapi_video_decoder_delegate.h
@@ -116,7 +116,6 @@ EncryptionScheme encryption_scheme_; ProtectedSessionState protected_session_state_; std::unique_ptr<DecryptConfig> decrypt_config_; - bool full_sample_; std::vector<uint8_t> hw_identifier_; std::map<std::string, std::vector<uint8_t>> hw_key_data_map_;
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc index 2dce0d8c..9ff92d1 100644 --- a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
@@ -335,7 +335,7 @@ codec == kCodecVP9 ? VaapiWrapper::kEncodeConstantQuantizationParameter : VaapiWrapper::kEncode; vaapi_wrapper_ = VaapiWrapper::CreateForVideoCodec( - mode, config.output_profile, + mode, config.output_profile, EncryptionScheme::kUnencrypted, base::BindRepeating(&ReportVaapiErrorToUMA, "Media.VaapiVideoEncodeAccelerator.VAAPIError")); if (!vaapi_wrapper_) { @@ -728,6 +728,7 @@ if (!vpp_vaapi_wrapper_) { vpp_vaapi_wrapper_ = VaapiWrapper::Create( VaapiWrapper::kVideoProcess, VAProfileNone, + EncryptionScheme::kUnencrypted, base::BindRepeating( &ReportVaapiErrorToUMA, "Media.VaapiVideoEncodeAccelerator.Vpp.VAAPIError"));
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc index 4fd51b8..a5debd39 100644 --- a/media/gpu/vaapi/vaapi_wrapper.cc +++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -787,8 +787,6 @@ {VAConfigAttribProtectedContentCipherBlockSize, VA_PC_BLOCK_SIZE_128}); required_attribs->push_back( {VAConfigAttribProtectedContentCipherMode, VA_PC_CIPHER_MODE_CTR}); - required_attribs->push_back({VAConfigAttribProtectedContentCipherSampleType, - VA_PC_SAMPLE_TYPE_FULLSAMPLE}); #endif } else { required_attribs->push_back({VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}); @@ -796,16 +794,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) if (mode == VaapiWrapper::kDecodeProtected && profile != VAProfileProtected) { - // TODO(jkardatzke): Remove this workarond once the iHD bug for full vs. - // subsample dependency here is fixed. VA_ENCRYPTION_TYPE_CTR_128 works for - // VP9. VA_ENCRYPTION_TYPE_CENC_CTR is needed for H264 full sample (and also - // works for H264 subsample). We can't know full vs. subsample at this point - // though, we only know codec. required_attribs->push_back( - {VAConfigAttribEncryption, - (profile == VAProfileVP9Profile0 || profile == VAProfileVP9Profile2) - ? VA_ENCRYPTION_TYPE_CTR_128 - : VA_ENCRYPTION_TYPE_CENC_CTR}); + {VAConfigAttribEncryption, VA_ENCRYPTION_TYPE_CENC_CTR}); } #endif @@ -1339,6 +1329,7 @@ scoped_refptr<VaapiWrapper> VaapiWrapper::Create( CodecMode mode, VAProfile va_profile, + EncryptionScheme encryption_scheme, const ReportErrorToUMACB& report_error_to_uma_cb) { if (!VASupportedProfiles::Get().IsProfileSupported(mode, va_profile)) { DVLOG(1) << "Unsupported va_profile: " << vaProfileStr(va_profile); @@ -1358,7 +1349,7 @@ scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper(mode)); if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) { - if (vaapi_wrapper->Initialize(mode, va_profile)) + if (vaapi_wrapper->Initialize(mode, va_profile, encryption_scheme)) return vaapi_wrapper; } LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " @@ -1370,9 +1361,10 @@ scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( CodecMode mode, VideoCodecProfile profile, + EncryptionScheme encryption_scheme, const ReportErrorToUMACB& report_error_to_uma_cb) { const VAProfile va_profile = ProfileToVAProfile(profile, mode); - return Create(mode, va_profile, report_error_to_uma_cb); + return Create(mode, va_profile, encryption_scheme, report_error_to_uma_cb); } // static @@ -1738,8 +1730,7 @@ } bool VaapiWrapper::CreateProtectedSession( - media::EncryptionScheme encryption, - bool full_sample, + EncryptionScheme encryption, const std::vector<uint8_t>& hw_config, std::vector<uint8_t>* hw_identifier_out) { #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -1748,7 +1739,7 @@ LOG(ERROR) << "Cannot attached protected context if not in protected mode"; return false; } - if (encryption == media::EncryptionScheme::kUnencrypted) { + if (encryption == EncryptionScheme::kUnencrypted) { LOG(ERROR) << "Must specify encryption scheme for protected mode"; return false; } @@ -1764,16 +1755,12 @@ } DCHECK(!required_attribs.empty()); - // We need to adjust the attributes for encryption scheme and sample mode. + // We need to adjust the attribute for encryption scheme. for (auto& attrib : required_attribs) { if (attrib.type == VAConfigAttribProtectedContentCipherMode) { - attrib.value = (encryption == media::EncryptionScheme::kCbcs) + attrib.value = (encryption == EncryptionScheme::kCbcs) ? VA_PC_CIPHER_MODE_CBC : VA_PC_CIPHER_MODE_CTR; - } else if (attrib.type == - VAConfigAttribProtectedContentCipherSampleType) { - attrib.value = full_sample ? VA_PC_SAMPLE_TYPE_FULLSAMPLE - : VA_PC_SAMPLE_TYPE_SUBSAMPLE; } } @@ -2573,7 +2560,9 @@ Deinitialize(); } -bool VaapiWrapper::Initialize(CodecMode mode, VAProfile va_profile) { +bool VaapiWrapper::Initialize(CodecMode mode, + VAProfile va_profile, + EncryptionScheme encryption_scheme) { #if DCHECK_IS_ON() if (mode == kEncodeConstantQuantizationParameter) { DCHECK_NE(va_profile, VAProfileJPEGBaseline) @@ -2581,6 +2570,12 @@ } #endif // DCHECK_IS_ON() +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (encryption_scheme != EncryptionScheme::kUnencrypted && + mode != kDecodeProtected) + return false; +#endif + const VAEntrypoint entrypoint = GetDefaultVaEntryPoint(mode, va_profile); base::AutoLock auto_lock(*va_lock_); @@ -2590,6 +2585,18 @@ return false; } + if (encryption_scheme != EncryptionScheme::kUnencrypted) { + DCHECK(!required_attribs.empty()); + // We need to adjust the attribute for encryption scheme. + for (auto& attrib : required_attribs) { + if (attrib.type == VAConfigAttribEncryption) { + attrib.value = (encryption_scheme == EncryptionScheme::kCbcs) + ? VA_ENCRYPTION_TYPE_CENC_CBC + : VA_ENCRYPTION_TYPE_CENC_CTR; + } + } + } + const VAStatus va_res = vaCreateConfig(va_display_, va_profile, entrypoint, required_attribs.empty() ? nullptr : &required_attribs[0],
diff --git a/media/gpu/vaapi/vaapi_wrapper.h b/media/gpu/vaapi/vaapi_wrapper.h index ee3f033..f3aad8b 100644 --- a/media/gpu/vaapi/vaapi_wrapper.h +++ b/media/gpu/vaapi/vaapi_wrapper.h
@@ -151,6 +151,7 @@ static scoped_refptr<VaapiWrapper> Create( CodecMode mode, VAProfile va_profile, + EncryptionScheme encryption_scheme, const ReportErrorToUMACB& report_error_to_uma_cb); // Create VaapiWrapper for VideoCodecProfile. It maps VideoCodecProfile @@ -160,6 +161,7 @@ static scoped_refptr<VaapiWrapper> CreateForVideoCodec( CodecMode mode, VideoCodecProfile profile, + EncryptionScheme encryption_scheme, const ReportErrorToUMACB& report_error_to_uma_cb); // Return the supported video encode profiles. @@ -265,14 +267,12 @@ // decoding context to enable encrypted video decoding. If it cannot be // attached now, it will be attached when the decoding context is created or // re-created. |encryption| should be the encryption scheme from the - // DecryptConfig, |full_sample| should be true if full sample (i.e. CENC v1) - // encryption is used. |hw_config| should have been obtained from the - // OEMCrypto implementation via the CdmFactoryDaemonProxy. |hw_identifier_out| - // is an output parameter which will return session specific information which - // can be passed through the ChromeOsCdmContext to retrieve encrypted key + // DecryptConfig. |hw_config| should have been obtained from the OEMCrypto + // implementation via the CdmFactoryDaemonProxy. |hw_identifier_out| is an + // output parameter which will return session specific information which can + // be passed through the ChromeOsCdmContext to retrieve encrypted key // information. Returns true on success and false otherwise. bool CreateProtectedSession(media::EncryptionScheme encryption, - bool full_sample, const std::vector<uint8_t>& hw_config, std::vector<uint8_t>* hw_identifier_out); @@ -476,7 +476,9 @@ FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVAImage); FRIEND_TEST_ALL_PREFIXES(VaapiUtilsTest, BadScopedVABufferMapping); - bool Initialize(CodecMode mode, VAProfile va_profile) WARN_UNUSED_RESULT; + bool Initialize(CodecMode mode, + VAProfile va_profile, + EncryptionScheme encryption_scheme) WARN_UNUSED_RESULT; void Deinitialize(); bool VaInitialize(const ReportErrorToUMACB& report_error_to_uma_cb) WARN_UNUSED_RESULT;
diff --git a/net/third_party/quiche/BUILD.gn b/net/third_party/quiche/BUILD.gn index 797deb8..f3b0b3d 100644 --- a/net/third_party/quiche/BUILD.gn +++ b/net/third_party/quiche/BUILD.gn
@@ -6,6 +6,10 @@ import("//testing/libfuzzer/fuzzer_test.gni") import("//third_party/protobuf/proto_library.gni") +config("quiche_config") { + include_dirs = [ "src" ] +} + # Since //net and //net/third_party/quiche have a circular dependency on each # other, exporting dependencies from the :quiche target directly does not work. # Thus, all public dependencies for QUICHE should go into the target below, @@ -13,6 +17,7 @@ source_set("quiche_public_deps") { visibility = [ "//net:net_public_deps" ] + public_configs = [ ":quiche_config" ] public_deps = [ "//third_party/abseil-cpp:absl" ] } @@ -639,6 +644,8 @@ cc_include = "net/base/net_export.h" component_build_force_source_set = true + proto_in_dir = "src" + deps = [ "//net:net_export_header" ] defines = [ "NET_IMPLEMENTATION" ]
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index f0540a5..51157a100 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -174,6 +174,9 @@ "host_power_save_blocker.h", "host_secret.cc", "host_secret.h", + "host_setting_keys.h", + "host_settings.cc", + "host_settings.h", "host_status_logger.cc", "host_status_logger.h", "host_status_monitor.cc", @@ -409,6 +412,8 @@ "desktop_resizer_mac.cc", "disconnect_window_mac.h", "disconnect_window_mac.mm", + "host_settings_mac.cc", + "host_settings_mac.h", "input_injector_mac.cc", "keyboard_layout_monitor_mac.cc", "pairing_registry_delegate_mac.cc", @@ -418,9 +423,13 @@ frameworks = [ "Accelerate.framework", "Carbon.framework", + "CoreAudio.framework", ] - deps += [ ":remoting_version" ] + deps += [ + ":remoting_version", + "//remoting/host/mac:constants", + ] } if (is_win) {
diff --git a/remoting/host/audio_capturer_mac.cc b/remoting/host/audio_capturer_mac.cc index d9b0cb2..48b4894 100644 --- a/remoting/host/audio_capturer_mac.cc +++ b/remoting/host/audio_capturer_mac.cc
@@ -10,8 +10,13 @@ #include "base/containers/flat_set.h" #include "base/logging.h" #include "base/no_destructor.h" +#include "base/strings/sys_string_conversions.h" #include "base/synchronization/lock.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "base/threading/thread_restrictions.h" +#include "remoting/base/logging.h" +#include "remoting/host/host_setting_keys.h" +#include "remoting/host/host_settings.h" #include "remoting/proto/audio.pb.h" namespace remoting { @@ -88,8 +93,10 @@ } // namespace -AudioCapturerMac::AudioCapturerMac() { +AudioCapturerMac::AudioCapturerMac(const std::string& audio_device_uid) + : audio_device_uid_(audio_device_uid) { DETACH_FROM_SEQUENCE(sequence_checker_); + DCHECK(!audio_device_uid.empty()); stream_description_.mSampleRate = kSampleRate; stream_description_.mFormatID = kAudioFormatLinearPCM; @@ -188,9 +195,6 @@ // This runs on AudioQueue's internal thread. For some reason if we specify // inCallbackRunLoop to current thread, then the callback will never get // called. - // TODO(yuweih): Search for the loopback device directly instead of relying on - // the default input device. This would allow the user to keep their - // microphone as the default input device. OSStatus err = AudioQueueNewInput(&stream_description_, &HandleInputBufferOnAQThread, /* inUserData= */ this, /* inCallbackRunLoop= */ NULL, @@ -200,6 +204,18 @@ return false; } + // Use the loopback device for input. + HOST_LOG << "Using loopback device: " << audio_device_uid_; + base::ScopedCFTypeRef<CFStringRef> device_uid = + base::SysUTF8ToCFStringRef(audio_device_uid_); + CFStringRef unowned_device_uid = device_uid.get(); + err = AudioQueueSetProperty(input_queue_, kAudioQueueProperty_CurrentDevice, + &unowned_device_uid, sizeof(unowned_device_uid)); + if (HandleError(err, + "AudioQueueSetProperty(kAudioQueueProperty_CurrentDevice)")) { + return false; + } + // Setup buffers. for (int i = 0; i < kNumberBuffers; i++) { // |buffer| will automatically be freed when |input_queue_| is released. @@ -216,6 +232,11 @@ // Start input queue. err = AudioQueueStart(input_queue_, NULL); + if (err == kAudioQueueErr_InvalidDevice) { + LOG(ERROR) << "Loopback device " << audio_device_uid_ + << " could not be located"; + return false; + } if (HandleError(err, "AudioQueueStart")) { return false; } @@ -260,29 +281,28 @@ // AudioCapturer -// AudioCapturer support on Mac is still experimental. - -#if defined(NDEBUG) - bool AudioCapturer::IsSupported() { - return false; -} - -std::unique_ptr<AudioCapturer> AudioCapturer::Create() { - NOTIMPLEMENTED(); - return nullptr; -} - -#else - -bool AudioCapturer::IsSupported() { + if (HostSettings::GetInstance() + ->GetString(kMacAudioCaptureDeviceUid) + .empty()) { + HOST_LOG << kMacAudioCaptureDeviceUid << " is not set or not a string. " + << "Audio capturer will be disabled."; + return false; + } + HOST_LOG << kMacAudioCaptureDeviceUid + << " is set. Audio capturer will be enabled."; return true; } std::unique_ptr<AudioCapturer> AudioCapturer::Create() { - return std::make_unique<AudioCapturerMac>(); + std::string device_uid = + HostSettings::GetInstance()->GetString(kMacAudioCaptureDeviceUid); + if (device_uid.empty()) { + // AudioCapturer::Create is still called even when IsSupported() returns + // false. + return nullptr; + } + return std::make_unique<AudioCapturerMac>(device_uid); } -#endif - } // namespace remoting
diff --git a/remoting/host/audio_capturer_mac.h b/remoting/host/audio_capturer_mac.h index e906201..a875e984 100644 --- a/remoting/host/audio_capturer_mac.h +++ b/remoting/host/audio_capturer_mac.h
@@ -7,6 +7,8 @@ #include <AudioToolbox/AudioToolbox.h> +#include <string> + #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" @@ -23,7 +25,7 @@ // audio on Mac through the loopback device. class AudioCapturerMac : public AudioCapturer { public: - AudioCapturerMac(); + explicit AudioCapturerMac(const std::string& audio_device_uid); ~AudioCapturerMac() override; // AudioCapturer interface. @@ -52,6 +54,8 @@ SEQUENCE_CHECKER(sequence_checker_); + std::string audio_device_uid_; + AudioStreamBasicDescription stream_description_; PacketCapturedCallback callback_; AudioQueueRef input_queue_ = nullptr;
diff --git a/remoting/host/host_setting_keys.h b/remoting/host/host_setting_keys.h new file mode 100644 index 0000000..159de7585 --- /dev/null +++ b/remoting/host/host_setting_keys.h
@@ -0,0 +1,19 @@ +// Copyright 2021 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 REMOTING_HOST_HOST_SETTING_KEYS_H_ +#define REMOTING_HOST_HOST_SETTING_KEYS_H_ + +#include "remoting/host/host_settings.h" + +namespace remoting { + +// If setting is provided, the Mac host will capture audio from the audio device +// specified by the UID and stream it to the client. See AudioCapturerMac for +// more information. +constexpr HostSettingKey kMacAudioCaptureDeviceUid = "audio_capture_device_uid"; + +} // namespace remoting + +#endif // REMOTING_HOST_HOST_SETTING_KEYS_H_
diff --git a/remoting/host/host_settings.cc b/remoting/host/host_settings.cc new file mode 100644 index 0000000..5ab6f015 --- /dev/null +++ b/remoting/host/host_settings.cc
@@ -0,0 +1,45 @@ +// Copyright 2021 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 "remoting/host/host_settings.h" + +#include "base/no_destructor.h" +#include "build/build_config.h" + +namespace remoting { + +namespace { + +class EmptyHostSettings : public HostSettings { + public: + std::string GetString(const HostSettingKey key) const override { + return std::string(); + } + + void InitializeInstance() override {} +}; + +} // namespace + +// static +void HostSettings::Initialize() { + GetInstance()->InitializeInstance(); +} + +HostSettings::HostSettings() = default; + +HostSettings::~HostSettings() = default; + +// HostSettings is currently neither implemented nor used on non-Mac platforms. +#if !defined(OS_APPLE) + +// static +HostSettings* HostSettings::GetInstance() { + static base::NoDestructor<EmptyHostSettings> instance; + return instance.get(); +} + +#endif + +} // namespace remoting
diff --git a/remoting/host/host_settings.h b/remoting/host/host_settings.h new file mode 100644 index 0000000..722d9f7 --- /dev/null +++ b/remoting/host/host_settings.h
@@ -0,0 +1,43 @@ +// Copyright 2021 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 REMOTING_HOST_HOST_SETTINGS_H_ +#define REMOTING_HOST_HOST_SETTINGS_H_ + +#include <string> + +#include "base/values.h" + +namespace remoting { + +using HostSettingKey = char[]; + +// A class to read host settings, which are simple key-value pairs unrelated to +// the host's identity, like UID of an audio device to capture audio from, or +// whether a feature should be enabled. +class HostSettings { + public: + // Initializes host settings. Must be called on a thread that allows blocking + // before calling GetValue(). + static void Initialize(); + + static HostSettings* GetInstance(); + + // Gets the value of the setting. Returns empty string if the value is not + // found. + virtual std::string GetString(const HostSettingKey key) const = 0; + + HostSettings(const HostSettings&) = delete; + HostSettings& operator=(const HostSettings&) = delete; + + protected: + HostSettings(); + virtual ~HostSettings(); + + virtual void InitializeInstance() = 0; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_HOST_SETTINGS_H_
diff --git a/remoting/host/host_settings_mac.cc b/remoting/host/host_settings_mac.cc new file mode 100644 index 0000000..fc9121c8 --- /dev/null +++ b/remoting/host/host_settings_mac.cc
@@ -0,0 +1,62 @@ +// Copyright 2021 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 "remoting/host/host_settings_mac.h" + +#include "base/files/file_util.h" +#include "base/json/json_file_value_serializer.h" +#include "base/logging.h" +#include "base/no_destructor.h" +#include "remoting/base/logging.h" +#include "remoting/host/mac/constants_mac.h" + +namespace remoting { + +HostSettingsMac::HostSettingsMac() = default; + +HostSettingsMac::~HostSettingsMac() = default; + +void HostSettingsMac::InitializeInstance() { + // TODO(yuweih): Make HostSettingsMac detect changes of the settings file. + if (settings_) { + return; + } + + base::FilePath settings_file(kHostSettingsFilePath); + if (!base::PathIsReadable(settings_file)) { + HOST_LOG << "Host settings file " << kHostSettingsFilePath + << " does not exist."; + return; + } + JSONFileValueDeserializer deserializer(settings_file); + int error_code; + std::string error_message; + settings_ = deserializer.Deserialize(&error_code, &error_message); + if (!settings_) { + LOG(WARNING) << "Failed to load " << kHostSettingsFilePath + << ". Code: " << error_code << ", message: " << error_message; + return; + } + HOST_LOG << "Host settings loaded."; +} + +std::string HostSettingsMac::GetString(const HostSettingKey key) const { + if (!settings_) { + VLOG(1) << "Either Initialize() has not been called, or the settings file " + "doesn't exist."; + return std::string(); + } + std::string* string_value = settings_->FindStringKey(key); + if (!string_value) { + return std::string(); + } + return *string_value; +} + +HostSettings* HostSettings::GetInstance() { + static base::NoDestructor<HostSettingsMac> instance; + return instance.get(); +} + +} // namespace remoting
diff --git a/remoting/host/host_settings_mac.h b/remoting/host/host_settings_mac.h new file mode 100644 index 0000000..30eddc7b --- /dev/null +++ b/remoting/host/host_settings_mac.h
@@ -0,0 +1,34 @@ +// Copyright 2021 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 REMOTING_HOST_HOST_SETTINGS_MAC_H_ +#define REMOTING_HOST_HOST_SETTINGS_MAC_H_ + +#include <memory> + +#include "remoting/host/host_settings.h" + +namespace remoting { + +class HostSettingsMac final : public HostSettings { + public: + HostSettingsMac(); + ~HostSettingsMac() override; + + // HostSettings implementation. + void InitializeInstance() override; + std::string GetString(const HostSettingKey key) const override; + + HostSettingsMac(const HostSettingsMac&) = delete; + HostSettingsMac& operator=(const HostSettingsMac&) = delete; + + private: + // TODO(yuweih): This needs to be guarded with a lock if we detect changes of + // the settings file. + std::unique_ptr<base::Value> settings_; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_HOST_SETTINGS_MAC_H_
diff --git a/remoting/host/it2me/it2me_native_messaging_host_main.cc b/remoting/host/it2me/it2me_native_messaging_host_main.cc index 3808a7e..a5da6b3 100644 --- a/remoting/host/it2me/it2me_native_messaging_host_main.cc +++ b/remoting/host/it2me/it2me_native_messaging_host_main.cc
@@ -20,6 +20,7 @@ #include "remoting/base/breakpad.h" #include "remoting/host/chromoting_host_context.h" #include "remoting/host/host_exit_codes.h" +#include "remoting/host/host_settings.h" #include "remoting/host/it2me/it2me_native_messaging_host.h" #include "remoting/host/logging.h" #include "remoting/host/native_messaging/native_messaging_pipe.h" @@ -80,6 +81,7 @@ base::CommandLine::Init(argc, argv); remoting::InitHostLogging(); + remoting::HostSettings::Initialize(); #if defined(OS_APPLE) // Needed so we don't leak objects when threads are created.
diff --git a/remoting/host/mac/constants_mac.cc b/remoting/host/mac/constants_mac.cc index 04e2a0a..a1f3558f 100644 --- a/remoting/host/mac/constants_mac.cc +++ b/remoting/host/mac/constants_mac.cc
@@ -20,6 +20,8 @@ const char kHostConfigFileName[] = SERVICE_NAME ".json"; const char kHostConfigFilePath[] = HELPER_TOOLS_DIR SERVICE_NAME ".json"; +const char kHostSettingsFilePath[] = + HELPER_TOOLS_DIR SERVICE_NAME ".settings.json"; const char kHostServiceBinaryPath[] = HELPER_TOOLS_DIR HOST_BUNDLE_NAME "/Contents/MacOS/remoting_me2me_host_service";
diff --git a/remoting/host/mac/constants_mac.h b/remoting/host/mac/constants_mac.h index a149d15..ff5048f 100644 --- a/remoting/host/mac/constants_mac.h +++ b/remoting/host/mac/constants_mac.h
@@ -17,6 +17,8 @@ extern const char kHostConfigFileName[]; extern const char kHostConfigFilePath[]; +extern const char kHostSettingsFilePath[]; + // This helper script is executed as root to enable/disable/configure the host // service. // It is also used (as non-root) to provide version information for the
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index c93b068..7a0bd73 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -67,6 +67,7 @@ #include "remoting/host/host_exit_codes.h" #include "remoting/host/host_main.h" #include "remoting/host/host_power_save_blocker.h" +#include "remoting/host/host_settings.h" #include "remoting/host/host_status_logger.h" #include "remoting/host/input_injector.h" #include "remoting/host/ipc_desktop_environment.h" @@ -831,6 +832,8 @@ return; } + HostSettings::Initialize(); + if (!report_offline_reason_.empty()) { // Don't need to do any UI initialization. context_->network_task_runner()->PostTask(
diff --git a/services/device/time_zone_monitor/time_zone_monitor_win.cc b/services/device/time_zone_monitor/time_zone_monitor_win.cc index 9f5d5a6..4bcdc5f5d 100644 --- a/services/device/time_zone_monitor/time_zone_monitor_win.cc +++ b/services/device/time_zone_monitor/time_zone_monitor_win.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/trace_event/trace_event.h" #include "third_party/icu/source/i18n/unicode/timezone.h" #include "ui/gfx/win/singleton_hwnd_observer.h" @@ -24,21 +25,42 @@ singleton_hwnd_observer_(new gfx::SingletonHwndObserver( base::BindRepeating(&TimeZoneMonitorWin::OnWndProc, base::Unretained(this)))) {} + TimeZoneMonitorWin(const TimeZoneMonitorWin&) = delete; + TimeZoneMonitorWin& operator=(const TimeZoneMonitorWin&) = delete; ~TimeZoneMonitorWin() override {} private: void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { - if (message != WM_TIMECHANGE) { - return; + if (message == WM_TIMECHANGE && !pending_update_notification_tasks_) { + // Traces show that in some cases there are multiple WM_TIMECHANGE while + // performing a power resume. Only sending one is enough + // (http://crbug.com/1074036). + pending_update_notification_tasks_ = true; + + // The notifications are sent through a delayed task to avoid running + // the observers code while the computer is still suspended. The thread + // controller is not dispatching delayed tasks uuntil the power resume + // signal is received. + constexpr auto kMinimalPostTaskDelay = + base::TimeDelta::FromMilliseconds(1); + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&TimeZoneMonitorWin::OnWmTimechangeReceived, + weak_ptr_factory_.GetWeakPtr()), + kMinimalPostTaskDelay); } - TRACE_EVENT0("browser", "TimeZoneMonitorWin::UpdateIcuAndNotifyClients"); + } + + void OnWmTimechangeReceived() { + TRACE_EVENT0("device", "TimeZoneMonitorWin::OnTimechangeReceived"); UpdateIcuAndNotifyClients(DetectHostTimeZoneFromIcu()); + pending_update_notification_tasks_ = false; } std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_; - - DISALLOW_COPY_AND_ASSIGN(TimeZoneMonitorWin); + bool pending_update_notification_tasks_ = false; + base::WeakPtrFactory<TimeZoneMonitorWin> weak_ptr_factory_{this}; }; // static
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 655b0f2a..e485359 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -214,6 +214,10 @@ #define SK_DISABLE_REDUCE_OPLIST_SPLITTING #endif +#ifndef SK_SUPPORT_LEGACY_INHERITED_PICTURE_SHADER_FILTER +#define SK_SUPPORT_LEGACY_INHERITED_PICTURE_SHADER_FILTER +#endif + // Max. verb count for paths rendered by the edge-AA tessellating path renderer. #define GR_AA_TESSELLATOR_MAX_VERB_COUNT 100
diff --git a/sql/database_unittest.cc b/sql/database_unittest.cc index df61053..9ae6a17 100644 --- a/sql/database_unittest.cc +++ b/sql/database_unittest.cc
@@ -853,13 +853,6 @@ EXPECT_FALSE(GetPathExists(wal_path)); } -// WAL mode is currently not supported on Fuchsia -#if !defined(OS_FUCHSIA) -INSTANTIATE_TEST_SUITE_P(JournalMode, SQLDatabaseTest, testing::Bool()); -#else -INSTANTIATE_TEST_SUITE_P(JournalMode, SQLDatabaseTest, testing::Values(false)); -#endif - #if defined(OS_POSIX) // This test operates on POSIX file permissions. TEST_P(SQLDatabaseTest, PosixFilePermissions) { db().Close(); @@ -1375,4 +1368,17 @@ #endif // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA) } +// WAL mode is currently not supported on Fuchsia. +#if !defined(OS_FUCHSIA) +INSTANTIATE_TEST_SUITE_P(JournalMode, SQLDatabaseTest, testing::Bool()); +INSTANTIATE_TEST_SUITE_P(JournalMode, + SQLDatabaseTestExclusiveMode, + testing::Bool()); +#else +INSTANTIATE_TEST_SUITE_P(JournalMode, SQLDatabaseTest, testing::Values(false)); +INSTANTIATE_TEST_SUITE_P(JournalMode, + SQLDatabaseTestExclusiveMode, + testing::Values(false)); +#endif + } // namespace sql
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 78b9246..8049616 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -990,8 +990,8 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3-384.90", - "os": "Ubuntu-14.04", + "gpu": "10de:1cb3-440.100", + "os": "Ubuntu-18.04", "pool": "chrome.tests.perf", "synthetic_product_name": "PowerEdge R230 (Dell Inc.)" }
diff --git a/testing/test.gni b/testing/test.gni index 473b486..a9a0ece 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -41,6 +41,20 @@ # Similar to the GN arg 'enable_run_ios_unittests_with_xctest' but # for build targets. template("test") { + # RTS + if (rts_exclude_file != "" && defined(invoker.sources) && + invoker.sources != []) { + # Normalize paths + abs_paths = get_path_info(invoker.sources, "abspath") + + # Filter + filtered_sources = filter_exclude(abs_paths, rts_exclusions) + + # Do the replacement + invoker.sources = [] + invoker.sources = filtered_sources + } + testonly = true if (!is_ios) { assert(!defined(invoker.is_xctest) || !invoker.is_xctest,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 6877c21d..47ad760 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -8111,8 +8111,7 @@ "default_locale": "en", "experiment_tag": "", "fetch_frequency": "15", - "summary_card_poster_url": "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", - "use_animated_gif_url": "false" + "use_animated_gif_url": "true" }, "enable_features": [ "VideoTutorials"
diff --git a/third_party/android_deps/build.gradle b/third_party/android_deps/build.gradle index 5622cf2a..3081e22 100644 --- a/third_party/android_deps/build.gradle +++ b/third_party/android_deps/build.gradle
@@ -11,7 +11,7 @@ } } dependencies { - classpath "org.owasp:dependency-check-gradle:5.3.2.1" + classpath "org.owasp:dependency-check-gradle:6+" } }
diff --git a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc index 63d5d4e5..ac2cb47 100644 --- a/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc +++ b/third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
@@ -131,6 +131,8 @@ data.dont_send_key_events_to_javascript(); out->barrel_button_for_drag_enabled = data.barrel_button_for_drag_enabled(); out->sync_xhr_in_documents_enabled = data.sync_xhr_in_documents_enabled(); + out->target_blank_implies_no_opener_enabled_will_be_removed = + data.target_blank_implies_no_opener_enabled_will_be_removed(); out->number_of_cpu_cores = data.number_of_cpu_cores(); out->editing_behavior = data.editing_behavior(); out->supports_multiple_windows = data.supports_multiple_windows();
diff --git a/third_party/blink/manual_tests/forms/eye-dropper.html b/third_party/blink/manual_tests/forms/eye-dropper.html index fb9cfca..736612e 100644 --- a/third_party/blink/manual_tests/forms/eye-dropper.html +++ b/third_party/blink/manual_tests/forms/eye-dropper.html
@@ -62,7 +62,13 @@ document.getElementById("color").addEventListener("input", function(e) { let entry = log("color updated to " + e.target.value + " expected: #ff0000"); let span = document.createElement("span"); - if (e.target.value == "#ff0000") { + + let red = parseInt(e.target.value.substring(1, 3), 16); + let green = parseInt(e.target.value.substring(3, 5), 16); + let blue = parseInt(e.target.value.substring(5, 7), 16); + // Make sure the selected color is close to pure red (#FF0000), but allow + // some deviation due to monitor color calibration. + if (red >= 0xC0 && green <= 0x3F && blue <= 0x3F) { span.innerText = "PASS "; span.classList.add("passed"); } else {
diff --git a/third_party/blink/public/common/web_preferences/web_preferences.h b/third_party/blink/public/common/web_preferences/web_preferences.h index 95ab020..64444803 100644 --- a/third_party/blink/public/common/web_preferences/web_preferences.h +++ b/third_party/blink/public/common/web_preferences/web_preferences.h
@@ -135,6 +135,8 @@ bool dont_send_key_events_to_javascript; bool barrel_button_for_drag_enabled = false; bool sync_xhr_in_documents_enabled; + // TODO(https://crbug.com/1163644): Remove once Chrome Apps are deprecated. + bool target_blank_implies_no_opener_enabled_will_be_removed = true; int number_of_cpu_cores; blink::mojom::EditingBehavior editing_behavior; bool supports_multiple_windows;
diff --git a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h index 145106c..c071879c 100644 --- a/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h +++ b/third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
@@ -360,6 +360,11 @@ return r.sync_xhr_in_documents_enabled; } + static bool target_blank_implies_no_opener_enabled_will_be_removed( + const blink::web_pref::WebPreferences& r) { + return r.target_blank_implies_no_opener_enabled_will_be_removed; + } + static uint32_t number_of_cpu_cores( const blink::web_pref::WebPreferences& r) { return r.number_of_cpu_cores;
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index 9117bb9a..4bfd95b 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3064,6 +3064,7 @@ kCrossOriginSubframeWithoutEmbeddingControl = 3742, kReadableStreamWithByteSource = 3743, kReadableStreamBYOBReader = 3744, + kEmbedElementWithoutTypeSrcChanged = 3745, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom index df3ffb49..519b354f 100644 --- a/third_party/blink/public/mojom/webpreferences/web_preferences.mojom +++ b/third_party/blink/public/mojom/webpreferences/web_preferences.mojom
@@ -188,6 +188,7 @@ bool dont_send_key_events_to_javascript; bool barrel_button_for_drag_enabled; bool sync_xhr_in_documents_enabled; + bool target_blank_implies_no_opener_enabled_will_be_removed; int32 number_of_cpu_cores; EditingBehavior editing_behavior; bool supports_multiple_windows;
diff --git a/third_party/blink/public/web/web_ax_object.h b/third_party/blink/public/web/web_ax_object.h index f54825b..6813404 100644 --- a/third_party/blink/public/web/web_ax_object.h +++ b/third_party/blink/public/web/web_ax_object.h
@@ -333,7 +333,6 @@ // Programmatically scrollable. BLINK_EXPORT bool IsScrollableContainer() const; // Also scrollable by user. - BLINK_EXPORT bool IsUserScrollable() const; BLINK_EXPORT gfx::Point GetScrollOffset() const; BLINK_EXPORT gfx::Point MinimumScrollOffset() const; BLINK_EXPORT gfx::Point MaximumScrollOffset() const;
diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h index 7e97b5df..9944af8 100644 --- a/third_party/blink/public/web/web_settings.h +++ b/third_party/blink/public/web/web_settings.h
@@ -219,6 +219,8 @@ virtual void SetSupportDeprecatedTargetDensityDPI(bool) = 0; virtual void SetSupportsMultipleWindows(bool) = 0; virtual void SetSyncXHRInDocumentsEnabled(bool) = 0; + // TODO(https://crbug.com/1163644): Remove once Chrome Apps are deprecated. + virtual void SetTargetBlankImpliesNoOpenerEnabledWillBeRemoved(bool) = 0; virtual void SetTextAreasAreResizable(bool) = 0; virtual void SetTextAutosizingEnabled(bool) = 0; virtual void SetAccessibilityFontScaleFactor(float) = 0;
diff --git a/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl b/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl index 6f917df..327431d 100644 --- a/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl
@@ -39,28 +39,16 @@ return; \ {{setting.name.to_class_data_member()}} = {{setting.name.to_snake_case()}}; \ {% if setting.invalidate %} - Invalidate(SettingsDelegate::k{{setting.invalidate}}Change); \ + {% for type in setting.invalidate %} + Invalidate(SettingsDelegate::ChangeType::k{{type}}); \ + {% endfor %} {% endif %} } \ {% endfor %} void Settings::SetFromStrings(const String& name, const String& value) { \ {% for setting in settings %} if (name == "{{setting.name}}") { \ - Set{{setting.name.to_upper_camel_case()}}( \ - {% if setting.type == 'String' %} - value \ - {% elif setting.type == 'bool' %} - value.IsEmpty() || value == "true" \ - {% elif setting.type == 'int' %} - value.ToInt() \ - {% elif setting.type == 'float' %} - value.ToFloat() \ - {% elif setting.type == 'double' %} - value.ToDouble() \ - {% else %} - static_cast<{{setting.type}}>(value.ToInt()) \ - {% endif %} - ); \ + Set{{setting.name.to_upper_camel_case()}}(FromString<{{setting.type}}>()(value)); \ return; \ } \ {% endfor %}
diff --git a/third_party/blink/renderer/core/animation/compositor_animations.cc b/third_party/blink/renderer/core/animation/compositor_animations.cc index 58a8aa4..395e378 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -800,9 +800,18 @@ } DCHECK(curve.get()); - auto keyframe_model = std::make_unique<CompositorKeyframeModel>( - *curve, target_property, 0, group, std::move(custom_property_name), - native_property_type); + std::unique_ptr<CompositorKeyframeModel> keyframe_model; + if (!custom_property_name.IsEmpty()) { + keyframe_model = std::make_unique<CompositorKeyframeModel>( + *curve, target_property, 0, group, std::move(custom_property_name)); + } else if (native_property_type != + CompositorPaintWorkletInput::NativePropertyType::kInvalid) { + keyframe_model = std::make_unique<CompositorKeyframeModel>( + *curve, target_property, 0, group, native_property_type); + } else { + keyframe_model = std::make_unique<CompositorKeyframeModel>( + *curve, target_property, 0, group); + } if (start_time) keyframe_model->SetStartTime(start_time.value());
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 69157fea..b216731 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.cc +++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc
@@ -624,6 +624,11 @@ settings_->SetSyncXHRInDocumentsEnabled(enabled); } +void WebSettingsImpl::SetTargetBlankImpliesNoOpenerEnabledWillBeRemoved( + bool enabled) { + settings_->SetTargetBlankImpliesNoOpenerEnabledWillBeRemoved(enabled); +} + void WebSettingsImpl::SetCaretBrowsingEnabled(bool enabled) { settings_->SetCaretBrowsingEnabled(enabled); }
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 2971a655..2a7838c 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.h +++ b/third_party/blink/renderer/core/exported/web_settings_impl.h
@@ -162,6 +162,7 @@ void SetSupportDeprecatedTargetDensityDPI(bool) override; void SetSupportsMultipleWindows(bool) override; void SetSyncXHRInDocumentsEnabled(bool) override; + void SetTargetBlankImpliesNoOpenerEnabledWillBeRemoved(bool) override; void SetTextAreasAreResizable(bool) override; void SetTextAutosizingEnabled(bool) override; void SetAccessibilityFontScaleFactor(float) override;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 0d1cf9b1..a49a490 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1404,6 +1404,8 @@ blink::WebNetworkStateNotifier::SetSaveDataEnabled(prefs.data_saver_enabled); settings->SetLocalStorageEnabled(prefs.local_storage_enabled); settings->SetSyncXHRInDocumentsEnabled(prefs.sync_xhr_in_documents_enabled); + settings->SetTargetBlankImpliesNoOpenerEnabledWillBeRemoved( + prefs.target_blank_implies_no_opener_enabled_will_be_removed); RuntimeEnabledFeatures::SetDatabaseEnabled(prefs.databases_enabled); settings->SetOfflineWebApplicationCacheEnabled( prefs.application_cache_enabled);
diff --git a/third_party/blink/renderer/core/frame/settings.cc b/third_party/blink/renderer/core/frame/settings.cc index b27f55e9..129589f 100644 --- a/third_party/blink/renderer/core/frame/settings.cc +++ b/third_party/blink/renderer/core/frame/settings.cc
@@ -36,6 +36,46 @@ namespace blink { +namespace { + +// For generated Settings::SetFromStrings(). +template <typename T> +struct FromString { + T operator()(const String& s) { return static_cast<T>(s.ToInt()); } +}; + +template <> +struct FromString<String> { + const String& operator()(const String& s) { return s; } +}; + +template <> +struct FromString<bool> { + bool operator()(const String& s) { return s.IsEmpty() || s == "true"; } +}; + +template <> +struct FromString<float> { + float operator()(const String& s) { return s.ToFloat(); } +}; + +template <> +struct FromString<double> { + double operator()(const String& s) { return s.ToDouble(); } +}; + +template <> +struct FromString<IntSize> { + IntSize operator()(const String& s) { + Vector<String> fields; + s.Split(',', fields); + return IntSize(fields.size() > 0 ? fields[0].ToInt() : 0, + fields.size() > 1 ? fields[1].ToInt() : 0); + } +}; + +} // namespace + // NOTEs // 1) EditingMacBehavior comprises builds on Mac; // 2) EditingWindowsBehavior comprises builds on Windows; @@ -67,8 +107,7 @@ static const bool kDefaultSelectTrailingWhitespaceEnabled = false; #endif -Settings::Settings() - : text_autosizing_enabled_(false) SETTINGS_INITIALIZER_LIST {} +Settings::Settings() : delegate_(nullptr) SETTINGS_INITIALIZER_LIST {} SETTINGS_SETTER_BODIES @@ -81,23 +120,4 @@ delegate_->SettingsChanged(change_type); } -void Settings::SetTextAutosizingEnabled(bool text_autosizing_enabled) { - if (text_autosizing_enabled_ == text_autosizing_enabled) - return; - - text_autosizing_enabled_ = text_autosizing_enabled; - Invalidate(SettingsDelegate::kTextAutosizingChange); -} - -// TODO: Move to Settings.json5 once make_settings can understand IntSize. -void Settings::SetTextAutosizingWindowSizeOverride( - const IntSize& text_autosizing_window_size_override) { - if (text_autosizing_window_size_override_ == - text_autosizing_window_size_override) - return; - - text_autosizing_window_size_override_ = text_autosizing_window_size_override; - Invalidate(SettingsDelegate::kTextAutosizingChange); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/settings.h b/third_party/blink/renderer/core/frame/settings.h index af8e5f4..5b6ab45 100644 --- a/third_party/blink/renderer/core/frame/settings.h +++ b/third_party/blink/renderer/core/frame/settings.h
@@ -63,20 +63,7 @@ return generic_font_family_settings_; } void NotifyGenericFontFamilyChange() { - Invalidate(SettingsDelegate::kFontFamilyChange); - } - - void SetTextAutosizingEnabled(bool); - bool TextAutosizingEnabled() const { return text_autosizing_enabled_; } - - void SetBypassCSP(bool enabled) { bypass_csp_ = enabled; } - bool BypassCSP() const { return bypass_csp_; } - - // Only set by web tests, and only used if TextAutosizingEnabled() returns - // true. - void SetTextAutosizingWindowSizeOverride(const IntSize&); - const IntSize& TextAutosizingWindowSizeOverride() const { - return text_autosizing_window_size_override_; + Invalidate(SettingsDelegate::ChangeType::kFontFamily); } SETTINGS_GETTERS_AND_SETTERS @@ -89,9 +76,6 @@ SettingsDelegate* delegate_; GenericFontFamilySettings generic_font_family_settings_; - IntSize text_autosizing_window_size_override_; - bool text_autosizing_enabled_ : 1; - bool bypass_csp_ = false; SETTINGS_MEMBER_VARIABLES
diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5 index 3af88df..29ea43a 100644 --- a/third_party/blink/renderer/core/frame/settings.json5 +++ b/third_party/blink/renderer/core/frame/settings.json5
@@ -28,10 +28,15 @@ // Valid parameters for data entries below. parameters: { type: { - default: "bool" + default: "bool", + valid_type: "str", // The string value should be a C++ type name }, initial: {}, - invalidate: {}, + invalidate: { + default: [], + valid_type: "list", + // See SettingsDelegate::ChangeType for valid values (without "k"), + }, }, data: [ @@ -70,7 +75,7 @@ { name: "minimumFontSize", initial: 0, - invalidate: "Style", + invalidate: ["Style"], type: "int", }, @@ -79,19 +84,19 @@ { name: "minimumLogicalFontSize", initial: 0, - invalidate: "Style", + invalidate: ["Style"], type: "int", }, { name: "defaultFontSize", initial: 0, - invalidate: "Style", + invalidate: ["Style"], type: "int", }, { name: "defaultFixedFontSize", initial: 0, - invalidate: "Style", + invalidate: ["Style"], type: "int", }, @@ -108,7 +113,7 @@ { name: "allowUniversalAccessFromFileURLs", initial: true, - invalidate: "UniversalAccess", + invalidate: ["UniversalAccess"], }, { name: "allowFileAccessFromFileURLs", @@ -133,17 +138,17 @@ { name: "HighlightAds", initial: false, - invalidate: "HighlightAds" + invalidate: ["HighlightAds"], }, { name: "textAreasAreResizable", initial: false, - invalidate: "Style", + invalidate: ["Style"], }, { name: "acceleratedCompositingEnabled", initial: false, - invalidate: "AcceleratedCompositing", + invalidate: ["AcceleratedCompositing"], }, { @@ -166,7 +171,7 @@ { name: "preferCompositingToLCDTextEnabled", initial: false, - invalidate: "AcceleratedCompositing", + invalidate: ["AcceleratedCompositing"], }, { @@ -231,7 +236,7 @@ { name: "immersiveModeEnabled", initial: false, - invalidate: "MediaControls", + invalidate: ["MediaControls"], }, // Only affects main thread scrolling @@ -246,7 +251,7 @@ { name: "threadedScrollingEnabled", initial: true, - invalidate: "Style", + invalidate: ["Style"], }, // Used in web tests for gesture tap highlights. Makes the highlights square @@ -285,6 +290,10 @@ initial: true, }, { + name: "targetBlankImpliesNoOpenerEnabledWillBeRemoved", + initial: true, + }, + { name: "cookieEnabled", initial: true, }, @@ -311,7 +320,7 @@ { name: "spatialNavigationEnabled", initial: false, - invalidate: "SpatialNavigation", + invalidate: ["SpatialNavigation"], }, // This setting adds a means to enable/disable touch initiated drag & drop. If @@ -407,13 +416,13 @@ { name: "forceZeroLayoutHeight", initial: false, - invalidate: "ViewportDescription", + invalidate: ["ViewportDescription"], }, { name: "mainFrameClipsContent", initial: true, - invalidate: "ViewportPaintProperties", + invalidate: ["ViewportPaintProperties"], }, // For android.webkit.WebSettings.setUseWideViewport() @@ -421,7 +430,7 @@ { name: "useWideViewport", initial: true, - invalidate: "ViewportDescription", + invalidate: ["ViewportDescription"], }, // For android.webkit.WebSettings.setLoadWithOverviewMode() @@ -429,7 +438,7 @@ { name: "loadWithOverviewMode", initial: true, - invalidate: "ViewportDescription", + invalidate: ["ViewportDescription"], }, // Used by android_webview to support legacy apps that inject script into a top-level initial empty @@ -463,14 +472,14 @@ { name: "caretBrowsingEnabled", initial: false, - invalidate: "Style", + invalidate: ["Style"], }, // Font scale factor for accessibility, applied as part of text autosizing. { name: "accessibilityFontScaleFactor", initial: "1.0", - invalidate: "TextAutosizing", + invalidate: ["TextAutosizing"], type: "double", }, @@ -478,13 +487,13 @@ { name: "mediaTypeOverride", initial: "\"\"", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "String", }, { name: "displayModeOverride", initial: "blink::mojom::DisplayMode::kUndefined", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "blink::mojom::DisplayMode", }, @@ -493,12 +502,12 @@ { name: "loadsImagesAutomatically", initial: false, - invalidate: "ImageLoading", + invalidate: ["ImageLoading"], }, { name: "imagesEnabled", initial: true, - invalidate: "ImageLoading", + invalidate: ["ImageLoading"], }, { name: "imageAnimationPolicy", @@ -517,18 +526,18 @@ { name: "pluginsEnabled", initial: false, - invalidate: "Plugins", + invalidate: ["Plugins"], }, { name: "viewportEnabled", initial: false, - invalidate: "ViewportDescription", + invalidate: ["ViewportDescription"], }, { name: "viewportMetaEnabled", initial: false, - invalidate: "ViewportDescription", + invalidate: ["ViewportDescription"], }, // When true, Blink will use the content width and viewport size to set the @@ -542,7 +551,7 @@ { name: "dnsPrefetchingEnabled", initial: false, - invalidate: "DNSPrefetching", + invalidate: ["DNSPrefetching"], }, // Clients that execute script should call ExecutionContext::canExecuteScripts() @@ -563,7 +572,7 @@ { name: "forceAndroidOverlayScrollbar", initial: false, - invalidate: "ScrollbarLayout", + invalidate: ["ScrollbarLayout"], }, // Set the timeout seconds of the network-quiet timers in IdlenessDetector. @@ -580,7 +589,7 @@ { name: "forceMainWorldInitialization", initial: false, - invalidate: "DOMWorlds", + invalidate: ["DOMWorlds"], }, // Forces TouchEventFeatureDetection conditional feature for all main @@ -597,7 +606,7 @@ { name: "deviceScaleAdjustment", initial: "1.0", - invalidate: "TextAutosizing", + invalidate: ["TextAutosizing"], type: "double", }, @@ -623,13 +632,13 @@ { name: "availablePointerTypes", initial: "ui::POINTER_TYPE_NONE", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "int", }, { name: "availableHoverTypes", initial: "ui::HOVER_TYPE_NONE", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "int", }, @@ -637,13 +646,13 @@ { name: "primaryPointerType", initial: "mojom::blink::PointerType::kPointerNone", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "blink::mojom::PointerType", }, { name: "primaryHoverType", initial: "mojom::blink::HoverType::kHoverNone", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "mojom::blink::HoverType", }, @@ -717,7 +726,7 @@ { name: "viewportStyle", initial: "mojom::blink::ViewportStyle::kDefault", - invalidate: "ViewportRule", + invalidate: ["ViewportRule"], type: "mojom::blink::ViewportStyle", }, @@ -726,7 +735,7 @@ { name: "textTrackKindUserPreference", initial: "TextTrackKindUserPreference::kDefault", - invalidate: "TextTrackKindUserPreference", + invalidate: ["TextTrackKindUserPreference"], type: "TextTrackKindUserPreference", }, @@ -836,7 +845,7 @@ { name: "hideScrollbars", initial: false, - invalidate: "ViewportPaintProperties", + invalidate: ["ViewportPaintProperties"], }, // Spellchecking is enabled by default for elements that do not specify it explicitly @@ -863,7 +872,7 @@ { name: "mediaControlsEnabled", initial: true, - invalidate: "MediaControls", + invalidate: ["MediaControls"], }, // Whether we should not update selection attributes when mutating selection range. @@ -886,7 +895,7 @@ { name: "forceDarkModeEnabled", initial: false, - invalidate: "ForceDark", + invalidate: ["ColorScheme", "Paint"], }, { @@ -1008,7 +1017,7 @@ { name: "preferredColorScheme", initial: "mojom::blink::PreferredColorScheme::kLight", - invalidate: "ColorScheme", + invalidate: ["ColorScheme"], type: "mojom::blink::PreferredColorScheme", }, @@ -1017,7 +1026,7 @@ { name: "preferredContrast", initial: "mojom::blink::PreferredContrast::kNoPreference", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "mojom::blink::PreferredContrast", }, @@ -1026,7 +1035,7 @@ { name: "prefersReducedMotion", initial: false, - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], }, { name: "DontSendKeyEventsToJavascript", @@ -1037,14 +1046,13 @@ { name: "navigationControls", initial: "NavigationControls::kNone", - invalidate: "MediaQuery", + invalidate: ["MediaQuery"], type: "NavigationControls", }, { name: "accessibilityAlwaysShowFocus", initial: false, - invalidate: "Style", - type: "bool" + invalidate: ["Style"], }, // aria-modal="true" on some platforms requires the accessibility tree to // be pruned so no other background content is exposed to assistive @@ -1053,7 +1061,6 @@ { name: "ariaModalPrunesAXTree", initial: false, - type: "bool", }, // The AXMenuList class provides a fake implementation of the // select element pop-up menu, which is required on platforms like @@ -1067,12 +1074,25 @@ { name: "selectionClipboardBufferAvailable", initial: false, - type: "bool", }, { name: "accessibilityIncludeSvgGElement", initial: false, - type: "bool", + }, + { + name: "bypassCSP", + initial: false, + }, + { + name: "textAutosizingEnabled", + initial: false, + invalidate: ["TextAutosizing"], + }, + // Only set by web tests, and only used if textAutosizingEnabled is true. + { + name: "textAutosizingWindowSizeOverride", + invalidate: ["TextAutosizing"], + type: "IntSize", }, ], }
diff --git a/third_party/blink/renderer/core/frame/settings_delegate.h b/third_party/blink/renderer/core/frame/settings_delegate.h index 5f00667..e631601 100644 --- a/third_party/blink/renderer/core/frame/settings_delegate.h +++ b/third_party/blink/renderer/core/frame/settings_delegate.h
@@ -50,30 +50,29 @@ // We currently use an enum instead of individual invalidation // functions to make generating Settings.in slightly easier. - enum ChangeType { - kStyleChange, - kViewportDescriptionChange, - kViewportRuleChange, - kViewportPaintPropertiesChange, - kDNSPrefetchingChange, - kImageLoadingChange, - kTextAutosizingChange, - kFontFamilyChange, - kAcceleratedCompositingChange, - kMediaQueryChange, - kAccessibilityStateChange, - kTextTrackKindUserPreferenceChange, - kDOMWorldsChange, - kMediaControlsChange, - kPluginsChange, - kHighlightAdsChange, - kPaintChange, - kScrollbarLayoutChange, - kColorSchemeChange, - kSpatialNavigationChange, - kUniversalAccessChange, - kVisionDeficiencyChange, - kForceDarkChange, + enum class ChangeType { + kStyle, + kViewportDescription, + kViewportRule, + kViewportPaintProperties, + kDNSPrefetching, + kImageLoading, + kTextAutosizing, + kFontFamily, + kAcceleratedCompositing, + kMediaQuery, + kAccessibilityState, + kTextTrackKindUserPreference, + kDOMWorlds, + kMediaControls, + kPlugins, + kHighlightAds, + kPaint, + kScrollbarLayout, + kColorScheme, + kSpatialNavigation, + kUniversalAccess, + kVisionDeficiency, }; virtual void SettingsChanged(ChangeType) = 0;
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc index dd71bae..5a579c3 100644 --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -1277,7 +1277,7 @@ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame()) ->GetDocument(); document->GetSettings()->SetTextAutosizingEnabled(true); - EXPECT_TRUE(document->GetSettings()->TextAutosizingEnabled()); + EXPECT_TRUE(document->GetSettings()->GetTextAutosizingEnabled()); web_view_helper.Resize(gfx::Size(viewport_width, viewport_height)); EXPECT_TRUE(SetTextAutosizingMultiplier(document, 2)); @@ -1306,7 +1306,7 @@ To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame()) ->GetDocument(); document->GetSettings()->SetTextAutosizingEnabled(true); - EXPECT_TRUE(document->GetSettings()->TextAutosizingEnabled()); + EXPECT_TRUE(document->GetSettings()->GetTextAutosizingEnabled()); web_view_helper.Resize(gfx::Size(490, 800)); @@ -1331,7 +1331,7 @@ Document* document = main_frame->GetDocument(); LocalFrameView* frame_view = web_view_helper.LocalMainFrame()->GetFrameView(); document->GetSettings()->SetTextAutosizingEnabled(true); - EXPECT_TRUE(document->GetSettings()->TextAutosizingEnabled()); + EXPECT_TRUE(document->GetSettings()->GetTextAutosizingEnabled()); web_view_helper.Resize(gfx::Size(viewport_width, viewport_height)); for (Frame* frame = main_frame; frame; frame = frame->Tree().TraverseNext()) {
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index f4137ea..5e1bcf7 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -544,7 +544,9 @@ } if (HasRel(kRelationNoOpener) || (EqualIgnoringASCIICase(target, "_blank") && !HasRel(kRelationOpener) && - RuntimeEnabledFeatures::TargetBlankImpliesNoOpenerEnabled())) { + RuntimeEnabledFeatures::TargetBlankImpliesNoOpenerEnabled() && + frame->GetSettings() + ->GetTargetBlankImpliesNoOpenerEnabledWillBeRemoved())) { frame_request.SetNoOpener(); }
diff --git a/third_party/blink/renderer/core/html/html_embed_element.cc b/third_party/blink/renderer/core/html/html_embed_element.cc index 0ea3c6f..35bc484 100644 --- a/third_party/blink/renderer/core/html/html_embed_element.cc +++ b/third_party/blink/renderer/core/html/html_embed_element.cc
@@ -126,6 +126,9 @@ if (FastHasAttribute(html_names::kTypeAttr)) { SetNeedsPluginUpdate(true); ReattachOnPluginChangeIfNeeded(); + } else { + UseCounter::Count(GetDocument(), + WebFeature::kEmbedElementWithoutTypeSrcChanged); } } } else {
diff --git a/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc b/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc index 10c1c63..ee57650 100644 --- a/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc +++ b/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
@@ -71,7 +71,7 @@ original_default_minimum_page_scale_factor_(0), original_default_maximum_page_scale_factor_(0), embedder_text_autosizing_enabled_( - web_view->GetPage()->GetSettings().TextAutosizingEnabled()), + web_view->GetPage()->GetSettings().GetTextAutosizingEnabled()), embedder_device_scale_adjustment_( web_view->GetPage()->GetSettings().GetDeviceScaleAdjustment()), embedder_prefer_compositing_to_lcd_text_enabled_(
diff --git a/third_party/blink/renderer/core/layout/hit_testing_test.cc b/third_party/blink/renderer/core/layout/hit_testing_test.cc index a6f7248..5b51ba8a 100644 --- a/third_party/blink/renderer/core/layout/hit_testing_test.cc +++ b/third_party/blink/renderer/core/layout/hit_testing_test.cc
@@ -173,4 +173,41 @@ EXPECT_FALSE(hit_result.BoxFragment()); } +TEST_F(HitTestingTest, ScrolledInline) { + SetBodyInnerHTML(R"HTML( + <style> + body { + margin: 0; + font-size: 50px; + line-height: 1; + } + #scroller { + width: 400px; + height: 5em; + overflow: scroll; + white-space: pre; + } + </style> + <div id="scroller">line1 +line2 +line3 +line4 +line5 +line6 +line7 +line8 +line9</div> + )HTML"); + + // Scroll #scroller by 2 lines. "line3" should be at the top. + Element* scroller = GetElementById("scroller"); + scroller->setScrollTop(100); + + const auto& text = *To<Text>(GetElementById("scroller")->firstChild()); + + // Expect to hit test position 12 (beginning of line3). + EXPECT_EQ(PositionWithAffinity(Position(text, 12)), + HitTest(PhysicalOffset(5, 5))); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index b5b16c03..7cd7914 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -826,11 +826,18 @@ // See All/LayoutViewHitTestTest.HitTestHorizontal/* and // All/LayoutViewHitTestTest.HitTestVerticalRL/* NGInlineCursor cursor; + const LayoutBlockFlow* containing_block_flow = ContainingNGBlockFlow(); + PhysicalOffset point_in_contents = point; + if (containing_block_flow->IsScrollContainer()) { + point_in_contents += PhysicalOffset( + containing_block_flow->PixelSnappedScrolledContentOffset()); + } for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) { if (!EnclosingIntRect(cursor.Current().RectInContainerFragment()) - .Contains(FlooredIntPoint(point))) + .Contains(FlooredIntPoint(point_in_contents))) continue; - if (auto position_with_affinity = cursor.PositionForPointInChild(point)) { + if (auto position_with_affinity = + cursor.PositionForPointInChild(point_in_contents)) { // Note: Due by Bidi adjustment, |position| isn't relative to this. const Position& position = position_with_affinity.GetPosition(); DCHECK(position.IsOffsetInAnchor()) << position; @@ -841,7 +848,7 @@ } } // Try for leading and trailing spaces between lines. - return ContainingNGBlockFlow()->PositionForPoint(point); + return containing_block_flow->PositionForPoint(point); } DCHECK(CanUseInlineBox(*this));
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc index c39d0c56..0494502 100644 --- a/third_party/blink/renderer/core/layout/scroll_anchor.cc +++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -673,6 +673,15 @@ } const SerializedAnchor ScrollAnchor::GetSerializedAnchor() { + if (auto* scroller_box = ScrollerLayoutBox(scroller_)) { + // This method may be called to find a serialized anchor on a document which + // needs a lifecycle update. Computing offsets below may currently compute + // style for ::first-line. If that is done with dirty active stylesheets, we + // may have null pointer crash as style computation assumes active sheets + // are up to date. Update active style if necessary here. + scroller_box->GetDocument().GetStyleEngine().UpdateActiveStyle(); + } + // It's safe to return saved_selector_ before checking anchor_object_, since // clearing anchor_object_ also clears saved_selector_. if (!saved_selector_.IsEmpty()) {
diff --git a/third_party/blink/renderer/core/layout/text_autosizer.cc b/third_party/blink/renderer/core/layout/text_autosizer.cc index 10936b7..c37fd886 100644 --- a/third_party/blink/renderer/core/layout/text_autosizer.cc +++ b/third_party/blink/renderer/core/layout/text_autosizer.cc
@@ -621,7 +621,7 @@ PageInfo previous_page_info(page_info_); page_info_.setting_enabled_ = - document_->GetSettings()->TextAutosizingEnabled(); + document_->GetSettings()->GetTextAutosizingEnabled(); if (!page_info_.setting_enabled_ || document_->Printing()) { page_info_.page_needs_autosizing_ = false; @@ -638,7 +638,7 @@ } else { LocalFrame& main_frame = To<LocalFrame>(frame); IntSize frame_size = - document_->GetSettings()->TextAutosizingWindowSizeOverride(); + document_->GetSettings()->GetTextAutosizingWindowSizeOverride(); if (frame_size.IsEmpty()) frame_size = WindowSize();
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 931f91b8..a5cc196 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -1764,7 +1764,7 @@ ContentSecurityPolicy* csp = MakeGarbageCollected<ContentSecurityPolicy>(); csp->SetOverrideURLForSelf(response.CurrentRequestUrl()); - if (frame_->GetSettings()->BypassCSP()) + if (frame_->GetSettings()->GetBypassCSP()) return csp; // Empty CSP. // Parse CSP from the HTTP response.
diff --git a/third_party/blink/renderer/core/loader/http_equiv.cc b/third_party/blink/renderer/core/loader/http_equiv.cc index d102213c..f39ba93 100644 --- a/third_party/blink/renderer/core/loader/http_equiv.cc +++ b/third_party/blink/renderer/core/loader/http_equiv.cc
@@ -97,7 +97,7 @@ const AtomicString& content) { if (!window || !window->GetFrame()) return; - if (window->GetFrame()->GetSettings()->BypassCSP()) + if (window->GetFrame()->GetSettings()->GetBypassCSP()) return; if (EqualIgnoringASCIICase(equiv, "content-security-policy")) { window->GetContentSecurityPolicy()->DidReceiveHeader(
diff --git a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc index 01dd7a2..d49caaae 100644 --- a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
@@ -71,8 +71,7 @@ client_->NotifyFetchFinishedSuccess(ModuleScriptCreationParams( /*source_url=*/url, /*base_url=*/url, ScriptSourceLocationType::kExternalFile, module_type, - script_resource->SourceText(), script_resource->CacheHandler(), - script_resource->GetResourceRequest().GetCredentialsMode(), streamer, + script_resource->SourceText(), script_resource->CacheHandler(), streamer, not_streamed_reason)); }
diff --git a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc index a5da398..3367e89 100644 --- a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc
@@ -110,8 +110,7 @@ /*source_url=*/fetch_params.Url(), /*base_url=*/fetch_params.Url(), ScriptSourceLocationType::kExternalFile, module_type, ParkableString(script_data->TakeSourceText().Impl()), - /*cache_handler=*/nullptr, - fetch_params.GetResourceRequest().GetCredentialsMode())); + /*cache_handler=*/nullptr)); } void InstalledServiceWorkerModuleScriptFetcher::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h b/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h index b9ecfb8..d6fec809 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h
@@ -33,7 +33,6 @@ const ModuleType module_type, const ParkableString& source_text, SingleCachedMetadataHandler* cache_handler, - network::mojom::CredentialsMode credentials_mode, ScriptStreamer* script_streamer = nullptr, ScriptStreamer::NotStreamingReason not_streaming_reason = ScriptStreamer::NotStreamingReason::kStreamingDisabled) @@ -45,7 +44,6 @@ source_text_(source_text), isolated_source_text_(), cache_handler_(cache_handler), - credentials_mode_(credentials_mode), script_streamer_(script_streamer), not_streaming_reason_(not_streaming_reason) { DCHECK(source_location_type == ScriptSourceLocationType::kExternalFile || @@ -65,9 +63,9 @@ String isolated_source_text = isolated_source_text_ ? isolated_source_text_.IsolatedCopy() : GetSourceText().ToString().IsolatedCopy(); - return ModuleScriptCreationParams( - SourceURL().Copy(), BaseURL().Copy(), source_location_type_, - GetModuleType(), isolated_source_text, GetFetchCredentialsMode()); + return ModuleScriptCreationParams(SourceURL().Copy(), BaseURL().Copy(), + source_location_type_, GetModuleType(), + isolated_source_text); } ModuleType GetModuleType() const { return module_type_; } @@ -91,17 +89,13 @@ ModuleScriptCreationParams CopyWithClearedSourceText() const { return ModuleScriptCreationParams( source_url_, base_url_, source_location_type_, module_type_, - ParkableString(), /*cache_handler=*/nullptr, credentials_mode_, + ParkableString(), /*cache_handler=*/nullptr, /*script_streamer=*/nullptr, ScriptStreamer::NotStreamingReason::kStreamingDisabled); } SingleCachedMetadataHandler* CacheHandler() const { return cache_handler_; } - network::mojom::CredentialsMode GetFetchCredentialsMode() const { - return credentials_mode_; - } - bool IsSafeToSendToAnotherThread() const { return source_url_.IsSafeToSendToAnotherThread() && base_url_.IsSafeToSendToAnotherThread() && is_isolated_; @@ -118,8 +112,7 @@ const KURL& base_url, ScriptSourceLocationType source_location_type, const ModuleType& module_type, - const String& isolated_source_text, - network::mojom::CredentialsMode credentials_mode) + const String& isolated_source_text) : source_url_(source_url), base_url_(base_url), source_location_type_(source_location_type), @@ -127,7 +120,6 @@ is_isolated_(true), source_text_(), isolated_source_text_(isolated_source_text), - credentials_mode_(credentials_mode), // The ScriptStreamer is intentionally cleared since it cannot be passed // across threads. This only disables script streaming on worklet // top-level scripts where the ModuleScriptCreationParams is @@ -150,8 +142,6 @@ // |cache_handler_| is cleared when crossing thread boundaries. Persistent<SingleCachedMetadataHandler> cache_handler_; - const network::mojom::CredentialsMode credentials_mode_; - // |script_streamer_| is cleared when crossing thread boundaries. Persistent<ScriptStreamer> script_streamer_; const ScriptStreamer::NotStreamingReason not_streaming_reason_;
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc index e2404e0..94560a2f1 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -102,7 +102,6 @@ } NotifyClient(resource->Url(), module_type, - script_resource->GetResourceRequest().GetCredentialsMode(), script_resource->SourceText(), resource->GetResponse(), script_resource->CacheHandler()); } @@ -110,7 +109,6 @@ void WorkerModuleScriptFetcher::NotifyClient( const KURL& request_url, ModuleType module_type, - const network::mojom::CredentialsMode credentials_mode, const ParkableString& source_text, const ResourceResponse& response, SingleCachedMetadataHandler* cache_handler) { @@ -188,7 +186,7 @@ client_->NotifyFetchFinishedSuccess(ModuleScriptCreationParams( /*source_url=*/url, /*base_url=*/url, ScriptSourceLocationType::kExternalFile, module_type, source_text, - cache_handler, credentials_mode)); + cache_handler)); } void WorkerModuleScriptFetcher::DidReceiveData(base::span<const char> span) { @@ -230,7 +228,6 @@ source_text_.Append(decoder_->Flush()); NotifyClient(worker_main_script_loader_->GetRequestURL(), ModuleType::kJavaScript, - network::mojom::CredentialsMode::kSameOrigin, ParkableString(source_text_.ToString().ReleaseImpl()), response, worker_main_script_loader_->CreateCachedMetadataHandler()); }
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h index f04f861..32be6a6 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h
@@ -49,7 +49,6 @@ void NotifyClient(const KURL& request_url, ModuleType module_type, - const network::mojom::CredentialsMode credentials_mode, const ParkableString& source_text, const ResourceResponse& response, SingleCachedMetadataHandler* cache_handler);
diff --git a/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc index bb6276e..ca3e6dd 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc
@@ -56,8 +56,7 @@ params.emplace(/*source_url=*/url, /*base_url=*/url, ScriptSourceLocationType::kExternalFile, module_type, script_resource->SourceText(), - script_resource->CacheHandler(), - script_resource->GetResourceRequest().GetCredentialsMode()); + script_resource->CacheHandler()); } // This will eventually notify |client| passed to
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 2d8f086..022b95e 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -621,12 +621,12 @@ return subframe_count_; } -void Page::SettingsChanged(SettingsDelegate::ChangeType change_type) { +void Page::SettingsChanged(ChangeType change_type) { switch (change_type) { - case SettingsDelegate::kStyleChange: + case ChangeType::kStyle: InitialStyleChanged(); break; - case SettingsDelegate::kViewportDescriptionChange: + case ChangeType::kViewportDescription: if (MainFrame() && MainFrame()->IsLocalFrame()) { DeprecatedLocalMainFrame() ->GetDocument() @@ -639,7 +639,7 @@ TextAutosizer::UpdatePageInfoInAllFrames(MainFrame()); } break; - case SettingsDelegate::kViewportPaintPropertiesChange: + case ChangeType::kViewportPaintProperties: GetVisualViewport().SetNeedsPaintPropertyUpdate(); GetVisualViewport().InitializeScrollbars(); if (auto* local_frame = DynamicTo<LocalFrame>(MainFrame())) { @@ -647,14 +647,14 @@ view->SetNeedsPaintPropertyUpdate(); } break; - case SettingsDelegate::kDNSPrefetchingChange: + case ChangeType::kDNSPrefetching: for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { if (auto* local_frame = DynamicTo<LocalFrame>(frame)) local_frame->GetDocument()->InitDNSPrefetch(); } break; - case SettingsDelegate::kImageLoadingChange: + case ChangeType::kImageLoading: for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { if (auto* local_frame = DynamicTo<LocalFrame>(frame)) { @@ -665,14 +665,14 @@ } } break; - case SettingsDelegate::kTextAutosizingChange: + case ChangeType::kTextAutosizing: if (!MainFrame()) break; // We need to update even for remote main frames since this setting // could be changed via InternalSettings. TextAutosizer::UpdatePageInfoInAllFrames(MainFrame()); break; - case SettingsDelegate::kFontFamilyChange: + case ChangeType::kFontFamily: for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { if (auto* local_frame = DynamicTo<LocalFrame>(frame)) @@ -681,10 +681,10 @@ .UpdateGenericFontFamilySettings(); } break; - case SettingsDelegate::kAcceleratedCompositingChange: + case ChangeType::kAcceleratedCompositing: UpdateAcceleratedCompositingSettings(); break; - case SettingsDelegate::kMediaQueryChange: + case ChangeType::kMediaQuery: for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { if (auto* local_frame = DynamicTo<LocalFrame>(frame)) { @@ -693,7 +693,7 @@ } } break; - case SettingsDelegate::kAccessibilityStateChange: + case ChangeType::kAccessibilityState: if (!MainFrame() || !MainFrame()->IsLocalFrame()) break; DeprecatedLocalMainFrame() @@ -701,7 +701,7 @@ ->AXObjectCacheOwner() .ClearAXObjectCache(); break; - case SettingsDelegate::kViewportRuleChange: { + case ChangeType::kViewportRule: { auto* main_local_frame = DynamicTo<LocalFrame>(MainFrame()); if (!main_local_frame) break; @@ -709,7 +709,7 @@ doc->GetStyleEngine().ViewportRulesChanged(); break; } - case SettingsDelegate::kTextTrackKindUserPreferenceChange: + case ChangeType::kTextTrackKindUserPreference: for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { if (auto* local_frame = DynamicTo<LocalFrame>(frame)) { @@ -720,7 +720,7 @@ } } break; - case SettingsDelegate::kDOMWorldsChange: { + case ChangeType::kDOMWorlds: { if (!GetSettings().GetForceMainWorldInitialization()) break; for (Frame* frame = MainFrame(); frame; @@ -733,7 +733,7 @@ } break; } - case SettingsDelegate::kMediaControlsChange: + case ChangeType::kMediaControls: for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { auto* local_frame = DynamicTo<LocalFrame>(frame); @@ -744,11 +744,11 @@ HTMLMediaElement::OnMediaControlsEnabledChange(doc); } break; - case SettingsDelegate::kPluginsChange: { + case ChangeType::kPlugins: { NotifyPluginsChanged(); break; } - case SettingsDelegate::kHighlightAdsChange: { + case ChangeType::kHighlightAds: { for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { if (auto* local_frame = DynamicTo<LocalFrame>(frame)) @@ -756,11 +756,11 @@ } break; } - case SettingsDelegate::kPaintChange: { + case ChangeType::kPaint: { InvalidatePaint(); break; } - case SettingsDelegate::kScrollbarLayoutChange: { + case ChangeType::kScrollbarLayout: { for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) { auto* local_frame = DynamicTo<LocalFrame>(frame); @@ -783,16 +783,16 @@ } break; } - case SettingsDelegate::kColorSchemeChange: + case ChangeType::kColorScheme: InvalidateColorScheme(); break; - case SettingsDelegate::kSpatialNavigationChange: + case ChangeType::kSpatialNavigation: if (spatial_navigation_controller_ || GetSettings().GetSpatialNavigationEnabled()) { GetSpatialNavigationController().OnSpatialNavigationSettingChanged(); } break; - case SettingsDelegate::kUniversalAccessChange: { + case ChangeType::kUniversalAccess: { if (!GetSettings().GetAllowUniversalAccessFromFileURLs()) break; for (Frame* frame = MainFrame(); frame; @@ -807,15 +807,11 @@ } break; } - case SettingsDelegate::kVisionDeficiencyChange: { + case ChangeType::kVisionDeficiency: { if (auto* main_local_frame = DynamicTo<LocalFrame>(MainFrame())) main_local_frame->GetDocument()->VisionDeficiencyChanged(); break; } - case SettingsDelegate::kForceDarkChange: - InvalidateColorScheme(); - InvalidatePaint(); - break; } } @@ -1092,21 +1088,21 @@ } media_feature_overrides_->SetOverride(media_feature, value); if (media_feature == "prefers-color-scheme") - SettingsChanged(SettingsDelegate::kColorSchemeChange); + SettingsChanged(ChangeType::kColorScheme); else - SettingsChanged(SettingsDelegate::kMediaQueryChange); + SettingsChanged(ChangeType::kMediaQuery); } void Page::ClearMediaFeatureOverrides() { media_feature_overrides_.reset(); - SettingsChanged(SettingsDelegate::kMediaQueryChange); - SettingsChanged(SettingsDelegate::kColorSchemeChange); + SettingsChanged(ChangeType::kMediaQuery); + SettingsChanged(ChangeType::kColorScheme); } void Page::SetVisionDeficiency(VisionDeficiency new_vision_deficiency) { if (new_vision_deficiency != vision_deficiency_) { vision_deficiency_ = new_vision_deficiency; - SettingsChanged(SettingsDelegate::kVisionDeficiencyChange); + SettingsChanged(ChangeType::kVisionDeficiency); } }
diff --git a/third_party/blink/renderer/core/script/module_map_test.cc b/third_party/blink/renderer/core/script/module_map_test.cc index 3362c55..5a3023a 100644 --- a/third_party/blink/renderer/core/script/module_map_test.cc +++ b/third_party/blink/renderer/core/script/module_map_test.cc
@@ -117,9 +117,8 @@ ModuleGraphLevel, ModuleScriptFetcher::Client* client) override { CHECK_EQ(request.GetScriptType(), mojom::blink::ScriptType::kModule); - TestRequest* test_request = MakeGarbageCollected<TestRequest>( - request.Url(), request.GetResourceRequest().GetCredentialsMode(), - client); + TestRequest* test_request = + MakeGarbageCollected<TestRequest>(request.Url(), client); modulator_->test_requests_.push_back(test_request); } String DebugName() const override { return "TestModuleScriptFetcher"; } @@ -148,21 +147,18 @@ } struct TestRequest final : public GarbageCollected<TestRequest> { - TestRequest(const KURL& url, - network::mojom::CredentialsMode credential_mode, - ModuleScriptFetcher::Client* client) - : url_(url), credential_mode_(credential_mode), client_(client) {} + TestRequest(const KURL& url, ModuleScriptFetcher::Client* client) + : url_(url), client_(client) {} void NotifyFetchFinished() { client_->NotifyFetchFinishedSuccess(ModuleScriptCreationParams( url_, url_, ScriptSourceLocationType::kExternalFile, ModuleType::kJavaScript, ParkableString(String("").ReleaseImpl()), - nullptr, credential_mode_)); + nullptr)); } void Trace(Visitor* visitor) const { visitor->Trace(client_); } private: const KURL url_; - const network::mojom::CredentialsMode credential_mode_; Member<ModuleScriptFetcher::Client> client_; }; HeapVector<Member<TestRequest>> test_requests_;
diff --git a/third_party/blink/renderer/core/script/module_script_test.cc b/third_party/blink/renderer/core/script/module_script_test.cc index ae5ab6a4..69ac133 100644 --- a/third_party/blink/renderer/core/script/module_script_test.cc +++ b/third_party/blink/renderer/core/script/module_script_test.cc
@@ -84,8 +84,8 @@ ModuleScriptCreationParams params( KURL("https://fox.url/script.js"), KURL("https://fox.url/"), ScriptSourceLocationType::kInline, ModuleType::kJavaScript, - ParkableString(source_text.IsolatedCopy().ReleaseImpl()), cache_handler, - network::mojom::CredentialsMode::kOmit); + ParkableString(source_text.IsolatedCopy().ReleaseImpl()), + cache_handler); return JSModuleScript::Create(params, modulator, ScriptFetchOptions()); }
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index 04faa7bf..d414833 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -728,7 +728,7 @@ ModuleScriptCreationParams params( source_url, base_url, ScriptSourceLocationType::kInline, ModuleType::kJavaScript, ParkableString(source_text.Impl()), - nullptr, options.CredentialsMode()); + nullptr); ModuleScript* module_script = JSModuleScript::Create(params, modulator, options, position);
diff --git a/third_party/blink/renderer/core/testing/internal_settings.cc b/third_party/blink/renderer/core/testing/internal_settings.cc index c82cc8b..bb4fc83 100644 --- a/third_party/blink/renderer/core/testing/internal_settings.cc +++ b/third_party/blink/renderer/core/testing/internal_settings.cc
@@ -64,9 +64,9 @@ : original_csp_(RuntimeEnabledFeatures:: ExperimentalContentSecurityPolicyFeaturesEnabled()), original_editing_behavior_(settings->GetEditingBehaviorType()), - original_text_autosizing_enabled_(settings->TextAutosizingEnabled()), + original_text_autosizing_enabled_(settings->GetTextAutosizingEnabled()), original_text_autosizing_window_size_override_( - settings->TextAutosizingWindowSizeOverride()), + settings->GetTextAutosizingWindowSizeOverride()), original_accessibility_font_scale_factor_( settings->GetAccessibilityFontScaleFactor()), original_media_type_override_(settings->GetMediaTypeOverride()), @@ -124,7 +124,7 @@ backup_.RestoreTo(GetSettings()); backup_ = Backup(GetSettings()); backup_.original_text_autosizing_enabled_ = - GetSettings()->TextAutosizingEnabled(); + GetSettings()->GetTextAutosizingEnabled(); InternalSettingsGenerated::resetToConsistentState(); }
diff --git a/third_party/blink/renderer/core/testing/module_test_base.cc b/third_party/blink/renderer/core/testing/module_test_base.cc index 03e2f769..13b07bf 100644 --- a/third_party/blink/renderer/core/testing/module_test_base.cc +++ b/third_party/blink/renderer/core/testing/module_test_base.cc
@@ -30,8 +30,7 @@ ModuleScriptCreationParams params( /*source_url=*/url, /*base_url=*/url, ScriptSourceLocationType::kExternalFile, ModuleType::kJavaScript, - ParkableString(source.Impl()), nullptr, - network::mojom::CredentialsMode::kOmit); + ParkableString(source.Impl()), nullptr); return ModuleRecord::Compile(isolate, params, ScriptFetchOptions(), TextPosition::MinimumPosition(), exception_state);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 4db3271..b4aeb2fd 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -961,6 +961,9 @@ } } } + + if (IsScrollableContainer()) + SerializeScrollAttributes(node_data); } void AXObject::SerializeTableAttributes(ui::AXNodeData* node_data) { @@ -1018,6 +1021,31 @@ } } +void AXObject::SerializeScrollAttributes(ui::AXNodeData* node_data) { + // Only mark as scrollable if user has actual scrollbars to use. + node_data->AddBoolAttribute(ax::mojom::blink::BoolAttribute::kScrollable, + IsUserScrollable()); + // Provide x,y scroll info if scrollable in any way (programmatically or via + // user). + const gfx::Point& scroll_offset = GetScrollOffset(); + node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kScrollX, + scroll_offset.x()); + node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kScrollY, + scroll_offset.y()); + + const gfx::Point& min_scroll_offset = MinimumScrollOffset(); + node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kScrollXMin, + min_scroll_offset.x()); + node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kScrollYMin, + min_scroll_offset.y()); + + const gfx::Point& max_scroll_offset = MaximumScrollOffset(); + node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kScrollXMax, + max_scroll_offset.x()); + node_data->AddIntAttribute(ax::mojom::blink::IntAttribute::kScrollYMax, + max_scroll_offset.y()); +} + void AXObject::SerializeStyleAttributes(ui::AXNodeData* node_data) { // Text attributes. if (BackgroundColor()) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 685fa3d..926e219 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -1316,6 +1316,7 @@ void SerializeSparseAttributes(ui::AXNodeData* node_data); void SerializeTableAttributes(ui::AXNodeData* node_data); void SerializeListAttributes(ui::AXNodeData* node_data); + void SerializeScrollAttributes(ui::AXNodeData* node_data); private: void UpdateDistributionForFlatTreeTraversal() const;
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc index 817bcd7..0bb1729 100644 --- a/third_party/blink/renderer/modules/exported/web_ax_object.cc +++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -849,13 +849,13 @@ WebString WebAXObject::GetName(ax::mojom::NameFrom& out_name_from, WebVector<WebAXObject>& out_name_objects) const { + out_name_from = ax::mojom::blink::NameFrom::kUninitialized; + if (IsDetached()) return WebString(); - ax::mojom::NameFrom name_from = ax::mojom::NameFrom::kUninitialized; HeapVector<Member<AXObject>> name_objects; - WebString result = private_->GetName(name_from, &name_objects); - out_name_from = name_from; + WebString result = private_->GetName(out_name_from, &name_objects); out_name_objects.reserve(name_objects.size()); out_name_objects.resize(name_objects.size()); @@ -877,15 +877,14 @@ ax::mojom::NameFrom name_from, ax::mojom::DescriptionFrom& out_description_from, WebVector<WebAXObject>& out_description_objects) const { + out_description_from = ax::mojom::blink::DescriptionFrom::kUninitialized; + if (IsDetached()) return WebString(); - ax::mojom::DescriptionFrom description_from = - ax::mojom::DescriptionFrom::kUninitialized; HeapVector<Member<AXObject>> description_objects; - String result = - private_->Description(name_from, description_from, &description_objects); - out_description_from = description_from; + String result = private_->Description(name_from, out_description_from, + &description_objects); out_description_objects.reserve(description_objects.size()); out_description_objects.resize(description_objects.size()); @@ -1238,12 +1237,6 @@ return private_->IsScrollableContainer(); } -bool WebAXObject::IsUserScrollable() const { - if (IsDetached()) - return false; - - return private_->IsUserScrollable(); -} gfx::Point WebAXObject::GetScrollOffset() const { if (IsDetached()) return gfx::Point();
diff --git a/third_party/blink/renderer/modules/hid/hid_collection_info.idl b/third_party/blink/renderer/modules/hid/hid_collection_info.idl index 787d63e..1bc289b 100644 --- a/third_party/blink/renderer/modules/hid/hid_collection_info.idl +++ b/third_party/blink/renderer/modules/hid/hid_collection_info.idl
@@ -12,6 +12,9 @@ // The 16-bit usage value associated with this collection. Zero if not set. unsigned short usage; + // The 8-bit collection type for this collection. + octet type; + // The subcollections of this collection, in the order they were encountered // in the report descriptor. sequence<HIDCollectionInfo> children;
diff --git a/third_party/blink/renderer/modules/hid/hid_device.cc b/third_party/blink/renderer/modules/hid/hid_device.cc index 2517808f..ecc7a54 100644 --- a/third_party/blink/renderer/modules/hid/hid_device.cc +++ b/third_party/blink/renderer/modules/hid/hid_device.cc
@@ -184,6 +184,7 @@ HIDCollectionInfo* result = HIDCollectionInfo::Create(); result->setUsage(collection.usage->usage); result->setUsagePage(collection.usage->usage_page); + result->setType(collection.collection_type); HeapVector<Member<HIDReportInfo>> input_reports; for (const auto& report : collection.input_reports) @@ -504,8 +505,14 @@ HIDReportItem* result = HIDReportItem::Create(); result->setIsAbsolute(!report_item.is_relative); result->setIsArray(!report_item.is_variable); + result->setIsBufferedBytes(report_item.is_buffered_bytes); + result->setIsConstant(report_item.is_constant); + result->setIsLinear(!report_item.is_non_linear); result->setIsRange(report_item.is_range); + result->setIsVolatile(report_item.is_volatile); result->setHasNull(report_item.has_null_position); + result->setHasPreferredState(!report_item.no_preferred_state); + result->setWrap(report_item.wrap); result->setReportSize(report_item.report_size); result->setReportCount(report_item.report_count); result->setUnitExponent(
diff --git a/third_party/blink/renderer/modules/hid/hid_report_item.idl b/third_party/blink/renderer/modules/hid/hid_report_item.idl index 01ee6d86..078c7e0 100644 --- a/third_party/blink/renderer/modules/hid/hid_report_item.idl +++ b/third_party/blink/renderer/modules/hid/hid_report_item.idl
@@ -40,13 +40,39 @@ // all inputs simultaneously. boolean isArray; + // True if the item emits a fixed-size stream of bytes, or false if the item + // is a bit field. + boolean isBufferedBytes; + + // True if the item is a read-only constant value, or false if the item is a + // report field with modifiable device data. + boolean isConstant; + + // True if there is a linear relationship between the measured value and the + // raw data from the device, or false if the data has been processed and no + // longer represents a linear relationship. + boolean isLinear; + // True if the usages for this item are defined by |usageMinimum| and // |usageMaximum| or false if the usages are defined by |usages|. boolean isRange; + // True if the item is a feature or output field that can change without + // host interaction, or false if the field should not change without host + // interaction. + boolean isVolatile; + // True if the item uses an out-of-bounds value when there is no input. boolean hasNull; + // True if the item has a preferred state to which it will return when the + // user is not physically interacting with the control. + boolean hasPreferredState; + + // True if the data rolls over when reaching either the extreme high or low + // value. + boolean wrap; + // An ordered list of 32-bit usage values associated with this item. Unused // if |isRange| is true. If |reportCount| is two or more, usages are // assigned from the list until the list is exhausted.
diff --git a/third_party/blink/renderer/modules/push_messaging/push_provider.cc b/third_party/blink/renderer/modules/push_messaging/push_provider.cc index 5e5dc5f..e426cf0 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_provider.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_provider.cc
@@ -6,9 +6,11 @@ #include <utility> +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h" #include "third_party/blink/public/mojom/push_messaging/push_messaging_status.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/modules/push_messaging/push_error.h" #include "third_party/blink/renderer/modules/push_messaging/push_messaging_utils.h" #include "third_party/blink/renderer/modules/push_messaging/push_subscription.h" @@ -45,8 +47,10 @@ // static mojom::blink::PushMessaging* PushProvider::GetPushMessagingRemote() { if (!push_messaging_manager_.is_bound()) { - Platform::Current()->GetBrowserInterfaceBroker()->GetInterface( - push_messaging_manager_.BindNewPipeAndPassReceiver( + GetSupplementable() + ->GetExecutionContext() + ->GetBrowserInterfaceBroker() + .GetInterface(push_messaging_manager_.BindNewPipeAndPassReceiver( GetSupplementable()->GetExecutionContext()->GetTaskRunner( TaskType::kMiscPlatformAPI))); }
diff --git a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc index 0a0c8a3..bf647430 100644 --- a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc +++ b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.cc
@@ -25,18 +25,42 @@ const CompositorAnimationCurve& curve, compositor_target_property::Type target_property, int keyframe_model_id, - int group_id, - const AtomicString& custom_property_name, - CompositorPaintWorkletInput::NativePropertyType native_property_type) { - if (!keyframe_model_id) - keyframe_model_id = AnimationIdProvider::NextKeyframeModelId(); - if (!group_id) - group_id = AnimationIdProvider::NextGroupId(); + int group_id) + : CompositorKeyframeModel( + curve, + keyframe_model_id, + group_id, + KeyframeModel::TargetPropertyId(target_property)) {} - keyframe_model_ = KeyframeModel::Create( - curve.CloneToAnimationCurve(), keyframe_model_id, group_id, - target_property, custom_property_name.Utf8().data(), - native_property_type); +CompositorKeyframeModel::CompositorKeyframeModel( + const CompositorAnimationCurve& curve, + compositor_target_property::Type target_property, + int keyframe_model_id, + int group_id, + const AtomicString& custom_property_name) + : CompositorKeyframeModel( + curve, + keyframe_model_id, + group_id, + KeyframeModel::TargetPropertyId(target_property, + custom_property_name.Utf8().data())) { + DCHECK(!custom_property_name.IsEmpty()); +} + +CompositorKeyframeModel::CompositorKeyframeModel( + const CompositorAnimationCurve& curve, + compositor_target_property::Type target_property, + int keyframe_model_id, + int group_id, + CompositorPaintWorkletInput::NativePropertyType native_property_type) + : CompositorKeyframeModel( + curve, + keyframe_model_id, + group_id, + KeyframeModel::TargetPropertyId(target_property, + native_property_type)) { + DCHECK_NE(native_property_type, + CompositorPaintWorkletInput::NativePropertyType::kInvalid); } CompositorKeyframeModel::~CompositorKeyframeModel() = default; @@ -49,10 +73,23 @@ return keyframe_model_->group(); } +CompositorKeyframeModel::CompositorKeyframeModel( + const CompositorAnimationCurve& curve, + int keyframe_model_id, + int group_id, + const KeyframeModel::TargetPropertyId& id) { + if (!keyframe_model_id) + keyframe_model_id = AnimationIdProvider::NextKeyframeModelId(); + if (!group_id) + group_id = AnimationIdProvider::NextGroupId(); + keyframe_model_ = KeyframeModel::Create(curve.CloneToAnimationCurve(), + keyframe_model_id, group_id, id); +} + compositor_target_property::Type CompositorKeyframeModel::TargetProperty() const { return static_cast<compositor_target_property::Type>( - keyframe_model_->target_property_id()); + keyframe_model_->target_property_type()); } void CompositorKeyframeModel::SetElementId(CompositorElementId element_id) {
diff --git a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h index d567310..4124964 100644 --- a/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h +++ b/third_party/blink/renderer/platform/animation/compositor_keyframe_model.h
@@ -35,17 +35,22 @@ using Direction = cc::KeyframeModel::Direction; using FillMode = cc::KeyframeModel::FillMode; - // The |custom_property_name| has a default value of an empty string, - // indicating that the animated property is a native property. When it is an - // animated custom property, it should be the property name. + CompositorKeyframeModel(const CompositorAnimationCurve&, + compositor_target_property::Type, + int keyframe_model_id, + int group_id); + // The |custom_property_name| is the name of animated custom property. + CompositorKeyframeModel(const CompositorAnimationCurve&, + compositor_target_property::Type, + int keyframe_model_id, + int group_id, + const AtomicString& custom_property_name); CompositorKeyframeModel( const CompositorAnimationCurve&, compositor_target_property::Type, int keyframe_model_id, int group_id, - const AtomicString& custom_property_name = "", - CompositorPaintWorkletInput::NativePropertyType native_property_type = - CompositorPaintWorkletInput::NativePropertyType::kInvalid); + CompositorPaintWorkletInput::NativePropertyType native_property_type); ~CompositorKeyframeModel(); // An id must be unique. @@ -91,6 +96,11 @@ } private: + CompositorKeyframeModel(const CompositorAnimationCurve& curve, + int keyframe_model_id, + int group_id, + const cc::KeyframeModel::TargetPropertyId& id); + std::unique_ptr<cc::KeyframeModel> keyframe_model_; DISALLOW_COPY_AND_ASSIGN(CompositorKeyframeModel);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index bb3298b..9c35cb5 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1831,8 +1831,7 @@ }, { name: "Serial", - origin_trial_feature_name: "Serial", - status: {"Android": "", "default": "experimental"}, + status: {"Android": "", "default": "stable"}, }, { name: "ServiceWorkerClientLifecycleState",
diff --git a/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc b/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc index 285de6bf..b968981 100644 --- a/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc +++ b/third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.cc
@@ -146,8 +146,11 @@ audio_bus_ = media::AudioBus::Create(number_of_channels, number_of_frames); } - audio_bus_->FromInterleaved(audio_data, number_of_frames, - bits_per_sample / 8); + // Only 16 bits per sample is ever used. The FromInterleaved() call should + // be updated if that is no longer the case. + DCHECK_EQ(bits_per_sample, 16); + audio_bus_->FromInterleaved<media::SignedInt16SampleTypeTraits>( + reinterpret_cast<const int16_t*>(audio_data), number_of_frames); media::AudioParameters params = MediaStreamAudioSource::GetAudioParameters(); if (!params.IsValid() ||
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 9616d463..0865e97 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2473,6 +2473,8 @@ crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-206.xht [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html [ Failure ] +crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html [ Failure ] crbug.com/626703 external/wpt/html/interaction/focus/document-level-focus-apis/document-has-system-focus.html [ Timeout ] crbug.com/626703 [ Mac11.0 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-set-keyframes.https.html [ Failure ] crbug.com/626703 external/wpt/websockets/cookies/004.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 289a084..0dd813e2 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -10099,6 +10099,13 @@ null, {} ] + ], + "nfc-prompt-manual.https.html": [ + "a8b0ce636c9b5de5d045713b3d6566b0f00b2c98", + [ + null, + {} + ] ] }, "web-share": { @@ -75099,7 +75106,7 @@ {} ] ], - "replaced-alignment-with-aspect-ratio-001.tentative.html": [ + "replaced-alignment-with-aspect-ratio-001.html": [ "d7ab97b9ec0091b7869b1fbb69e7317ced70cc20", [ null, @@ -75112,7 +75119,7 @@ {} ] ], - "replaced-alignment-with-aspect-ratio-002.tentative.html": [ + "replaced-alignment-with-aspect-ratio-002.html": [ "1a4e344dd045806ed512d9e3562d9f3b96d1fbd8", [ null, @@ -101865,6 +101872,32 @@ {} ] ], + "flex-aspect-ratio-025.html": [ + "fa9ce8ebce69f02e6b13d9d2233d1e3b46c7f1ab", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], + "flex-aspect-ratio-026.html": [ + "1df14468632baa8ffd03d690f7ddaa618acd7bf6", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], "grid-aspect-ratio-001.html": [ "ce91fe4e4e8b2bb7f610fb230a292f59188ff95b", [ @@ -174217,7 +174250,7 @@ [] ], "sab.js": [ - "c7fd1a742e64f66744b416584952effe29fda208", + "d40dd7cca8da10ad321067e638c772550f1a042f", [] ], "security-features": { @@ -196023,7 +196056,7 @@ }, "support": { "grid-child-utils.js": [ - "d75ad6eb7061349e5453c204235a172778528f6a", + "5e0c5caad12a879e68637b7ba058e44a89eafa01", [] ] }, @@ -211923,6 +211956,10 @@ "74e580747083b3e9ff8d48876c08b83ddaa8d5cb", [] ], + "serialize-custom-props-expected.txt": [ + "5dbde36cf866c4473fb005971edb4dfca1829cbc", + [] + ], "serialize-values-expected.txt": [ "f9c57d1a9fa21eca0068acc357132ff272b61c92", [] @@ -215152,7 +215189,7 @@ ], "admin": { "index.md": [ - "3073b9678fe890efee20ac122e73d30f0ce7fbb1", + "59569fd464c46c2010a48c8c62d8bfdd88b021c1", [] ], "pywebsocket3.rst": [ @@ -220431,7 +220468,7 @@ [] ], "Ahem.ttf.headers": [ - "659e3760fba9ee28df2a8bebb8bc27905b2ae0a3", + "6a0df8b1f530b45f34b3356599b057406d1eaecb", [] ], "CSSTest": { @@ -235475,7 +235512,7 @@ ], "tools": { "format_json.py": [ - "1059ac793aaf2fb5ee875ed9d7e8a02c0040be9e", + "6386d418de1199df47a2f97376b7dbb38f4bbb28", [] ] } @@ -237070,7 +237107,7 @@ ] }, "lint.ignore": [ - "b8f22011a155c1003a8bbe177e6ad0a1cd186b19", + "049d4f81235cbe0538f41e7066c9cd98405b6a68", [] ], "loading": { @@ -241454,6 +241491,14 @@ "d7b1f473416baf9f060e2d3d843f7943df0f25e0", [] ], + "avoid-prefetching-on-text-plain-inner.html": [ + "518e2465418ad6aaecc5a6fb3957eeef38259240", + [] + ], + "avoid-prefetching-on-text-plain-inner.html.headers": [ + "a1f9e38d9090c74e488c9dbce3bc339e243e3e60", + [] + ], "download-resources-expected.txt": [ "9721540846bbec4bdc596864ed86643a354c72e8", [] @@ -244286,7 +244331,7 @@ ], "textcontrols": { "selectionchange.tentative-expected.txt": [ - "444eafbe213b66faf8362f362e3605d33ebe1652", + "75062363bf08b2aa1788c074ed620d30692eddc1", [] ] } @@ -248712,6 +248757,10 @@ ] }, "scripted": { + "SVGAnimatedEnumeration-SVGFECompositeElement-expected.txt": [ + "48365c539fffe9049f04e809ddb52a32a629703a", + [] + ], "SVGAnimatedRect-expected.txt": [ "cdc41ca795298f0cac130afa8ea317a1403ab290", [] @@ -296267,28 +296316,28 @@ ] ], "grid-alignment-implies-size-change-011.html": [ - "b53c32d5e8b5169edbc41cd7d9069fe1cc1a70bd", + "c06918538ddd961eac6c7e46a8d5ce11aec2d529", [ null, {} ] ], "grid-alignment-implies-size-change-012.html": [ - "4151e7b060e3b0baaa7c069fbe2d0e27b46e7b52", + "1fe7d2696fdf749e9fc467268f96119b695016e9", [ null, {} ] ], "grid-alignment-implies-size-change-013.html": [ - "e87481f530c96d04e08080e6acad6beb157e2b7c", + "266e2124fbf5b2f4d31ec72b93a6b5727106292a", [ null, {} ] ], "grid-alignment-implies-size-change-014.html": [ - "b74f09d138e97c71d5d4de608cd37a447ab573ed", + "23f79cba32479a5a519f452a0118d1cc28cc70ab", [ null, {} @@ -296309,14 +296358,14 @@ ] ], "grid-alignment-implies-size-change-017.html": [ - "b9b9114879c640eb6450f90d5f1521e1739e7bc9", + "2f45db5eaee7bd342d6312881f7987081d950083", [ null, {} ] ], "grid-alignment-implies-size-change-018.html": [ - "e9bfe63e62013abd79d085ed77a00583d5500281", + "2aa06ab2e9450da32948774fb796f5eb0f5c3231", [ null, {} @@ -296393,21 +296442,21 @@ ] ], "grid-alignment-implies-size-change-029.html": [ - "afe909f81f7dbc41c5d91ec57c095b5b086361a6", + "6d41acfb2a9ed4d08101a23bcfdcfa0599650343", [ null, {} ] ], "grid-alignment-implies-size-change-030.html": [ - "d3924e326567655a17715e3921e344a887a7ded9", + "559f04a11ead33261202ddd3d896b68e2175dbf8", [ null, {} ] ], "grid-alignment-implies-size-change-031.html": [ - "528e08b881c23bf6ab9e8813c5c0eb0fa96baf8a", + "843e1b2acd9759da5186f034c873c413bd048351", [ null, {} @@ -296435,14 +296484,14 @@ ] ], "grid-alignment-implies-size-change-035.html": [ - "18bb1bd061c7e29858dde266705e0649633b4217", + "b4b0725d8d67015222bcb260e15d581dbf35181c", [ null, {} ] ], "grid-alignment-implies-size-change-036.html": [ - "e63ce4fccdf45207b6cb11d1fd27e01b2cd62bee", + "99396bf17321d5b66036485465e41f9628720a83", [ null, {} @@ -311606,6 +311655,13 @@ {} ] ], + "calc-rounds-to-integer.html": [ + "80589785c36e14d0859b3f4a5555f7e9d47ac963", + [ + null, + {} + ] + ], "calc-serialization-002.html": [ "a06b33e492e323386c40c333b22bd344e281fd98", [ @@ -313463,6 +313519,13 @@ {} ] ], + "serialize-custom-props.html": [ + "cfe96ff0aacb983e66b5ccee305cc5fe84d10d72", + [ + null, + {} + ] + ], "serialize-media-rule.html": [ "90561fdf70971874adc8db08144a421d03392608", [ @@ -314055,6 +314118,15 @@ {} ] ], + "mouseEvent-offsetXY-svg.html": [ + "c0bd16448529b63424813b93022cfb215396cadd", + [ + null, + { + "testdriver": true + } + ] + ], "mouseEvent.html": [ "d50959729239599ff057a71143553b4a53f88975", [ @@ -315336,14 +315408,14 @@ ] ], "focus-in-focus-event-001.html": [ - "bd4145a3fe5390c55a4e7e9eb29bbcfa922bdf1e", + "0639b7785eb3c3eacb4e4478557caf80a3f7511e", [ null, {} ] ], "focus-visible-001.html": [ - "068368995794c0559d3551ca3dc3471f7d777240", + "d580b0771f85e7536abb2bce4e539b77e4ddeed6", [ null, { @@ -315352,7 +315424,7 @@ ] ], "focus-visible-002.html": [ - "2846ae465a5665ca1d33db3f4c0ec14bf620a47e", + "441c1dae9883d73f01093f56870a965f3d1a8aa4", [ null, { @@ -315362,7 +315434,7 @@ ] ], "focus-visible-003.html": [ - "9d57225708a89bfae2c1549144d2284f7f138ba6", + "aa73b4da44f0e831dbbd5516bd71daef245e7e65", [ null, { @@ -315371,7 +315443,7 @@ ] ], "focus-visible-004.html": [ - "318d1eeb05430bd06fb166b8ffc13fa0b67c0c5c", + "b30b9e2938ab4ed4e3972340953649c21e0085d9", [ null, { @@ -315380,7 +315452,7 @@ ] ], "focus-visible-005.html": [ - "4aec863e3b9af3d5ba568de34a320bf92dda2adf", + "c86c0574153243edd5f3c5a4f9ee24cb73e61374", [ null, { @@ -315389,7 +315461,7 @@ ] ], "focus-visible-006.html": [ - "89d9782ac8eb439154d5f65f95f622d2c25acf3f", + "a5256c107a7fd967cde60d2f67b2154a5c8145cf", [ null, { @@ -315407,7 +315479,7 @@ ] ], "focus-visible-008.html": [ - "c84985fe1015ee756459ad23967810988b38fedb", + "5f5b54e1f0f1f5deaf2bceac7b0cd41d50672f61", [ null, { @@ -315416,21 +315488,21 @@ ] ], "focus-visible-009.html": [ - "bbadd578e004e5b84203979c3a6c07a820bd7564", + "d9edb69c574aa1c7912ab66397d4bf1ab1590a37", [ null, {} ] ], "focus-visible-010.html": [ - "cfd4282e9b599b0caa62cbbfa15ea34d88217a29", + "8d02edbc3e6bd5ec257c652a4bf1fe07149ba699", [ null, {} ] ], "focus-visible-011.html": [ - "3d66dc91386ecc1fb7c7cc166150550c5a65275d", + "d45f5d8ed0f3903da5b5c37ea5a13ccbe690ceca", [ null, { @@ -315439,7 +315511,7 @@ ] ], "focus-visible-012.html": [ - "dcb00e18d2535a6ab826f089d1034185de6be446", + "b27abbe39c01b202196f5e25159da26cb5089f8e", [ null, { @@ -315448,14 +315520,14 @@ ] ], "focus-visible-014.html": [ - "8e52570e79b163cd91f9aca1e0d4ee545fa5c51d", + "6a4aef6e2bdf3c277b52ddb50679bc240b4cf744", [ null, {} ] ], "focus-visible-015.html": [ - "21568f3b0639a8df388eabffbea045ecf570cb8a", + "685baeb7bad07ad45a8efda163dba5db94b9ffe8", [ null, { @@ -315464,7 +315536,7 @@ ] ], "focus-visible-016.html": [ - "64d9bb777fb547f42639f14f51b92248ff606109", + "a65e5a5b3dd6aa2be7aa733d01725242e8b01cc4", [ null, { @@ -316382,7 +316454,7 @@ ], "parser": { "parser-constructs-custom-element-in-document-write.html": [ - "3b5256677d0d08f2dac9240df06abc334f577f7c", + "14c830b9ba961e701ea39656f42a73cd638e65df", [ null, {} @@ -369471,6 +369543,15 @@ ] ] }, + "embedded-content": { + "audio-controls-intrinsic-size.html": [ + "6cbbcd02f5a0215801d960a319924bd86c90c70a", + [ + null, + {} + ] + ] + }, "svg-embedded-sizing": { "svg-in-img-auto.html": [ "cef353067610e3ef5255163c395d2433b466ea37", @@ -385473,6 +385554,13 @@ {} ] ], + "same-document-with-document-root.html": [ + "15cb7c4cbc278079b15da8af6bfa11a2d6ad3ddc", + [ + null, + {} + ] + ], "same-document-zero-size-target.html": [ "20bd11d4beb1e8bdd623eaad96f11788747f0d15", [ @@ -399060,6 +399148,13 @@ {} ] ], + "avoid-prefetching-on-text-plain.html": [ + "487cbbcaba75285ae6dd381fefe39b061ae6464f", + [ + null, + {} + ] + ], "delaying-onload-link-preload-after-discovery.html": [ "1c856d16d409479746f4c18c65028c38a026fbba", [ @@ -411723,6 +411818,20 @@ {} ] ], + "fetch-cross-origin-redirect.https.html": [ + "e11f21a45755b3fa6da42025d1730d23e8fc4bfb", + [ + null, + {} + ] + ], + "font-timestamps.html": [ + "56ecb5c4bfddb60e783ee77cd308b28a0c4ea9c2", + [ + null, + {} + ] + ], "idlharness.any.js": [ "aa860d3dd16a712fb3e81b5393c5ca2f3dccfde7", [ @@ -411767,7 +411876,7 @@ ] ], "iframe-failed-commit.html": [ - "bd51d33c80f2f5d0f9ab2d1fc644302747c2979a", + "56fe1d594f9479e3be31292147876741aebc7fa3", [ null, {} @@ -412066,7 +412175,7 @@ ] ], "resource_timing_cross_origin_redirect.html": [ - "9342f5b88389d2bf0f831dcf669192f5644024d5", + "60a7ef1564b788ab529b8d1f5e35429d82f76911", [ null, {} @@ -412096,7 +412205,7 @@ ] ], "status-codes-create-entry.html": [ - "c31505a452da6b6af146febcd15ca62ff186a767", + "cc0cd8ccb88250331186c38554b09ff8515cacee", [ null, {} @@ -413525,7 +413634,7 @@ ], "textcontrols": { "selectionchange.tentative.html": [ - "2216a4b514f9932118c2f8b645b4e4a1656117f2", + "adec8b31f3e096eb28ae0246164d637da10bd5ee", [ null, {} @@ -426314,7 +426423,7 @@ ] ], "SVGAnimatedEnumeration-SVGFECompositeElement.html": [ - "e6315b434504e754872dd460988187957efbfb07", + "0e99f5fe9cb3335f54591d75e75bffdc0262d0d2", [ null, {} @@ -450634,7 +450743,7 @@ ] ], "event-timeout.any.js": [ - "da8ca11bb8ea1a8ef673be20ae2de8715a4d1130", + "c73cd1a48540511a5f527b49668aac18e5330169", [ "xhr/event-timeout.any.html", {
diff --git a/third_party/blink/web_tests/external/wpt/common/sab.js b/third_party/blink/web_tests/external/wpt/common/sab.js index c7fd1a7..d40dd7c 100644 --- a/third_party/blink/web_tests/external/wpt/common/sab.js +++ b/third_party/blink/web_tests/external/wpt/common/sab.js
@@ -5,6 +5,9 @@ if (type === "ArrayBuffer") { return new ArrayBuffer(length); } else if (type === "SharedArrayBuffer") { + if (sabConstructor.name !== "SharedArrayBuffer") { + throw new Error("WebAssembly.Memory does not support shared:true"); + } return new sabConstructor(length); } else { throw new Error("type has to be ArrayBuffer or SharedArrayBuffer");
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/name-tests.html b/third_party/blink/web_tests/external/wpt/cookies/http-state/name-tests.html deleted file mode 100644 index e962539..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/name-tests.html +++ /dev/null
@@ -1,63 +0,0 @@ -<!doctype html> -<html> - <head> - <meta charset=utf-8> - <title>Tests basic cookie setting functionality</title> - <meta name=help href="https://tools.ietf.org/html/rfc6265#page-8"> - <meta name="timeout" content="long"> - - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="resources/cookie-http-state-template.js"></script> - </head> - <body> - <div id="log"></div> - <div id="iframes"></div> - <script> - setup({ explicit_timeout: true }); - - const TEST_CASES = [ - {file: "name0001", name: "name0001"}, - {file: "name0002", name: "name0002"}, - {file: "name0003", name: "name0003"}, - {file: "name0004", name: "name0004"}, - {file: "name0005", name: "name0005"}, - {file: "name0006", name: "name0006"}, - {file: "name0007", name: "name0007"}, - {file: "name0008", name: "name0008"}, - {file: "name0009", name: "name0009"}, - {file: "name0010", name: "name0010"}, - {file: "name0011", name: "name0011"}, - {file: "name0012", name: "name0012"}, - {file: "name0013", name: "name0013"}, - {file: "name0014", name: "name0014"}, - {file: "name0015", name: "name0015"}, - {file: "name0016", name: "name0016"}, - {file: "name0017", name: "name0017"}, - {file: "name0018", name: "name0018"}, - {file: "name0019", name: "name0019"}, - {file: "name0020", name: "name0020"}, - {file: "name0021", name: "name0021"}, - {file: "name0022", name: "name0022"}, - {file: "name0023", name: "name0023"}, - {file: "name0024", name: "name0024"}, - {file: "name0025", name: "name0025"}, - {file: "name0026", name: "name0026"}, - {file: "name0027", name: "name0027"}, - {file: "name0028", name: "name0028"}, - {file: "name0029", name: "name0029"}, - {file: "name0030", name: "name0030"}, - {file: "name0031", name: "name0031"}, - {file: "name0032", name: "name0032"}, - {file: "name0033", name: "name0033"}, - ]; - - for (const i in TEST_CASES) { - const t = TEST_CASES[i]; - promise_test(createCookieTest(t.file), - t.file + " - " + t.name); - } - - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0001-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0001-expected deleted file mode 100644 index 9652792..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0001-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0001-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0001-test deleted file mode 100644 index 3ce5f5f..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0001-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0002-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0002-expected deleted file mode 100644 index d4d3cda8..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0002-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: 1=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0002-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0002-test deleted file mode 100644 index d6eac8a..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0002-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: 1=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0003-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0003-expected deleted file mode 100644 index 0c00f45..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0003-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: $=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0003-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0003-test deleted file mode 100644 index 7ea9615..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0003-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: $=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0004-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0004-expected deleted file mode 100644 index b079529..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0004-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: !a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0004-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0004-test deleted file mode 100644 index 99f0e61..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0004-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: !a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0005-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0005-expected deleted file mode 100644 index a0f031b..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0005-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: @a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0005-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0005-test deleted file mode 100644 index 9e33e0c..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0005-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: @a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0006-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0006-expected deleted file mode 100644 index ee0e7d7c..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0006-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: #a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0006-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0006-test deleted file mode 100644 index fbd03632..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0006-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: #a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0007-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0007-expected deleted file mode 100644 index 6d6e56e..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0007-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: $a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0007-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0007-test deleted file mode 100644 index d41e64b..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0007-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: $a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0008-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0008-expected deleted file mode 100644 index a4b8c242..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0008-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: %a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0008-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0008-test deleted file mode 100644 index 7afcf70..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0008-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: %a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0009-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0009-expected deleted file mode 100644 index 49506ac..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0009-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: ^a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0009-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0009-test deleted file mode 100644 index f40d2c4..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0009-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: ^a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0010-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0010-expected deleted file mode 100644 index 1e725578..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0010-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: &a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0010-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0010-test deleted file mode 100644 index fb4fd92..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0010-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: &a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0011-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0011-expected deleted file mode 100644 index 260d702..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0011-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: *a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0011-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0011-test deleted file mode 100644 index b36b723..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0011-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: *a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0012-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0012-expected deleted file mode 100644 index 0a2686a..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0012-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: (a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0012-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0012-test deleted file mode 100644 index 6927aac6..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0012-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: (a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0013-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0013-expected deleted file mode 100644 index 87dec78b..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0013-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: )a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0013-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0013-test deleted file mode 100644 index 59ada98..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0013-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: )a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0014-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0014-expected deleted file mode 100644 index 82bfe0e..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0014-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: -a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0014-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0014-test deleted file mode 100644 index a113e99..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0014-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: -a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0015-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0015-expected deleted file mode 100644 index 390b77b..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0015-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: _a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0015-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0015-test deleted file mode 100644 index 60fc074..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0015-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: _a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0016-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0016-expected deleted file mode 100644 index 7d4d9e33..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0016-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: +=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0016-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0016-test deleted file mode 100644 index 371dbcd..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0016-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: +=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0017-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0017-expected deleted file mode 100644 index 9652792..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0017-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0017-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0017-test deleted file mode 100644 index 0561431..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0017-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: =a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0018-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0018-expected deleted file mode 100644 index 9652792..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0018-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0018-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0018-test deleted file mode 100644 index e86a4836..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0018-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: a =bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0019-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0019-expected deleted file mode 100644 index 8d0bc2d..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0019-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: "a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0019-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0019-test deleted file mode 100644 index d48e3f6..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0019-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: "a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0020-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0020-expected deleted file mode 100644 index aa9cd6d..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0020-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: "a=b"=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0020-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0020-test deleted file mode 100644 index b84f64d17..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0020-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: "a=b"=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0021-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0021-expected deleted file mode 100644 index 206ff76..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0021-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: "a=qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0021-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0021-test deleted file mode 100644 index 56b319e..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0021-test +++ /dev/null
@@ -1,2 +0,0 @@ -Set-Cookie: "a=b"=bar -Set-Cookie: "a=qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0022-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0022-expected deleted file mode 100644 index b14d4f69..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0022-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0022-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0022-test deleted file mode 100644 index cc59ff1..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0022-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0023-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0023-expected deleted file mode 100644 index 5ab27668..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0023-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0023-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0023-test deleted file mode 100644 index b7f9cc2..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0023-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo;bar=baz
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0024-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0024-expected deleted file mode 100644 index 5ac4f25..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0024-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: $Version=1
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0024-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0024-test deleted file mode 100644 index da7b696..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0024-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: $Version=1; foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0025-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0025-expected deleted file mode 100644 index 68c38595..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0025-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: ==a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0025-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0025-test deleted file mode 100644 index 708f006..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0025-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: ===a=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0026-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0026-expected deleted file mode 100644 index b14d4f69..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0026-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0026-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0026-test deleted file mode 100644 index bbeb77a0..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0026-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0027-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0027-expected deleted file mode 100644 index b14d4f69..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0027-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0027-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0027-test deleted file mode 100644 index d222227..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0027-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo=bar ;
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0028-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0028-expected deleted file mode 100644 index f14f993..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0028-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: a
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0028-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0028-test deleted file mode 100644 index 1c197e3..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0028-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: =a
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0029-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0029-expected deleted file mode 100644 index e69de29..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0029-expected +++ /dev/null
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0029-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0029-test deleted file mode 100644 index 4421246..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0029-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: =
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0030-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0030-expected deleted file mode 100644 index a391380..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0030-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo bar=baz
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0030-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0030-test deleted file mode 100644 index cf3ff16..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0030-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo bar=baz
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0031-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0031-expected deleted file mode 100644 index 0cd5a50..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0031-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: "foo
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0031-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0031-test deleted file mode 100644 index 9394184..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0031-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: "foo;bar"=baz
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0032-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0032-expected deleted file mode 100644 index f4f7f3ff..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0032-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: "foo\"bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0032-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0032-test deleted file mode 100644 index 93fc9752..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0032-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: "foo\"bar;baz"=qux
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0033-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0033-expected deleted file mode 100644 index 6e7762e..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0033-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: aaa
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0033-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0033-test deleted file mode 100644 index 7bbdd89..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/name0033-test +++ /dev/null
@@ -1,2 +0,0 @@ -Set-Cookie: =foo=bar -Set-Cookie: aaa
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0001-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0001-expected deleted file mode 100644 index b14d4f69..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0001-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0001-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0001-test deleted file mode 100644 index 38b7dd2..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0001-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo= bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0002-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0002-expected deleted file mode 100644 index 9e96a81..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0002-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo="bar"
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0002-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0002-test deleted file mode 100644 index bed691f..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0002-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo="bar"
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0003-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0003-expected deleted file mode 100644 index 5cc2d46..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0003-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo=" bar "
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0003-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0003-test deleted file mode 100644 index ce1d455..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0003-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo=" bar "
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0004-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0004-expected deleted file mode 100644 index 400030f..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0004-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo="bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0004-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0004-test deleted file mode 100644 index c569216..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0004-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo="bar;baz"
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0005-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0005-expected deleted file mode 100644 index cad285f7..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0005-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo="bar=baz"
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0005-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0005-test deleted file mode 100644 index 514c0f1..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0005-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo="bar=baz"
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0006-expected b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0006-expected deleted file mode 100644 index b14d4f69..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0006-expected +++ /dev/null
@@ -1 +0,0 @@ -Cookie: foo=bar
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0006-test b/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0006-test deleted file mode 100644 index a939a82..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/resources/test-files/value0006-test +++ /dev/null
@@ -1 +0,0 @@ -Set-Cookie: foo = bar ; ttt
diff --git a/third_party/blink/web_tests/external/wpt/cookies/http-state/value-tests.html b/third_party/blink/web_tests/external/wpt/cookies/http-state/value-tests.html deleted file mode 100644 index 0d8daae..0000000 --- a/third_party/blink/web_tests/external/wpt/cookies/http-state/value-tests.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!doctype html> -<html> - <head> - <meta charset=utf-8> - <title>Tests basic cookie setting functionality</title> - <meta name=help href="https://tools.ietf.org/html/rfc6265#page-8"> - - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="resources/cookie-http-state-template.js"></script> - </head> - <body> - <div id="log"></div> - <div id="iframes"></div> - <script> - setup({ explicit_timeout: true }); - - const TEST_CASES = [ - {file: "value0001", name: "value0001"}, - {file: "value0002", name: "value0002"}, - {file: "value0003", name: "value0003"}, - {file: "value0004", name: "value0004"}, - {file: "value0005", name: "value0005"}, - {file: "value0006", name: "value0006"}, - ]; - - for (const i in TEST_CASES) { - const t = TEST_CASES[i]; - promise_test(createCookieTest(t.file), - t.file + " - " + t.name); - } - - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/cookies/name/name.html b/third_party/blink/web_tests/external/wpt/cookies/name/name.html index 18fd8765..39fdc75 100644 --- a/third_party/blink/web_tests/external/wpt/cookies/name/name.html +++ b/third_party/blink/web_tests/external/wpt/cookies/name/name.html
@@ -12,9 +12,6 @@ <body> <div id=log></div> <script> - // TODO: there is more to test here, these tests capture the old - // ported http-state tests. Feel free to delete this comment when more - // are added. const nameTests = [ { cookie: "test1=; path = /", @@ -23,16 +20,88 @@ defaultValue: false, }, { + cookie: "=test=2", + expected: "test=2", + name: "Set a nameless cookie (that has an = in its value)", + }, + { + cookie: "===test=2b", + expected: "==test=2b", + name: "Set a nameless cookie (that has multiple ='s in its value)", + }, + { + cookie: "=test2c", + expected: "test2c", + name: "Set a nameless cookie", + }, + { + cookie: "test =3", + expected: "test=3", + name: "Remove trailing WSP characters from the name string", + }, + { + cookie: " test=4", + expected: "test=4", + name: "Remove leading WSP characters from the name string", + }, + { + cookie: ['"test=5"=test', '"test=5'], + expected: '"test=5', + name: "Only return the new cookie (with the same name)", + }, + { + cookie: "test6;cool=dude", + expected: "test6", + name: "Ignore invalid attributes after nameless cookie", + }, + { + cookie: "$Version=1; test=7", + expected: "$Version=1", + name: "Ignore invalid attributes after valid name (that looks like Cookie2 Version attribute)", + }, + { + cookie: "test test=8", + expected: "test test=8", + name: "Set a cookie that has whitespace in its name", + }, + { + cookie: '"test9;test"=9', + expected: '"test9', + name: "Set a nameless cookie ignoring characters after first ;", + }, + { + cookie: '"test\"10;baz"=qux', + expected: '"test\"10', + name: "Set a nameless cookie ignoring characters after first ; (2)", + }, + { + cookie: ["=test=11", "test11"], + expected: "test11", + name: "Return the most recent nameless cookie", + }, + { + cookie: "=", + expected: "", + name: "Ignore cookie with empty name and empty value", + }, + { cookie: "", expected: "", name: "Ignore cookie with no name or value", }, - ]; for (const test of nameTests) { httpCookieTest(test.cookie, test.expected, test.name); } + + for (const name of ["a", "1", "$", "!a", "@a", "#a", "$a", "%a", + "^a", "&a", "*a", "(a", ")a", "-a", "_a", "+", + '"a', '"a=b"' + ]) { + const cookie = `${name}=test`; + httpCookieTest(cookie, cookie, `Name is set as expected for ${name}=test`); + } </script> </body> </html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/cookies/value/value.html b/third_party/blink/web_tests/external/wpt/cookies/value/value.html index c473a6bf..c191083 100644 --- a/third_party/blink/web_tests/external/wpt/cookies/value/value.html +++ b/third_party/blink/web_tests/external/wpt/cookies/value/value.html
@@ -91,6 +91,41 @@ expected: 'test="14 "', name: "Set cookie ignoring whitespace after value endquote", }, + { + cookie: "test=15 ;", + expected: "test=15", + name: "Ignore whitespace and ; after value", + }, + { + cookie: "test= 16", + expected: "test=16", + name: "Ignore whitespace preceding value", + }, + { + cookie: 'test="17"', + expected: 'test="17"', + name: "Set cookie with quotes in value", + }, + { + cookie: 'test=" 18 "', + expected: 'test=" 18 "', + name: "Set cookie keeping whitespace inside quoted value", + }, + { + cookie: 'test="19;wow"', + expected: 'test="19', + name: "Set cookie value ignoring characters after semicolon", + }, + { + cookie: 'test="20=20"', + expected: 'test="20=20"', + name: "Set cookie with another = inside quoted value", + }, + { + cookie: "test = 21 ; ttt", + expected: "test=21", + name: "Set cookie ignoring whitespace surrounding value and characters after first semicolon", + }, ]; for (const test of valueTests) {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/support/grid-child-utils.js b/third_party/blink/web_tests/external/wpt/css/css-grid/support/grid-child-utils.js index d75ad6e..5e0c5ca 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/support/grid-child-utils.js +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/support/grid-child-utils.js
@@ -5,7 +5,7 @@ const gridChildHelperCol = "col"; // Helper for building testcases for grid-template-* with a child div in -// multiple positions. Prop is expected ot be one of gridChildHelperRow or +// multiple positions. Prop is expected to be one of gridChildHelperRow or // gridChildHelperCol, to select testing grid rows or grid columns, // respectively. // The child div is found by the id of 'child'.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html new file mode 100644 index 0000000..fa9ce8e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> + <title>CSS aspect-ratio: Test flex item's resolved width/min-width with border-box box-sizing in a row flex container</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="https://www.mozilla.org/"> + <link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio"> + <link rel="match" href="../../reference/ref-filled-green-200px-square.html" /> + <style> + .flexContainer { + display: flex; + flex-direction: row; + width: 1px; + } + .item { + background: green; + padding-top: 15px; + box-sizing: border-box; + } + </style> + + <p>Test passes if there is a filled green square and <strong>no red</strong>.</p> + + <!-- In the following four flex containers, the aspect-ratio works with border-box. --> + <div class="flexContainer" style="width: auto;"> + <!-- The border-box height 25px is transferred to the main axis, + yielding a resolved flex base size of 200px. --> + <div class="item" style="min-width:0; height: 25px; aspect-ratio: 8/1;"></div> + </div> + + <div class="flexContainer"> + <!-- The border-box height 25px is transferred to the main axis, + yielding a resolved min-width:auto of 200px. --> + <div class="item" style="height: 25px; aspect-ratio: 8/1;"></div> + </div> + + <div class="flexContainer"> + <!-- The border-box min-height 25px is transferred to the main axis, + yielding a resolved min-width:auto of 200px. --> + <div class="item" style="min-height: 25px; aspect-ratio: 8/1;"></div> + </div> + + <div class="flexContainer"> + <!-- The border-box height 25px (clamped by max-height) is transferred to the main axis, + yielding a resolved min-width:auto of 200px. --> + <div class="item" style="max-height: 25px; height: 100px; aspect-ratio: 8/1;"></div> + </div> + + <!-- In the following four flex containers, the aspect-ratio works with content-box + because its value contains 'auto'. --> + <div class="flexContainer" style="width: auto;"> + <!-- The content-box height 10px is transferred to the main axis, + yielding a resolved flex base size of 200px. --> + <div class="item" style="min-width:0; height: 25px; aspect-ratio: auto 20/1;"></div> + </div> + + <div class="flexContainer"> + <!-- The content-box height 10px is transferred to the main axis, + yielding a resolved min-width:auto of 200px. --> + <div class="item" style="height: 25px; aspect-ratio: auto 20/1;"></div> + </div> + + <div class="flexContainer"> + <!-- The content-box min-height 10px is transferred to the main axis, + yielding a resolved min-width:auto of 200px. --> + <div class="item" style="min-height: 25px; aspect-ratio: auto 20/1;"></div> + </div> + + <div class="flexContainer"> + <!-- The content-box height 10px (clamped by max-height) is transferred + to the main axis, yielding a resolved min-width:auto of 200px. --> + <div class="item" style="max-height: 25px; height: 100px; aspect-ratio: auto 20/1;"></div> + </div> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html new file mode 100644 index 0000000..1df1446 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-026.html
@@ -0,0 +1,77 @@ +<!DOCTYPE html> +<html> + <title>CSS aspect-ratio: Test flex item's resolved height/min-height with border-box box-sizing in a column flex container</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="https://www.mozilla.org/"> + <link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio"> + <link rel="match" href="../../reference/ref-filled-green-200px-square.html" /> + <style> + .flexContainer { + display: flex; + flex-direction: column; + float: left; + height: 1px; + } + .item { + background: green; + padding-left: 15px; + box-sizing: border-box; + } + .item > div { + height: 500px; /* Set a large content size suggestion for flex item. */ + } + </style> + + <p>Test passes if there is a filled green square and <strong>no red</strong>.</p> + + <!-- In the following four flex containers, the aspect-ratio works with border-box. --> + <div class="flexContainer" style="height: auto;"> + <!-- The border-box width 25px is transferred to the main axis, + yielding a resolved flex base size of 200px. --> + <div class="item" style="min-height:0; width: 25px; aspect-ratio: 1/8;"><div></div></div> + </div> + + <div class="flexContainer"> + <!-- The border-box width 25px is transferred to the main axis, + yielding a resolved min-height:auto of 200px. --> + <div class="item" style="width: 25px; aspect-ratio: 1/8;"><div></div></div> + </div> + + <div class="flexContainer"> + <!-- The border-box min-width 25px is transferred to the main axis, + yielding a resolved min-height:auto of 200px. --> + <div class="item" style="min-width: 25px; aspect-ratio: 1/8;"><div></div></div> + </div> + + <div class="flexContainer"> + <!-- The border-box width 25px (clamped by max-width) is transferred to the main axis, + yielding a resolved min-height:auto of 200px. --> + <div class="item" style="max-width: 25px; width: 100px; aspect-ratio: 1/8;"><div></div></div> + </div> + + <!-- In the following four flex containers, the aspect-ratio works with content-box + because its value contains 'auto'. --> + <div class="flexContainer" style="height: auto;"> + <!-- The content-box width 10px is transferred to the main axis, + yielding a resolved flex base size of 200px. --> + <div class="item" style="min-height:0; width: 25px; aspect-ratio: auto 1/20;"><div></div></div> + </div> + + <div class="flexContainer"> + <!-- The content-box width 10px is transferred to the main axis, + yielding a resolved min-height:auto of 200px. --> + <div class="item" style="width: 25px; aspect-ratio: auto 1/20;"><div></div></div> + </div> + + <div class="flexContainer"> + <!-- The content-box min-width 10px is transferred to the main axis, + yielding a resolved min-height:auto of 200px. --> + <div class="item" style="min-width: 25px; aspect-ratio: auto 1/20;"><div></div></div> + </div> + + <div class="flexContainer"> + <!-- The content-box width 10px (clamped by max-width) is transferred to the main axis, + yielding a resolved min-height:auto of 200px. --> + <div class="item" style="max-width: 25px; width: 100px; aspect-ratio: auto 1/20;"><div></div></div> + </div> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-rounds-to-integer.html b/third_party/blink/web_tests/external/wpt/css/css-values/calc-rounds-to-integer.html new file mode 100644 index 0000000..8058978 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-values/calc-rounds-to-integer.html
@@ -0,0 +1,120 @@ +<!doctype html> +<title>Calc rounds to integer</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<link rel=author title="Tab Atkins-Bittner" href="https://www.xanthir.com/contact/"> +<link rel="help" href="https://drafts.csswg.org/css-values/#calc-range"> +<link rel="help" href="https://drafts.csswg.org/css-easing/#funcdef-step-easing-function-steps"> +<link rel="help" href="https://drafts.csswg.org/css-multicol-2/#column-span"> +<link rel="help" href="https://drafts.csswg.org/css-lists/#propdef-counter-reset"> +<link rel="help" href="https://drafts.csswg.org/css-lists/#propdef-counter-increment"> +<link rel="help" href="https://drafts.csswg.org/css-lists/#propdef-counter-set"> +<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-feature-settings-prop"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#propdef-grid-template-rows"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#propdef-grid-row"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-hyphenate-limit-chars"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-hyphenate-limit-lines"> +<link rel="help" href="https://drafts.csswg.org/css-inline-3/#propdef-initial-letter"> +<link rel="help" href="https://drafts.csswg.org/css-overflow-4/#propdef-max-lines"> +<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#propdef-order"> +<link rel="help" href="https://drafts.csswg.org/css-break-4/#propdef-orphans"> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-4/#propdef-text-combine-upright"> +<link rel="help" href="https://drafts.csswg.org/css-break-4/#propdef-widows"> +<link rel="help" href="https://drafts.csswg.org/css2/#propdef-z-index"> +<!-- + Verifying that, per V&U, a calc() that results in a non-integer value + gets rounded to the nearest integer + when used in a place that requires <integer> specifically. + This tests both straight-up decimal-point values, + and scinot, which is defined to parse as <number-token>. +--> +<body> + +<script> + +runTests("animation-timing-function", "steps(xxx)"); +runTests("column-span"); +runTests("counter-increment", "foo xxx"); +runTests("counter-reset", "foo xxx"); +runTests("counter-set", "foo xxx"); +runTests("font-feature-settings", '"fooo" xxx'); +runTests("grid-row"); +runTests("grid-template-rows", "repeat(xxx, 10px)"); +runTests("hyphenate-limit-chars"); +runTests("hyphenate-limit-lines"); +runTests("initial-letter", "1.1 xxx"); +runTests("max-lines"); +runTests("order"); +runTests("orphans"); +runTests("text-combine-upright", "digits xxx"); +runTests("transition-timing-function", "steps(xxx)"); +runTests("widows"); +runTests("z-index"); + + +function runTests(prop, valPattern="xxx") { + const el = document.body; + + // Don't spuriously fail bc the prop or val isn't supported. + if(!verifySupport(el, prop, valPattern)) return; + + const validValues = [ + "10", + "calc(10)", + "calc(10.1)", + "calc(1e1)", + "calc(1.1e1)", + ]; + const invalidValues = [ + "1e1", + "1.1e1", + "10.1", + ]; + for(let testVal of validValues) { + testInt(el, prop, testVal, valPattern); + } + for(let testVal of invalidValues) { + testIntInvalid(el, prop, testVal, valPattern); + } +} + +function verifySupport(el, prop, valPattern) { + let testVal = "10"; + if(valPattern !== undefined) { + testVal = valPattern.replace("xxx", testVal); + } + el.removeAttribute("style"); + const nullVal = getComputedStyle(el)[prop]; + el.style.setProperty(prop, testVal); + return getComputedStyle(el)[prop] != nullVal; +} + +function testInt(el, prop, testVal, valPattern) { + // to avoid needing to specify serialization, + // just test whether it parses at all + if(valPattern !== undefined) { + testVal = valPattern.replace("xxx", testVal); + } + test(()=>{ + el.removeAttribute("style"); + const nullVal = getComputedStyle(el)[prop]; + el.style.setProperty(prop, testVal); + assert_not_equals(getComputedStyle(el)[prop], nullVal); + }, `${prop} should accept "${testVal}"`) +} + +function testIntInvalid(el, prop, testVal, valPattern) { + // similarly, just verify it doesn't parse at all + if(valPattern !== undefined) { + testVal = valPattern.replace("xxx", testVal); + } + test(()=>{ + el.removeAttribute("style"); + const nullVal = getComputedStyle(el)[prop]; + el.style.setProperty(prop, testVal); + assert_equals(getComputedStyle(el)[prop], nullVal); + }, `${prop} should not accept "${testVal}"`) +} + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/mouseEvent-offsetXY-svg.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/mouseEvent-offsetXY-svg.html new file mode 100644 index 0000000..c0bd164 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/mouseEvent-offsetXY-svg.html
@@ -0,0 +1,27 @@ +<!doctype html> +<title>MouseEvent.offsetX/Y returns coordinates relative to the root svg</title> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<link rel="author" title="Mozilla" href="https://mozilla.org"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1684973"> +<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/1508"> +<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsetx"> +<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> +<style> + body { margin: 0 } +</style> +<svg width=100 height=100> + <rect width=30 height=30 x=50 y=50 fill=green></rect> +</svg> +<script> +let t = async_test(); +let rect = document.querySelector("rect"); +rect.addEventListener("click", t.step_func_done(function(e) { + assert_true(e.offsetX >= 50); + assert_true(e.offsetY >= 50); +})) + +test_driver.click(rect); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/serialize-custom-props-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/serialize-custom-props-expected.txt new file mode 100644 index 0000000..5dbde36c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/cssom/serialize-custom-props-expected.txt
@@ -0,0 +1,23 @@ +This is a testharness.js-based test. +PASS z-index can take a 4-digit integer +PASS An unregistered custom prop can take a 4-digit integer +PASS An <integer> custom prop can take a 4-digit integer +PASS z-index can take a custom property set to a 4-digit integer +PASS z-index can take a 6-digit integer +PASS An unregistered custom prop can take a 6-digit integer +PASS An <integer> custom prop can take a 6-digit integer +PASS z-index can take a custom property set to a 6-digit integer +PASS z-index can take a 8-digit integer +FAIL An unregistered custom prop can take a 8-digit integer assert_equals: expected "11111111" but got "1.11111e+7" +FAIL An <integer> custom prop can take a 8-digit integer assert_equals: expected "11111111" but got "1.11111e+7" +PASS z-index can take a custom property set to a 8-digit integer +PASS z-index can take a 12-digit integer +FAIL An unregistered custom prop can take a 12-digit integer assert_equals: expected "111111111111" but got "1.11111e+11" +FAIL An <integer> custom prop can take a 12-digit integer assert_equals: expected "111111111111" but got "1.11111e+11" +PASS z-index can take a custom property set to a 12-digit integer +PASS z-index can take a 25-digit integer +FAIL An unregistered custom prop can take a 25-digit integer assert_equals: expected "1111111111111111111111111" but got "1.11111e+24" +FAIL An <integer> custom prop can take a 25-digit integer assert_equals: expected "1111111111111111111111111" but got "1.11111e+24" +PASS z-index can take a custom property set to a 25-digit integer +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/serialize-custom-props.html b/third_party/blink/web_tests/external/wpt/css/cssom/serialize-custom-props.html new file mode 100644 index 0000000..cfe96ff0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/cssom/serialize-custom-props.html
@@ -0,0 +1,69 @@ +<link rel=author title="Tab Atkins-Bittner" href="https://www.xanthir.com/contact/"> +<link rel="help" href="https://drafts.csswg.org/css-values/#calc-range"> +<body><!doctype html> +<title>Serializing Integers Never Uses Scinot</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<link rel=author title="Tab Atkins-Bittner" href="https://www.xanthir.com/contact/"> +<link rel="help" href="https://drafts.csswg.org/cssom/#serialize-a-css-component-value"> +<!-- + Per CSSOM, integers always serialize all their digits out. + They never serialize to scinot, regardless of size, + because that makes them stop being an integer. + This applies to custom properties as well. +--> +<body> + +<script> + +try { +CSS.registerProperty({ + name: "--two", + value: "<integer>", + inherits: true, + initial: -1 +}); +}catch(e){} + +testIntLength(4); +testIntLength(6); +testIntLength(8); +testIntLength(12); +// JS starts serializing with scinot at 22 digits... +testIntLength(25); + +function testIntLength(len) { + let el = document.body; + const val = "1".repeat(len); + test(()=>{ + el.removeAttribute("style"); + const nullVal = getComputedStyle(el).zIndex; + el.style.zIndex=val; + assert_not_equals(getComputedStyle(el).zIndex, nullVal) + }, `z-index can take a ${len}-digit integer`); + + test(()=>{ + el.removeAttribute("style"); + el.style.setProperty("--one", val); + assert_equals(getComputedStyle(el).getPropertyValue("--one"), val); + }, `An unregistered custom prop can take a ${len}-digit integer`); + + test(()=>{ + el.removeAttribute("style"); + el.style.setProperty("--two", val); + assert_equals(getComputedStyle(el).getPropertyValue("--two"), val); + }, `An <integer> custom prop can take a ${len}-digit integer`); + + test(()=>{ + el.removeAttribute("style"); + el.style.zIndex = val; + const standardVal = getComputedStyle(el).zIndex; + el.removeAttribute("style"); + el.style.setProperty("--three", val); + el.style.zIndex = "var(--three)"; + assert_equals(getComputedStyle(el).zIndex, standardVal); + }, `z-index can take a custom property set to a ${len}-digit integer`); +} + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-in-focus-event-001.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-in-focus-event-001.html index bd4145a3..0639b77 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-in-focus-event-001.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-in-focus-event-001.html
@@ -14,7 +14,7 @@ var focused = document.querySelector(':focus'); test(() => { assert_equals(e.target, focused, "':focus' matches event.target"); - }, "Checks that ':focus' pseudo-class matches inside 'focus' evente handler"); + }, "Checks that ':focus' pseudo-class matches inside 'focus' event handler"); }, false); input.focus(); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-001.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-001.html index 0683689..d580b07 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-001.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-001.html
@@ -13,6 +13,7 @@ <style> @supports not (selector(:focus-visible)) { :focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-002.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-002.html index 2846ae46..441c1da 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-002.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-002.html
@@ -14,6 +14,7 @@ <style> @supports not (selector(:focus-visible)) { :focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html index 9d572257..aa73b4d 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-003.html
@@ -14,6 +14,7 @@ @supports not (selector(:focus-visible)) { :focus { outline: red solid 5px; + background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html index 318d1ee..b30b9e2 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-004.html
@@ -14,6 +14,7 @@ @supports not (selector(:focus-visible)) { :focus { outline: red solid 5px; + background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-005.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-005.html index 4aec863..c86c057 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-005.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-005.html
@@ -13,6 +13,7 @@ @supports not (selector(:focus-visible)) { :focus { outline: red solid 5px; + background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-006.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-006.html index 89d9782..a5256c1 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-006.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-006.html
@@ -10,6 +10,13 @@ <script src="/resources/testdriver.js"></script> <script src="/resources/testdriver-vendor.js"></script> <style> + @supports not (selector(:focus-visible)) { + :focus { + outline: red solid 5px; + background-color: red; + } + } + span[contenteditable] { border: 1px solid black; background-color: white;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-008.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-008.html index c84985f..5f5b54e 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-008.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-008.html
@@ -12,6 +12,7 @@ <style> @supports not (selector(:focus-visible)) { #el:focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-009.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-009.html index bbadd578..d9edb69 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-009.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-009.html
@@ -9,7 +9,8 @@ <script src="/resources/testharnessreport.js"></script> <style> @supports not (selector(:focus-visible)) { - #buton:focus { + #button:focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-010.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-010.html index cfd4282..8d02edbc 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-010.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-010.html
@@ -10,6 +10,7 @@ <style> @supports not (selector(:focus-visible)) { :focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-011.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-011.html index 3d66dc9..d45f5d8e 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-011.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-011.html
@@ -12,6 +12,7 @@ <style> @supports not (selector(:focus-visible)) { #next:focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-012.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-012.html index dcb00e1..b27abbe3 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-012.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-012.html
@@ -13,6 +13,7 @@ <style> @supports not (selector(:focus-visible)) { :focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-014.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-014.html index 8e52570e..6a4aef6 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-014.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-014.html
@@ -9,6 +9,7 @@ <style> @supports not (selector(:focus-visible)) { :focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html index 21568f3..685baeb 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-015.html
@@ -11,6 +11,7 @@ <style> @supports not (selector(:focus-visible)) { :focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html index 64d9bb77..a65e5a5 100644 --- a/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html +++ b/third_party/blink/web_tests/external/wpt/css/selectors/focus-visible-016.html
@@ -11,6 +11,7 @@ <style> @supports not (selector(:focus-visible)) { :focus { + outline: red solid 5px; background-color: red; } }
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/parser/parser-constructs-custom-element-in-document-write.html b/third_party/blink/web_tests/external/wpt/custom-elements/parser/parser-constructs-custom-element-in-document-write.html index 3b52566..14c830b 100644 --- a/third_party/blink/web_tests/external/wpt/custom-elements/parser/parser-constructs-custom-element-in-document-write.html +++ b/third_party/blink/web_tests/external/wpt/custom-elements/parser/parser-constructs-custom-element-in-document-write.html
@@ -14,10 +14,16 @@ <div id="log"></div> <script> -class MyCustomElement extends HTMLElement { } +var numberOfChildNodesInConnectedCallback = 0; + +class MyCustomElement extends HTMLElement { + connectedCallback() { + numberOfChildNodesInConnectedCallback = this.childNodes.length; + } +} customElements.define('my-custom-element', MyCustomElement); -document.write('<my-custom-element></my-custom-element>'); +document.write('<my-custom-element>hello <b>world</b></my-custom-element>'); test(function () { var instance = document.querySelector('my-custom-element'); @@ -27,6 +33,11 @@ }, 'HTML parser must instantiate custom elements inside document.write'); +test(function () { + assert_equals(numberOfChildNodesInConnectedCallback, 0); + +}, 'HTML parser should call connectedCallback before appending child nodes inside document.write'); + </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/docs/admin/index.md b/third_party/blink/web_tests/external/wpt/docs/admin/index.md index 3073b96..59569fd4 100644 --- a/third_party/blink/web_tests/external/wpt/docs/admin/index.md +++ b/third_party/blink/web_tests/external/wpt/docs/admin/index.md
@@ -44,15 +44,13 @@ - (unknown registrar): http://testthewebforward.org - web-human@w3.org - [Google Domains](https://domains.google/): https://wpt.fyi + - smcgruer@google.com - foolip@google.com - - robertma@google.com - - mike@bocoup.com - (Google internal): https://wpt.live https://wptpr.live + - smcgruer@google.com - foolip@google.com - - robertma@google.com - [GitHub](https://github.com/): web-platform-tests - [@foolip](https://github.com/foolip) - - [@Hexcles](https://github.com/Hexcles) - [@jgraham](https://github.com/jgraham) - [@plehegar](https://github.com/plehegar) - [@thejohnjansen](https://github.com/thejohnjansen) @@ -62,15 +60,12 @@ - [@plehegar](https://github.com/plehegar) - [@sideshowbarker](https://github.com/sideshowbarker) - [Google Cloud Platform](https://cloud.google.com/): wptdashboard{-staging} - - robertma@google.com - smcgruer@google.com - foolip@google.com - [Google Cloud Platform](https://cloud.google.com/): wpt-live - smcgruer@google.com - - robertma@google.com - [Google Cloud Platform](https://cloud.google.com/): wpt-pr-bot - smcgruer@google.com - - robertma@google.com - E-mail address: wpt.pr.bot@gmail.com - smcgruer@google.com - boaz@bocoup.com
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/audio-controls-intrinsic-size.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/audio-controls-intrinsic-size.html new file mode 100644 index 0000000..6cbbcd0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/embedded-content/audio-controls-intrinsic-size.html
@@ -0,0 +1,25 @@ +<!doctype html> +<title>Audio intrinsic size doesn't depend on its max size</title> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1683979"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div style="display: inline-block"> + <audio controls style="max-width: 99%" id="test"></audio> +</div> +<script> +let audio = document.getElementById("test"); + +function computeSize() { + return audio.getBoundingClientRect().width; +} + +let size = computeSize(); +async_test(function(t) { + requestAnimationFrame(t.step_func(function() { + assert_equals(computeSize(), size, "Shouldn't have changed size"); + requestAnimationFrame(t.step_func_done(function() { + assert_equals(computeSize(), size, "Shouldn't have changed size"); + })); + })); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/data-driven/tools/format_json.py b/third_party/blink/web_tests/external/wpt/import-maps/data-driven/tools/format_json.py index 1059ac7..6386d41 100644 --- a/third_party/blink/web_tests/external/wpt/import-maps/data-driven/tools/format_json.py +++ b/third_party/blink/web_tests/external/wpt/import-maps/data-driven/tools/format_json.py
@@ -12,7 +12,7 @@ def main(): for filename in sys.argv[1:]: - print filename + print(filename) try: spec = json.load( open(filename, u'r'), object_pairs_hook=collections.OrderedDict)
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/same-document-with-document-root.html b/third_party/blink/web_tests/external/wpt/intersection-observer/same-document-with-document-root.html new file mode 100644 index 0000000..15cb7c4c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/intersection-observer/same-document-with-document-root.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta name="viewport" content="width=device-width,initial-scale=1"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="./resources/intersection-observer-test-utils.js"></script> + +<style> + pre, + #log { + position: absolute; + top: 0; + left: 200px; + } + + .spacer { + height: calc(100vh + 100px); + } + + #target { + width: 100px; + height: 100px; + background-color: green; + } +</style> + +<div class="spacer"></div> +<div id="target"></div> +<div class="spacer"></div> + +<script> + var vw = document.documentElement.clientWidth; + var vh = document.documentElement.clientHeight; + + var entries = []; + var target; + + runTestCycle(function () { + target = document.getElementById("target"); + assert_true(!!target, "target exists"); + var observer = new IntersectionObserver(function (changes) { + entries = entries.concat(changes) + }, {root: document}); + observer.observe(target); + entries = entries.concat(observer.takeRecords()); + assert_equals(entries.length, 0, "No initial notifications."); + runTestCycle(step0, "First rAF."); + }, "IntersectionObserver in a single document using document as root."); + + function step0() { + document.scrollingElement.scrollTop = 300; + runTestCycle(step1, "document.scrollingElement.scrollTop = 300"); + checkLastEntry(entries, 0, [8, 108, vh + 108, vh + 208, 0, 0, 0, 0, 0, vw, 0, vh, false]); + } + + function step1() { + document.scrollingElement.scrollTop = 0; + checkLastEntry(entries, 1, [8, 108, vh - 192, vh - 92, 8, 108, vh - 192, vh - 92, 0, vw, 0, vh, true]); + } +</script> +
diff --git a/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative-expected.txt index 444eafb..7506236 100644 --- a/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative-expected.txt +++ b/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative-expected.txt
@@ -3,6 +3,7 @@ FAIL Modifying selectionEnd value of the input element assert_equals: expected 1 but got 0 FAIL Calling setSelectionRange() on the input element assert_equals: expected 1 but got 0 FAIL Calling select() on the input element assert_equals: expected 1 but got 0 +FAIL Calling setRangeText() on the input element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionStart value on the input element FAIL Setting the same selectionStart value twice on the input element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionEnd value on the input element @@ -14,6 +15,7 @@ FAIL Modifying selectionEnd value of the disconnected input element assert_equals: expected 1 but got 0 FAIL Calling setSelectionRange() on the disconnected input element assert_equals: expected 1 but got 0 FAIL Calling select() on the disconnected input element assert_equals: expected 1 but got 0 +FAIL Calling setRangeText() on the disconnected input element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionStart value on the disconnected input element FAIL Setting the same selectionStart value twice on the disconnected input element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionEnd value on the disconnected input element @@ -25,6 +27,7 @@ FAIL Modifying selectionEnd value of the textarea element assert_equals: expected 1 but got 0 FAIL Calling setSelectionRange() on the textarea element assert_equals: expected 1 but got 0 FAIL Calling select() on the textarea element assert_equals: expected 1 but got 0 +FAIL Calling setRangeText() on the textarea element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionStart value on the textarea element FAIL Setting the same selectionStart value twice on the textarea element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionEnd value on the textarea element @@ -36,6 +39,7 @@ FAIL Modifying selectionEnd value of the disconnected textarea element assert_equals: expected 1 but got 0 FAIL Calling setSelectionRange() on the disconnected textarea element assert_equals: expected 1 but got 0 FAIL Calling select() on the disconnected textarea element assert_equals: expected 1 but got 0 +FAIL Calling setRangeText() on the disconnected textarea element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionStart value on the disconnected textarea element FAIL Setting the same selectionStart value twice on the disconnected textarea element assert_equals: expected 1 but got 0 PASS Setting initial zero selectionEnd value on the disconnected textarea element
diff --git a/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative.html b/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative.html index 2216a4b5..adec8b3 100644 --- a/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative.html +++ b/third_party/blink/web_tests/external/wpt/selection/textcontrols/selectionchange.tentative.html
@@ -103,6 +103,15 @@ promise_test(async () => { await data.initialize(); + target.setRangeText("newmiddle", 2, 3, "select"); + + await data.assert_empty_spin(); + assert_equals(collector.events.length, 1); + }, `Calling setRangeText() on ${name}`); + + promise_test(async () => { + await data.initialize(); + target.selectionStart = 0; await data.assert_empty_spin();
diff --git a/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement-expected.txt b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement-expected.txt new file mode 100644 index 0000000..48365c5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Use of SVGAnimatedEnumeration within SVGFECompositeElement Failed to set the 'baseVal' property on 'SVGAnimatedEnumeration': The enumeration value provided is 0, which is not settable. +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html index e6315b4..0e99f5fe9 100644 --- a/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html +++ b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html
@@ -34,13 +34,18 @@ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR); assert_equals(feCompositeElement.getAttribute('operator'), "xor"); + // Switch to 'lighter'. + feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_LIGHTER; + assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_LIGHTER); + assert_equals(feCompositeElement.getAttribute('operator'), "lighter"); + // Switch to 'arithmetic'. feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC; assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC); assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic"); // Try setting invalid values. - assert_throws_js(TypeError, function() { feCompositeElement.operator.baseVal = 7; }); + assert_throws_js(TypeError, function() { feCompositeElement.operator.baseVal = 8; }); assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC); assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic"); @@ -56,10 +61,5 @@ feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER; assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER); assert_equals(feCompositeElement.getAttribute('operator'), "over"); - - // Switch to 'lighter'. - assert_equals(SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_LIGHTER, undefined); - feCompositeElement.setAttribute("operator", "lighter"); - assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_UNKNOWN); }); -</script> \ No newline at end of file +</script>
diff --git a/third_party/blink/web_tests/external/wpt/xhr/event-timeout.any.js b/third_party/blink/web_tests/external/wpt/xhr/event-timeout.any.js index da8ca11b..c73cd1a 100644 --- a/third_party/blink/web_tests/external/wpt/xhr/event-timeout.any.js +++ b/third_party/blink/web_tests/external/wpt/xhr/event-timeout.any.js
@@ -14,5 +14,5 @@ client.send(null); test.step_timeout(() => { assert_unreached("ontimeout not called."); - }, 10); + }, 1000); });
diff --git a/third_party/blink/web_tests/hid/hidDevice_deviceInfo.html b/third_party/blink/web_tests/http/tests/hid/hidDevice_deviceInfo.html similarity index 83% rename from third_party/blink/web_tests/hid/hidDevice_deviceInfo.html rename to third_party/blink/web_tests/http/tests/hid/hidDevice_deviceInfo.html index 66c515b..4f1184f 100644 --- a/third_party/blink/web_tests/hid/hidDevice_deviceInfo.html +++ b/third_party/blink/web_tests/http/tests/hid/hidDevice_deviceInfo.html
@@ -1,14 +1,11 @@ <!DOCTYPE html> <body> -<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="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/services/device/public/mojom/hid.mojom.js"></script> -<script src="file:///gen/third_party/blink/public/mojom/hid/hid.mojom.js"></script> -<script src="resources/hid-test-utils.js"></script> -<script> +<script type="module"> +import '/resources/testharness.js'; +import '/resources/testharnessreport.js'; + +import {hid_test, trustedClick} from './resources/hid-test-utils.js'; +import {GENERIC_DESKTOP_GAME_PAD, HID_COLLECTION_TYPE_APPLICATION, HidBusType, HidCollectionInfo, HidReportDescription, HidReportItem, HidUsageAndPage, PAGE_BUTTON, PAGE_GENERIC_DESKTOP} from '/gen/services/device/public/mojom/hid.mojom.m.js'; const kTestVendorId = 0x1234; const kTestProductId = 0xabcd; @@ -23,15 +20,15 @@ // gamepad-like device with one input report. The input report has a single // 8-bit field with a button usage. function createDeviceWithInputReport(fake) { - const nullUsage = new device.mojom.HidUsageAndPage(); - const buttonUsage = new device.mojom.HidUsageAndPage(); - buttonUsage.usagePage = device.mojom.PAGE_BUTTON; + const nullUsage = new HidUsageAndPage(); + const buttonUsage = new HidUsageAndPage(); + buttonUsage.usagePage = PAGE_BUTTON; buttonUsage.usage = kButtonPrimary; - const gamePadUsage = new device.mojom.HidUsageAndPage(); - gamePadUsage.usagePage = device.mojom.PAGE_GENERIC_DESKTOP; - gamePadUsage.usage = device.mojom.GENERIC_DESKTOP_GAME_PAD; + const gamePadUsage = new HidUsageAndPage(); + gamePadUsage.usagePage = PAGE_GENERIC_DESKTOP; + gamePadUsage.usage = GENERIC_DESKTOP_GAME_PAD; - const reportItem = new device.mojom.HidReportItem(); + const reportItem = new HidReportItem(); reportItem.isRange = false; reportItem.isConstant = false; // Data. reportItem.isVariable = true; // Variable. @@ -58,14 +55,14 @@ reportItem.reportSize = 8; // 1 byte. reportItem.reportCount = 1; - const report = new device.mojom.HidReportDescription(); + const report = new HidReportDescription(); report.reportId = kTestReportId; report.items = [reportItem]; - const collection = new device.mojom.HidCollectionInfo(); + const collection = new HidCollectionInfo(); collection.usage = gamePadUsage; collection.reportIds = [kTestReportId]; - collection.collectionType = device.mojom.HID_COLLECTION_TYPE_APP_APPLICATION; + collection.collectionType = HID_COLLECTION_TYPE_APPLICATION; collection.inputReports = [report]; collection.outputReports = []; collection.featureReports = []; @@ -75,7 +72,7 @@ // The device guid will be set by fake.addDevice(). deviceInfo.productName = kTestProductName; deviceInfo.serialNumber = kTestSerialNumber; - deviceInfo.busType = device.mojom.HidBusType.HID_BUS_TYPE_USB; + deviceInfo.busType = HidBusType.HID_BUS_TYPE_USB; deviceInfo.reportDescriptor = []; deviceInfo.collections = [collection]; deviceInfo.hasReportId = true; @@ -106,10 +103,9 @@ assert_equals(d.collections.length, 1, 'device.collections.length'); const c = d.collections[0]; - assert_equals(c.usagePage, device.mojom.PAGE_GENERIC_DESKTOP, - 'collection.usagePage'); - assert_equals(c.usage, device.mojom.GENERIC_DESKTOP_GAME_PAD, - 'collection.usage'); + assert_equals(c.usagePage, PAGE_GENERIC_DESKTOP, 'collection.usagePage'); + assert_equals(c.usage, GENERIC_DESKTOP_GAME_PAD, 'collection.usage'); + assert_equals(c.type, HID_COLLECTION_TYPE_APPLICATION, 'collection.type'); assert_equals(c.children.length, 0, 'collection.children.length'); assert_equals(c.inputReports.length, 1, 'collection.inputReports.length'); assert_equals(c.outputReports.length, 0, 'collection.outputReports.length'); @@ -122,8 +118,14 @@ const i = r.items[0]; assert_true(i.isAbsolute, 'reportItem.isAbsolute'); assert_false(i.isArray, 'reportItem.isArray'); + assert_false(i.isBufferedBytes, 'reportItem.isBufferedBytes'); + assert_false(i.isConstant, 'reportItem.isConstant'); + assert_true(i.isLinear, 'reportItem.isLinear'); assert_false(i.isRange, 'reportItem.isRange'); + assert_false(i.isVolatile, 'reportItem.isVolatile'); assert_false(i.hasNull, 'reportItem.hasNull'); + assert_true(i.hasPreferredState, 'reportItem.hasPreferredState'); + assert_false(i.wrap, 'reportItem.wrap'); assert_equals(i.usages.length, 1, 'reportItem.usages.length'); assert_equals(i.usages[0], 0x00090001, 'reportItem.usages[0]'); assert_equals(i.usageMinimum, 0, 'reportItem.usageMinimum');
diff --git a/third_party/blink/web_tests/hid/hidDevice_openAndClose.html b/third_party/blink/web_tests/http/tests/hid/hidDevice_openAndClose.html similarity index 81% rename from third_party/blink/web_tests/hid/hidDevice_openAndClose.html rename to third_party/blink/web_tests/http/tests/hid/hidDevice_openAndClose.html index 1765dc7..5cab2d60 100644 --- a/third_party/blink/web_tests/hid/hidDevice_openAndClose.html +++ b/third_party/blink/web_tests/http/tests/hid/hidDevice_openAndClose.html
@@ -1,14 +1,10 @@ <!DOCTYPE html> <body> -<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="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/services/device/public/mojom/hid.mojom.js"></script> -<script src="file:///gen/third_party/blink/public/mojom/hid/hid.mojom.js"></script> -<script src="resources/hid-test-utils.js"></script> -<script> +<script type="module"> +import '/resources/testharness.js'; +import '/resources/testharnessreport.js'; + +import {hid_test, trustedClick} from './resources/hid-test-utils.js'; const kTestVendorId = 0x1234; const kTestProductId = 0xabcd;
diff --git a/third_party/blink/web_tests/hid/hidDevice_reports.html b/third_party/blink/web_tests/http/tests/hid/hidDevice_reports.html similarity index 87% rename from third_party/blink/web_tests/hid/hidDevice_reports.html rename to third_party/blink/web_tests/http/tests/hid/hidDevice_reports.html index af85f895..ae3bc6a8 100644 --- a/third_party/blink/web_tests/hid/hidDevice_reports.html +++ b/third_party/blink/web_tests/http/tests/hid/hidDevice_reports.html
@@ -1,14 +1,10 @@ <!DOCTYPE html> <body> -<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="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/services/device/public/mojom/hid.mojom.js"></script> -<script src="file:///gen/third_party/blink/public/mojom/hid/hid.mojom.js"></script> -<script src="resources/hid-test-utils.js"></script> -<script> +<script type="module"> +import '/resources/testharness.js'; +import '/resources/testharnessreport.js'; + +import {compareDataViews, hid_test, oninputreport, trustedClick} from './resources/hid-test-utils.js'; const kTestVendorId = 0x1234; const kTestProductId = 0xabcd;
diff --git a/third_party/blink/web_tests/hid/hid_connectionEvents.html b/third_party/blink/web_tests/http/tests/hid/hid_connectionEvents.html similarity index 75% rename from third_party/blink/web_tests/hid/hid_connectionEvents.html rename to third_party/blink/web_tests/http/tests/hid/hid_connectionEvents.html index de214f5..c71d4d1 100644 --- a/third_party/blink/web_tests/hid/hid_connectionEvents.html +++ b/third_party/blink/web_tests/http/tests/hid/hid_connectionEvents.html
@@ -1,11 +1,9 @@ <!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/services/device/public/mojom/hid.mojom.js"></script> -<script src="file:///gen/third_party/blink/public/mojom/hid/hid.mojom.js"></script> -<script src="resources/hid-test-utils.js"></script> -<script> +<script type="module"> +import '/resources/testharness.js'; +import '/resources/testharnessreport.js'; + +import {hid_test} from './resources/hid-test-utils.js'; const kTestVendorId = 0x1234; const kTestProductId = 0xabcd;
diff --git a/third_party/blink/web_tests/hid/hid_getDevices.html b/third_party/blink/web_tests/http/tests/hid/hid_getDevices.html similarity index 73% rename from third_party/blink/web_tests/hid/hid_getDevices.html rename to third_party/blink/web_tests/http/tests/hid/hid_getDevices.html index f5652ec7..1cf603c 100644 --- a/third_party/blink/web_tests/hid/hid_getDevices.html +++ b/third_party/blink/web_tests/http/tests/hid/hid_getDevices.html
@@ -1,18 +1,17 @@ <!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/services/device/public/mojom/hid.mojom.js"></script> -<script src="file:///gen/third_party/blink/public/mojom/hid/hid.mojom.js"></script> -<script src="resources/hid-test-utils.js"></script> -<script> +<script type="module"> +import '../resources/testharness.js'; +import '../resources/testharnessreport.js'; + +import {hid_test} from './resources/hid-test-utils.js'; + +import {HidService} from '/gen/third_party/blink/public/mojom/hid/hid.mojom.m.js'; const kTestVendorId = 0x1234; const kTestProductId = 0xabcd; promise_test(async () => { - let interceptor = - new MojoInterfaceInterceptor(blink.mojom.HidService.name); + let interceptor = new MojoInterfaceInterceptor(HidService.$interfaceName); interceptor.oninterfacerequest = e => e.handle.close(); interceptor.start();
diff --git a/third_party/blink/web_tests/hid/hid_requestDevice.html b/third_party/blink/web_tests/http/tests/hid/hid_requestDevice.html similarity index 85% rename from third_party/blink/web_tests/hid/hid_requestDevice.html rename to third_party/blink/web_tests/http/tests/hid/hid_requestDevice.html index 1c09732..8e62859b 100644 --- a/third_party/blink/web_tests/hid/hid_requestDevice.html +++ b/third_party/blink/web_tests/http/tests/hid/hid_requestDevice.html
@@ -1,14 +1,12 @@ <!DOCTYPE html> <body> -<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="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/services/device/public/mojom/hid.mojom.js"></script> -<script src="file:///gen/third_party/blink/public/mojom/hid/hid.mojom.js"></script> -<script src="resources/hid-test-utils.js"></script> -<script> +<script type="module"> +import '../resources/testharness.js'; +import '../resources/testharnessreport.js'; + +import {hid_test, trustedClick} from './resources/hid-test-utils.js'; + +import {HidService} from '/gen/third_party/blink/public/mojom/hid/hid.mojom.m.js'; const kTestVendorId = 0x1234; const kTestProductId = 0xabcd; @@ -19,8 +17,7 @@ }, 'requestDevice() rejects without a user gesture'); promise_test(async (t) => { - let interceptor = - new MojoInterfaceInterceptor(blink.mojom.HidService.name); + let interceptor = new MojoInterfaceInterceptor(HidService.$interfaceName); interceptor.oninterfacerequest = e => e.handle.close(); interceptor.start();
diff --git a/third_party/blink/web_tests/hid/resources/hid-test-utils.js b/third_party/blink/web_tests/http/tests/hid/resources/hid-test-utils.js similarity index 86% rename from third_party/blink/web_tests/hid/resources/hid-test-utils.js rename to third_party/blink/web_tests/http/tests/hid/resources/hid-test-utils.js index f1338b6..c5733f9 100644 --- a/third_party/blink/web_tests/hid/resources/hid-test-utils.js +++ b/third_party/blink/web_tests/http/tests/hid/resources/hid-test-utils.js
@@ -1,5 +1,13 @@ +import '/resources/testdriver.js'; +import '/resources/testdriver-vendor.js'; +import '/resources/testharness.js'; +import '/resources/testharnessreport.js'; + +import {HidConnection, HidConnectionReceiver, HidDeviceInfo, HidManagerClientRemote} from '/gen/services/device/public/mojom/hid.mojom.m.js'; +import {HidService, HidServiceReceiver} from '/gen/third_party/blink/public/mojom/hid/hid.mojom.m.js'; + // Compare two DataViews byte-by-byte. -function compareDataViews(actual, expected) { +export function compareDataViews(actual, expected) { assert_true(actual instanceof DataView, 'actual is DataView'); assert_true(expected instanceof DataView, 'expected is DataView'); assert_equals(actual.byteLength, expected.byteLength, 'lengths equal'); @@ -10,8 +18,8 @@ } // Returns a Promise that resolves once |device| receives an input report. -function oninputreport(device) { - assert_true(device instanceof HIDDevice) +export function oninputreport(device) { + assert_true(device instanceof HIDDevice); return new Promise(resolve => { device.oninputreport = resolve; }); } @@ -21,15 +29,14 @@ class FakeHidConnection { constructor(client) { this.client_ = client; + this.receiver_ = new HidConnectionReceiver(this); this.expectedWrites_ = []; this.expectedGetFeatureReports_ = []; this.expectedSendFeatureReports_ = []; } - bind(request) { - assert_equals(this.binding, undefined); - this.binding = new mojo.Binding(device.mojom.HidConnection, this, request); - this.binding.setConnectionErrorHandler(() => { this.binding = undefined; }); + bindNewPipeAndPassRemote() { + return this.receiver_.$.bindNewPipeAndPassRemote(); } // Simulate an input report sent from the device to the host. The connection @@ -46,8 +53,8 @@ // parameters of the next write call must match |reportId| and |buffer|. queueExpectedWrite(success, reportId, reportData) { this.expectedWrites_.push({ - params: { reportId: reportId, data: reportData }, - result: { success: success }, + params: {reportId, data: reportData}, + result: {success}, }); } @@ -56,8 +63,8 @@ // The parameter of the next getFeatureReport call must match |reportId|. queueExpectedGetFeatureReport(success, reportId, reportData) { this.expectedGetFeatureReports_.push({ - params: { reportId: reportId, }, - result: { success: success, buffer: reportData }, + params: {reportId}, + result: {success, buffer: reportData}, }); } @@ -67,8 +74,8 @@ // |buffer|. queueExpectedSendFeatureReport(success, reportId, reportData) { this.expectedSendFeatureReports_.push({ - params: { reportId: reportId, data: reportData }, - result: { success: success }, + params: {reportId, data: reportData}, + result: {success}, }); } @@ -79,6 +86,8 @@ assert_equals(this.expectedSendFeatureReports_.length, 0); } + read() {} + // Implementation of HidConnection::Write. Causes an assertion failure if // there are no expected write operations, or if the parameters do not match // the expected call. @@ -133,10 +142,9 @@ // granted permission. class FakeHidService { constructor() { - this.interceptor_ = - new MojoInterfaceInterceptor(blink.mojom.HidService.name); + this.interceptor_ = new MojoInterfaceInterceptor(HidService.$interfaceName); this.interceptor_.oninterfacerequest = e => this.bind(e.handle); - this.bindingSet_ = new mojo.BindingSet(blink.mojom.HidService); + this.receiver_ = new HidServiceReceiver(this); this.nextGuidValue_ = 0; this.reset(); } @@ -159,7 +167,7 @@ // Creates and returns a HidDeviceInfo with the specified device IDs. makeDevice(vendorId, productId) { let guidValue = ++this.nextGuidValue_; - let info = new device.mojom.HidDeviceInfo(); + let info = new HidDeviceInfo(); info.guid = 'guid-' + guidValue.toString(); info.physicalDeviceId = 'physical-device-id-' + guidValue.toString(); info.vendorId = vendorId; @@ -214,11 +222,11 @@ } bind(handle) { - this.bindingSet_.addBinding(this, handle); + this.receiver_.$.bindHandle(handle); } registerClient(client) { - this.client_ = new device.mojom.HidManagerClientAssociatedPtr(client); + this.client_ = client; } // Returns an array of connected devices. Normally this would only include @@ -229,30 +237,28 @@ this.devices_.forEach((value) => { devices = devices.concat(value); }); - return { devices: devices }; + return {devices}; } // Simulates a device chooser prompt, returning |selectedDevices_| as the // simulated selection. |filters| is ignored. async requestDevice(filters) { - return { devices: this.selectedDevices_ }; + return {devices: this.selectedDevices_}; } // Returns a fake connection to the device with the specified GUID. If // |connectionClient| is not null, its onInputReport method will be called // when input reports are received. async connect(guid, connectionClient) { - let fakeConnection = new FakeHidConnection(connectionClient); - let connectionPtr = new device.mojom.HidConnectionPtr(); - fakeConnection.bind(mojo.makeRequest(connectionPtr)); + const fakeConnection = new FakeHidConnection(connectionClient); this.fakeConnections_.set(guid, fakeConnection); - return { connection: connectionPtr }; + return {connection: fakeConnection.bindNewPipeAndPassRemote()}; } } let fakeHidService = new FakeHidService(); -function hid_test(func, name, properties) { +export function hid_test(func, name, properties) { promise_test(async (test) => { fakeHidService.start(); try { @@ -264,7 +270,7 @@ }, name, properties); } -function trustedClick() { +export function trustedClick() { return new Promise(resolve => { let button = document.createElement('button'); button.textContent = 'click to continue test';
diff --git a/third_party/blink/web_tests/plugins/embed-src-change-usecounter.html b/third_party/blink/web_tests/plugins/embed-src-change-usecounter.html new file mode 100644 index 0000000..771ed59 --- /dev/null +++ b/third_party/blink/web_tests/plugins/embed-src-change-usecounter.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<embed id=embedid src="../http/tests/resources/test.mp4"> + +<script> +test(() => { + embedid.src = '../http/tests/resources/test.webm'; + assert_true(internals.isUseCounted(document, 3745)); +}, 'Verifies that changing embed src gets use counted.'); +</script>
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt index 493dd253..d7c52ed2 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
@@ -42,6 +42,8 @@ PASS window.cached_navigator_mediaSession.playbackState is 'none' PASS window.cached_navigator_presentation.defaultRequest is null PASS window.cached_navigator_presentation.receiver is null +PASS window.cached_navigator_serial.onconnect is null +PASS window.cached_navigator_serial.ondisconnect is null PASS window.cached_navigator_serviceWorker.controller is null PASS window.cached_navigator_serviceWorker.oncontrollerchange is null PASS window.cached_navigator_serviceWorker.onmessage is null
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt index e2c76e8..463e454 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
@@ -42,6 +42,8 @@ PASS window.cached_navigator_mediaSession.playbackState is 'none' PASS window.cached_navigator_presentation.defaultRequest is null PASS window.cached_navigator_presentation.receiver is null +PASS window.cached_navigator_serial.onconnect is null +PASS window.cached_navigator_serial.ondisconnect is null PASS window.cached_navigator_serviceWorker.controller is null PASS window.cached_navigator_serviceWorker.oncontrollerchange is null PASS window.cached_navigator_serviceWorker.onmessage is null
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt index b8d1facc..350b91e 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
@@ -42,6 +42,8 @@ PASS window.cached_navigator_mediaSession.playbackState is 'none' PASS window.cached_navigator_presentation.defaultRequest is null PASS window.cached_navigator_presentation.receiver is null +PASS window.cached_navigator_serial.onconnect is null +PASS window.cached_navigator_serial.ondisconnect is null PASS window.cached_navigator_serviceWorker.controller is null PASS window.cached_navigator_serviceWorker.oncontrollerchange is null PASS window.cached_navigator_serviceWorker.onmessage is null
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt index 77c9e4ec..e8c74642 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -48,6 +48,8 @@ PASS oldChildWindow.navigator.presentation.receiver is newChildWindow.navigator.presentation.receiver PASS oldChildWindow.navigator.product is newChildWindow.navigator.product PASS oldChildWindow.navigator.productSub is newChildWindow.navigator.productSub +PASS oldChildWindow.navigator.serial.onconnect is newChildWindow.navigator.serial.onconnect +PASS oldChildWindow.navigator.serial.ondisconnect is newChildWindow.navigator.serial.ondisconnect PASS oldChildWindow.navigator.serviceWorker.controller is newChildWindow.navigator.serviceWorker.controller PASS oldChildWindow.navigator.serviceWorker.oncontrollerchange is newChildWindow.navigator.serviceWorker.oncontrollerchange PASS oldChildWindow.navigator.serviceWorker.onmessage is newChildWindow.navigator.serviceWorker.onmessage
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt index 9b14739..c0da977 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt
@@ -35,6 +35,7 @@ picture-in-picture publickey-credentials-get screen-wake-lock +serial sync-xhr usb xr-spatial-tracking
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 58e9629c..1142718 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1116,6 +1116,28 @@ [Worker] getter statusCode [Worker] getter violatedDirective [Worker] method constructor +[Worker] interface Serial : EventTarget +[Worker] attribute @@toStringTag +[Worker] getter onconnect +[Worker] getter ondisconnect +[Worker] method constructor +[Worker] method getPorts +[Worker] setter onconnect +[Worker] setter ondisconnect +[Worker] interface SerialPort : EventTarget +[Worker] attribute @@toStringTag +[Worker] getter onconnect +[Worker] getter ondisconnect +[Worker] getter readable +[Worker] getter writable +[Worker] method close +[Worker] method constructor +[Worker] method getInfo +[Worker] method getSignals +[Worker] method open +[Worker] method setSignals +[Worker] setter onconnect +[Worker] setter ondisconnect [Worker] interface ServiceWorkerRegistration : EventTarget [Worker] attribute @@toStringTag [Worker] getter active @@ -2745,6 +2767,7 @@ [Worker] getter permissions [Worker] getter platform [Worker] getter product +[Worker] getter serial [Worker] getter storage [Worker] getter usb [Worker] getter userAgent
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 1d964008..31af8656 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -4599,6 +4599,7 @@ getter product getter productSub getter scheduling + getter serial getter serviceWorker getter storage getter usb @@ -6999,6 +7000,29 @@ attribute @@toStringTag getter error method constructor +interface Serial : EventTarget + attribute @@toStringTag + getter onconnect + getter ondisconnect + method constructor + method getPorts + method requestPort + setter onconnect + setter ondisconnect +interface SerialPort : EventTarget + attribute @@toStringTag + getter onconnect + getter ondisconnect + getter readable + getter writable + method close + method constructor + method getInfo + method getSignals + method open + method setSignals + setter onconnect + setter ondisconnect interface ServiceWorker : EventTarget attribute @@toStringTag getter onerror
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn index fab8905..17cf9cda 100644 --- a/third_party/boringssl/BUILD.gn +++ b/third_party/boringssl/BUILD.gn
@@ -96,7 +96,9 @@ } else if (current_cpu == "arm64") { if (is_linux || is_chromeos || is_android) { sources += crypto_sources_linux_aarch64 - } else if (is_ios) { + } else if (is_apple) { + # TODO(davidben): Rename all the file lists, etc., upstream from mac + # and ios to apple. sources += crypto_sources_ios_aarch64 } else { public_configs = [ ":no_asm_config" ]
diff --git a/third_party/libgav1/BUILD.gn b/third_party/libgav1/BUILD.gn index 85add2a09..e4d870b 100644 --- a/third_party/libgav1/BUILD.gn +++ b/third_party/libgav1/BUILD.gn
@@ -66,6 +66,7 @@ public_configs = [ ":public_libgav1_config" ] sources = gav1_dsp_sources + gav1_dsp_headers_sources + sources += gav1_dsp_avx2_sources + gav1_dsp_avx2_headers_sources } # SSE4 sources are split to their own target as Chrome is currently built @@ -83,7 +84,7 @@ } sources = gav1_dsp_sse4_sources + gav1_dsp_sse4_headers_sources + - gav1_dsp_headers_sources + gav1_dsp_headers_sources + gav1_dsp_avx2_headers_sources } static_library("libgav1") {
diff --git a/third_party/libgav1/README.chromium b/third_party/libgav1/README.chromium index 3cd0bda..8004e1e 100644 --- a/third_party/libgav1/README.chromium +++ b/third_party/libgav1/README.chromium
@@ -2,9 +2,9 @@ Short Name: libgav1 URL: https://chromium.googlesource.com/codecs/libgav1/ Version: 0 -Date: Saturday August 22 2020 +Date: Wednesday January 06 2021 Branch: master -Commit: a9449e612bc251b4271bbe1e3a0d12e9809bf74c +Commit: a5ee0e00923c355ef3aad2b2829365a9fde84430 License: Apache 2.0 License File: libgav1/LICENSE Security Critical: yes
diff --git a/third_party/libgav1/generate_libgav1_src_gni.go b/third_party/libgav1/generate_libgav1_src_gni.go index e84d6bb7..ef6c044 100644 --- a/third_party/libgav1/generate_libgav1_src_gni.go +++ b/third_party/libgav1/generate_libgav1_src_gni.go
@@ -34,10 +34,17 @@ for _, file := range files { if file.IsDir() { paths = append(paths, getCppFiles(filepath.Join(dir, file.Name()))...) + continue } ext := filepath.Ext(file.Name()) if ext == ".cc" || ext == ".h" { - paths = append(paths, filepath.Join(dir, file.Name())) + isTestFile, err := filepath.Match("*_test.*", file.Name()) + if err != nil { + panic(err) + } + if !isTestFile { + paths = append(paths, filepath.Join(dir, file.Name())) + } } } return paths @@ -102,7 +109,7 @@ for _, d := range topDirs { if strings.HasPrefix(f, d) { var bd string - for _, asm := range []string{"sse4"} { + for _, asm := range []string{"sse4", "avx2"} { pattern := "*_" + asm + "*" if match, err := filepath.Match(pattern, filepath.Base(f)); err != nil { panic(err)
diff --git a/third_party/libgav1/libgav1_srcs.gni b/third_party/libgav1/libgav1_srcs.gni index 92ba942..6ac5fef 100644 --- a/third_party/libgav1/libgav1_srcs.gni +++ b/third_party/libgav1/libgav1_srcs.gni
@@ -84,6 +84,18 @@ "//third_party/libgav1/src/src/dsp/weight_mask.cc", ] +gav1_dsp_avx2_sources = [ + "//third_party/libgav1/src/src/dsp/x86/convolve_avx2.cc", + "//third_party/libgav1/src/src/dsp/x86/loop_restoration_10bit_avx2.cc", + "//third_party/libgav1/src/src/dsp/x86/loop_restoration_avx2.cc", +] + +gav1_dsp_avx2_headers_sources = [ + "//third_party/libgav1/src/src/dsp/x86/common_avx2.h", + "//third_party/libgav1/src/src/dsp/x86/convolve_avx2.h", + "//third_party/libgav1/src/src/dsp/x86/loop_restoration_avx2.h", +] + gav1_dsp_headers_sources = [ "//third_party/libgav1/src/src/dsp/arm/average_blend_neon.h", "//third_party/libgav1/src/src/dsp/arm/cdef_neon.h", @@ -131,12 +143,14 @@ "//third_party/libgav1/src/src/dsp/x86/cdef_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/convolve_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/distance_weighted_blend_sse4.cc", + "//third_party/libgav1/src/src/dsp/x86/film_grain_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/intra_edge_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/intrapred_cfl_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/intrapred_smooth_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/intrapred_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/inverse_transform_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/loop_filter_sse4.cc", + "//third_party/libgav1/src/src/dsp/x86/loop_restoration_10bit_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/loop_restoration_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/mask_blend_sse4.cc", "//third_party/libgav1/src/src/dsp/x86/motion_field_projection_sse4.cc", @@ -153,6 +167,7 @@ "//third_party/libgav1/src/src/dsp/x86/common_sse4.h", "//third_party/libgav1/src/src/dsp/x86/convolve_sse4.h", "//third_party/libgav1/src/src/dsp/x86/distance_weighted_blend_sse4.h", + "//third_party/libgav1/src/src/dsp/x86/film_grain_sse4.h", "//third_party/libgav1/src/src/dsp/x86/intra_edge_sse4.h", "//third_party/libgav1/src/src/dsp/x86/intrapred_sse4.h", "//third_party/libgav1/src/src/dsp/x86/inverse_transform_sse4.h",
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index c73dd1d..8fc5f5a 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -994,6 +994,7 @@ 'linux-perfetto-rel': 'perfetto_release_trybot', 'linux-rel': 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange_code_coverage', 'linux-rel-builderful': 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange_code_coverage', + 'linux-rts': 'release_trybot_rts', 'linux-trusty-rel': 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange', 'linux-viz-rel': 'release_trybot', 'linux-warmed': 'release_trybot_no_symbols_use_dummy_lastchange_code_coverage', @@ -2592,6 +2593,10 @@ 'no_goma', ], + 'release_trybot_rts': [ + 'release_bot', 'rts_bot', + ], + 'tsan_disable_nacl_debug_bot': [ 'tsan', 'disable_nacl', 'debug_bot', ], @@ -3238,6 +3243,10 @@ 'gn_args': 'enable_resource_allowlist_generation=true', }, + 'rts_bot': { + 'gn_args': 'rts_exclude_file="//testing/rts_exclude_file.txt"', + }, + 'shared': { 'gn_args': 'is_component_build=true', },
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json index f58bdfc..b786fde6 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
@@ -554,6 +554,14 @@ "use_goma": true } }, + "linux-rts": { + "gn_args": { + "is_component_build": false, + "is_debug": false, + "rts_exclude_file": "//testing/rts_exclude_file.txt", + "use_goma": true + } + }, "linux-trusty-rel": { "gn_args": { "dcheck_always_on": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index dddd234e..27e293f 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -16721,6 +16721,7 @@ <int value="0" label="Drag and drop"/> <int value="1" label="Move-window-to-desk keyboard shortcut"/> <int value="2" label="Send to desk menu"/> + <int value="3" label="Assign to desk menu"/> </enum> <enum name="DesksSwitchSource"> @@ -30754,6 +30755,7 @@ <int value="3742" label="CrossOriginSubframeWithoutEmbeddingControl"/> <int value="3743" label="ReadableStreamWithByteSource"/> <int value="3744" label="ReadableStreamBYOBReader"/> + <int value="3745" label="EmbedElementWithoutTypeSrcChanged"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -66758,7 +66760,6 @@ <int value="6" label="SYNC_UPDATE_SUCCESS"/> <int value="7" label="SYNC_UPDATE_CONVERTED_TO_ADD"/> <int value="8" label="MIGRATE_SAFE_FOR_AUTOREPLACE_PLAY_API_ENGINE"/> - <int value="9" label="MIGRATE_SAFE_FOR_AUTOREPLACE_RESET_UNDERSCORE_KEYWORD"/> </enum> <enum name="SearchWidgetUseInfo"> @@ -74324,6 +74325,19 @@ <int value="15" label="Automatic translation, by user preference"/> </enum> +<enum name="TranslateUIInteraction"> + <int value="0" label="Uninitialized"/> + <int value="1" label="Translate page"/> + <int value="2" label="Revert translation"/> + <int value="3" label="Always translate language"/> + <int value="4" label="Change source language"/> + <int value="5" label="Change target language"/> + <int value="6" label="Never translate language"/> + <int value="7" label="Never translate site"/> + <int value="8" label="Close UI explicitly"/> + <int value="9" label="Close UI by lost focus"/> +</enum> + <enum name="TrendingTileEvent"> <int value="0" label="Tile was shown"/> <int value="1" label="Tile was removed"/>
diff --git a/tools/metrics/histograms/histograms_xml/crostini/histograms.xml b/tools/metrics/histograms/histograms_xml/crostini/histograms.xml index f841a65..347a2d8 100644 --- a/tools/metrics/histograms/histograms_xml/crostini/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/crostini/histograms.xml
@@ -35,7 +35,7 @@ </variants> <histogram name="Crostini.AppLaunch" enum="CrostiniAppLaunchAppType" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -45,7 +45,7 @@ </histogram> <histogram name="Crostini.AppLaunchResult" enum="CrostiniResult" - expires_after="2021-05-30"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -54,7 +54,7 @@ </histogram> <histogram name="Crostini.AppsInstalledAtLogin" units="apps" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -65,7 +65,7 @@ </histogram> <histogram name="Crostini.AvailableDiskCancel" units="MiB" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -77,7 +77,7 @@ </histogram> <histogram name="Crostini.AvailableDiskError" units="MiB" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -89,7 +89,7 @@ </histogram> <histogram name="Crostini.AvailableDiskSuccess" units="MiB" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -101,14 +101,14 @@ </histogram> <histogram name="Crostini.Backup" enum="CrostiniExportContainerResult" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary>Result of crostini backup.</summary> </histogram> <histogram name="Crostini.BackupCompressedSizeLog2" units="units" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -119,7 +119,7 @@ </histogram> <histogram name="Crostini.BackupContainerSizeLog2" units="units" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -130,7 +130,7 @@ </histogram> <histogram name="Crostini.BackupSizeRatio" units="units" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -140,21 +140,21 @@ </histogram> <histogram name="Crostini.BackupTimeFailed" units="ms" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary>Time taken for failed backup.</summary> </histogram> <histogram name="Crostini.BackupTimeSuccess" units="ms" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary>Time taken for successful backup.</summary> </histogram> <histogram name="Crostini.CleanSession.RestarterResult" enum="CrostiniResult" - expires_after="2021-06-13"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -165,7 +165,7 @@ </histogram> <histogram name="Crostini.ContainerOsVersion" enum="CrostiniContainerOsVersion" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -175,7 +175,7 @@ </histogram> <histogram name="Crostini.Crosvm.CpuPercentage" units="%" - expires_after="2021-06-20"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -186,7 +186,7 @@ </histogram> <histogram name="Crostini.Crosvm.Processes.Count" units="processes" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -196,7 +196,7 @@ </histogram> <histogram name="Crostini.Crosvm.RssPercentage" units="%" - expires_after="2021-06-13"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -207,7 +207,7 @@ </histogram> <histogram name="Crostini.DiskResize.Result" enum="CrostiniDiskImageStatus" - expires_after="2021-05-30"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>davidmunro@google.com</owner> <summary> @@ -217,7 +217,7 @@ </histogram> <histogram name="Crostini.DiskResize.Started" enum="BooleanAttempted" - expires_after="2021-05-30"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>davidmunro@google.com</owner> <summary> @@ -229,7 +229,7 @@ </histogram> <histogram name="Crostini.DiskType" enum="CrostiniDiskImageType" - expires_after="2021-03-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>davidmunro@google.com</owner> <summary> @@ -242,7 +242,7 @@ </histogram> <histogram name="Crostini.EngagementTime.{Variant}" units="ms" - expires_after="2021-04-18"> + expires_after="2022-01-06"> <owner>davidmunro@google.com</owner> <owner>clumptini@google.com</owner> <summary> @@ -274,7 +274,7 @@ </histogram> <histogram name="Crostini.FilesystemCorruption" enum="CorruptionStates" - expires_after="2021-06-13"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -284,7 +284,7 @@ </histogram> <histogram name="Crostini.InvalidStateTransition" enum="CrostiniInstallerState" - expires_after="2021-04-04"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -297,7 +297,7 @@ </histogram> <histogram name="Crostini.RecoverySource" enum="CrostiniUISurface" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -307,7 +307,7 @@ </histogram> <histogram name="Crostini.Restarter.Started" enum="BooleanAttempted" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -317,7 +317,7 @@ </histogram> <histogram name="Crostini.RestarterResult" enum="CrostiniResult" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -327,7 +327,7 @@ </histogram> <histogram name="Crostini.RestarterTimeInState.{state}" units="ms" - expires_after="2021-05-16"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -340,28 +340,28 @@ </histogram> <histogram name="Crostini.Restore" enum="CrostiniImportContainerResult" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary>Result of crostini restore.</summary> </histogram> <histogram name="Crostini.RestoreTimeFailed" units="ms" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary>Time taken for failed restore.</summary> </histogram> <histogram name="Crostini.RestoreTimeSuccess" units="ms" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary>Time taken for successful restore.</summary> </histogram> <histogram name="Crostini.SettingsEvent" enum="CrostiniSettingsEvent" - expires_after="2021-04-18"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <owner>victorhsieh@chromium.org</owner> @@ -369,7 +369,7 @@ </histogram> <histogram name="Crostini.Setup.Started" enum="BooleanAttempted" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -379,7 +379,7 @@ </histogram> <histogram name="Crostini.SetupResult" enum="CrostiniSetupResult" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -389,7 +389,7 @@ </histogram> <histogram name="Crostini.SetupSource" enum="CrostiniUISurface" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -399,7 +399,7 @@ </histogram> <histogram name="Crostini.Stability" enum="GuestOsFailureClasses" - expires_after="2021-06-09"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -410,7 +410,7 @@ </histogram> <histogram name="Crostini.TerminalSettingsChanged" - enum="CrostiniTerminalSetting" expires_after="2021-03-31"> + enum="CrostiniTerminalSetting" expires_after="2022-01-06"> <owner>joelhockey@chromium.org</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -422,7 +422,7 @@ </histogram> <histogram name="Crostini.TimeFromDeviceSetupToInstall" units="ms" - expires_after="2021-06-20"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -431,7 +431,7 @@ </histogram> <histogram name="Crostini.TimeToInstallCancel" units="ms" - expires_after="2021-06-20"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -442,7 +442,7 @@ </histogram> <histogram name="Crostini.TimeToInstallError" units="ms" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -454,7 +454,7 @@ </histogram> <histogram name="Crostini.TimeToInstallSuccess" units="ms" - expires_after="2021-05-16"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -465,7 +465,7 @@ </histogram> <histogram name="Crostini.UncleanSession.RestarterResult" enum="CrostiniResult" - expires_after="2021-06-27"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -476,7 +476,7 @@ </histogram> <histogram name="Crostini.UninstallResult" enum="CrostiniUninstallResult" - expires_after="2021-06-06"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -486,7 +486,7 @@ </histogram> <histogram name="Crostini.UninstallSource" enum="CrostiniUISurface" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -496,7 +496,7 @@ </histogram> <histogram base="true" name="Crostini.UnsupportedNotification.Reason" - enum="CrostiniUnsupportedNotificationReason" expires_after="2021-01-31"> + enum="CrostiniUnsupportedNotificationReason" expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -508,7 +508,7 @@ <histogram name="Crostini.UpgradeAvailable" enum="CrostiniUpgradeAvailableNotificationClosed" - expires_after="2021-07-15"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -518,7 +518,7 @@ </histogram> <histogram name="Crostini.UpgradeDialogEvent" enum="CrostiniUpgradeDialogEvent" - expires_after="2021-05-09"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary> @@ -528,7 +528,7 @@ </histogram> <histogram name="Crostini.UpgradeSource" enum="CrostiniUISurface" - expires_after="2021-01-31"> + expires_after="2022-01-06"> <owner>clumptini@google.com</owner> <owner>tbuckley@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml index e3ac3c5..b7b66e30 100644 --- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -8205,8 +8205,6 @@ </suffix> <suffix name="FeedJournalDatabase" label="Database for Feed journal storage."/> - <suffix name="FeedKeyValueDatabase" - label="Database for key value cache used in feed rendering."/> <suffix name="FeedStorageDatabase" label="Databases for Feed Storage."> <obsolete> Deprecated since 08/18.
diff --git a/tools/metrics/histograms/histograms_xml/interstitial/histograms.xml b/tools/metrics/histograms/histograms_xml/interstitial/histograms.xml index ce22312..81d402bc 100644 --- a/tools/metrics/histograms/histograms_xml/interstitial/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/interstitial/histograms.xml
@@ -30,7 +30,7 @@ </histogram> <histogram name="interstitial.decision" enum="SecurityInterstitialDecision" - expires_after="M89"> + expires_after="M94"> <owner>estark@chromium.org</owner> <owner>carlosil@chromium.org</owner> <summary> @@ -42,7 +42,7 @@ </histogram> <histogram name="interstitial.decision.repeat_visit" - enum="SecurityInterstitialDecision" expires_after="M89"> + enum="SecurityInterstitialDecision" expires_after="M94"> <owner>felt@chromium.org</owner> <owner>carlosil@chromium.org</owner> <summary> @@ -55,7 +55,7 @@ </histogram> <histogram name="interstitial.interaction" - enum="SecurityInterstitialInteraction" expires_after="M89"> + enum="SecurityInterstitialInteraction" expires_after="M94"> <owner>estark@chromium.org</owner> <owner>carlosil@chromium.org</owner> <summary> @@ -96,7 +96,7 @@ </histogram> <histogram name="interstitial.ssl.cause.overridable" enum="SSLErrorCauses" - expires_after="M89"> + expires_after="M94"> <owner>estark@chromium.org</owner> <owner>carlosil@chromium.org</owner> <summary> @@ -142,8 +142,9 @@ </histogram> <histogram name="interstitial.ssl.did_user_revoke_decisions2" - enum="BooleanRevoked" expires_after="M89"> + enum="BooleanRevoked" expires_after="M94"> <owner>carlosil@chromium.org</owner> + <owner>security-enamel@chromium.org</owner> <summary> Specifies when a user enters the page info menu whether or not the user pressed the SSL decisions revoke button. This is logged when the page info @@ -161,7 +162,7 @@ </histogram> <histogram name="interstitial.ssl_error_handler" enum="SSLErrorHandlerEvent" - expires_after="M89"> + expires_after="M94"> <owner>meacer@chromium.org</owner> <owner>carlosil@chromium.org</owner> <owner>estark@chromium.org</owner> @@ -184,7 +185,7 @@ </histogram> <histogram name="interstitial.ssl_error_type" enum="SSLErrorTypes" - expires_after="M89"> + expires_after="M94"> <owner>estark@chromium.org</owner> <owner>carlosil@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/media/histograms.xml b/tools/metrics/histograms/histograms_xml/media/histograms.xml index 319e46d..18c3da7a 100644 --- a/tools/metrics/histograms/histograms_xml/media/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/media/histograms.xml
@@ -3589,7 +3589,7 @@ </histogram> <histogram name="Media.VAJDA.ResponseToClient" - enum="MjpegDecodeAcceleratorErrorCode" expires_after="2020-03-21"> + enum="MjpegDecodeAcceleratorErrorCode" expires_after="2022-01-07"> <owner>andrescj@chromium.org</owner> <owner>chromeos-gfx@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/navigation/histograms.xml b/tools/metrics/histograms/histograms_xml/navigation/histograms.xml index 88dbf0c..72ec02b 100644 --- a/tools/metrics/histograms/histograms_xml/navigation/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/navigation/histograms.xml
@@ -619,7 +619,7 @@ </summary> </histogram> -<histogram name="Navigation.EngagementTime.HTTP" units="ms" expires_after="M89"> +<histogram name="Navigation.EngagementTime.HTTP" units="ms" expires_after="M94"> <owner>estark@chromium.org</owner> <owner>security-enamel@chromium.org</owner> <summary> @@ -629,7 +629,7 @@ </histogram> <histogram name="Navigation.EngagementTime.HTTPS" units="ms" - expires_after="M89"> + expires_after="M94"> <owner>estark@chromium.org</owner> <owner>security-enamel@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml b/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml index a278c9e4..a2870393 100644 --- a/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml
@@ -336,7 +336,7 @@ </summary> </histogram> -<histogram name="Omnibox.HoverTime" units="ms" expires_after="M88"> +<histogram name="Omnibox.HoverTime" units="ms" expires_after="M94"> <owner>estark@chromium.org</owner> <owner>carlosil@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/printing/histograms.xml b/tools/metrics/histograms/histograms_xml/printing/histograms.xml index a64f5af5..37e1f65 100644 --- a/tools/metrics/histograms/histograms_xml/printing/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/printing/histograms.xml
@@ -350,6 +350,9 @@ <histogram name="Printing.CUPS.ValidPpdReference" enum="BooleanSuccess" expires_after="2020-08-01"> + <obsolete> + Data no longer needed. Bug is resolved. 2020-12. + </obsolete> <owner>skau@chromium.org</owner> <owner>luum@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/security/histograms.xml b/tools/metrics/histograms/histograms_xml/security/histograms.xml index 8f67c0e..b564ae3 100644 --- a/tools/metrics/histograms/histograms_xml/security/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/security/histograms.xml
@@ -544,7 +544,7 @@ </histogram> <histogram name="Security.SecurityLevel.InsecureMainFrameFormSubmission" - enum="SecurityLevel" expires_after="M89"> + enum="SecurityLevel" expires_after="M94"> <owner>estark@chromium.org</owner> <owner>livvielin@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/tab/histograms.xml b/tools/metrics/histograms/histograms_xml/tab/histograms.xml index 9d77af9c..5702aef 100644 --- a/tools/metrics/histograms/histograms_xml/tab/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/tab/histograms.xml
@@ -1505,7 +1505,7 @@ </histogram> <histogram name="Tabs.SadTab.Feedback.Event" enum="SadTabEvent" - expires_after="M85"> + expires_after="2021-06-01"> <owner>sonnyrao@chromium.org</owner> <owner>jamescook@chromium.org</owner> <summary> @@ -1599,7 +1599,7 @@ </histogram> <histogram name="Tabs.SadTab.Reload.Event" enum="SadTabEvent" - expires_after="M85"> + expires_after="2021-06-01"> <owner>sonnyrao@chromium.org</owner> <owner>jamescook@chromium.org</owner> <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 2b21554..f7df7d0 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -13373,6 +13373,154 @@ <metric name="TargetLanguage" semantic_type="ST_DEMOGRAPHIC_INFO"/> </event> +<event name="TranslatePageLoad"> + <owner>curranmax@chromium.org</owner> + <owner>megjablon@chromium.org</owner> + <owner>chrome-language@google.com</owner> + <summary> + Summary of the user's interaction with Translate from the beginning of the + page load to when the event is recorded. This event is recorded when a page + load is completed and every time that Chrome is backgrounded during the + course of the page load. This means we can record multiple events for a + single page load, but it guarentees that we will still record data in + instances where the user backgrounds then kills Chrome. + </summary> + <metric name="FinalSourceLanguage" semantic_type="ST_DEMOGRAPHIC_INFO" + enum="CLD3LanguageCode"> + <summary> + The source language at the time the event is recorded. In most cases this + will match the intial source language, but the user can change the source + language manually if they want. Note that the semantic_type attribute is + included in order to remain consistent with the previous Translate UKM + proto. + </summary> + </metric> + <metric name="FinalState" enum="TranslateState"> + <summary> + At the time this event is recorded, the state of Translate. This includes + whether the page is translated or not and if no UI is shown, just the + omnibox icon is shown, or the full translate UI is shown. + </summary> + </metric> + <metric name="FinalTargetLanguage" semantic_type="ST_DEMOGRAPHIC_INFO" + enum="CLD3LanguageCode"> + <summary> + The target language at the time the event is recorded. In most cases this + will match the initial target language, but the user can change the target + language manually if they want. Note that the semantic_type attribute is + included in order to remain consistent with the previous Translate UKM + proto. + </summary> + </metric> + <metric name="FirstTranslateError" enum="TranslateError"> + <summary> + The first error to occur within Translate for this page load. + </summary> + </metric> + <metric name="FirstUIInteraction" enum="TranslateUIInteraction"> + <summary> + The user's first interaction with the Translate UI. + </summary> + </metric> + <metric name="InitialSourceLanguage" semantic_type="ST_DEMOGRAPHIC_INFO" + enum="CLD3LanguageCode"> + <summary> + The initial source language that Translate determines for the page. Note + that the semantic_type attribute is included in order to remain consistent + with the previous Translate UKM proto. + </summary> + </metric> + <metric name="InitialSourceLanguageInContentLanguages" enum="Boolean"> + <summary> + Signals whether the initial source language is in the list of the user's + content languages. The user's content languages loosely match with the + languages the user has translated to before or has blocked for + translation. + </summary> + </metric> + <metric name="InitialState" enum="TranslateState"> + <summary> + At the beginning of the page load, the state of Translate. This includes + whether the page is translated or not and if no UI is shown, just the + omnibox icon is shown, or the full translate UI is shown. + </summary> + </metric> + <metric name="InitialTargetLanguage" semantic_type="ST_DEMOGRAPHIC_INFO" + enum="CLD3LanguageCode"> + <summary> + The initial target language that Translate thinks it should translate to. + Note that the semantic_type attribute is included in order to remain + consistent with the previous Translate UKM proto. + </summary> + </metric> + <metric name="MaxTimeToTranslate"> + <summary> + Across all translations during this page load, the maximum amount of time + (in milliseconds) it took to translate the page. + </summary> + </metric> + <metric name="NumReversions"> + <summary> + The number of times a translation was reverted. + </summary> + </metric> + <metric name="NumTargetLanguageChanges"> + <summary> + The number of times that the target language was changed by the user over + the course of this page load. + </summary> + </metric> + <metric name="NumTranslateErrors"> + <summary> + The number of errors to occur within Translate for this page load. + </summary> + </metric> + <metric name="NumTranslations"> + <summary> + The number of times the page was translated. + </summary> + </metric> + <metric name="NumUIInteractions"> + <summary> + The number of times that the user interacts with the Translate UI. + </summary> + </metric> + <metric name="RankerDecision" enum="TranslateRankerDecision"> + <summary> + Decision of the Ranker whether to show the UI or not. + </summary> + </metric> + <metric name="RankerVersion"> + <summary> + Version of Ranker used for this page load. + </summary> + </metric> + <metric name="SequenceNumber"> + <summary> + In case multiple events are logged for one page load, we track the + sequence in the order each event is logged. + </summary> + </metric> + <metric name="TotalTimeNotTranslated"> + <summary> + The amount of time (in seconds) this page was in the foreground and not + translated. + </summary> + </metric> + <metric name="TotalTimeTranslated"> + <summary> + The amount of time (in seconds) this page was in the foreground and + translated. + </summary> + </metric> + <metric name="TriggerDecision" enum="TranslateTriggerDecision"> + <summary> + The highest priority trigger that determined the initial state of + Translate for this page load. + </summary> + </metric> +</event> + <event name="TrustedWebActivity.Open" singular="True"> <owner>peconn@chromium.org</owner> <summary>
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py index 1c35c5f..4e8cb9a 100644 --- a/tools/perf/benchmarks/benchmark_smoke_unittest.py +++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -101,11 +101,12 @@ # The list of benchmark names to be excluded from our smoke tests. _BLACK_LIST_TEST_NAMES = [ 'memory.long_running_idle_gmail_background_tbmv2', - 'tab_search', # crbug.com/1159462 + 'tab_search', # crbug.com/1159462 'tab_switching.typical_25', 'UNSCHEDULED_oortonline_tbmv2', 'webrtc', # crbug.com/932036 - 'v8.runtime_stats.top_25' # Fails in Windows, crbug.com/1043048 + 'v8.runtime_stats.top_25', # Fails in Windows, crbug.com/1043048 + 'UNSCHEDULED_blink_perf.webgpu_fast_call', # crbug.com/1164115 ]
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index d6474d43..44c516f 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -697,8 +697,8 @@ 'platform': 'linux', 'dimension': { - 'gpu': '10de:1cb3-384.90', - 'os': 'Ubuntu-14.04', + 'gpu': '10de:1cb3-440.100', + 'os': 'Ubuntu-18.04', 'pool': 'chrome.tests.perf', 'synthetic_product_name': 'PowerEdge R230 (Dell Inc.)' },
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 8fa635d..b371e75 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": "dd34e440b0a4d39037a1d2b3ed76eb75a67932b5", - "remote_path": "perfetto_binaries/trace_processor_shell/win/5ff758df67da94d17734c2e70eb6738c4902953e/trace_processor_shell.exe" + "hash": "e966ca8bd8894222cc224f0256aa5b32aef94669", + "remote_path": "perfetto_binaries/trace_processor_shell/win/070ef598892aee3d5cfb628f577867217c863142/trace_processor_shell.exe" }, "mac": { - "hash": "dd8bde783d9cb141102961446d65f755560432cb", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/5ff758df67da94d17734c2e70eb6738c4902953e/trace_processor_shell" + "hash": "e714905178b25795c55a9468c15a3aa0a4038d47", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/070ef598892aee3d5cfb628f577867217c863142/trace_processor_shell" }, "linux": { - "hash": "11280ccdc5bb43e61153805c87207334f12c39f7", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/603d14ec2a266fdcf4734d1d42605e2d317e48d8/trace_processor_shell" + "hash": "153bdd7d922d3d225b8c2855de063cf00ff59efa", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/070ef598892aee3d5cfb628f577867217c863142/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 8e310dd..7d86df1 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -217,7 +217,7 @@ <item id="open_search" added_in_milestone="62" hash_code="107267424" type="0" content_hash_code="83025542" os_list="linux,windows" file_path="components/search_engines/template_url_fetcher.cc"/> <item id="openscreen_message" added_in_milestone="83" hash_code="23036184" type="0" content_hash_code="124395439" os_list="linux,windows" file_path="components/openscreen_platform/udp_socket.cc"/> <item id="openscreen_tls_message" added_in_milestone="83" hash_code="40127335" type="0" content_hash_code="15991338" os_list="linux,windows" file_path="components/openscreen_platform/tls_connection_factory.cc"/> - <item id="optimization_guide_model" added_in_milestone="79" hash_code="106373593" type="0" content_hash_code="32403047" os_list="linux,windows" file_path="chrome/browser/optimization_guide/prediction/prediction_model_fetcher.cc"/> + <item id="optimization_guide_model" added_in_milestone="79" hash_code="106373593" type="0" content_hash_code="32403047" os_list="linux,windows" file_path="components/optimization_guide/core/prediction_model_fetcher.cc"/> <item id="optimization_guide_model_download" added_in_milestone="88" hash_code="100143055" type="0" content_hash_code="97983899" os_list="linux,windows" file_path="chrome/browser/optimization_guide/prediction/prediction_model_download_manager.cc"/> <item id="origin_policy_loader" added_in_milestone="69" hash_code="6483617" type="0" content_hash_code="134028975" os_list="linux,windows" file_path="services/network/origin_policy/origin_policy_fetcher.cc"/> <item id="parallel_download_job" added_in_milestone="62" hash_code="135118587" type="0" content_hash_code="105330419" os_list="linux,windows" file_path="components/download/internal/common/parallel_download_job.cc"/>
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc index 75108ad..ca98973 100644 --- a/ui/aura/client/aura_constants.cc +++ b/ui/aura/client/aura_constants.cc
@@ -75,6 +75,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSkipImeProcessing, false) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(base::string16, kTitleKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(int, kTopViewInset, 0) +DEFINE_UI_CLASS_PROPERTY_KEY(bool, kVisibleOnAllWorkspacesKey, false) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kWindowIconKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowCornerRadiusKey, -1) DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowWorkspaceKey, kUnassignedWorkspace)
diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h index eb22477..bb97f9b 100644 --- a/ui/aura/client/aura_constants.h +++ b/ui/aura/client/aura_constants.h
@@ -154,6 +154,9 @@ // the web contents for app windows and varies for fullscreen windows. AURA_EXPORT extern const WindowProperty<int>* const kTopViewInset; +// A property key to store whether this window is visible on all workspaces. +AURA_EXPORT extern const WindowProperty<bool>* const kVisibleOnAllWorkspacesKey; + // A property key to store the window icon, typically 16x16 for title bars. AURA_EXPORT extern const WindowProperty<gfx::ImageSkia*>* const kWindowIconKey;
diff --git a/ui/base/ime/chromeos/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc index 7a62712c..9bc9912 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.cc +++ b/ui/base/ime/chromeos/input_method_chromeos.cc
@@ -501,8 +501,7 @@ if (client != GetTextInputClient()) return dispatch_details; - if (HasInputMethodResult()) - ProcessInputMethodResult(event, handled); + MaybeProcessPendingInputMethodResult(event, handled); // In case the focus was changed when sending input method results to the // focused window. @@ -564,8 +563,9 @@ return details; } -void InputMethodChromeOS::ProcessInputMethodResult(ui::KeyEvent* event, - bool handled) { +void InputMethodChromeOS::MaybeProcessPendingInputMethodResult( + ui::KeyEvent* event, + bool handled) { TextInputClient* client = GetTextInputClient(); DCHECK(client); @@ -621,10 +621,6 @@ (!composing_text_ && result_text_.length() == 1)); } -bool InputMethodChromeOS::HasInputMethodResult() const { - return result_text_.length() || composition_changed_; -} - void InputMethodChromeOS::CommitText(const std::string& text) { if (text.empty()) return;
diff --git a/ui/base/ime/chromeos/input_method_chromeos.h b/ui/base/ime/chromeos/input_method_chromeos.h index 90e836c..2805383 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.h +++ b/ui/base/ime/chromeos/input_method_chromeos.h
@@ -122,9 +122,9 @@ ui::EventDispatchDetails ProcessUnfilteredKeyPressEvent(ui::KeyEvent* event) WARN_UNUSED_RESULT; - // Sends input method result caused by the given key event to the focused text - // input client. - void ProcessInputMethodResult(ui::KeyEvent* event, bool filtered); + // Processes any pending input method operations that issued while handling + // the key event. Does not do anything if there were no pending operations. + void MaybeProcessPendingInputMethodResult(ui::KeyEvent* event, bool filtered); // Checks if the pending input method result needs inserting into the focused // text input client as a single character.
diff --git a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc index 24f53cc..4bf8a8d 100644 --- a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc +++ b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
@@ -1175,6 +1175,20 @@ EXPECT_FALSE(input_method_manager_->state()->is_jp_ime()); } +TEST_F(InputMethodChromeOSKeyEventTest, SetAutocorrectRangeRunsAfterKeyEvent) { + input_type_ = TEXT_INPUT_TYPE_TEXT; + ime_->OnTextInputTypeChanged(this); + ime_->CommitText("a"); + + ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); + ime_->DispatchKeyEvent(&event); + ime_->SetAutocorrectRange(gfx::Range(0, 1)); + std::move(mock_ime_engine_handler_->last_passed_callback()) + .Run(/*handled=*/true); + + EXPECT_EQ(gfx::Range(0, 1), GetAutocorrectRange()); +} + TEST_F(InputMethodChromeOSKeyEventTest, SetAutocorrectRangeRunsAfterCommitText) { input_type_ = TEXT_INPUT_TYPE_TEXT;
diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc index e500dee..f2815ed 100644 --- a/ui/base/x/selection_owner.cc +++ b/ui/base/x/selection_owner.cc
@@ -164,7 +164,7 @@ } void SelectionOwner::OnSelectionClear(const x11::SelectionClearEvent& event) { - DLOG(ERROR) << "SelectionClear"; + DVLOG(1) << "SelectionClear"; // TODO(erg): If we receive a SelectionClear event while we're handling data, // we need to delay clearing.
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn index 890c3ae9..c36f3b2 100644 --- a/ui/compositor/BUILD.gn +++ b/ui/compositor/BUILD.gn
@@ -151,6 +151,8 @@ "test/test_suite.h", "test/test_utils.cc", "test/test_utils.h", + "test/throughput_report_checker.cc", + "test/throughput_report_checker.h", ] if (is_android) {
diff --git a/ui/compositor/animation_throughput_reporter_unittest.cc b/ui/compositor/animation_throughput_reporter_unittest.cc index e0ceb01..99f6b19 100644 --- a/ui/compositor/animation_throughput_reporter_unittest.cc +++ b/ui/compositor/animation_throughput_reporter_unittest.cc
@@ -15,6 +15,7 @@ #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/test/animation_throughput_reporter_test_base.h" +#include "ui/compositor/test/throughput_report_checker.h" #include "ui/gfx/geometry/rect.h" namespace ui { @@ -27,22 +28,18 @@ layer.SetOpacity(0.5f); root_layer()->Add(&layer); - base::RunLoop run_loop; + ThroughputReportChecker checker(this); { LayerAnimator* animator = layer.GetAnimator(); - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - run_loop.Quit(); - })); + AnimationThroughputReporter reporter(animator, + checker.repeating_callback()); ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(48)); layer.SetOpacity(1.0f); } // The animation starts in next frame (16ms) and ends 48 ms later. - Advance(base::TimeDelta::FromMilliseconds(64)); - run_loop.Run(); + EXPECT_TRUE(checker.WaitUntilReported()); } // Tests animation throughput collection with implicit animation setup before @@ -51,14 +48,11 @@ Layer layer; layer.SetOpacity(0.5f); - base::RunLoop run_loop; + ThroughputReportChecker checker(this); { LayerAnimator* animator = layer.GetAnimator(); - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - run_loop.Quit(); - })); + AnimationThroughputReporter reporter(animator, + checker.repeating_callback()); ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(48)); @@ -67,8 +61,7 @@ // Attach to root after animation setup. root_layer()->Add(&layer); - Advance(base::TimeDelta::FromMilliseconds(64)); - run_loop.Run(); + EXPECT_TRUE(checker.WaitUntilReported()); } // Tests animation throughput collection with explicitly created animation @@ -78,21 +71,15 @@ layer.SetOpacity(0.5f); root_layer()->Add(&layer); - base::RunLoop run_loop; - { - LayerAnimator* animator = layer.GetAnimator(); - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - run_loop.Quit(); - })); + ThroughputReportChecker checker(this); + LayerAnimator* animator = layer.GetAnimator(); + AnimationThroughputReporter reporter(animator, checker.repeating_callback()); - animator->ScheduleAnimation( - new LayerAnimationSequence(LayerAnimationElement::CreateOpacityElement( - 1.0f, base::TimeDelta::FromMilliseconds(48)))); - } - Advance(base::TimeDelta::FromMilliseconds(64)); - run_loop.Run(); + animator->ScheduleAnimation( + new LayerAnimationSequence(LayerAnimationElement::CreateOpacityElement( + 1.0f, base::TimeDelta::FromMilliseconds(48)))); + + EXPECT_TRUE(checker.WaitUntilReported()); } // Tests animation throughput collection for a persisted animator of a Layer. @@ -106,24 +93,18 @@ new LayerAnimator(base::TimeDelta::FromMilliseconds(48)); layer->SetAnimator(animator); - std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>(); // |reporter| keeps reporting as long as it is alive. - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - run_loop->Quit(); - })); + ThroughputReportChecker checker(this); + AnimationThroughputReporter reporter(animator, checker.repeating_callback()); // Report data for animation of opacity goes to 1. layer->SetOpacity(1.0f); - Advance(base::TimeDelta::FromMilliseconds(64)); - run_loop->Run(); + EXPECT_TRUE(checker.WaitUntilReported()); // Report data for animation of opacity goes to 0.5. - run_loop = std::make_unique<base::RunLoop>(); + checker.reset(); layer->SetOpacity(0.5f); - Advance(base::TimeDelta::FromMilliseconds(64)); - run_loop->Run(); + EXPECT_TRUE(checker.WaitUntilReported()); } // Tests animation throughput not reported when animation is aborted. @@ -132,13 +113,14 @@ layer->SetOpacity(0.5f); root_layer()->Add(layer.get()); + ThroughputReportChecker checker(this, /*fail_if_reported=*/true); + + // Reporter started monitoring animation, then deleted, which should be + // reported when the animation ends. { LayerAnimator* animator = layer->GetAnimator(); - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - ADD_FAILURE() << "No report for aborted animations."; - })); + AnimationThroughputReporter reporter(animator, + checker.repeating_callback()); ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(48)); @@ -150,6 +132,9 @@ // Wait a bit to ensure that report does not happen. Advance(base::TimeDelta::FromMilliseconds(100)); + + // TODO(crbug.com/1158510): Test the scenario where the report exists when the + // layer is removed. } // Tests no report and no leak when underlying layer is gone before reporter. @@ -158,13 +143,9 @@ layer->SetOpacity(0.5f); root_layer()->Add(layer.get()); + ThroughputReportChecker checker(this, /*fail_if_reported=*/true); LayerAnimator* animator = layer->GetAnimator(); - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - ADD_FAILURE() << "No report for aborted animations."; - })); - + AnimationThroughputReporter reporter(animator, checker.repeating_callback()); { ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(48)); @@ -184,14 +165,11 @@ layer->SetOpacity(0.5f); root_layer()->Add(layer.get()); + ThroughputReportChecker checker(this, /*fail_if_reported=*/true); { LayerAnimator* animator = layer->GetAnimator(); - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - ADD_FAILURE() << "No report for aborted animations."; - })); - + AnimationThroughputReporter reporter(animator, + checker.repeating_callback()); ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(48)); layer->SetOpacity(1.0f); @@ -211,16 +189,12 @@ auto layer = std::make_unique<Layer>(); layer->SetOpacity(0.5f); + ThroughputReportChecker checker(this, /*fail_if_reported=*/true); LayerAnimator* animator = layer->GetAnimator(); - // Schedule an animation without being attached to a root. { - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - ADD_FAILURE() << "No report for aborted animations."; - })); - + AnimationThroughputReporter reporter(animator, + checker.repeating_callback()); ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50)); layer->SetOpacity(1.0f); @@ -243,16 +217,12 @@ layer->SetBounds(gfx::Rect(0, 0, 1, 2)); root_layer()->Add(layer.get()); + ThroughputReportChecker checker(this, /*fail_if_reported=*/true); LayerAnimator* animator = layer->GetAnimator(); - // Schedule an animation that will be preempted. No report should happen. { - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - ADD_FAILURE() << "No report for aborted animations."; - })); - + AnimationThroughputReporter reporter(animator, + checker.repeating_callback()); ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(50)); layer->SetOpacity(0.5f); @@ -260,14 +230,10 @@ } // Animate to new target. Report should happen. - base::RunLoop run_loop; + ThroughputReportChecker checker2(this); { - AnimationThroughputReporter reporter( - animator, base::BindLambdaForTesting( - [&](const cc::FrameSequenceMetrics::CustomReportData&) { - run_loop.Quit(); - })); - + AnimationThroughputReporter reporter(animator, + checker2.repeating_callback()); ScopedLayerAnimationSettings settings(animator); settings.SetPreemptionStrategy( LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); @@ -275,8 +241,7 @@ layer->SetOpacity(1.0f); layer->SetBounds(gfx::Rect(0, 0, 5, 6)); } - Advance(base::TimeDelta::FromMilliseconds(64)); - run_loop.Run(); + EXPECT_TRUE(checker2.WaitUntilReported()); } } // namespace ui
diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc index c8aac298..d7b9d1d 100644 --- a/ui/compositor/layer_animation_element.cc +++ b/ui/compositor/layer_animation_element.cc
@@ -452,7 +452,7 @@ duration())); std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( std::move(animation_curve), keyframe_model_id(), animation_group_id(), - cc::TargetProperty::OPACITY)); + cc::KeyframeModel::TargetPropertyId(cc::TargetProperty::OPACITY))); return keyframe_model; } @@ -522,7 +522,7 @@ duration())); std::unique_ptr<cc::KeyframeModel> keyframe_model(cc::KeyframeModel::Create( std::move(animation_curve), keyframe_model_id(), animation_group_id(), - cc::TargetProperty::TRANSFORM)); + cc::KeyframeModel::TargetPropertyId(cc::TargetProperty::TRANSFORM))); return keyframe_model; }
diff --git a/ui/compositor/test/animation_throughput_reporter_test_base.cc b/ui/compositor/test/animation_throughput_reporter_test_base.cc index 31a24a5..dc796ee 100644 --- a/ui/compositor/test/animation_throughput_reporter_test_base.cc +++ b/ui/compositor/test/animation_throughput_reporter_test_base.cc
@@ -47,14 +47,14 @@ void AnimationThroughputReporterTestBase::Advance( const base::TimeDelta& delta) { -#if BUILDFLAG(IS_CHROMEOS_ASH) - task_environment_.FastForwardBy(delta); -#else - base::RunLoop run_loop; + run_loop_ = std::make_unique<base::RunLoop>(); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop.QuitClosure(), delta); - run_loop.Run(); -#endif + FROM_HERE, run_loop_->QuitClosure(), delta); + run_loop_->Run(); +} + +void AnimationThroughputReporterTestBase::QuitRunLoop() { + run_loop_->Quit(); } } // namespace ui
diff --git a/ui/compositor/test/animation_throughput_reporter_test_base.h b/ui/compositor/test/animation_throughput_reporter_test_base.h index f3dce44..e383325 100644 --- a/ui/compositor/test/animation_throughput_reporter_test_base.h +++ b/ui/compositor/test/animation_throughput_reporter_test_base.h
@@ -15,6 +15,10 @@ #include "ui/compositor/layer.h" #include "ui/compositor/test/test_compositor_host.h" +namespace base { +class RunLoop; +} + namespace ui { class TestContextFactories; @@ -39,13 +43,11 @@ // Advances the time by |delta|. void Advance(const base::TimeDelta& delta); + void QuitRunLoop(); + private: base::test::TaskEnvironment task_environment_{ -#if BUILDFLAG(IS_CHROMEOS_ASH) - base::test::TaskEnvironment::TimeSource::MOCK_TIME, -#endif - base::test::TaskEnvironment::MainThreadType::UI - }; + base::test::TaskEnvironment::MainThreadType::UI}; std::unique_ptr<TestContextFactories> context_factories_; std::unique_ptr<TestCompositorHost> host_; @@ -54,6 +56,8 @@ // A timer to generate continuous compositor frames to trigger throughput // data being transferred back. base::RepeatingTimer frame_generation_timer_; + + std::unique_ptr<base::RunLoop> run_loop_; }; } // namespace ui
diff --git a/ui/compositor/test/throughput_report_checker.cc b/ui/compositor/test/throughput_report_checker.cc new file mode 100644 index 0000000..5559b7d7 --- /dev/null +++ b/ui/compositor/test/throughput_report_checker.cc
@@ -0,0 +1,26 @@ +// 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/throughput_report_checker.h" + +#include "base/time/time.h" +#include "ui/compositor/test/animation_throughput_reporter_test_base.h" + +namespace ui { + +bool ThroughputReportChecker::WaitUntilReported() { + DCHECK(!reported_); + test_base_->Advance(base::TimeDelta::FromSeconds(5)); + return reported_; +} + +void ThroughputReportChecker::OnReport( + const cc::FrameSequenceMetrics::CustomReportData&) { + reported_ = true; + if (fail_if_reported_) + ADD_FAILURE() << "It should not be reported."; + test_base_->QuitRunLoop(); +} + +} // namespace ui
diff --git a/ui/compositor/test/throughput_report_checker.h b/ui/compositor/test/throughput_report_checker.h new file mode 100644 index 0000000..c7837a7 --- /dev/null +++ b/ui/compositor/test/throughput_report_checker.h
@@ -0,0 +1,58 @@ +// 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_THROUGHPUT_REPORT_CHECKER_H_ +#define UI_COMPOSITOR_TEST_THROUGHPUT_REPORT_CHECKER_H_ + +#include <memory> + +#include "base/bind.h" +#include "cc/metrics/frame_sequence_metrics.h" + +namespace ui { +class AnimationThroughputReporterTestBase; + +class ThroughputReportChecker { + public: + using ReportRepeatingCallback = base::RepeatingCallback<void( + const cc::FrameSequenceMetrics::CustomReportData&)>; + using ReportOnceCallback = base::OnceCallback<void( + const cc::FrameSequenceMetrics::CustomReportData&)>; + + explicit ThroughputReportChecker( + AnimationThroughputReporterTestBase* test_base, + bool fail_if_reported = false) + : test_base_(test_base), fail_if_reported_(fail_if_reported) {} + ThroughputReportChecker(const ThroughputReportChecker&) = delete; + ThroughputReportChecker& operator=(const ThroughputReportChecker&) = delete; + ~ThroughputReportChecker() = default; + + bool reported() const { return reported_; } + + void reset() { reported_ = false; } + + ReportRepeatingCallback repeating_callback() { + return base::BindRepeating(&ThroughputReportChecker::OnReport, + base::Unretained(this)); + } + ReportOnceCallback once_callback() { + return base::BindOnce(&ThroughputReportChecker::OnReport, + base::Unretained(this)); + } + + // It waits until reported up to 5 seconds timeout. Returns true if it's + // reported. + bool WaitUntilReported(); + + private: + void OnReport(const cc::FrameSequenceMetrics::CustomReportData&); + + AnimationThroughputReporterTestBase* test_base_; + bool reported_ = false; + bool fail_if_reported_ = false; +}; + +} // namespace ui + +#endif // UI_COMPOSITOR_TEST_THROUGHPUT_REPORT_CHECKER_H_
diff --git a/ui/compositor/total_animation_throughput_reporter_unittest.cc b/ui/compositor/total_animation_throughput_reporter_unittest.cc index f24ec32..13589e4 100644 --- a/ui/compositor/total_animation_throughput_reporter_unittest.cc +++ b/ui/compositor/total_animation_throughput_reporter_unittest.cc
@@ -10,114 +10,47 @@ #include "base/test/bind.h" #include "base/time/time.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "cc/metrics/frame_sequence_metrics.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_sequence.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/test/animation_throughput_reporter_test_base.h" -#include "ui/gfx/geometry/rect.h" +#include "ui/compositor/test/throughput_report_checker.h" namespace ui { -namespace { - -class TestReporter : public TotalAnimationThroughputReporter { - public: - explicit TestReporter(AnimationThroughputReporterTestBase* test_base) - : ui::TotalAnimationThroughputReporter( - test_base->compositor(), - base::BindRepeating(&TestReporter::Reported, - base::Unretained(this))), - test_base_(test_base) {} - TestReporter(AnimationThroughputReporterTestBase* test_base, - bool should_delete) - : ui::TotalAnimationThroughputReporter( - test_base->compositor(), - base::BindOnce(&TestReporter::Reported, base::Unretained(this)), - should_delete), - test_base_(test_base) {} - - TestReporter(const TestReporter&) = delete; - TestReporter& operator=(const TestReporter&) = delete; - ~TestReporter() override = default; - - void AdvanceUntilReported(const base::TimeDelta& delta) { - DCHECK(!reported_); - test_base_->Advance(delta); -#if !BUILDFLAG(IS_CHROMEOS_ASH) - // Non ash-chrome platform uses native event loop which doesn't work well - // with mock time, so we still need to run the event loop. - if (!reported_) { - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - } -#endif - } - - bool reported() const { return reported_; } - - void reset() { reported_ = false; } - - private: - void Reported(const cc::FrameSequenceMetrics::CustomReportData&) { - reported_ = true; -#if !BUILDFLAG(IS_CHROMEOS_ASH) - if (run_loop_) - run_loop_->Quit(); -#endif - } - - AnimationThroughputReporterTestBase* test_base_; - bool reported_ = false; -#if !BUILDFLAG(IS_CHROMEOS_ASH) - std::unique_ptr<base::RunLoop> run_loop_; -#endif -}; - -} // namespace using TotalAnimationThroughputReporterTest = AnimationThroughputReporterTestBase; -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_SingleAnimation DISABLED_SingleAnimation -#else -#define MAYBE_SingleAnimation SingleAnimation -#endif -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_SingleAnimation) { +TEST_F(TotalAnimationThroughputReporterTest, SingleAnimation) { Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); { LayerAnimator* animator = layer.GetAnimator(); - ScopedLayerAnimationSettings settings(animator); settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(48)); layer.SetOpacity(1.0f); } Advance(base::TimeDelta::FromMilliseconds(32)); - EXPECT_FALSE(reporter.reported()); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(32)); - EXPECT_TRUE(reporter.reported()); + EXPECT_FALSE(checker.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_StopAnimation DISABLED_StopAnimation -#else -#define MAYBE_StopAnimation StopAnimation -#endif // Tests the stopping last animation will trigger the animation. -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_StopAnimation) { +TEST_F(TotalAnimationThroughputReporterTest, StopAnimation) { Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); { LayerAnimator* animator = layer.GetAnimator(); @@ -126,10 +59,9 @@ layer.SetOpacity(1.0f); } Advance(base::TimeDelta::FromMilliseconds(32)); - EXPECT_FALSE(reporter.reported()); + EXPECT_FALSE(checker.reported()); layer.GetAnimator()->StopAnimating(); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(32)); - EXPECT_TRUE(reporter.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } // Tests the longest animation will trigger the report. @@ -138,7 +70,9 @@ layer1.SetOpacity(0.5f); root_layer()->Add(&layer1); - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); { LayerAnimator* animator = layer1.GetAnimator(); @@ -159,29 +93,22 @@ } Advance(base::TimeDelta::FromMilliseconds(32)); - EXPECT_FALSE(reporter.reported()); + EXPECT_FALSE(checker.reported()); Advance(base::TimeDelta::FromMilliseconds(32)); - EXPECT_FALSE(reporter.reported()); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(200)); - EXPECT_TRUE(reporter.reported()); + EXPECT_FALSE(checker.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_MultipleAnimationsOnSingleLayer \ - DISABLED_MultipleAnimationsOnSingleLayer -#else -#define MAYBE_MultipleAnimationsOnSingleLayer MultipleAnimationsOnSingleLayer -#endif // Tests the longest animation on a single layer will triger the report. -TEST_F(TotalAnimationThroughputReporterTest, - MAYBE_MultipleAnimationsOnSingleLayer) { +TEST_F(TotalAnimationThroughputReporterTest, MultipleAnimationsOnSingleLayer) { Layer layer; layer.SetOpacity(0.5f); layer.SetLayerBrightness(0.5f); root_layer()->Add(&layer); - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); { LayerAnimator* animator = layer.GetAnimator(); @@ -198,24 +125,19 @@ } Advance(base::TimeDelta::FromMilliseconds(64)); - EXPECT_FALSE(reporter.reported()); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(48)); - EXPECT_TRUE(reporter.reported()); + EXPECT_FALSE(checker.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_AddAnimationWhileAnimating DISABLED_AddAnimationWhileAnimating -#else -#define MAYBE_AddAnimationWhileAnimating AddAnimationWhileAnimating -#endif // Tests adding new animation will extends the duration. -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_AddAnimationWhileAnimating) { +TEST_F(TotalAnimationThroughputReporterTest, AddAnimationWhileAnimating) { Layer layer1; layer1.SetOpacity(0.5f); root_layer()->Add(&layer1); - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); { LayerAnimator* animator = layer1.GetAnimator(); @@ -225,7 +147,7 @@ } Advance(base::TimeDelta::FromMilliseconds(32)); - EXPECT_FALSE(reporter.reported()); + EXPECT_FALSE(checker.reported()); // Add new animation while animating. Layer layer2; @@ -242,25 +164,20 @@ // The animation time is extended. Advance(base::TimeDelta::FromMilliseconds(32)); - EXPECT_FALSE(reporter.reported()); + EXPECT_FALSE(checker.reported()); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(32)); - EXPECT_TRUE(reporter.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_RemoveWhileAnimating DISABLED_RemoveWhileAnimating -#else -#define MAYBE_RemoveWhileAnimating RemoveWhileAnimating -#endif // Tests removing last animation will call report callback. -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_RemoveWhileAnimating) { +TEST_F(TotalAnimationThroughputReporterTest, RemoveWhileAnimating) { auto layer1 = std::make_unique<Layer>(); layer1->SetOpacity(0.5f); root_layer()->Add(layer1.get()); - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); { LayerAnimator* animator = layer1->GetAnimator(); @@ -281,22 +198,15 @@ layer2.SetOpacity(1.0f); } Advance(base::TimeDelta::FromMilliseconds(48)); - EXPECT_FALSE(reporter.reported()); + EXPECT_FALSE(checker.reported()); layer1.reset(); // Aborting will be processed in next frame. - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(16)); - EXPECT_TRUE(reporter.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_StartWhileAnimating DISABLED_StartWhileAnimating -#else -#define MAYBE_StartWhileAnimating StartWhileAnimating -#endif // Make sure the reporter can start measuring even if the animation // has started. -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_StartWhileAnimating) { +TEST_F(TotalAnimationThroughputReporterTest, StartWhileAnimating) { Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); @@ -309,20 +219,15 @@ layer.SetOpacity(1.0f); } Advance(base::TimeDelta::FromMilliseconds(32)); - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); EXPECT_TRUE(reporter.IsMeasuringForTesting()); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(100)); - EXPECT_TRUE(reporter.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_PersistedAnimation DISABLED_PersistedAnimation -#else -#define MAYBE_PersistedAnimation PersistedAnimation -#endif // Tests the reporter is called multiple times for persistent animation. -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_PersistedAnimation) { +TEST_F(TotalAnimationThroughputReporterTest, PersistedAnimation) { Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); @@ -333,28 +238,22 @@ layer.SetAnimator(animator); // |reporter| keeps reporting as long as it is alive. - TestReporter reporter(this); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter(compositor(), + checker.repeating_callback()); // Report data for animation of opacity goes to 1. layer.SetOpacity(1.0f); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(100)); - EXPECT_TRUE(reporter.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); // Report data for animation of opacity goes to 0.5. - reporter.reset(); + checker.reset(); layer.SetOpacity(0.5f); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(100)); - EXPECT_TRUE(reporter.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_OnceReporter DISABLED_OnceReporter -#else -#define MAYBE_OnceReporter OnceReporter -#endif // Make sure the once reporter is called only once. -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_OnceReporter) { +TEST_F(TotalAnimationThroughputReporterTest, OnceReporter) { Layer layer; layer.SetOpacity(0.5f); root_layer()->Add(&layer); @@ -364,29 +263,24 @@ new LayerAnimator(base::TimeDelta::FromMilliseconds(32)); layer.SetAnimator(animator); - TestReporter reporter(this, /*should_delete=*/false); + ThroughputReportChecker checker(this); + TotalAnimationThroughputReporter reporter( + compositor(), checker.once_callback(), /*should_delete=*/false); // Report data for animation of opacity goes to 1. layer.SetOpacity(1.0f); - reporter.AdvanceUntilReported(base::TimeDelta::FromMilliseconds(100)); - EXPECT_TRUE(reporter.reported()); + EXPECT_TRUE(checker.WaitUntilReported()); // Report data for animation of opacity goes to 0.5. - reporter.reset(); + checker.reset(); layer.SetOpacity(1.0f); Advance(base::TimeDelta::FromMilliseconds(100)); - EXPECT_FALSE(reporter.reported()); + EXPECT_FALSE(checker.reported()); } -// Flaky on ChromeOS: crbug.com/1157649 -#if defined(OS_CHROMEOS) -#define MAYBE_OnceReporterShouldDelete DISABLED_OnceReporterShouldDelete -#else -#define MAYBE_OnceReporterShouldDelete OnceReporterShouldDelete -#endif // One reporter marked as "should_delete" should be deleted when // reported. -TEST_F(TotalAnimationThroughputReporterTest, MAYBE_OnceReporterShouldDelete) { +TEST_F(TotalAnimationThroughputReporterTest, OnceReporterShouldDelete) { class DeleteTestReporter : public TotalAnimationThroughputReporter { public: DeleteTestReporter(Compositor* compositor, @@ -425,14 +319,7 @@ // Report data for animation of opacity goes to 1. layer.SetOpacity(1.0f); -#if BUILDFLAG(IS_CHROMEOS_ASH) - Advance(base::TimeDelta::FromMilliseconds(48)); - EXPECT_FALSE(run_loop.running()); -#else - // Non ash-chrome platform uses native event loop which doesn't work - // with mock time, so we need to run more the event loop. run_loop.Run(); -#endif EXPECT_TRUE(deleted); }
diff --git a/ui/file_manager/externs/background/file_browser_background_full.js b/ui/file_manager/externs/background/file_browser_background_full.js index e8c2e7d..efa0f34e 100644 --- a/ui/file_manager/externs/background/file_browser_background_full.js +++ b/ui/file_manager/externs/background/file_browser_background_full.js
@@ -80,4 +80,21 @@ * @param {boolean} enable */ forceFileOperationErrorForTest(enable) {} + + /** + * Registers a dialog (file picker or save as) in the background page. + * Dialogs are opened by the browser directly and should register themselves + * in the background page. + * @param {!Window} window + */ + registerDialog(window) {} + + /** + * Launches a new File Manager window. + * + * @param {Object=} opt_appState App state. + * @return {!Promise<chrome.app.window.AppWindow|string>} Resolved with the + * App ID. + */ + async launchFileManager(opt_appState) {} }
diff --git a/ui/file_manager/externs/background_window.js b/ui/file_manager/externs/background_window.js index 81f424d..410d8fce 100644 --- a/ui/file_manager/externs/background_window.js +++ b/ui/file_manager/externs/background_window.js
@@ -19,14 +19,5 @@ * @type {!BackgroundBase} */ this.background; - - /** - * @type {!Object} - */ - this.launcher = {}; } - /** - * @param {Window} window - */ - registerDialog(window) {} }
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js index 3cf30a8..6f4aa4d 100644 --- a/ui/file_manager/file_manager/background/js/background.js +++ b/ui/file_manager/file_manager/background/js/background.js
@@ -184,6 +184,33 @@ } /** + * Registers dialog window to the background page. + * + * @param {!Window} dialogWindow Window of the dialog. + */ + registerDialog(dialogWindow) { + const id = DIALOG_ID_PREFIX + (nextFileManagerDialogID++); + this.dialogs[id] = dialogWindow; + if (window.IN_TEST) { + dialogWindow.IN_TEST = true; + } + dialogWindow.addEventListener('pagehide', () => { + delete this.dialogs[id]; + }); + } + + /** + * Launches a new File Manager window. + * + * @param {Object=} opt_appState App state. + * @return {!Promise<chrome.app.window.AppWindow|string>} Resolved with the + * App ID. + */ + async launchFileManager(opt_appState) { + return launcher.launchFileManager(opt_appState); + } + + /** * Opens the volume root (or opt directoryPath) in main UI. * * @param {!Event} event An event with the volumeId or @@ -553,21 +580,6 @@ */ let nextFileManagerDialogID = 0; -/** - * Registers dialog window to the background page. - * - * @param {!Window} dialogWindow Window of the dialog. - */ -/* #export */ function registerDialog(dialogWindow) { - const id = DIALOG_ID_PREFIX + (nextFileManagerDialogID++); - window.background.dialogs[id] = dialogWindow; - if (window.IN_TEST) { - dialogWindow.IN_TEST = true; - } - dialogWindow.addEventListener('pagehide', () => { - delete window.background.dialogs[id]; - }); -} /** @const {!string} */ const GPLUS_PHOTOS_APP_ORIGIN = @@ -577,7 +589,8 @@ * Singleton instance of Background object. * @type {!FileBrowserBackgroundFull} */ -window.background = new FileBrowserBackgroundImpl(); +/* #export */ const background = new FileBrowserBackgroundImpl(); +window.background = background; /** * Lastly, end recording of the background page Load.BackgroundScript metric.
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index d19e849..1cff976 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -505,7 +505,7 @@ * @param {Object=} appState App state. */ launchFileManager(appState) { - this.backgroundPage_.launcher.launchFileManager(appState); + this.fileBrowserBackground_.launchFileManager(appState); } /** @@ -867,7 +867,7 @@ await new Promise(resolve => this.fileBrowserBackground_.ready(resolve)); loadTimeData.data = this.fileBrowserBackground_.stringData; if (util.runningInBrowser()) { - this.backgroundPage_.registerDialog(window); + this.fileBrowserBackground_.registerDialog(window); } this.fileOperationManager_ = this.fileBrowserBackground_.fileOperationManager;
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 31edd89c..ac195b3 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -51,8 +51,9 @@ "host/shell_object_factory.h", "host/shell_popup_wrapper.cc", "host/shell_popup_wrapper.h", - "host/shell_surface_wrapper.cc", "host/shell_surface_wrapper.h", + "host/shell_toplevel_wrapper.cc", + "host/shell_toplevel_wrapper.h", "host/wayland_auxiliary_window.cc", "host/wayland_auxiliary_window.h", "host/wayland_buffer_manager_connector.cc", @@ -138,6 +139,8 @@ "host/xdg_popup_wrapper_impl.h", "host/xdg_surface_wrapper_impl.cc", "host/xdg_surface_wrapper_impl.h", + "host/xdg_toplevel_wrapper_impl.cc", + "host/xdg_toplevel_wrapper_impl.h", "host/zwp_primary_selection_device.cc", "host/zwp_primary_selection_device.h", "host/zwp_primary_selection_device_manager.cc", @@ -147,6 +150,12 @@ "host/zwp_text_input_wrapper.h", "host/zwp_text_input_wrapper_v1.cc", "host/zwp_text_input_wrapper_v1.h", + "host/zxdg_popup_v6_wrapper_impl.cc", + "host/zxdg_popup_v6_wrapper_impl.h", + "host/zxdg_surface_v6_wrapper_impl.cc", + "host/zxdg_surface_v6_wrapper_impl.h", + "host/zxdg_toplevel_v6_wrapper_impl.cc", + "host/zxdg_toplevel_v6_wrapper_impl.h", "ozone_platform_wayland.cc", "ozone_platform_wayland.h", ]
diff --git a/ui/ozone/platform/wayland/host/shell_object_factory.cc b/ui/ozone/platform/wayland/host/shell_object_factory.cc index dea7148..ed7842b 100644 --- a/ui/ozone/platform/wayland/host/shell_object_factory.cc +++ b/ui/ozone/platform/wayland/host/shell_object_factory.cc
@@ -8,20 +8,37 @@ #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h" #include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h" +#include "ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h" +#include "ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.h" +#include "ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h" +#include "ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h" namespace ui { ShellObjectFactory::ShellObjectFactory() = default; ShellObjectFactory::~ShellObjectFactory() = default; -std::unique_ptr<ShellSurfaceWrapper> -ShellObjectFactory::CreateShellSurfaceWrapper(WaylandConnection* connection, - WaylandWindow* wayland_window) { - if (connection->shell() || connection->shell_v6()) { +std::unique_ptr<ShellToplevelWrapper> +ShellObjectFactory::CreateShellToplevelWrapper(WaylandConnection* connection, + WaylandWindow* wayland_window) { + if (connection->shell()) { auto surface = std::make_unique<XDGSurfaceWrapperImpl>(wayland_window, connection); - return surface->Initialize(true /* with_top_level */) ? std::move(surface) - : nullptr; + if (!surface->Initialize()) + return nullptr; + + auto toplevel = std::make_unique<XDGToplevelWrapperImpl>( + std::move(surface), wayland_window, connection); + return toplevel->Initialize() ? std::move(toplevel) : nullptr; + } else if (connection->shell_v6()) { + auto surface = + std::make_unique<ZXDGSurfaceV6WrapperImpl>(wayland_window, connection); + if (!surface->Initialize()) + return nullptr; + + auto toplevel = std::make_unique<ZXDGToplevelV6WrapperImpl>( + std::move(surface), wayland_window, connection); + return toplevel->Initialize() ? std::move(toplevel) : nullptr; } LOG(WARNING) << "Shell protocol is not available."; return nullptr; @@ -31,15 +48,24 @@ WaylandConnection* connection, WaylandWindow* wayland_window, const gfx::Rect& bounds) { - if (connection->shell() || connection->shell_v6()) { + if (connection->shell()) { auto surface = std::make_unique<XDGSurfaceWrapperImpl>(wayland_window, connection); - if (!surface->Initialize(false /* with_top_level */)) + if (!surface->Initialize()) return nullptr; auto popup = std::make_unique<XDGPopupWrapperImpl>(std::move(surface), wayland_window); return popup->Initialize(connection, bounds) ? std::move(popup) : nullptr; + } else if (connection->shell_v6()) { + auto surface = + std::make_unique<ZXDGSurfaceV6WrapperImpl>(wayland_window, connection); + if (!surface->Initialize()) + return nullptr; + + auto popup = std::make_unique<ZXDGPopupV6WrapperImpl>(std::move(surface), + wayland_window); + return popup->Initialize(connection, bounds) ? std::move(popup) : nullptr; } LOG(WARNING) << "Shell protocol is not available."; return nullptr;
diff --git a/ui/ozone/platform/wayland/host/shell_object_factory.h b/ui/ozone/platform/wayland/host/shell_object_factory.h index a915326c..da3472a 100644 --- a/ui/ozone/platform/wayland/host/shell_object_factory.h +++ b/ui/ozone/platform/wayland/host/shell_object_factory.h
@@ -13,7 +13,7 @@ namespace ui { -class ShellSurfaceWrapper; +class ShellToplevelWrapper; class ShellPopupWrapper; class WaylandConnection; class WaylandWindow; @@ -27,8 +27,8 @@ ShellObjectFactory(); ~ShellObjectFactory(); - // Creates and initializes a ShellSurfaceWrapper. - std::unique_ptr<ShellSurfaceWrapper> CreateShellSurfaceWrapper( + // Creates and initializes a ShellToplevelWrapper. + std::unique_ptr<ShellToplevelWrapper> CreateShellToplevelWrapper( WaylandConnection* connection, WaylandWindow* wayland_window); @@ -41,4 +41,4 @@ } // namespace ui -#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_OBJECT_FACTORY_H_ \ No newline at end of file +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_OBJECT_FACTORY_H_
diff --git a/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc b/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc index f9f5aaa..469d2b9 100644 --- a/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc +++ b/ui/ozone/platform/wayland/host/shell_popup_wrapper.cc
@@ -6,6 +6,10 @@ #include "base/check_op.h" #include "base/notreached.h" +#include "ui/ozone/platform/wayland/common/wayland_util.h" +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_event_source.h" +#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h" namespace ui { @@ -79,4 +83,117 @@ return anchor_rect; } +WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds) { + WlAnchor anchor = WlAnchor::None; + switch (menu_type) { + case MenuType::TYPE_RIGHT_CLICK: + anchor = WlAnchor::TopLeft; + break; + case MenuType::TYPE_3DOT_PARENT_MENU: + anchor = WlAnchor::BottomRight; + break; + case MenuType::TYPE_3DOT_CHILD_MENU: + // Chromium may want to manually position a child menu on the left side of + // its parent menu. Thus, react accordingly. Positive x means the child is + // located on the right side of the parent and negative - on the left + // side. + if (bounds.x() >= 0) + anchor = WlAnchor::TopRight; + else + anchor = WlAnchor::TopLeft; + break; + case MenuType::TYPE_UNKNOWN: + NOTREACHED() << "Unsupported menu type"; + break; + } + + return anchor; +} + +WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds) { + WlGravity gravity = WlGravity::None; + switch (menu_type) { + case MenuType::TYPE_RIGHT_CLICK: + gravity = WlGravity::BottomRight; + break; + case MenuType::TYPE_3DOT_PARENT_MENU: + gravity = WlGravity::BottomRight; + break; + case MenuType::TYPE_3DOT_CHILD_MENU: + // Chromium may want to manually position a child menu on the left side of + // its parent menu. Thus, react accordingly. Positive x means the child is + // located on the right side of the parent and negative - on the left + // side. + if (bounds.x() >= 0) + gravity = WlGravity::BottomRight; + else + gravity = WlGravity::BottomLeft; + break; + case MenuType::TYPE_UNKNOWN: + NOTREACHED() << "Unsupported menu type"; + break; + } + + return gravity; +} + +WlConstraintAdjustment GetConstraintAdjustment(MenuType menu_type) { + WlConstraintAdjustment constraint = WlConstraintAdjustment::None; + + switch (menu_type) { + case MenuType::TYPE_RIGHT_CLICK: + constraint = WlConstraintAdjustment::SlideX | + WlConstraintAdjustment::SlideY | + WlConstraintAdjustment::FlipY; + break; + case MenuType::TYPE_3DOT_PARENT_MENU: + constraint = + WlConstraintAdjustment::SlideX | WlConstraintAdjustment::FlipY; + break; + case MenuType::TYPE_3DOT_CHILD_MENU: + constraint = + WlConstraintAdjustment::SlideY | WlConstraintAdjustment::FlipX; + break; + case MenuType::TYPE_UNKNOWN: + NOTREACHED() << "Unsupported menu type"; + break; + } + + return constraint; +} + +MenuType ShellPopupWrapper::GetMenuTypeForPositioner( + WaylandConnection* connection, + WaylandWindow* parent_window) const { + bool is_right_click_menu = + connection->event_source()->last_pointer_button_pressed() & + EF_RIGHT_MOUSE_BUTTON; + + // Different types of menu require different anchors, constraint adjustments, + // gravity and etc. + if (is_right_click_menu) + return MenuType::TYPE_RIGHT_CLICK; + else if (!wl::IsMenuType(parent_window->type())) + return MenuType::TYPE_3DOT_PARENT_MENU; + else + return MenuType::TYPE_3DOT_CHILD_MENU; +} + +bool ShellPopupWrapper::CanGrabPopup(WaylandConnection* connection) const { + // When drag process starts, as described the protocol - + // https://goo.gl/1Mskq3, the client must have an active implicit grab. If + // we try to create a popup and grab it, it will be immediately dismissed. + // Thus, do not take explicit grab during drag process. + if (connection->IsDragInProgress() || !connection->seat()) + return false; + + // According to the definition of the xdg protocol, the grab request must be + // used in response to some sort of user action like a button press, key + // press, or touch down event. + EventType last_event_type = connection->event_serial().event_type; + return last_event_type == ET_TOUCH_PRESSED || + last_event_type == ET_KEY_PRESSED || + last_event_type == ET_MOUSE_PRESSED; +} + } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/shell_popup_wrapper.h b/ui/ozone/platform/wayland/host/shell_popup_wrapper.h index 2970549..14ca68a97 100644 --- a/ui/ozone/platform/wayland/host/shell_popup_wrapper.h +++ b/ui/ozone/platform/wayland/host/shell_popup_wrapper.h
@@ -11,6 +11,7 @@ namespace ui { class WaylandConnection; +class WaylandWindow; enum class MenuType { TYPE_RIGHT_CLICK, @@ -73,11 +74,18 @@ // Initializes the popup surface. virtual bool Initialize(WaylandConnection* connection, const gfx::Rect& bounds) = 0; + + MenuType GetMenuTypeForPositioner(WaylandConnection* connection, + WaylandWindow* parent_window) const; + bool CanGrabPopup(WaylandConnection* connection) const; }; gfx::Rect GetAnchorRect(MenuType menu_type, const gfx::Rect& menu_bounds, const gfx::Rect& parent_window_bounds); +WlAnchor GetAnchor(MenuType menu_type, const gfx::Rect& bounds); +WlGravity GetGravity(MenuType menu_type, const gfx::Rect& bounds); +WlConstraintAdjustment GetConstraintAdjustment(MenuType menu_type); } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/shell_surface_wrapper.h b/ui/ozone/platform/wayland/host/shell_surface_wrapper.h index ff5ab6c..de2dceb7 100644 --- a/ui/ozone/platform/wayland/host/shell_surface_wrapper.h +++ b/ui/ozone/platform/wayland/host/shell_surface_wrapper.h
@@ -5,90 +5,27 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_ #define UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_ -#include "base/strings/string16.h" -#include "ui/ozone/platform/wayland/common/wayland_object.h" - namespace gfx { class Rect; } namespace ui { -class WaylandConnection; - -enum class DecorationMode { - // Client-side decoration for a window. - // In this case, the client is responsible for drawing decorations - // for a window (e.g. caption bar, close button). This is suitable for - // windows using custom frame. - kClientSide = 1, - // Server-side decoration for a window. - // In this case, the ash window manager is responsible for drawing - // decorations. This is suitable for windows using native frame. - // e.g. taskmanager. - kServerSide -}; - -// Wrapper interface for different wayland shells shell versions. +// Wrapper interface for different wayland xdg-shell surface versions. class ShellSurfaceWrapper { public: virtual ~ShellSurfaceWrapper() {} - // Initializes the ShellSurface. Some protocols may require to create shell - // surface without toplevel role and assign a popup role to it later. - virtual bool Initialize(bool with_toplevel) = 0; - - // Sets a native window to maximized state. - virtual void SetMaximized() = 0; - - // Unsets a native window from maximized state. - virtual void UnSetMaximized() = 0; - - // Sets a native window to fullscreen state. - virtual void SetFullscreen() = 0; - - // Unsets a native window from fullscreen state. - virtual void UnSetFullscreen() = 0; - - // Sets a native window to minimized state. - virtual void SetMinimized() = 0; - - // Tells wayland to start interactive window drag. - virtual void SurfaceMove(WaylandConnection* connection) = 0; - - // Tells wayland to start interactive window resize. - virtual void SurfaceResize(WaylandConnection* connection, - uint32_t hittest) = 0; - - // Sets a title of a native window. - virtual void SetTitle(const base::string16& title) = 0; + // Initializes the ShellSurface. + virtual bool Initialize() = 0; // Sends acknowledge configure event back to wayland. virtual void AckConfigure() = 0; // Sets a desired window geometry once wayland requests client to do so. virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0; - - // Sets the minimum size for the top level. - virtual void SetMinSize(int32_t width, int32_t height) = 0; - - // Sets the maximum size for the top level. - virtual void SetMaxSize(int32_t width, int32_t height) = 0; - - // Sets an app id of the native window that is shown as an application name - // and hints the compositor that it can group application surfaces together by - // their app id. This also helps the compositor to identify application's - // .desktop file and use the icon set there. - virtual void SetAppId(const std::string& app_id) = 0; - - // In case of kClientSide or kServerSide, this function sends a - // request to the wayland compositor to update the decoration mode - // for a surface associated with this top level window. - virtual void SetDecoration(DecorationMode decoration) = 0; }; -bool CheckIfWlArrayHasValue(struct wl_array* wl_array, uint32_t value); - } // namespace ui #endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_SURFACE_WRAPPER_H_
diff --git a/ui/ozone/platform/wayland/host/shell_surface_wrapper.cc b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.cc similarity index 92% rename from ui/ozone/platform/wayland/host/shell_surface_wrapper.cc rename to ui/ozone/platform/wayland/host/shell_toplevel_wrapper.cc index ea7d3ca..e84d7ca 100644 --- a/ui/ozone/platform/wayland/host/shell_surface_wrapper.cc +++ b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.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/ozone/platform/wayland/host/shell_surface_wrapper.h" +#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h" namespace ui {
diff --git a/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h new file mode 100644 index 0000000..0352f48 --- /dev/null +++ b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h
@@ -0,0 +1,95 @@ +// Copyright 2021 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_OZONE_PLATFORM_WAYLAND_HOST_SHELL_TOPLEVEL_WRAPPER_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_TOPLEVEL_WRAPPER_H_ + +#include "base/strings/string16.h" +#include "ui/ozone/platform/wayland/common/wayland_object.h" + +namespace gfx { +class Rect; +} + +namespace ui { + +class WaylandConnection; + +// A wrapper around different versions of xdg toplevels. Allows +// WaylandToplevelWindow to set window-like properties such as maximize, +// fullscreen, and minimize, set application-specific metadata like title and +// id, as well as trigger user interactive operations such as interactive resize +// and move. +class ShellToplevelWrapper { + public: + enum class DecorationMode { + // Client-side decoration for a window. + // In this case, the client is responsible for drawing decorations + // for a window (e.g. caption bar, close button). This is suitable for + // windows using custom frame. + kClientSide = 1, + // Server-side decoration for a window. + // In this case, the ash window manager is responsible for drawing + // decorations. This is suitable for windows using native frame. + // e.g. taskmanager. + kServerSide + }; + + virtual ~ShellToplevelWrapper() = default; + + // Initializes the ShellToplevel. + virtual bool Initialize() = 0; + + // Sets a native window to maximized state. + virtual void SetMaximized() = 0; + + // Unsets a native window from maximized state. + virtual void UnSetMaximized() = 0; + + // Sets a native window to fullscreen state. + virtual void SetFullscreen() = 0; + + // Unsets a native window from fullscreen state. + virtual void UnSetFullscreen() = 0; + + // Sets a native window to minimized state. + virtual void SetMinimized() = 0; + + // Tells wayland to start interactive window drag. + virtual void SurfaceMove(WaylandConnection* connection) = 0; + + // Tells wayland to start interactive window resize. + virtual void SurfaceResize(WaylandConnection* connection, + uint32_t hittest) = 0; + + // Sets a title of a native window. + virtual void SetTitle(const base::string16& title) = 0; + + // Sets a desired window geometry once wayland requests client to do so. + virtual void SetWindowGeometry(const gfx::Rect& bounds) = 0; + + // Sets the minimum size for the top level. + virtual void SetMinSize(int32_t width, int32_t height) = 0; + + // Sets the maximum size for the top level. + virtual void SetMaxSize(int32_t width, int32_t height) = 0; + + // Sets an app id of the native window that is shown as an application name + // and hints the compositor that it can group application surfaces together by + // their app id. This also helps the compositor to identify application's + // .desktop file and use the icon set there. + virtual void SetAppId(const std::string& app_id) = 0; + + // In case of kClientSide or kServerSide, this function sends a request to the + // wayland compositor to update the decoration mode for a surface associated + // with this top level window. + virtual void SetDecoration(DecorationMode decoration) = 0; +}; + +// Look for |value| in |wl_array| in C++ style. +bool CheckIfWlArrayHasValue(struct wl_array* wl_array, uint32_t value); + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_SHELL_TOPLEVEL_WRAPPER_H_
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc index 1de78dcc..acfc1e7 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -12,7 +12,7 @@ #include "ui/base/hit_test.h" #include "ui/gfx/native_widget_types.h" #include "ui/ozone/platform/wayland/host/shell_object_factory.h" -#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" +#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h" #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_event_source.h" @@ -40,21 +40,21 @@ WaylandToplevelWindow::~WaylandToplevelWindow() = default; -bool WaylandToplevelWindow::CreateShellSurface() { +bool WaylandToplevelWindow::CreateShellToplevel() { ShellObjectFactory factory; - shell_surface_ = factory.CreateShellSurfaceWrapper(connection(), this); - if (!shell_surface_) { - LOG(ERROR) << "Failed to create a ShellSurface."; + shell_toplevel_ = factory.CreateShellToplevelWrapper(connection(), this); + if (!shell_toplevel_) { + LOG(ERROR) << "Failed to create a ShellToplevel."; return false; } #if BUILDFLAG(IS_CHROMEOS_LACROS) - shell_surface_->SetAppId(window_unique_id_); + shell_toplevel_->SetAppId(window_unique_id_); #else - shell_surface_->SetAppId(wm_class_class_); + shell_toplevel_->SetAppId(wm_class_class_); #endif SetDecorationMode(); - shell_surface_->SetTitle(window_title_); + shell_toplevel_->SetTitle(window_title_); SetSizeConstraints(); TriggerStateChanges(); InitializeAuraShellSurface(); @@ -64,10 +64,10 @@ void WaylandToplevelWindow::ApplyPendingBounds() { if (pending_bounds_dip_.IsEmpty()) return; - DCHECK(shell_surface_); + DCHECK(shell_toplevel_); SetBoundsDip(pending_bounds_dip_); - shell_surface_->SetWindowGeometry(pending_bounds_dip_); + shell_toplevel_->SetWindowGeometry(pending_bounds_dip_); pending_bounds_dip_ = gfx::Rect(); connection()->ScheduleFlush(); } @@ -75,22 +75,22 @@ void WaylandToplevelWindow::DispatchHostWindowDragMovement( int hittest, const gfx::Point& pointer_location_in_px) { - DCHECK(shell_surface_); + DCHECK(shell_toplevel_); connection()->event_source()->ResetPointerFlags(); if (hittest == HTCAPTION) - shell_surface_->SurfaceMove(connection()); + shell_toplevel_->SurfaceMove(connection()); else - shell_surface_->SurfaceResize(connection(), hittest); + shell_toplevel_->SurfaceResize(connection(), hittest); connection()->ScheduleFlush(); } void WaylandToplevelWindow::Show(bool inactive) { - if (shell_surface_) + if (shell_toplevel_) return; - if (!CreateShellSurface()) { + if (!CreateShellToplevel()) { Close(); return; } @@ -104,7 +104,7 @@ } void WaylandToplevelWindow::Hide() { - if (!shell_surface_) + if (!shell_toplevel_) return; if (child_window()) { @@ -112,7 +112,7 @@ set_child_window(nullptr); } - shell_surface_.reset(); + shell_toplevel_.reset(); connection()->ScheduleFlush(); // Detach buffer from surface in order to completely shutdown menus and @@ -123,7 +123,7 @@ bool WaylandToplevelWindow::IsVisible() const { // X and Windows return true if the window is minimized. For consistency, do // the same. - return !!shell_surface_ || state_ == PlatformWindowState::kMinimized; + return !!shell_toplevel_ || state_ == PlatformWindowState::kMinimized; } void WaylandToplevelWindow::SetTitle(const base::string16& title) { @@ -132,8 +132,8 @@ window_title_ = title; - if (shell_surface_) { - shell_surface_->SetTitle(title); + if (shell_toplevel_) { + shell_toplevel_->SetTitle(title); connection()->ScheduleFlush(); } } @@ -167,7 +167,7 @@ } void WaylandToplevelWindow::Restore() { - DCHECK(shell_surface_); + DCHECK(shell_toplevel_); // Differently from other platforms, under Wayland, unmaximizing the dragged // window before starting the drag loop is not needed as it is assumed to be @@ -188,7 +188,7 @@ void WaylandToplevelWindow::SizeConstraintsChanged() { // Size constraints only make sense for normal windows. - if (!shell_surface_) + if (!shell_toplevel_) return; DCHECK(delegate()); @@ -209,7 +209,7 @@ if (use_native_frame_ == use_native_frame) return; use_native_frame_ = use_native_frame; - if (shell_surface_) + if (shell_toplevel_) SetDecorationMode(); } @@ -330,7 +330,7 @@ } void WaylandToplevelWindow::TriggerStateChanges() { - if (!shell_surface_) + if (!shell_toplevel_) return; // Call UnSetMaximized only if current state is normal. Otherwise, if the @@ -338,15 +338,15 @@ // UnSetMaximized may result in wrong restored window position that clients // are not allowed to know about. if (state_ == PlatformWindowState::kMinimized) { - shell_surface_->SetMinimized(); + shell_toplevel_->SetMinimized(); } else if (state_ == PlatformWindowState::kFullScreen) { - shell_surface_->SetFullscreen(); + shell_toplevel_->SetFullscreen(); } else if (previous_state_ == PlatformWindowState::kFullScreen) { - shell_surface_->UnSetFullscreen(); + shell_toplevel_->UnSetFullscreen(); } else if (state_ == PlatformWindowState::kMaximized) { - shell_surface_->SetMaximized(); + shell_toplevel_->SetMaximized(); } else if (state_ == PlatformWindowState::kNormal) { - shell_surface_->UnSetMaximized(); + shell_toplevel_->UnSetMaximized(); } connection()->ScheduleFlush(); @@ -364,9 +364,9 @@ void WaylandToplevelWindow::SetSizeConstraints() { if (min_size_.has_value()) - shell_surface_->SetMinSize(min_size_->width(), min_size_->height()); + shell_toplevel_->SetMinSize(min_size_->width(), min_size_->height()); if (max_size_.has_value()) - shell_surface_->SetMaxSize(max_size_->width(), max_size_->height()); + shell_toplevel_->SetMaxSize(max_size_->width(), max_size_->height()); connection()->ScheduleFlush(); } @@ -387,7 +387,7 @@ void WaylandToplevelWindow::InitializeAuraShellSurface() { // InitializeAuraShellSurface() should be called after the XDG surface is // initialized. - DCHECK(shell_surface_); + DCHECK(shell_toplevel_); if (connection()->zaura_shell() && !aura_surface_) { aura_surface_.reset(zaura_shell_get_aura_surface( @@ -397,13 +397,15 @@ } void WaylandToplevelWindow::SetDecorationMode() { - DCHECK(shell_surface_); + DCHECK(shell_toplevel_); if (use_native_frame_) { // Set server-side decoration for windows using a native frame, // e.g. taskmanager - shell_surface_->SetDecoration(DecorationMode::kServerSide); + shell_toplevel_->SetDecoration( + ShellToplevelWrapper::DecorationMode::kServerSide); } else { - shell_surface_->SetDecoration(DecorationMode::kClientSide); + shell_toplevel_->SetDecoration( + ShellToplevelWrapper::DecorationMode::kClientSide); } }
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h index 591ca199..eb0636a 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -14,7 +14,7 @@ namespace ui { -class ShellSurfaceWrapper; +class ShellToplevelWrapper; class WaylandToplevelWindow : public WaylandWindow, public WmMoveResizeHandler, @@ -27,7 +27,7 @@ WaylandToplevelWindow& operator=(const WaylandToplevelWindow&) = delete; ~WaylandToplevelWindow() override; - ShellSurfaceWrapper* shell_surface() const { return shell_surface_.get(); } + ShellToplevelWrapper* shell_toplevel() const { return shell_toplevel_.get(); } // Apply the bounds specified in the most recent configure event. This should // be called after processing all pending events in the wayland connection. @@ -77,11 +77,11 @@ void SetWindowState(PlatformWindowState state); // Creates a surface window, which is visible as a main window. - bool CreateShellSurface(); + bool CreateShellToplevel(); WmMoveResizeHandler* AsWmMoveResizeHandler(); - // Propagates the |min_size_| and |max_size_| to the ShellSurface. + // Propagates the |min_size_| and |max_size_| to the ShellToplevel. void SetSizeConstraints(); void SetOrResetRestoredBounds(); @@ -94,7 +94,7 @@ void SetDecorationMode(); // Wrappers around shell surface. - std::unique_ptr<ShellSurfaceWrapper> shell_surface_; + std::unique_ptr<ShellToplevelWrapper> shell_toplevel_; // These bounds attributes below have suffices that indicate units used. // Wayland operates in DIP but the platform operates in physical pixels so @@ -127,7 +127,7 @@ std::string wm_class_class_; #endif - // Title of the ShellSurface. + // Title of the ShellToplevel. base::string16 window_title_; // Max and min sizes of the WaylandToplevelWindow window.
diff --git a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc index cee4e46..ceffc66f 100644 --- a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc +++ b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc
@@ -17,17 +17,17 @@ #include "ui/gfx/geometry/rect.h" #include "ui/ozone/platform/wayland/common/wayland_util.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" -#include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/host/wayland_pointer.h" #include "ui/ozone/platform/wayland/host/wayland_popup.h" #include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h" #include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h" +#include "ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h" namespace ui { namespace { -uint32_t TranslateAnchorStable(WlAnchor anchor) { +uint32_t TranslateAnchor(WlAnchor anchor) { switch (anchor) { case WlAnchor::None: return XDG_POSITIONER_ANCHOR_NONE; @@ -50,7 +50,7 @@ } } -uint32_t TranslateGravityStable(WlGravity gravity) { +uint32_t TranslateGravity(WlGravity gravity) { switch (gravity) { case WlGravity::None: return XDG_POSITIONER_GRAVITY_NONE; @@ -73,7 +73,7 @@ } } -uint32_t TranslateContraintAdjustmentStable( +uint32_t TranslateContraintAdjustment( WlConstraintAdjustment constraint_adjustment) { uint32_t res = 0; if ((constraint_adjustment & WlConstraintAdjustment::SlideX) != @@ -97,175 +97,14 @@ return res; } -uint32_t TranslateAnchorV6(WlAnchor anchor) { - switch (anchor) { - case WlAnchor::None: - return ZXDG_POSITIONER_V6_ANCHOR_NONE; - case WlAnchor::Top: - return ZXDG_POSITIONER_V6_ANCHOR_TOP; - case WlAnchor::Bottom: - return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM; - case WlAnchor::Left: - return ZXDG_POSITIONER_V6_ANCHOR_LEFT; - case WlAnchor::Right: - return ZXDG_POSITIONER_V6_ANCHOR_RIGHT; - case WlAnchor::TopLeft: - return ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_LEFT; - case WlAnchor::BottomLeft: - return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_LEFT; - case WlAnchor::TopRight: - return ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_RIGHT; - case WlAnchor::BottomRight: - return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_RIGHT; - } -} - -uint32_t TranslateGravityV6(WlGravity gravity) { - switch (gravity) { - case WlGravity::None: - return ZXDG_POSITIONER_V6_GRAVITY_NONE; - case WlGravity::Top: - return ZXDG_POSITIONER_V6_GRAVITY_TOP; - case WlGravity::Bottom: - return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM; - case WlGravity::Left: - return ZXDG_POSITIONER_V6_GRAVITY_LEFT; - case WlGravity::Right: - return ZXDG_POSITIONER_V6_GRAVITY_RIGHT; - case WlGravity::TopLeft: - return ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_LEFT; - case WlGravity::BottomLeft: - return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM | - ZXDG_POSITIONER_V6_GRAVITY_LEFT; - case WlGravity::TopRight: - return ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_RIGHT; - case WlGravity::BottomRight: - return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM | - ZXDG_POSITIONER_V6_GRAVITY_RIGHT; - } -} - -uint32_t TranslateContraintAdjustmentV6( - WlConstraintAdjustment constraint_adjustment) { - uint32_t res = 0; - if ((constraint_adjustment & WlConstraintAdjustment::SlideX) != - WlConstraintAdjustment::None) - res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X; - if ((constraint_adjustment & WlConstraintAdjustment::SlideY) != - WlConstraintAdjustment::None) - res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y; - if ((constraint_adjustment & WlConstraintAdjustment::FlipX) != - WlConstraintAdjustment::None) - res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X; - if ((constraint_adjustment & WlConstraintAdjustment::FlipY) != - WlConstraintAdjustment::None) - res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y; - if ((constraint_adjustment & WlConstraintAdjustment::ResizeX) != - WlConstraintAdjustment::None) - res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X; - if ((constraint_adjustment & WlConstraintAdjustment::ResizeY) != - WlConstraintAdjustment::None) - res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y; - return res; -} - -uint32_t GetAnchor(MenuType menu_type, const gfx::Rect& bounds, bool stable) { - WlAnchor anchor = WlAnchor::None; - switch (menu_type) { - case MenuType::TYPE_RIGHT_CLICK: - anchor = WlAnchor::TopLeft; - break; - case MenuType::TYPE_3DOT_PARENT_MENU: - anchor = WlAnchor::BottomRight; - break; - case MenuType::TYPE_3DOT_CHILD_MENU: - // Chromium may want to manually position a child menu on the left side of - // its parent menu. Thus, react accordingly. Positive x means the child is - // located on the right side of the parent and negative - on the left - // side. - if (bounds.x() >= 0) - anchor = WlAnchor::TopRight; - else - anchor = WlAnchor::TopLeft; - break; - case MenuType::TYPE_UNKNOWN: - NOTREACHED() << "Unsupported menu type"; - break; - } - - if (stable) - return TranslateAnchorStable(anchor); - else { - return TranslateAnchorV6(anchor); - } -} - -uint32_t GetGravity(MenuType menu_type, const gfx::Rect& bounds, bool stable) { - WlGravity gravity = WlGravity::None; - switch (menu_type) { - case MenuType::TYPE_RIGHT_CLICK: - gravity = WlGravity::BottomRight; - break; - case MenuType::TYPE_3DOT_PARENT_MENU: - gravity = WlGravity::BottomRight; - break; - case MenuType::TYPE_3DOT_CHILD_MENU: - // Chromium may want to manually position a child menu on the left side of - // its parent menu. Thus, react accordingly. Positive x means the child is - // located on the right side of the parent and negative - on the left - // side. - if (bounds.x() >= 0) - gravity = WlGravity::BottomRight; - else - gravity = WlGravity::BottomLeft; - break; - case MenuType::TYPE_UNKNOWN: - NOTREACHED() << "Unsupported menu type"; - break; - } - - if (stable) - return TranslateGravityStable(gravity); - else { - return TranslateGravityV6(gravity); - } -} - -uint32_t GetConstraintAdjustment(MenuType menu_type, bool stable) { - WlConstraintAdjustment constraint = WlConstraintAdjustment::None; - - switch (menu_type) { - case MenuType::TYPE_RIGHT_CLICK: - constraint = WlConstraintAdjustment::SlideX | - WlConstraintAdjustment::SlideY | - WlConstraintAdjustment::FlipY; - break; - case MenuType::TYPE_3DOT_PARENT_MENU: - constraint = - WlConstraintAdjustment::SlideX | WlConstraintAdjustment::FlipY; - break; - case MenuType::TYPE_3DOT_CHILD_MENU: - constraint = - WlConstraintAdjustment::SlideY | WlConstraintAdjustment::FlipX; - break; - case MenuType::TYPE_UNKNOWN: - NOTREACHED() << "Unsupported menu type"; - break; - } - if (stable) - return TranslateContraintAdjustmentStable(constraint); - else { - return TranslateContraintAdjustmentV6(constraint); - } -} - } // namespace XDGPopupWrapperImpl::XDGPopupWrapperImpl( std::unique_ptr<XDGSurfaceWrapperImpl> surface, WaylandWindow* wayland_window) - : wayland_window_(wayland_window), xdg_surface_(std::move(surface)) { - DCHECK(xdg_surface_); + : wayland_window_(wayland_window), + xdg_surface_wrapper_(std::move(surface)) { + DCHECK(xdg_surface_wrapper_); DCHECK(wayland_window_ && wayland_window_->parent_window()); } @@ -286,15 +125,16 @@ static_cast<WaylandPopup*>(wayland_window_->parent_window()); XDGPopupWrapperImpl* popup = static_cast<XDGPopupWrapperImpl*>(wayland_popup->shell_popup()); - parent_xdg_surface = popup->xdg_surface(); + parent_xdg_surface = popup->xdg_surface_wrapper(); } else { WaylandToplevelWindow* wayland_surface = static_cast<WaylandToplevelWindow*>(wayland_window_->parent_window()); parent_xdg_surface = - static_cast<XDGSurfaceWrapperImpl*>(wayland_surface->shell_surface()); + static_cast<XDGToplevelWrapperImpl*>(wayland_surface->shell_toplevel()) + ->xdg_surface_wrapper(); } - if (!xdg_surface_ || !parent_xdg_surface) + if (!xdg_surface_wrapper_ || !parent_xdg_surface) return false; auto new_bounds = bounds; @@ -306,8 +146,6 @@ if (connection->shell()) return InitializeStable(connection, new_bounds, parent_xdg_surface); - else if (connection->shell_v6()) - return InitializeV6(connection, new_bounds, parent_xdg_surface); return false; } @@ -316,16 +154,16 @@ const gfx::Rect& bounds, XDGSurfaceWrapperImpl* parent_xdg_surface) { static const struct xdg_popup_listener xdg_popup_listener = { - &XDGPopupWrapperImpl::ConfigureStable, - &XDGPopupWrapperImpl::PopupDoneStable, + &XDGPopupWrapperImpl::Configure, + &XDGPopupWrapperImpl::PopupDone, }; - struct xdg_positioner* positioner = CreatePositionerStable( - connection, wayland_window_->parent_window(), bounds); + struct xdg_positioner* positioner = + CreatePositioner(connection, wayland_window_->parent_window(), bounds); if (!positioner) return false; - xdg_popup_.reset(xdg_surface_get_popup(xdg_surface_->xdg_surface(), + xdg_popup_.reset(xdg_surface_get_popup(xdg_surface_wrapper_->xdg_surface(), parent_xdg_surface->xdg_surface(), positioner)); if (!xdg_popup_) @@ -342,7 +180,7 @@ return true; } -struct xdg_positioner* XDGPopupWrapperImpl::CreatePositionerStable( +struct xdg_positioner* XDGPopupWrapperImpl::CreatePositioner( WaylandConnection* connection, WaylandWindow* parent_window, const gfx::Rect& bounds) { @@ -366,115 +204,19 @@ xdg_positioner_set_anchor_rect(positioner, anchor_rect.x(), anchor_rect.y(), anchor_rect.width(), anchor_rect.height()); xdg_positioner_set_size(positioner, bounds.width(), bounds.height()); - xdg_positioner_set_anchor(positioner, GetAnchor(menu_type, bounds, true)); - xdg_positioner_set_gravity(positioner, GetGravity(menu_type, bounds, true)); + xdg_positioner_set_anchor(positioner, + TranslateAnchor(GetAnchor(menu_type, bounds))); + xdg_positioner_set_gravity(positioner, + TranslateGravity(GetGravity(menu_type, bounds))); xdg_positioner_set_constraint_adjustment( - positioner, GetConstraintAdjustment(menu_type, true)); + positioner, + TranslateContraintAdjustment(GetConstraintAdjustment(menu_type))); return positioner; } -bool XDGPopupWrapperImpl::InitializeV6( - WaylandConnection* connection, - const gfx::Rect& bounds, - XDGSurfaceWrapperImpl* parent_xdg_surface) { - static const struct zxdg_popup_v6_listener zxdg_popup_v6_listener = { - &XDGPopupWrapperImpl::ConfigureV6, - &XDGPopupWrapperImpl::PopupDoneV6, - }; - - zxdg_positioner_v6* positioner = - CreatePositionerV6(connection, wayland_window_->parent_window(), bounds); - if (!positioner) - return false; - - zxdg_popup_v6_.reset(zxdg_surface_v6_get_popup( - xdg_surface_->zxdg_surface(), parent_xdg_surface->zxdg_surface(), - positioner)); - if (!zxdg_popup_v6_) - return false; - - zxdg_positioner_v6_destroy(positioner); - - if (CanGrabPopup(connection)) { - zxdg_popup_v6_grab(zxdg_popup_v6_.get(), connection->seat(), - connection->serial()); - } - zxdg_popup_v6_add_listener(zxdg_popup_v6_.get(), &zxdg_popup_v6_listener, - this); - - wayland_window_->root_surface()->Commit(); - return true; -} - -zxdg_positioner_v6* XDGPopupWrapperImpl::CreatePositionerV6( - WaylandConnection* connection, - WaylandWindow* parent_window, - const gfx::Rect& bounds) { - struct zxdg_positioner_v6* positioner; - positioner = zxdg_shell_v6_create_positioner(connection->shell_v6()); - if (!positioner) - return nullptr; - - auto menu_type = GetMenuTypeForPositioner(connection, parent_window); - - // The parent we got must be the topmost in the stack of the same family - // windows. - DCHECK_EQ(parent_window->GetTopMostChildWindow(), parent_window); - - // Place anchor to the end of the possible position. - gfx::Rect anchor_rect = GetAnchorRect( - menu_type, bounds, - gfx::ScaleToRoundedRect(parent_window->GetBounds(), - 1.0 / parent_window->buffer_scale())); - - zxdg_positioner_v6_set_anchor_rect(positioner, anchor_rect.x(), - anchor_rect.y(), anchor_rect.width(), - anchor_rect.height()); - zxdg_positioner_v6_set_size(positioner, bounds.width(), bounds.height()); - zxdg_positioner_v6_set_anchor(positioner, - GetAnchor(menu_type, bounds, false)); - zxdg_positioner_v6_set_gravity(positioner, - GetGravity(menu_type, bounds, false)); - zxdg_positioner_v6_set_constraint_adjustment( - positioner, GetConstraintAdjustment(menu_type, false)); - return positioner; -} - -MenuType XDGPopupWrapperImpl::GetMenuTypeForPositioner( - WaylandConnection* connection, - WaylandWindow* parent_window) const { - bool is_right_click_menu = - connection->event_source()->last_pointer_button_pressed() & - EF_RIGHT_MOUSE_BUTTON; - - // Different types of menu require different anchors, constraint adjustments, - // gravity and etc. - if (is_right_click_menu) - return MenuType::TYPE_RIGHT_CLICK; - else if (!wl::IsMenuType(parent_window->type())) - return MenuType::TYPE_3DOT_PARENT_MENU; - else - return MenuType::TYPE_3DOT_CHILD_MENU; -} - -bool XDGPopupWrapperImpl::CanGrabPopup(WaylandConnection* connection) const { - // When drag process starts, as described the protocol - - // https://goo.gl/1Mskq3, the client must have an active implicit grab. If - // we try to create a popup and grab it, it will be immediately dismissed. - // Thus, do not take explicit grab during drag process. - if (connection->IsDragInProgress() || !connection->seat()) - return false; - - // According to the definition of the xdg protocol, the grab request must be - // used in response to some sort of user action like a button press, key - // press, or touch down event. - EventType last_event_type = connection->event_serial().event_type; - return last_event_type == ET_TOUCH_PRESSED || - last_event_type == ET_KEY_PRESSED || - last_event_type == ET_MOUSE_PRESSED; -} - +// static void XDGPopupWrapperImpl::Configure(void* data, + struct xdg_popup* xdg_popup, int32_t x, int32_t y, int32_t width, @@ -492,7 +234,7 @@ } // static -void XDGPopupWrapperImpl::PopupDone(void* data) { +void XDGPopupWrapperImpl::PopupDone(void* data, struct xdg_popup* xdg_popup) { WaylandWindow* window = static_cast<XDGPopupWrapperImpl*>(data)->wayland_window_; DCHECK(window); @@ -500,41 +242,9 @@ window->OnCloseRequest(); } -// static -void XDGPopupWrapperImpl::ConfigureStable(void* data, - struct xdg_popup* xdg_popup, - int32_t x, - int32_t y, - int32_t width, - int32_t height) { - Configure(data, x, y, width, height); -} - -// static -void XDGPopupWrapperImpl::PopupDoneStable(void* data, - struct xdg_popup* xdg_popup) { - PopupDone(data); -} - -// static -void XDGPopupWrapperImpl::ConfigureV6(void* data, - struct zxdg_popup_v6* zxdg_popup_v6, - int32_t x, - int32_t y, - int32_t width, - int32_t height) { - Configure(data, x, y, width, height); -} - -// static -void XDGPopupWrapperImpl::PopupDoneV6(void* data, - struct zxdg_popup_v6* zxdg_popup_v6) { - PopupDone(data); -} - -XDGSurfaceWrapperImpl* XDGPopupWrapperImpl::xdg_surface() { - DCHECK(xdg_surface_.get()); - return xdg_surface_.get(); +XDGSurfaceWrapperImpl* XDGPopupWrapperImpl::xdg_surface_wrapper() const { + DCHECK(xdg_surface_wrapper_.get()); + return xdg_surface_wrapper_.get(); } } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h index 62f38a2..2ffb230 100644 --- a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h +++ b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.h
@@ -16,7 +16,7 @@ class WaylandConnection; class WaylandWindow; -// Popup wrapper for xdg-shell stable and xdg-shell-unstable-v6 +// Popup wrapper for xdg-shell stable class XDGPopupWrapperImpl : public ShellPopupWrapper { public: XDGPopupWrapperImpl(std::unique_ptr<XDGSurfaceWrapperImpl> surface, @@ -30,57 +30,30 @@ private: bool InitializeStable(WaylandConnection* connection, const gfx::Rect& bounds, - XDGSurfaceWrapperImpl* parent_xdg_surface); - struct xdg_positioner* CreatePositionerStable(WaylandConnection* connection, - WaylandWindow* parent_window, - const gfx::Rect& bounds); - - bool InitializeV6(WaylandConnection* connection, - const gfx::Rect& bounds, - XDGSurfaceWrapperImpl* parent_xdg_surface); - struct zxdg_positioner_v6* CreatePositionerV6(WaylandConnection* connection, - WaylandWindow* parent_window, - const gfx::Rect& bounds); - - MenuType GetMenuTypeForPositioner(WaylandConnection* connection, - WaylandWindow* parent_window) const; - - bool CanGrabPopup(WaylandConnection* connection) const; + XDGSurfaceWrapperImpl* parent_xdg_surface_wrapper); + struct xdg_positioner* CreatePositioner(WaylandConnection* connection, + WaylandWindow* parent_window, + const gfx::Rect& bounds); // xdg_popup_listener static void Configure(void* data, - int32_t x, - int32_t y, - int32_t width, - int32_t height); - static void ConfigureStable(void* data, struct xdg_popup* xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height); - static void ConfigureV6(void* data, - struct zxdg_popup_v6* zxdg_popup_v6, - int32_t x, - int32_t y, - int32_t width, - int32_t height); - static void PopupDone(void* data); - static void PopupDoneStable(void* data, struct xdg_popup* xdg_popup); - static void PopupDoneV6(void* data, struct zxdg_popup_v6* zxdg_popup_v6); + static void PopupDone(void* data, struct xdg_popup* xdg_popup); - XDGSurfaceWrapperImpl* xdg_surface(); + XDGSurfaceWrapperImpl* xdg_surface_wrapper() const; // Non-owned WaylandWindow that uses this popup. WaylandWindow* const wayland_window_; // Ground surface for this popup. - std::unique_ptr<XDGSurfaceWrapperImpl> xdg_surface_; + std::unique_ptr<XDGSurfaceWrapperImpl> xdg_surface_wrapper_; // XDG Shell Stable object. wl::Object<xdg_popup> xdg_popup_; - // XDG Shell V6 object. - wl::Object<zxdg_popup_v6> zxdg_popup_v6_; DISALLOW_COPY_AND_ASSIGN(XDGPopupWrapperImpl); };
diff --git a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc index 1957a55..8d5bf2f3 100644 --- a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc +++ b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.cc
@@ -4,14 +4,8 @@ #include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h" -#include <xdg-decoration-unstable-v1-client-protocol.h> #include <xdg-shell-client-protocol.h> -#include <xdg-shell-unstable-v6-client-protocol.h> -#include "base/strings/utf_string_conversions.h" -#include "ui/base/hit_test.h" -#include "ui/ozone/platform/wayland/common/wayland_util.h" -#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" @@ -19,281 +13,19 @@ XDGSurfaceWrapperImpl::XDGSurfaceWrapperImpl(WaylandWindow* wayland_window, WaylandConnection* connection) - : wayland_window_(wayland_window), - connection_(connection), - decoration_mode_(DecorationMode::kClientSide) {} + : wayland_window_(wayland_window), connection_(connection) {} -XDGSurfaceWrapperImpl::~XDGSurfaceWrapperImpl() {} +XDGSurfaceWrapperImpl::~XDGSurfaceWrapperImpl() = default; -bool XDGSurfaceWrapperImpl::Initialize(bool with_toplevel) { - if (connection_->shell()) - return InitializeStable(with_toplevel); - else if (connection_->shell_v6()) - return InitializeV6(with_toplevel); - NOTREACHED() << "Wrong shell protocol"; - return false; -} - -void XDGSurfaceWrapperImpl::SetMaximized() { - if (xdg_toplevel_) { - xdg_toplevel_set_maximized(xdg_toplevel_.get()); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_set_maximized(zxdg_toplevel_v6_.get()); +bool XDGSurfaceWrapperImpl::Initialize() { + if (!connection_->shell()) { + NOTREACHED() << "Wrong shell protocol"; + return false; } -} -void XDGSurfaceWrapperImpl::UnSetMaximized() { - if (xdg_toplevel_) { - xdg_toplevel_unset_maximized(xdg_toplevel_.get()); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_unset_maximized(zxdg_toplevel_v6_.get()); - } -} - -void XDGSurfaceWrapperImpl::SetFullscreen() { - if (xdg_toplevel_) { - xdg_toplevel_set_fullscreen(xdg_toplevel_.get(), nullptr); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_set_fullscreen(zxdg_toplevel_v6_.get(), nullptr); - } -} - -void XDGSurfaceWrapperImpl::UnSetFullscreen() { - if (xdg_toplevel_) { - xdg_toplevel_unset_fullscreen(xdg_toplevel_.get()); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_unset_fullscreen(zxdg_toplevel_v6_.get()); - } -} - -void XDGSurfaceWrapperImpl::SetMinimized() { - if (xdg_toplevel_) { - xdg_toplevel_set_minimized(xdg_toplevel_.get()); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_set_minimized(zxdg_toplevel_v6_.get()); - } -} - -void XDGSurfaceWrapperImpl::SurfaceMove(WaylandConnection* connection) { - if (xdg_toplevel_) { - xdg_toplevel_move(xdg_toplevel_.get(), connection_->seat(), - connection_->serial()); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_move(zxdg_toplevel_v6_.get(), connection_->seat(), - connection_->serial()); - } -} - -void XDGSurfaceWrapperImpl::SurfaceResize(WaylandConnection* connection, - uint32_t hittest) { - if (xdg_toplevel_) { - xdg_toplevel_resize(xdg_toplevel_.get(), connection_->seat(), - connection_->serial(), - wl::IdentifyDirection(*connection, hittest)); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_resize(zxdg_toplevel_v6_.get(), connection_->seat(), - connection_->serial(), - wl::IdentifyDirection(*connection, hittest)); - } -} - -void XDGSurfaceWrapperImpl::SetTitle(const base::string16& title) { - if (xdg_toplevel_) { - xdg_toplevel_set_title(xdg_toplevel_.get(), - base::UTF16ToUTF8(title).c_str()); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_set_title(zxdg_toplevel_v6_.get(), - base::UTF16ToUTF8(title).c_str()); - } -} - -void XDGSurfaceWrapperImpl::AckConfigure() { - if (xdg_surface_) { - xdg_surface_ack_configure(xdg_surface_.get(), pending_configure_serial_); - } else { - DCHECK(zxdg_surface_v6_); - zxdg_surface_v6_ack_configure(zxdg_surface_v6_.get(), - pending_configure_serial_); - } - connection_->wayland_window_manager()->NotifyWindowConfigured( - wayland_window_); -} - -void XDGSurfaceWrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) { - if (xdg_surface_) { - xdg_surface_set_window_geometry(xdg_surface_.get(), bounds.x(), bounds.y(), - bounds.width(), bounds.height()); - } else { - DCHECK(zxdg_surface_v6_); - zxdg_surface_v6_set_window_geometry(zxdg_surface_v6_.get(), bounds.x(), - bounds.y(), bounds.width(), - bounds.height()); - } -} - -void XDGSurfaceWrapperImpl::SetMinSize(int32_t width, int32_t height) { - if (xdg_toplevel_) { - xdg_toplevel_set_min_size(xdg_toplevel_.get(), width, height); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_set_min_size(zxdg_toplevel_v6_.get(), width, height); - } -} - -void XDGSurfaceWrapperImpl::SetMaxSize(int32_t width, int32_t height) { - if (xdg_toplevel_) { - xdg_toplevel_set_max_size(xdg_toplevel_.get(), width, height); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_set_max_size(zxdg_toplevel_v6_.get(), width, height); - } -} - -void XDGSurfaceWrapperImpl::SetAppId(const std::string& app_id) { - if (xdg_toplevel_) { - xdg_toplevel_set_app_id(xdg_toplevel_.get(), app_id.c_str()); - } else { - DCHECK(zxdg_toplevel_v6_); - zxdg_toplevel_v6_set_app_id(zxdg_toplevel_v6_.get(), app_id.c_str()); - } -} - -void XDGSurfaceWrapperImpl::SetDecoration(DecorationMode decoration) { - SetTopLevelDecorationMode(decoration); -} - -// static -void XDGSurfaceWrapperImpl::ConfigureStable(void* data, - struct xdg_surface* xdg_surface, - uint32_t serial) { - auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); - DCHECK(surface); - surface->pending_configure_serial_ = serial; - - surface->AckConfigure(); -} - -// static -void XDGSurfaceWrapperImpl::ConfigureTopLevelStable( - void* data, - struct xdg_toplevel* xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array* states) { - auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); - DCHECK(surface); - - bool is_maximized = - CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_MAXIMIZED); - bool is_fullscreen = - CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_FULLSCREEN); - bool is_activated = - CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_ACTIVATED); - - surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized, - is_fullscreen, is_activated); -} - -// static -void XDGSurfaceWrapperImpl::CloseTopLevelStable( - void* data, - struct xdg_toplevel* xdg_toplevel) { - auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); - DCHECK(surface); - surface->wayland_window_->OnCloseRequest(); -} - -void XDGSurfaceWrapperImpl::SetTopLevelDecorationMode( - DecorationMode requested_mode) { - if (!zxdg_toplevel_decoration_ || requested_mode == decoration_mode_) - return; - - decoration_mode_ = requested_mode; - zxdg_toplevel_decoration_v1_set_mode(zxdg_toplevel_decoration_.get(), - static_cast<uint32_t>(requested_mode)); -} - -// static -void XDGSurfaceWrapperImpl::ConfigureV6(void* data, - struct zxdg_surface_v6* zxdg_surface_v6, - uint32_t serial) { - auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); - DCHECK(surface); - surface->pending_configure_serial_ = serial; - - surface->AckConfigure(); -} - -// static -void XDGSurfaceWrapperImpl::ConfigureTopLevelV6( - void* data, - struct zxdg_toplevel_v6* zxdg_toplevel_v6, - int32_t width, - int32_t height, - struct wl_array* states) { - auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); - DCHECK(surface); - - bool is_maximized = - CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED); - bool is_fullscreen = - CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN); - bool is_activated = - CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED); - - surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized, - is_fullscreen, is_activated); -} - -// static -void XDGSurfaceWrapperImpl::CloseTopLevelV6( - void* data, - struct zxdg_toplevel_v6* zxdg_toplevel_v6) { - auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); - DCHECK(surface); - surface->wayland_window_->OnCloseRequest(); -} - -zxdg_surface_v6* XDGSurfaceWrapperImpl::zxdg_surface() const { - DCHECK(zxdg_surface_v6_); - return zxdg_surface_v6_.get(); -} - -xdg_surface* XDGSurfaceWrapperImpl::xdg_surface() const { - DCHECK(xdg_surface_); - return xdg_surface_.get(); -} - -// static -void XDGSurfaceWrapperImpl::ConfigureDecoration( - void* data, - struct zxdg_toplevel_decoration_v1* decoration, - uint32_t mode) { - auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); - DCHECK(surface); - surface->SetTopLevelDecorationMode(static_cast<DecorationMode>(mode)); -} - -bool XDGSurfaceWrapperImpl::InitializeStable(bool with_toplevel) { static const xdg_surface_listener xdg_surface_listener = { - &XDGSurfaceWrapperImpl::ConfigureStable, + &XDGSurfaceWrapperImpl::Configure, }; - static const xdg_toplevel_listener xdg_toplevel_listener = { - &XDGSurfaceWrapperImpl::ConfigureTopLevelStable, - &XDGSurfaceWrapperImpl::CloseTopLevelStable, - }; - - // if this surface is created for the popup role, mark that it requires - // configuration acknowledgement on each configure event. - surface_for_popup_ = !with_toplevel; xdg_surface_.reset(xdg_wm_base_get_xdg_surface( connection_->shell(), wayland_window_->root_surface()->surface())); @@ -301,84 +33,39 @@ LOG(ERROR) << "Failed to create xdg_surface"; return false; } + xdg_surface_add_listener(xdg_surface_.get(), &xdg_surface_listener, this); - // XDGPopup requires a separate surface to be created, so this is just a - // request to get an xdg_surface for it. - if (surface_for_popup_) { - connection_->ScheduleFlush(); - return true; - } - - xdg_toplevel_.reset(xdg_surface_get_toplevel(xdg_surface_.get())); - if (!xdg_toplevel_) { - LOG(ERROR) << "Failed to create xdg_toplevel"; - return false; - } - - xdg_toplevel_add_listener(xdg_toplevel_.get(), &xdg_toplevel_listener, this); - - InitializeXdgDecoration(); - - wayland_window_->root_surface()->Commit(); connection_->ScheduleFlush(); return true; } -bool XDGSurfaceWrapperImpl::InitializeV6(bool with_toplevel) { - static const zxdg_surface_v6_listener zxdg_surface_v6_listener = { - &XDGSurfaceWrapperImpl::ConfigureV6, - }; - static const zxdg_toplevel_v6_listener zxdg_toplevel_v6_listener = { - &XDGSurfaceWrapperImpl::ConfigureTopLevelV6, - &XDGSurfaceWrapperImpl::CloseTopLevelV6, - }; - - // if this surface is created for the popup role, mark that it requires - // configuration acknowledgement on each configure event. - surface_for_popup_ = !with_toplevel; - - zxdg_surface_v6_.reset(zxdg_shell_v6_get_xdg_surface( - connection_->shell_v6(), wayland_window_->root_surface()->surface())); - if (!zxdg_surface_v6_) { - LOG(ERROR) << "Failed to create zxdg_surface"; - return false; - } - zxdg_surface_v6_add_listener(zxdg_surface_v6_.get(), - &zxdg_surface_v6_listener, this); - // XDGPopupV6 requires a separate surface to be created, so this is just a - // request to get an xdg_surface for it. - if (surface_for_popup_) { - connection_->ScheduleFlush(); - return true; - } - - zxdg_toplevel_v6_.reset(zxdg_surface_v6_get_toplevel(zxdg_surface_v6_.get())); - if (!zxdg_toplevel_v6_) { - LOG(ERROR) << "Failed to create zxdg_toplevel"; - return false; - } - zxdg_toplevel_v6_add_listener(zxdg_toplevel_v6_.get(), - &zxdg_toplevel_v6_listener, this); - - InitializeXdgDecoration(); - - wayland_window_->root_surface()->Commit(); - connection_->ScheduleFlush(); - return true; +void XDGSurfaceWrapperImpl::AckConfigure() { + DCHECK(xdg_surface_); + xdg_surface_ack_configure(xdg_surface_.get(), pending_configure_serial_); + connection_->wayland_window_manager()->NotifyWindowConfigured( + wayland_window_); } -void XDGSurfaceWrapperImpl::InitializeXdgDecoration() { - if (connection_->xdg_decoration_manager_v1()) { - DCHECK(!zxdg_toplevel_decoration_); - static const zxdg_toplevel_decoration_v1_listener decoration_listener = { - &XDGSurfaceWrapperImpl::ConfigureDecoration, - }; - zxdg_toplevel_decoration_.reset( - zxdg_decoration_manager_v1_get_toplevel_decoration( - connection_->xdg_decoration_manager_v1(), xdg_toplevel_.get())); - zxdg_toplevel_decoration_v1_add_listener(zxdg_toplevel_decoration_.get(), - &decoration_listener, this); - } +void XDGSurfaceWrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) { + DCHECK(xdg_surface_); + xdg_surface_set_window_geometry(xdg_surface_.get(), bounds.x(), bounds.y(), + bounds.width(), bounds.height()); +} + +// static +void XDGSurfaceWrapperImpl::Configure(void* data, + struct xdg_surface* xdg_surface, + uint32_t serial) { + auto* surface = static_cast<XDGSurfaceWrapperImpl*>(data); + DCHECK(surface); + surface->pending_configure_serial_ = serial; + + surface->AckConfigure(); +} + +xdg_surface* XDGSurfaceWrapperImpl::xdg_surface() const { + DCHECK(xdg_surface_); + return xdg_surface_.get(); } } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h index 6cbb8b68..3210806 100644 --- a/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h +++ b/ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h
@@ -7,8 +7,6 @@ #include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" -#include <xdg-decoration-unstable-v1-client-protocol.h> - #include <cstdint> #include <string> @@ -24,7 +22,7 @@ class WaylandConnection; class WaylandWindow; -// Surface wrapper for xdg-shell stable and xdg-shell-unstable-v6 +// Surface wrapper for xdg-shell stable class XDGSurfaceWrapperImpl : public ShellSurfaceWrapper { public: XDGSurfaceWrapperImpl(WaylandWindow* wayland_window, @@ -34,85 +32,25 @@ ~XDGSurfaceWrapperImpl() override; // ShellSurfaceWrapper overrides: - bool Initialize(bool with_toplevel) override; - void SetMaximized() override; - void UnSetMaximized() override; - void SetFullscreen() override; - void UnSetFullscreen() override; - void SetMinimized() override; - void SurfaceMove(WaylandConnection* connection) override; - void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override; - void SetTitle(const base::string16& title) override; + bool Initialize() override; void AckConfigure() override; void SetWindowGeometry(const gfx::Rect& bounds) override; - void SetMinSize(int32_t width, int32_t height) override; - void SetMaxSize(int32_t width, int32_t height) override; - void SetAppId(const std::string& app_id) override; - void SetDecoration(DecorationMode decoration) override; // xdg_surface_listener - static void ConfigureV6(void* data, - struct zxdg_surface_v6* zxdg_surface_v6, - uint32_t serial); - static void ConfigureTopLevelV6(void* data, - struct zxdg_toplevel_v6* zxdg_toplevel_v6, - int32_t width, - int32_t height, - struct wl_array* states); - - static void ConfigureStable(void* data, - struct xdg_surface* xdg_surface, - uint32_t serial); - static void ConfigureTopLevelStable(void* data, - struct xdg_toplevel* xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array* states); - - // xdg_toplevel_listener - static void CloseTopLevelStable(void* data, - struct xdg_toplevel* xdg_toplevel); - static void CloseTopLevelV6(void* data, - struct zxdg_toplevel_v6* zxdg_toplevel_v6); - - // Send request to wayland compositor to enable a requested decoration mode. - void SetTopLevelDecorationMode(DecorationMode requested_mode); - - // zxdg_decoration_listener - static void ConfigureDecoration( - void* data, - struct zxdg_toplevel_decoration_v1* decoration, - uint32_t mode); + static void Configure(void* data, + struct xdg_surface* xdg_surface, + uint32_t serial); struct xdg_surface* xdg_surface() const; - zxdg_surface_v6* zxdg_surface() const; private: - // Initializes using XDG Shell Stable protocol. - bool InitializeStable(bool with_toplevel); - // Initializes using XDG Shell V6 protocol. - bool InitializeV6(bool with_toplevel); - - // Initializes the xdg-decoration protocol extension, if available. - void InitializeXdgDecoration(); - // Non-owing WaylandWindow that uses this surface wrapper. WaylandWindow* const wayland_window_; WaylandConnection* const connection_; uint32_t pending_configure_serial_ = 0; - wl::Object<zxdg_surface_v6> zxdg_surface_v6_; - wl::Object<zxdg_toplevel_v6> zxdg_toplevel_v6_; wl::Object<struct xdg_surface> xdg_surface_; - wl::Object<xdg_toplevel> xdg_toplevel_; - wl::Object<zxdg_toplevel_decoration_v1> zxdg_toplevel_decoration_; - - bool surface_for_popup_ = false; - - // On client side, it keeps track of the decoration mode currently in - // use if xdg-decoration protocol extension is available. - DecorationMode decoration_mode_; }; } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc new file mode 100644 index 0000000..56695c4 --- /dev/null +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc
@@ -0,0 +1,197 @@ +// Copyright 2021 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/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h" + +#include <xdg-decoration-unstable-v1-client-protocol.h> +#include <xdg-shell-client-protocol.h> +#include <xdg-shell-unstable-v6-client-protocol.h> + +#include "base/strings/utf_string_conversions.h" +#include "ui/base/hit_test.h" +#include "ui/ozone/platform/wayland/common/wayland_util.h" +#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_window.h" +#include "ui/ozone/platform/wayland/host/xdg_surface_wrapper_impl.h" + +namespace ui { + +XDGToplevelWrapperImpl::XDGToplevelWrapperImpl( + std::unique_ptr<XDGSurfaceWrapperImpl> surface, + WaylandWindow* wayland_window, + WaylandConnection* connection) + : xdg_surface_wrapper_(std::move(surface)), + wayland_window_(wayland_window), + connection_(connection), + decoration_mode_(DecorationMode::kClientSide) {} + +XDGToplevelWrapperImpl::~XDGToplevelWrapperImpl() = default; + +bool XDGToplevelWrapperImpl::Initialize() { + if (!connection_->shell()) { + NOTREACHED() << "Wrong shell protocol"; + return false; + } + + static const xdg_toplevel_listener xdg_toplevel_listener = { + &XDGToplevelWrapperImpl::ConfigureTopLevel, + &XDGToplevelWrapperImpl::CloseTopLevel, + }; + + if (!xdg_surface_wrapper_) + return false; + + xdg_toplevel_.reset( + xdg_surface_get_toplevel(xdg_surface_wrapper_->xdg_surface())); + if (!xdg_toplevel_) { + LOG(ERROR) << "Failed to create xdg_toplevel"; + return false; + } + + xdg_toplevel_add_listener(xdg_toplevel_.get(), &xdg_toplevel_listener, this); + + InitializeXdgDecoration(); + + wayland_window_->root_surface()->Commit(); + connection_->ScheduleFlush(); + return true; +} + +void XDGToplevelWrapperImpl::SetMaximized() { + DCHECK(xdg_toplevel_); + xdg_toplevel_set_maximized(xdg_toplevel_.get()); +} + +void XDGToplevelWrapperImpl::UnSetMaximized() { + DCHECK(xdg_toplevel_); + xdg_toplevel_unset_maximized(xdg_toplevel_.get()); +} + +void XDGToplevelWrapperImpl::SetFullscreen() { + DCHECK(xdg_toplevel_); + xdg_toplevel_set_fullscreen(xdg_toplevel_.get(), nullptr); +} + +void XDGToplevelWrapperImpl::UnSetFullscreen() { + DCHECK(xdg_toplevel_); + xdg_toplevel_unset_fullscreen(xdg_toplevel_.get()); +} + +void XDGToplevelWrapperImpl::SetMinimized() { + DCHECK(xdg_toplevel_); + xdg_toplevel_set_minimized(xdg_toplevel_.get()); +} + +void XDGToplevelWrapperImpl::SurfaceMove(WaylandConnection* connection) { + DCHECK(xdg_toplevel_); + xdg_toplevel_move(xdg_toplevel_.get(), connection->seat(), + connection->serial()); +} + +void XDGToplevelWrapperImpl::SurfaceResize(WaylandConnection* connection, + uint32_t hittest) { + DCHECK(xdg_toplevel_); + xdg_toplevel_resize(xdg_toplevel_.get(), connection->seat(), + connection->serial(), + wl::IdentifyDirection(*connection, hittest)); +} + +void XDGToplevelWrapperImpl::SetTitle(const base::string16& title) { + DCHECK(xdg_toplevel_); + xdg_toplevel_set_title(xdg_toplevel_.get(), base::UTF16ToUTF8(title).c_str()); +} + +void XDGToplevelWrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) { + xdg_surface_wrapper_->SetWindowGeometry(bounds); +} + +void XDGToplevelWrapperImpl::SetMinSize(int32_t width, int32_t height) { + DCHECK(xdg_toplevel_); + xdg_toplevel_set_min_size(xdg_toplevel_.get(), width, height); +} + +void XDGToplevelWrapperImpl::SetMaxSize(int32_t width, int32_t height) { + DCHECK(xdg_toplevel_); + xdg_toplevel_set_max_size(xdg_toplevel_.get(), width, height); +} + +void XDGToplevelWrapperImpl::SetAppId(const std::string& app_id) { + DCHECK(xdg_toplevel_); + xdg_toplevel_set_app_id(xdg_toplevel_.get(), app_id.c_str()); +} + +void XDGToplevelWrapperImpl::SetDecoration(DecorationMode decoration) { + SetTopLevelDecorationMode(decoration); +} + +// static +void XDGToplevelWrapperImpl::ConfigureTopLevel( + void* data, + struct xdg_toplevel* xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array* states) { + auto* surface = static_cast<XDGToplevelWrapperImpl*>(data); + DCHECK(surface); + + bool is_maximized = + CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_MAXIMIZED); + bool is_fullscreen = + CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_FULLSCREEN); + bool is_activated = + CheckIfWlArrayHasValue(states, XDG_TOPLEVEL_STATE_ACTIVATED); + + surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized, + is_fullscreen, is_activated); +} + +// static +void XDGToplevelWrapperImpl::CloseTopLevel(void* data, + struct xdg_toplevel* xdg_toplevel) { + auto* surface = static_cast<XDGToplevelWrapperImpl*>(data); + DCHECK(surface); + surface->wayland_window_->OnCloseRequest(); +} + +void XDGToplevelWrapperImpl::SetTopLevelDecorationMode( + DecorationMode requested_mode) { + if (!zxdg_toplevel_decoration_ || requested_mode == decoration_mode_) + return; + + decoration_mode_ = requested_mode; + zxdg_toplevel_decoration_v1_set_mode(zxdg_toplevel_decoration_.get(), + static_cast<uint32_t>(requested_mode)); +} + +// static +void XDGToplevelWrapperImpl::ConfigureDecoration( + void* data, + struct zxdg_toplevel_decoration_v1* decoration, + uint32_t mode) { + auto* surface = static_cast<XDGToplevelWrapperImpl*>(data); + DCHECK(surface); + surface->SetTopLevelDecorationMode(static_cast<DecorationMode>(mode)); +} + +void XDGToplevelWrapperImpl::InitializeXdgDecoration() { + if (connection_->xdg_decoration_manager_v1()) { + DCHECK(!zxdg_toplevel_decoration_); + static const zxdg_toplevel_decoration_v1_listener decoration_listener = { + &XDGToplevelWrapperImpl::ConfigureDecoration, + }; + zxdg_toplevel_decoration_.reset( + zxdg_decoration_manager_v1_get_toplevel_decoration( + connection_->xdg_decoration_manager_v1(), xdg_toplevel_.get())); + zxdg_toplevel_decoration_v1_add_listener(zxdg_toplevel_decoration_.get(), + &decoration_listener, this); + } +} + +XDGSurfaceWrapperImpl* XDGToplevelWrapperImpl::xdg_surface_wrapper() const { + DCHECK(xdg_surface_wrapper_.get()); + return xdg_surface_wrapper_.get(); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h new file mode 100644 index 0000000..14314c6e --- /dev/null +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
@@ -0,0 +1,87 @@ +// Copyright 2021 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_OZONE_PLATFORM_WAYLAND_HOST_XDG_TOPLEVEL_WRAPPER_IMPL_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_XDG_TOPLEVEL_WRAPPER_IMPL_H_ + +#include <memory> + +#include "base/macros.h" +#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h" + +namespace ui { + +class XDGSurfaceWrapperImpl; +class WaylandConnection; +class WaylandWindow; + +// Toplevel wrapper for xdg-shell stable +class XDGToplevelWrapperImpl : public ShellToplevelWrapper { + public: + XDGToplevelWrapperImpl(std::unique_ptr<XDGSurfaceWrapperImpl> surface, + WaylandWindow* wayland_window, + WaylandConnection* connection); + XDGToplevelWrapperImpl(const XDGToplevelWrapperImpl&) = delete; + XDGToplevelWrapperImpl& operator=(const XDGToplevelWrapperImpl&) = delete; + ~XDGToplevelWrapperImpl() override; + + // ShellSurfaceWrapper overrides: + bool Initialize() override; + void SetMaximized() override; + void UnSetMaximized() override; + void SetFullscreen() override; + void UnSetFullscreen() override; + void SetMinimized() override; + void SurfaceMove(WaylandConnection* connection) override; + void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override; + void SetTitle(const base::string16& title) override; + void SetWindowGeometry(const gfx::Rect& bounds) override; + void SetMinSize(int32_t width, int32_t height) override; + void SetMaxSize(int32_t width, int32_t height) override; + void SetAppId(const std::string& app_id) override; + void SetDecoration(DecorationMode decoration) override; + + XDGSurfaceWrapperImpl* xdg_surface_wrapper() const; + + private: + // xdg_toplevel_listener + static void ConfigureTopLevel(void* data, + struct xdg_toplevel* xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array* states); + static void CloseTopLevel(void* data, struct xdg_toplevel* xdg_toplevel); + + // zxdg_decoration_listener + static void ConfigureDecoration( + void* data, + struct zxdg_toplevel_decoration_v1* decoration, + uint32_t mode); + + // Send request to wayland compositor to enable a requested decoration mode. + void SetTopLevelDecorationMode(DecorationMode requested_mode); + + // Initializes the xdg-decoration protocol extension, if available. + void InitializeXdgDecoration(); + + // Ground surface for this toplevel wrapper. + std::unique_ptr<XDGSurfaceWrapperImpl> xdg_surface_wrapper_; + + // Non-owing WaylandWindow that uses this toplevel wrapper. + WaylandWindow* const wayland_window_; + WaylandConnection* const connection_; + + // XDG Shell Stable object. + wl::Object<xdg_toplevel> xdg_toplevel_; + + wl::Object<zxdg_toplevel_decoration_v1> zxdg_toplevel_decoration_; + + // On client side, it keeps track of the decoration mode currently in + // use if xdg-decoration protocol extension is available. + DecorationMode decoration_mode_; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_XDG_TOPLEVEL_WRAPPER_IMPL_H_
diff --git a/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc b/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc new file mode 100644 index 0000000..9b65ac38 --- /dev/null +++ b/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.cc
@@ -0,0 +1,257 @@ +// Copyright 2021 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/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.h" + +#include <xdg-shell-unstable-v6-client-protocol.h> + +#include <memory> + +#include "base/environment.h" +#include "base/nix/xdg_util.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/types/event_type.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/ozone/platform/wayland/common/wayland_util.h" +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_pointer.h" +#include "ui/ozone/platform/wayland/host/wayland_popup.h" +#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h" +#include "ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h" +#include "ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h" + +namespace ui { + +namespace { + +uint32_t TranslateAnchor(WlAnchor anchor) { + switch (anchor) { + case WlAnchor::None: + return ZXDG_POSITIONER_V6_ANCHOR_NONE; + case WlAnchor::Top: + return ZXDG_POSITIONER_V6_ANCHOR_TOP; + case WlAnchor::Bottom: + return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM; + case WlAnchor::Left: + return ZXDG_POSITIONER_V6_ANCHOR_LEFT; + case WlAnchor::Right: + return ZXDG_POSITIONER_V6_ANCHOR_RIGHT; + case WlAnchor::TopLeft: + return ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_LEFT; + case WlAnchor::BottomLeft: + return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_LEFT; + case WlAnchor::TopRight: + return ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_RIGHT; + case WlAnchor::BottomRight: + return ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_RIGHT; + } +} + +uint32_t TranslateGravity(WlGravity gravity) { + switch (gravity) { + case WlGravity::None: + return ZXDG_POSITIONER_V6_GRAVITY_NONE; + case WlGravity::Top: + return ZXDG_POSITIONER_V6_GRAVITY_TOP; + case WlGravity::Bottom: + return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM; + case WlGravity::Left: + return ZXDG_POSITIONER_V6_GRAVITY_LEFT; + case WlGravity::Right: + return ZXDG_POSITIONER_V6_GRAVITY_RIGHT; + case WlGravity::TopLeft: + return ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_LEFT; + case WlGravity::BottomLeft: + return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM | + ZXDG_POSITIONER_V6_GRAVITY_LEFT; + case WlGravity::TopRight: + return ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_RIGHT; + case WlGravity::BottomRight: + return ZXDG_POSITIONER_V6_GRAVITY_BOTTOM | + ZXDG_POSITIONER_V6_GRAVITY_RIGHT; + } +} + +uint32_t TranslateConstraintAdjustment( + WlConstraintAdjustment constraint_adjustment) { + uint32_t res = 0; + if ((constraint_adjustment & WlConstraintAdjustment::SlideX) != + WlConstraintAdjustment::None) + res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X; + if ((constraint_adjustment & WlConstraintAdjustment::SlideY) != + WlConstraintAdjustment::None) + res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y; + if ((constraint_adjustment & WlConstraintAdjustment::FlipX) != + WlConstraintAdjustment::None) + res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X; + if ((constraint_adjustment & WlConstraintAdjustment::FlipY) != + WlConstraintAdjustment::None) + res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y; + if ((constraint_adjustment & WlConstraintAdjustment::ResizeX) != + WlConstraintAdjustment::None) + res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X; + if ((constraint_adjustment & WlConstraintAdjustment::ResizeY) != + WlConstraintAdjustment::None) + res |= ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y; + return res; +} + +} // namespace + +ZXDGPopupV6WrapperImpl::ZXDGPopupV6WrapperImpl( + std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface, + WaylandWindow* wayland_window) + : wayland_window_(wayland_window), + zxdg_surface_v6_wrapper_(std::move(surface)) { + DCHECK(zxdg_surface_v6_wrapper_); + DCHECK(wayland_window_ && wayland_window_->parent_window()); +} + +ZXDGPopupV6WrapperImpl::~ZXDGPopupV6WrapperImpl() = default; + +bool ZXDGPopupV6WrapperImpl::Initialize(WaylandConnection* connection, + const gfx::Rect& bounds) { + if (!connection->shell() && !connection->shell_v6()) { + NOTREACHED() << "Wrong shell protocol"; + return false; + } + + ZXDGSurfaceV6WrapperImpl* parent_xdg_surface = nullptr; + // If the parent window is a popup, the surface of that popup must be used as + // a parent. + if (wl::IsMenuType(wayland_window_->parent_window()->type())) { + auto* wayland_popup = + static_cast<WaylandPopup*>(wayland_window_->parent_window()); + ZXDGPopupV6WrapperImpl* popup = + static_cast<ZXDGPopupV6WrapperImpl*>(wayland_popup->shell_popup()); + parent_xdg_surface = popup->zxdg_surface_v6_wrapper(); + } else { + WaylandToplevelWindow* wayland_surface = + static_cast<WaylandToplevelWindow*>(wayland_window_->parent_window()); + parent_xdg_surface = static_cast<ZXDGToplevelV6WrapperImpl*>( + wayland_surface->shell_toplevel()) + ->zxdg_surface_v6_wrapper(); + } + + if (!zxdg_surface_v6_wrapper_ || !parent_xdg_surface) + return false; + + auto new_bounds = bounds; + // Wayland doesn't allow empty bounds. If a zero or negative size is set, the + // invalid_input error is raised. Thus, use the least possible one. + // WaylandPopup will update its bounds upon the following configure event. + if (new_bounds.IsEmpty()) + new_bounds.set_size({1, 1}); + + if (connection->shell_v6()) + return InitializeV6(connection, new_bounds, parent_xdg_surface); + + return false; +} + +bool ZXDGPopupV6WrapperImpl::InitializeV6( + WaylandConnection* connection, + const gfx::Rect& bounds, + ZXDGSurfaceV6WrapperImpl* parent_xdg_surface) { + static const struct zxdg_popup_v6_listener zxdg_popup_v6_listener = { + &ZXDGPopupV6WrapperImpl::Configure, + &ZXDGPopupV6WrapperImpl::PopupDone, + }; + + zxdg_positioner_v6* positioner = + CreatePositioner(connection, wayland_window_->parent_window(), bounds); + if (!positioner) + return false; + + zxdg_popup_v6_.reset(zxdg_surface_v6_get_popup( + zxdg_surface_v6_wrapper_->zxdg_surface(), + parent_xdg_surface->zxdg_surface(), positioner)); + if (!zxdg_popup_v6_) + return false; + + zxdg_positioner_v6_destroy(positioner); + + if (CanGrabPopup(connection)) { + zxdg_popup_v6_grab(zxdg_popup_v6_.get(), connection->seat(), + connection->serial()); + } + zxdg_popup_v6_add_listener(zxdg_popup_v6_.get(), &zxdg_popup_v6_listener, + this); + + wayland_window_->root_surface()->Commit(); + return true; +} + +zxdg_positioner_v6* ZXDGPopupV6WrapperImpl::CreatePositioner( + WaylandConnection* connection, + WaylandWindow* parent_window, + const gfx::Rect& bounds) { + struct zxdg_positioner_v6* positioner; + positioner = zxdg_shell_v6_create_positioner(connection->shell_v6()); + if (!positioner) + return nullptr; + + auto menu_type = GetMenuTypeForPositioner(connection, parent_window); + + // The parent we got must be the topmost in the stack of the same family + // windows. + DCHECK_EQ(parent_window->GetTopMostChildWindow(), parent_window); + + // Place anchor to the end of the possible position. + gfx::Rect anchor_rect = GetAnchorRect( + menu_type, bounds, + gfx::ScaleToRoundedRect(parent_window->GetBounds(), + 1.0 / parent_window->buffer_scale())); + + zxdg_positioner_v6_set_anchor_rect(positioner, anchor_rect.x(), + anchor_rect.y(), anchor_rect.width(), + anchor_rect.height()); + zxdg_positioner_v6_set_size(positioner, bounds.width(), bounds.height()); + zxdg_positioner_v6_set_anchor(positioner, + TranslateAnchor(GetAnchor(menu_type, bounds))); + zxdg_positioner_v6_set_gravity( + positioner, TranslateGravity(GetGravity(menu_type, bounds))); + zxdg_positioner_v6_set_constraint_adjustment( + positioner, + TranslateConstraintAdjustment(GetConstraintAdjustment(menu_type))); + return positioner; +} + +// static +void ZXDGPopupV6WrapperImpl::Configure(void* data, + struct zxdg_popup_v6* zxdg_popup_v6, + int32_t x, + int32_t y, + int32_t width, + int32_t height) { + // As long as the Wayland compositor repositions/requires to position windows + // relative to their parents, do not propagate final bounds information to + // Chromium. The browser places windows in respect to screen origin, but + // Wayland requires doing so in respect to parent window's origin. To properly + // place windows, the bounds are translated and adjusted according to the + // Wayland compositor needs during WaylandWindow::CreateXdgPopup call. + WaylandWindow* window = + static_cast<ZXDGPopupV6WrapperImpl*>(data)->wayland_window_; + DCHECK(window); + window->HandlePopupConfigure({x, y, width, height}); +} + +// static +void ZXDGPopupV6WrapperImpl::PopupDone(void* data, + struct zxdg_popup_v6* zxdg_popup_v6) { + WaylandWindow* window = + static_cast<ZXDGPopupV6WrapperImpl*>(data)->wayland_window_; + DCHECK(window); + window->Hide(); + window->OnCloseRequest(); +} + +ZXDGSurfaceV6WrapperImpl* ZXDGPopupV6WrapperImpl::zxdg_surface_v6_wrapper() + const { + DCHECK(zxdg_surface_v6_wrapper_.get()); + return zxdg_surface_v6_wrapper_.get(); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.h b/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.h new file mode 100644 index 0000000..b7113c37 --- /dev/null +++ b/ui/ozone/platform/wayland/host/zxdg_popup_v6_wrapper_impl.h
@@ -0,0 +1,63 @@ +// Copyright 2021 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_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_POPUP_V6_WRAPPER_IMPL_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_POPUP_V6_WRAPPER_IMPL_H_ + +#include <memory> + +#include "base/macros.h" +#include "ui/ozone/platform/wayland/host/shell_popup_wrapper.h" + +namespace ui { + +class ZXDGSurfaceV6WrapperImpl; +class WaylandConnection; +class WaylandWindow; + +// Popup wrapper for xdg-shell-unstable-v6 +class ZXDGPopupV6WrapperImpl : public ShellPopupWrapper { + public: + ZXDGPopupV6WrapperImpl(std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface, + WaylandWindow* wayland_window); + ~ZXDGPopupV6WrapperImpl() override; + + // XDGPopupWrapper: + bool Initialize(WaylandConnection* connection, + const gfx::Rect& bounds) override; + + private: + bool InitializeV6(WaylandConnection* connection, + const gfx::Rect& bounds, + ZXDGSurfaceV6WrapperImpl* parent_zxdg_surface_v6_wrapper); + struct zxdg_positioner_v6* CreatePositioner(WaylandConnection* connection, + WaylandWindow* parent_window, + const gfx::Rect& bounds); + + // zxdg_popup_v6_listener + static void Configure(void* data, + struct zxdg_popup_v6* zxdg_popup_v6, + int32_t x, + int32_t y, + int32_t width, + int32_t height); + static void PopupDone(void* data, struct zxdg_popup_v6* zxdg_popup_v6); + + ZXDGSurfaceV6WrapperImpl* zxdg_surface_v6_wrapper() const; + + // Non-owned WaylandWindow that uses this popup. + WaylandWindow* const wayland_window_; + + // Ground surface for this popup. + std::unique_ptr<ZXDGSurfaceV6WrapperImpl> zxdg_surface_v6_wrapper_; + + // XDG Shell V6 object. + wl::Object<zxdg_popup_v6> zxdg_popup_v6_; + + DISALLOW_COPY_AND_ASSIGN(ZXDGPopupV6WrapperImpl); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_POPUP_V6_WRAPPER_IMPL_H_
diff --git a/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.cc b/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.cc new file mode 100644 index 0000000..e203be2b --- /dev/null +++ b/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.cc
@@ -0,0 +1,76 @@ +// Copyright 2021 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/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h" + +#include <xdg-shell-unstable-v6-client-protocol.h> + +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_window.h" + +namespace ui { + +ZXDGSurfaceV6WrapperImpl::ZXDGSurfaceV6WrapperImpl( + WaylandWindow* wayland_window, + WaylandConnection* connection) + : wayland_window_(wayland_window), connection_(connection) {} + +ZXDGSurfaceV6WrapperImpl::~ZXDGSurfaceV6WrapperImpl() = default; + +bool ZXDGSurfaceV6WrapperImpl::Initialize() { + if (!connection_->shell_v6()) { + NOTREACHED() << "Wrong shell protocol"; + return false; + } + + static const zxdg_surface_v6_listener zxdg_surface_v6_listener = { + &ZXDGSurfaceV6WrapperImpl::Configure, + }; + + zxdg_surface_v6_.reset(zxdg_shell_v6_get_xdg_surface( + connection_->shell_v6(), wayland_window_->root_surface()->surface())); + if (!zxdg_surface_v6_) { + LOG(ERROR) << "Failed to create zxdg_surface"; + return false; + } + + zxdg_surface_v6_add_listener(zxdg_surface_v6_.get(), + &zxdg_surface_v6_listener, this); + connection_->ScheduleFlush(); + return true; +} + +void ZXDGSurfaceV6WrapperImpl::AckConfigure() { + DCHECK(zxdg_surface_v6_); + zxdg_surface_v6_ack_configure(zxdg_surface_v6_.get(), + pending_configure_serial_); + connection_->wayland_window_manager()->NotifyWindowConfigured( + wayland_window_); +} + +void ZXDGSurfaceV6WrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) { + DCHECK(zxdg_surface_v6_); + zxdg_surface_v6_set_window_geometry(zxdg_surface_v6_.get(), bounds.x(), + bounds.y(), bounds.width(), + bounds.height()); +} + +// static +void ZXDGSurfaceV6WrapperImpl::Configure( + void* data, + struct zxdg_surface_v6* zxdg_surface_v6, + uint32_t serial) { + auto* surface = static_cast<ZXDGSurfaceV6WrapperImpl*>(data); + DCHECK(surface); + surface->pending_configure_serial_ = serial; + + surface->AckConfigure(); +} + +zxdg_surface_v6* ZXDGSurfaceV6WrapperImpl::zxdg_surface() const { + DCHECK(zxdg_surface_v6_); + return zxdg_surface_v6_.get(); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h b/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h new file mode 100644 index 0000000..c52b44e --- /dev/null +++ b/ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h
@@ -0,0 +1,58 @@ +// Copyright 2021 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_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_SURFACE_V6_WRAPPER_IMPL_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_SURFACE_V6_WRAPPER_IMPL_H_ + +#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" + +#include <cstdint> +#include <string> + +#include "base/strings/string16.h" +#include "ui/ozone/platform/wayland/common/wayland_object.h" + +namespace gfx { +class Rect; +} + +namespace ui { + +class WaylandConnection; +class WaylandWindow; + +// Surface wrapper for xdg-shell-unstable-v6 +class ZXDGSurfaceV6WrapperImpl : public ShellSurfaceWrapper { + public: + ZXDGSurfaceV6WrapperImpl(WaylandWindow* wayland_window, + WaylandConnection* connection); + ZXDGSurfaceV6WrapperImpl(const ZXDGSurfaceV6WrapperImpl&) = delete; + ZXDGSurfaceV6WrapperImpl& operator=(const ZXDGSurfaceV6WrapperImpl&) = delete; + ~ZXDGSurfaceV6WrapperImpl() override; + + // ShellSurfaceWrapper overrides: + bool Initialize() override; + void AckConfigure() override; + void SetWindowGeometry(const gfx::Rect& bounds) override; + + // zxdg_surface_v6_listener + static void Configure(void* data, + struct zxdg_surface_v6* zxdg_surface_v6, + uint32_t serial); + + zxdg_surface_v6* zxdg_surface() const; + + private: + // Non-owing WaylandWindow that uses this surface wrapper. + WaylandWindow* const wayland_window_; + WaylandConnection* const connection_; + + uint32_t pending_configure_serial_ = 0; + + wl::Object<zxdg_surface_v6> zxdg_surface_v6_; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_SURFACE_V6_WRAPPER_IMPL_H_
diff --git a/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc b/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc new file mode 100644 index 0000000..49ddd77 --- /dev/null +++ b/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.cc
@@ -0,0 +1,161 @@ +// Copyright 2021 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/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h" + +#include <xdg-decoration-unstable-v1-client-protocol.h> +#include <xdg-shell-client-protocol.h> +#include <xdg-shell-unstable-v6-client-protocol.h> + +#include "base/strings/utf_string_conversions.h" +#include "ui/base/hit_test.h" +#include "ui/ozone/platform/wayland/common/wayland_util.h" +#include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" +#include "ui/ozone/platform/wayland/host/wayland_connection.h" +#include "ui/ozone/platform/wayland/host/wayland_window.h" +#include "ui/ozone/platform/wayland/host/zxdg_surface_v6_wrapper_impl.h" + +namespace ui { + +ZXDGToplevelV6WrapperImpl::ZXDGToplevelV6WrapperImpl( + std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface, + WaylandWindow* wayland_window, + WaylandConnection* connection) + : zxdg_surface_v6_wrapper_(std::move(surface)), + wayland_window_(wayland_window), + connection_(connection) {} + +ZXDGToplevelV6WrapperImpl::~ZXDGToplevelV6WrapperImpl() = default; + +bool ZXDGToplevelV6WrapperImpl::Initialize() { + if (!connection_->shell_v6()) { + NOTREACHED() << "Wrong shell protocol"; + return false; + } + + static const zxdg_toplevel_v6_listener zxdg_toplevel_v6_listener = { + &ZXDGToplevelV6WrapperImpl::ConfigureTopLevel, + &ZXDGToplevelV6WrapperImpl::CloseTopLevel, + }; + + if (!zxdg_surface_v6_wrapper_) + return false; + + zxdg_toplevel_v6_.reset( + zxdg_surface_v6_get_toplevel(zxdg_surface_v6_wrapper_->zxdg_surface())); + if (!zxdg_toplevel_v6_) { + LOG(ERROR) << "Failed to create zxdg_toplevel"; + return false; + } + zxdg_toplevel_v6_add_listener(zxdg_toplevel_v6_.get(), + &zxdg_toplevel_v6_listener, this); + + wayland_window_->root_surface()->Commit(); + connection_->ScheduleFlush(); + return true; +} + +void ZXDGToplevelV6WrapperImpl::SetMaximized() { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_set_maximized(zxdg_toplevel_v6_.get()); +} + +void ZXDGToplevelV6WrapperImpl::UnSetMaximized() { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_unset_maximized(zxdg_toplevel_v6_.get()); +} + +void ZXDGToplevelV6WrapperImpl::SetFullscreen() { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_set_fullscreen(zxdg_toplevel_v6_.get(), nullptr); +} + +void ZXDGToplevelV6WrapperImpl::UnSetFullscreen() { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_unset_fullscreen(zxdg_toplevel_v6_.get()); +} + +void ZXDGToplevelV6WrapperImpl::SetMinimized() { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_set_minimized(zxdg_toplevel_v6_.get()); +} + +void ZXDGToplevelV6WrapperImpl::SurfaceMove(WaylandConnection* connection) { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_move(zxdg_toplevel_v6_.get(), connection->seat(), + connection->serial()); +} + +void ZXDGToplevelV6WrapperImpl::SurfaceResize(WaylandConnection* connection, + uint32_t hittest) { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_resize(zxdg_toplevel_v6_.get(), connection->seat(), + connection->serial(), + wl::IdentifyDirection(*connection, hittest)); +} + +void ZXDGToplevelV6WrapperImpl::SetTitle(const base::string16& title) { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_set_title(zxdg_toplevel_v6_.get(), + base::UTF16ToUTF8(title).c_str()); +} + +void ZXDGToplevelV6WrapperImpl::SetWindowGeometry(const gfx::Rect& bounds) { + zxdg_surface_v6_wrapper_->SetWindowGeometry(bounds); +} + +void ZXDGToplevelV6WrapperImpl::SetMinSize(int32_t width, int32_t height) { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_set_min_size(zxdg_toplevel_v6_.get(), width, height); +} + +void ZXDGToplevelV6WrapperImpl::SetMaxSize(int32_t width, int32_t height) { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_set_max_size(zxdg_toplevel_v6_.get(), width, height); +} + +void ZXDGToplevelV6WrapperImpl::SetAppId(const std::string& app_id) { + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_set_app_id(zxdg_toplevel_v6_.get(), app_id.c_str()); +} + +void ZXDGToplevelV6WrapperImpl::SetDecoration(DecorationMode decoration) {} + +// static +void ZXDGToplevelV6WrapperImpl::ConfigureTopLevel( + void* data, + struct zxdg_toplevel_v6* zxdg_toplevel_v6, + int32_t width, + int32_t height, + struct wl_array* states) { + auto* surface = static_cast<ZXDGToplevelV6WrapperImpl*>(data); + DCHECK(surface); + + bool is_maximized = + CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED); + bool is_fullscreen = + CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN); + bool is_activated = + CheckIfWlArrayHasValue(states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED); + + surface->wayland_window_->HandleSurfaceConfigure(width, height, is_maximized, + is_fullscreen, is_activated); +} + +// static +void ZXDGToplevelV6WrapperImpl::CloseTopLevel( + void* data, + struct zxdg_toplevel_v6* zxdg_toplevel_v6) { + auto* surface = static_cast<ZXDGToplevelV6WrapperImpl*>(data); + DCHECK(surface); + surface->wayland_window_->OnCloseRequest(); +} + +ZXDGSurfaceV6WrapperImpl* ZXDGToplevelV6WrapperImpl::zxdg_surface_v6_wrapper() + const { + DCHECK(zxdg_surface_v6_wrapper_.get()); + return zxdg_surface_v6_wrapper_.get(); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h b/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h new file mode 100644 index 0000000..29b8300c --- /dev/null +++ b/ui/ozone/platform/wayland/host/zxdg_toplevel_v6_wrapper_impl.h
@@ -0,0 +1,71 @@ +// Copyright 2021 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_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_TOPLEVEL_V6_WRAPPER_IMPL_H_ +#define UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_TOPLEVEL_V6_WRAPPER_IMPL_H_ + +#include <memory> + +#include "base/macros.h" +#include "ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h" + +namespace ui { + +class ZXDGSurfaceV6WrapperImpl; +class WaylandConnection; +class WaylandWindow; + +// Toplevel wrapper for xdg-shell-unstable-v6 +class ZXDGToplevelV6WrapperImpl : public ShellToplevelWrapper { + public: + ZXDGToplevelV6WrapperImpl(std::unique_ptr<ZXDGSurfaceV6WrapperImpl> surface, + WaylandWindow* wayland_window, + WaylandConnection* connection); + ZXDGToplevelV6WrapperImpl(const ZXDGToplevelV6WrapperImpl&) = delete; + ZXDGToplevelV6WrapperImpl& operator=(const ZXDGToplevelV6WrapperImpl&) = + delete; + ~ZXDGToplevelV6WrapperImpl() override; + + // ShellSurfaceWrapper overrides: + bool Initialize() override; + void SetMaximized() override; + void UnSetMaximized() override; + void SetFullscreen() override; + void UnSetFullscreen() override; + void SetMinimized() override; + void SurfaceMove(WaylandConnection* connection) override; + void SurfaceResize(WaylandConnection* connection, uint32_t hittest) override; + void SetTitle(const base::string16& title) override; + void SetWindowGeometry(const gfx::Rect& bounds) override; + void SetMinSize(int32_t width, int32_t height) override; + void SetMaxSize(int32_t width, int32_t height) override; + void SetAppId(const std::string& app_id) override; + void SetDecoration(DecorationMode decoration) override; + + ZXDGSurfaceV6WrapperImpl* zxdg_surface_v6_wrapper() const; + + private: + // zxdg_toplevel_v6_listener + static void ConfigureTopLevel(void* data, + struct zxdg_toplevel_v6* zxdg_toplevel_v6, + int32_t width, + int32_t height, + struct wl_array* states); + static void CloseTopLevel(void* data, + struct zxdg_toplevel_v6* zxdg_toplevel_v6); + + // Ground surface for this toplevel wrapper. + std::unique_ptr<ZXDGSurfaceV6WrapperImpl> zxdg_surface_v6_wrapper_; + + // Non-owing WaylandWindow that uses this toplevel wrapper. + WaylandWindow* const wayland_window_; + WaylandConnection* const connection_; + + // XDG Shell V6 object. + wl::Object<zxdg_toplevel_v6> zxdg_toplevel_v6_; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_HOST_ZXDG_TOPLEVEL_V6_WRAPPER_IMPL_H_
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index fb96af0..b50f3e3 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -620,6 +620,11 @@ Emoji && Symbols </message> </if> + <if expr="chromeos"> + <message name="IDS_APP_SHOW_CLIPBOARD_HISTORY" desc="The context menu item to show the clipboard history menu."> + Clipboard + </message> + </if> <!-- Generic terms --> <message name="IDS_APP_OK" desc="Used for Ok on buttons">
diff --git a/ui/strings/ui_strings_grd/IDS_APP_SHOW_CLIPBOARD_HISTORY.png.sha1 b/ui/strings/ui_strings_grd/IDS_APP_SHOW_CLIPBOARD_HISTORY.png.sha1 new file mode 100644 index 0000000..edfc185 --- /dev/null +++ b/ui/strings/ui_strings_grd/IDS_APP_SHOW_CLIPBOARD_HISTORY.png.sha1
@@ -0,0 +1 @@ +5ab94be1bbbebc839acf4bb0b07c6b5f8ce60b99 \ No newline at end of file
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 308e63f6..6570153 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -180,6 +180,7 @@ "controls/tree/tree_view_controller.h", "controls/tree/tree_view_drawing_provider.h", "controls/views_text_services_context_menu.h", + "controls/views_text_services_context_menu_base.h", "debug_utils.h", "drag_controller.h", "drag_utils.h", @@ -386,7 +387,6 @@ "controls/tree/tree_view_controller.cc", "controls/tree/tree_view_drawing_provider.cc", "controls/views_text_services_context_menu_base.cc", - "controls/views_text_services_context_menu_base.h", "debug_utils.cc", "drag_utils.cc", "focus/external_focus_tracker.cc", @@ -562,6 +562,10 @@ if (is_chromeos_ash || is_chromeos_lacros) { sources += [ "controls/menu/menu_config_chromeos.cc" ] + if (!is_chromeos_lacros) { + public += [ "controls/views_text_services_context_menu_chromeos.h" ] + sources += [ "controls/views_text_services_context_menu_chromeos.cc" ] + } } if (is_mac) {
diff --git a/ui/views/controls/views_text_services_context_menu_base.cc b/ui/views/controls/views_text_services_context_menu_base.cc index a2c0df0..531ebe3 100644 --- a/ui/views/controls/views_text_services_context_menu_base.cc +++ b/ui/views/controls/views_text_services_context_menu_base.cc
@@ -85,7 +85,7 @@ return command_id == IDS_CONTENT_CONTEXT_EMOJI; } -#if !defined(OS_APPLE) +#if !defined(OS_APPLE) && !BUILDFLAG(IS_CHROMEOS_ASH) // static std::unique_ptr<ViewsTextServicesContextMenu> ViewsTextServicesContextMenu::Create(ui::SimpleMenuModel* menu,
diff --git a/ui/views/controls/views_text_services_context_menu_base.h b/ui/views/controls/views_text_services_context_menu_base.h index 2318cf8..f3568f52 100644 --- a/ui/views/controls/views_text_services_context_menu_base.h +++ b/ui/views/controls/views_text_services_context_menu_base.h
@@ -7,12 +7,14 @@ #include "build/build_config.h" #include "ui/views/controls/views_text_services_context_menu.h" +#include "ui/views/views_export.h" namespace views { // This base class is used to add and handle text service items in the textfield // context menu. Specific platforms may subclass and add additional items. -class ViewsTextServicesContextMenuBase : public ViewsTextServicesContextMenu { +class VIEWS_EXPORT ViewsTextServicesContextMenuBase + : public ViewsTextServicesContextMenu { public: ViewsTextServicesContextMenuBase(ui::SimpleMenuModel* menu, Textfield* client); @@ -31,7 +33,7 @@ bool SupportsCommand(int command_id) const override; protected: -#if defined(OS_APPLE) +#if defined(OS_APPLE) || defined(OS_CHROMEOS) Textfield* client() { return client_; } const Textfield* client() const { return client_; } #endif
diff --git a/ui/views/controls/views_text_services_context_menu_chromeos.cc b/ui/views/controls/views_text_services_context_menu_chromeos.cc new file mode 100644 index 0000000..5a2d082 --- /dev/null +++ b/ui/views/controls/views_text_services_context_menu_chromeos.cc
@@ -0,0 +1,79 @@ +// Copyright 2021 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/views/controls/views_text_services_context_menu_chromeos.h" + +#include <utility> + +#include "base/no_destructor.h" +#include "ui/views/controls/views_text_services_context_menu_base.h" + +namespace views { + +namespace { + +using ImplFactory = ViewsTextServicesContextMenuChromeos::ImplFactory; +ImplFactory& GetImplFactory() { + static base::NoDestructor<ImplFactory> impl_factory; + return *impl_factory; +} + +} // namespace + +// static +void ViewsTextServicesContextMenuChromeos::SetImplFactory( + ImplFactory impl_factory) { + GetImplFactory() = std::move(impl_factory); +} + +ViewsTextServicesContextMenuChromeos::ViewsTextServicesContextMenuChromeos( + ui::SimpleMenuModel* menu, + Textfield* client) { + auto& impl_factory = GetImplFactory(); + + // In unit tests, `impl_factory` may not be set. Use + // `ViewTextServicesContextMenuBase` in that case. + if (impl_factory) + impl_ = impl_factory.Run(menu, client); + else + impl_ = std::make_unique<ViewsTextServicesContextMenuBase>(menu, client); +} + +ViewsTextServicesContextMenuChromeos::~ViewsTextServicesContextMenuChromeos() = + default; + +bool ViewsTextServicesContextMenuChromeos::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { + return impl_->GetAcceleratorForCommandId(command_id, accelerator); +} + +bool ViewsTextServicesContextMenuChromeos::IsCommandIdChecked( + int command_id) const { + return impl_->IsCommandIdChecked(command_id); +} + +bool ViewsTextServicesContextMenuChromeos::IsCommandIdEnabled( + int command_id) const { + return impl_->IsCommandIdEnabled(command_id); +} + +void ViewsTextServicesContextMenuChromeos::ExecuteCommand(int command_id, + int event_flags) { + return impl_->ExecuteCommand(command_id, event_flags); +} + +bool ViewsTextServicesContextMenuChromeos::SupportsCommand( + int command_id) const { + return impl_->IsCommandIdEnabled(command_id); +} + +// static +std::unique_ptr<ViewsTextServicesContextMenu> +ViewsTextServicesContextMenu::Create(ui::SimpleMenuModel* menu, + Textfield* client) { + return std::make_unique<ViewsTextServicesContextMenuChromeos>(menu, client); +} + +} // namespace views
diff --git a/ui/views/controls/views_text_services_context_menu_chromeos.h b/ui/views/controls/views_text_services_context_menu_chromeos.h new file mode 100644 index 0000000..4dfd7d0 --- /dev/null +++ b/ui/views/controls/views_text_services_context_menu_chromeos.h
@@ -0,0 +1,51 @@ +// Copyright 2021 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_VIEWS_CONTROLS_VIEWS_TEXT_SERVICES_CONTEXT_MENU_CHROMEOS_H_ +#define UI_VIEWS_CONTROLS_VIEWS_TEXT_SERVICES_CONTEXT_MENU_CHROMEOS_H_ + +#include <memory> + +#include "ui/views/controls/views_text_services_context_menu.h" +#include "ui/views/views_export.h" + +namespace views { + +// This class is used to add and handle text service items in the text context +// menu under the CrOS environment. +class VIEWS_EXPORT ViewsTextServicesContextMenuChromeos + : public ViewsTextServicesContextMenu { + public: + using ImplFactory = base::RepeatingCallback<std::unique_ptr< + ViewsTextServicesContextMenu>(ui::SimpleMenuModel*, Textfield*)>; + + // Injects the method to construct `impl_`. + static void SetImplFactory(ImplFactory factory); + + ViewsTextServicesContextMenuChromeos(ui::SimpleMenuModel* menu, + Textfield* client); + ViewsTextServicesContextMenuChromeos( + const ViewsTextServicesContextMenuChromeos&) = delete; + ViewsTextServicesContextMenuChromeos& operator=( + const ViewsTextServicesContextMenuChromeos&) = delete; + ~ViewsTextServicesContextMenuChromeos() override; + + // ViewsTextServicesContextMenu: + bool GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) const override; + bool IsCommandIdChecked(int command_id) const override; + bool IsCommandIdEnabled(int command_id) const override; + void ExecuteCommand(int command_id, int event_flags) override; + bool SupportsCommand(int command_id) const override; + + private: + // CrOS functionality must be provided by the embedder, so requests are + // forwarded to this concrete object, whose construction can be controlled by + // `SetImplFactory()`. + std::unique_ptr<ViewsTextServicesContextMenu> impl_; +}; + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_VIEWS_TEXT_SERVICES_CONTEXT_MENU_CHROMEOS_H_
diff --git a/ui/views/metadata/type_conversion.cc b/ui/views/metadata/type_conversion.cc index ac0cf76..7b51d5c 100644 --- a/ui/views/metadata/type_conversion.cc +++ b/ui/views/metadata/type_conversion.cc
@@ -19,6 +19,24 @@ namespace views { namespace metadata { +base::Optional<SkColor> RgbaPiecesToSkColor( + const std::vector<base::StringPiece16>& pieces, + size_t start_piece) { + int r, g, b; + double a; + return ((pieces.size() >= start_piece + 4) && + base::StringToInt(pieces[start_piece], &r) && + base::IsValueInRangeForNumericType<uint8_t>(r) && + base::StringToInt(pieces[start_piece + 1], &g) && + base::IsValueInRangeForNumericType<uint8_t>(g) && + base::StringToInt(pieces[start_piece + 2], &b) && + base::IsValueInRangeForNumericType<uint8_t>(b) && + base::StringToDouble(pieces[start_piece + 3], &a)) + ? base::make_optional(SkColorSetARGB( + base::ClampRound<SkAlpha>(a * SK_AlphaOPAQUE), r, g, b)) + : base::nullopt; +} + const base::string16& GetNullOptStr() { static const base::NoDestructor<base::string16> kNullOptStr( base::ASCIIToUTF16("<Empty>")); @@ -215,16 +233,15 @@ const auto members = base::SplitStringPiece( member_string, base::ASCIIToUTF16(","), base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - int x, y, r, g, b, a; + int x, y; double blur; + const auto color = RgbaPiecesToSkColor(members, 3); if ((members.size() == 7) && base::StringToInt(members[0], &x) && base::StringToInt(members[1], &y) && base::StringToDouble(UTF16ToASCII(members[2]), &blur) && - base::StringToInt(members[3], &r) && - base::StringToInt(members[4], &g) && - base::StringToInt(members[5], &b) && base::StringToInt(members[6], &a)) - ret.emplace_back(gfx::Vector2d(x, y), blur, SkColorSetARGB(a, r, g, b)); + color.has_value()) + ret.emplace_back(gfx::Vector2d(x, y), blur, color.value()); } return ret; }
diff --git a/ui/views/metadata/type_conversion.h b/ui/views/metadata/type_conversion.h index 9ba57d4..cf770a3 100644 --- a/ui/views/metadata/type_conversion.h +++ b/ui/views/metadata/type_conversion.h
@@ -107,6 +107,13 @@ // String Conversions --------------------------------------------------------- +// Converts the four elements of |pieces| beginning at |start_piece| to an +// SkColor by assuming the pieces are split from a string like "rgba(r,g,b,a)". +// Returns nullopt if conversion was unsuccessful. +VIEWS_EXPORT base::Optional<SkColor> RgbaPiecesToSkColor( + const std::vector<base::StringPiece16>& pieces, + size_t start_piece); + #define DECLARE_CONVERSIONS(T) \ template <> \ struct VIEWS_EXPORT TypeConverter<T> { \
diff --git a/ui/views/metadata/type_conversion_unittest.cc b/ui/views/metadata/type_conversion_unittest.cc index d1630597..c9d36c2 100644 --- a/ui/views/metadata/type_conversion_unittest.cc +++ b/ui/views/metadata/type_conversion_unittest.cc
@@ -95,7 +95,7 @@ TEST_F(TypeConversionTest, TestConversion_StringToShadowValues) { base::Optional<gfx::ShadowValues> opt_result = metadata::TypeConverter<gfx::ShadowValues>::FromString(base::ASCIIToUTF16( - "[ (6,4),0.53,rgba(23,44,0,255); (93,83),4.33,rgba(10,20,0,15) ]")); + "[ (6,4),0.53,rgba(23,44,0,1); (93,83),4.33,rgba(10,20,0,0.059) ]")); EXPECT_EQ(opt_result.has_value(), true); gfx::ShadowValues result = opt_result.value();
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index ede9124..b5d6fe4a 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc
@@ -253,6 +253,8 @@ SetRestoreBounds(window_, window_bounds); else SetBounds(window_bounds); + // For similar reasons, wait to set visible on all workspaces. + SetVisibleOnAllWorkspaces(params.visible_on_all_workspaces); window_->SetEventTargetingPolicy( params.accept_events ? aura::EventTargetingPolicy::kTargetAndDescendants : aura::EventTargetingPolicy::kNone); @@ -657,11 +659,13 @@ } void NativeWidgetAura::SetVisibleOnAllWorkspaces(bool always_visible) { - // Not implemented on chromeos or for child widgets. + window_->SetProperty(aura::client::kVisibleOnAllWorkspacesKey, + always_visible); } bool NativeWidgetAura::IsVisibleOnAllWorkspaces() const { - return false; + return window_ && + window_->GetProperty(aura::client::kVisibleOnAllWorkspacesKey); } void NativeWidgetAura::Maximize() {
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn index c2e2d2e4..a261bcb7 100644 --- a/ui/webui/resources/cr_components/BUILD.gn +++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -143,6 +143,7 @@ "chromeos/cellular_setup/cellular_setup_icons.m.js", "chromeos/cellular_setup/cellular_setup.m.js", "chromeos/cellular_setup/cellular_types.m.js", + "chromeos/cellular_setup/confirmation_code_page.m.js", "chromeos/cellular_setup/esim_flow_ui.m.js", "chromeos/cellular_setup/final_page.m.js", "chromeos/cellular_setup/mojo_interface_provider.m.js", @@ -153,6 +154,7 @@ "chromeos/cellular_setup/provisioning_page.m.js", "chromeos/cellular_setup/psim_flow_ui.m.js", "chromeos/cellular_setup/setup_selection_flow.m.js", + "chromeos/cellular_setup/cellular_eid_popup.m.js", "chromeos/cellular_setup/setup_loading_page.m.js", "chromeos/cellular_setup/subflow_behavior.m.js", "chromeos/cellular_setup/webview_post_util.m.js", @@ -259,6 +261,8 @@ "chromeos/cellular_setup/cellular_setup.js", "chromeos/cellular_setup/cellular_types.html", "chromeos/cellular_setup/cellular_types.js", + "chromeos/cellular_setup/confirmation_code_page.html", + "chromeos/cellular_setup/confirmation_code_page.js", "chromeos/cellular_setup/esim_flow_ui.html", "chromeos/cellular_setup/esim_flow_ui.js", "chromeos/cellular_setup/final_page.html", @@ -279,6 +283,8 @@ "chromeos/cellular_setup/psim_flow_ui.js", "chromeos/cellular_setup/setup_selection_flow.html", "chromeos/cellular_setup/setup_selection_flow.js", + "chromeos/cellular_setup/cellular_eid_popup.html", + "chromeos/cellular_setup/cellular_eid_popup.js", "chromeos/cellular_setup/setup_loading_page.html", "chromeos/cellular_setup/setup_loading_page.js", "chromeos/cellular_setup/subflow_behavior.html",
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn index 293475a..1d59ced 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
@@ -14,9 +14,11 @@ ":activation_code_page", ":base_page", ":button_bar", + ":cellular_eid_popup", ":cellular_setup", ":cellular_setup_delegate", ":cellular_types", + ":confirmation_code_page", ":esim_manager_listener_behavior", ":esim_manager_utils", ":final_page", @@ -81,6 +83,10 @@ ] } +js_library("confirmation_code_page") { + deps = [ "//ui/webui/resources/js:i18n_behavior" ] +} + js_library("profile_discovery_list_page") { deps = [ "//third_party/polymer/v1_0/components-chromium/iron-list:iron-list-extracted", @@ -111,6 +117,7 @@ deps = [ ":activation_code_page", ":cellular_setup_delegate", + ":confirmation_code_page", ":esim_manager_utils", ":mojo_interface_provider", ":profile_discovery_list_item", @@ -129,6 +136,10 @@ ] } +js_library("cellular_eid_popup") { + deps = [ "//ui/webui/resources/js:i18n_behavior" ] +} + js_library("subflow_behavior") { deps = [ ":cellular_types", @@ -182,6 +193,7 @@ ":cellular_setup.m", ":cellular_setup_delegate.m", ":cellular_types.m", + ":confirmation_code_page.m", ":esim_flow_ui.m", ":esim_manager_listener_behavior.m", ":esim_manager_utils.m", @@ -228,6 +240,12 @@ extra_deps = [ ":activation_code_page_module" ] } +js_library("confirmation_code_page.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.m.js" ] + deps = [ "//ui/webui/resources/js:i18n_behavior.m" ] + extra_deps = [ ":confirmation_code_page_module" ] +} + js_library("profile_discovery_list_item.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/profile_discovery_list_item.m.js" ] deps = [ "//ui/webui/resources/js:i18n_behavior.m" ] @@ -350,6 +368,7 @@ ":activation_code_page.m", ":cellular_setup_delegate.m", ":cellular_types.m", + ":confirmation_code_page.m", ":esim_manager_utils.m", ":final_page.m", ":mojo_interface_provider.m", @@ -373,6 +392,12 @@ extra_deps = [ ":setup_selection_flow_module" ] } +js_library("cellular_eid_popup.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.m.js" ] + deps = [ "//ui/webui/resources/js:i18n_behavior.m" ] + extra_deps = [ ":cellular_eid_popup_module" ] +} + js_library("cellular_setup.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.m.js" ] deps = [ @@ -392,8 +417,10 @@ ":activation_code_page_module", ":base_page_module", ":button_bar_module", + ":cellular_eid_popup_module", ":cellular_setup_icons_module", ":cellular_setup_module", + ":confirmation_code_page_module", ":esim_flow_ui_module", ":final_page_module", ":modulize", @@ -438,6 +465,14 @@ auto_imports = cr_components_chromeos_auto_imports } +polymer_modulizer("confirmation_code_page") { + js_file = "confirmation_code_page.js" + html_file = "confirmation_code_page.html" + html_type = "dom-module" + namespace_rewrites = cr_components_chromeos_namespace_rewrites + auto_imports = cr_components_chromeos_auto_imports +} + polymer_modulizer("setup_loading_page") { js_file = "setup_loading_page.js" html_file = "setup_loading_page.html" @@ -494,6 +529,14 @@ auto_imports = cr_components_chromeos_auto_imports } +polymer_modulizer("cellular_eid_popup") { + js_file = "cellular_eid_popup.js" + html_file = "cellular_eid_popup.html" + html_type = "dom-module" + namespace_rewrites = cr_components_chromeos_namespace_rewrites + auto_imports = cr_components_chromeos_auto_imports +} + polymer_modulizer("cellular_setup") { js_file = "cellular_setup.js" html_file = "cellular_setup.html"
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/cellular_eid_popup.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html similarity index 80% rename from chrome/browser/resources/settings/chromeos/internet_page/cellular_eid_popup.html rename to ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html index d4e3484a..c0ef8b78 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/cellular_eid_popup.html +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.html
@@ -4,14 +4,10 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="../../chromeos/os_settings_icons_css.html"> -<link rel="import" href="./internet_shared_css.html"> <dom-module id="cellular-eid-popup"> <template> - <style include="cr-shared-style - os-settings-icons - settings-shared internet-shared iron-flex"> + <style include="cr-shared-style iron-flex"> .cellular-network-list-header { border-top: var(--cr-separator-line); @@ -58,19 +54,19 @@ aria-describedby="eidDescription"> <div class="header"> <div id="eidTitle" class="title" arian-hidden="true"> - $i18n{eidPopupTitle} + [[i18n('eidPopupTitle')]] </div> <cr-icon-button id="eidPopupCloseIcon" iron-icon="cr:close" - title="$i18n{closeEidPopupButtonLabel}" - aria-label="$i18n{closeEidPopupButtonLabel}" + title="[[i18n('closeEidPopupButtonLabel')]]" + aria-label="[[i18n('closeEidPopupButtonLabel')]]" on-click="onCloseTap_"> </cr-icon-button> </div> <div class="body"> <div id="eidDescription" arian-hidden="true"> - $i18n{eidPopupDescription} + [[i18n('eidPopupDescription')]] </div> <!-- TODO(crbug/1093185): Add eid code --> </div>
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/cellular_eid_popup.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.js similarity index 100% rename from chrome/browser/resources/settings/chromeos/internet_page/cellular_eid_popup.js rename to ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_popup.js
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html new file mode 100644 index 0000000..2d24cee --- /dev/null +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.html
@@ -0,0 +1,18 @@ +<link rel="import" href="../../../html/polymer.html"> + +<link rel="import" href="../../../html/i18n_behavior.html"> +<link rel="import" href="base_page.html"> + +<dom-module id="confirmation-code-page"> + <template> + <style include="iron-flex"> + </style> + <base-page> + <div slot="page-body" class="layout horizontal center-center"> + <!-- TODO(crbug.com/1093185): Create UI for confirmation code page. --> + Please enter your confirmation code for [[getProfileName_(profileProperties_)]]. + </div> + </base-page> + </template> + <script src="confirmation_code_page.js"></script> +</dom-module>
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.js new file mode 100644 index 0000000..84b91e80 --- /dev/null +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/confirmation_code_page.js
@@ -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. + +/** + * Page in eSIM Cellular Setup flow shown if an eSIM profile requires a + * confirmation code to install. This element contains an input for the user to + * enter the confirmation code. + */ +Polymer({ + is: 'confirmation-code-page', + + behaviors: [I18nBehavior], + + properties: { + /** + * @type {?chromeos.cellularSetup.mojom.ESimProfileRemote} + */ + profile: { + type: Object, + observer: 'onProfileChanged_', + }, + + /** + * @type {?chromeos.cellularSetup.mojom.ESimProfileProperties} + * @private + */ + profileProperties_: { + type: Object, + value: null, + }, + }, + + /** @private */ + onProfileChanged_() { + if (!this.profile) { + this.profileProperties_ = null; + return; + } + this.profile.getProperties().then(response => { + this.profileProperties_ = response.properties; + }); + }, + + /** + * @return {string} + * @private + */ + getProfileName_() { + if (!this.profileProperties_) { + return ''; + } + return String.fromCharCode(...this.profileProperties_.name.data); + }, +}); \ No newline at end of file
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html index f6f0cbc..79704c5 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.html
@@ -11,6 +11,7 @@ <link rel="import" href="activation_code_page.html"> <link rel="import" href="final_page.html"> <link rel="import" href="profile_discovery_list_page.html"> +<link rel="import" href="confirmation_code_page.html"> <dom-module id="esim-flow-ui"> <template> @@ -37,6 +38,9 @@ show-no-profiles-message="[[getShowNoProfilesMessage_(pendingProfiles_)]]" show-error="{{showError_}}"> </activation-code-page> + <confirmation-code-page id="confirmationCodePage" + profile="[[selectedProfile_]]"> + </confirmation-code-page> <final-page id="finalPage" delegate="[[delegate]]"
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js index 71f8b81..414a91a 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_flow_ui.js
@@ -8,6 +8,7 @@ PROFILE_LOADING: 'profileLoadingPage', PROFILE_DISCOVERY: 'profileDiscoveryPage', ACTIVATION_CODE: 'activationCodePage', + CONFIRMATION_CODE: 'confirmationCodePage', FINAL: 'finalPage', }; @@ -15,6 +16,7 @@ /* #export */ const ESimUiState = { PROFILE_SEARCH: 'profile-search', ACTIVATION_CODE_ENTRY: 'activation-code-entry', + CONFIRMATION_CODE_ENTRY: 'confirmation-code-entry', PROFILE_SELECTION: 'profile-selection', SETUP_FINISH: 'setup-finish', }; @@ -73,7 +75,7 @@ }, /** - * Profile selected in profileDiscoveryPage to be installed. + * Profile selected to be installed. * @type {?chromeos.cellularSetup.mojom.ESimProfileRemote} * @private */ @@ -141,9 +143,10 @@ this.state_ = ESimUiState.ACTIVATION_CODE_ENTRY; break; case 1: + this.selectedProfile_ = profiles[0]; // Assume installing the profile doesn't require a confirmation // code, send an empty string. - profiles[0].installProfile('').then( + this.selectedProfile_.installProfile('').then( this.handleProfileInstallResponse_.bind(this)); break; default: @@ -159,8 +162,6 @@ * response */ handleProfileInstallResponse_(response) { - // TODO(crbug.com/1093185) Handle - // confirmation code if needed. this.showError_ = response.result !== chromeos.cellularSetup.mojom.ProfileInstallResult.kSuccess; if (response.result === @@ -168,6 +169,11 @@ response.result === chromeos.cellularSetup.mojom.ProfileInstallResult.kFailure) { this.state_ = ESimUiState.SETUP_FINISH; + } else if ( + response.result === + chromeos.cellularSetup.mojom.ProfileInstallResult + .kErrorNeedsConfirmationCode) { + this.state_ = ESimUiState.CONFIRMATION_CODE_ENTRY; } }, @@ -180,6 +186,9 @@ case ESimUiState.ACTIVATION_CODE_ENTRY: this.selectedESimPageName_ = ESimPageName.ACTIVATION_CODE; break; + case ESimUiState.CONFIRMATION_CODE_ENTRY: + this.selectedESimPageName_ = ESimPageName.CONFIRMATION_CODE; + break; case ESimUiState.PROFILE_SELECTION: this.selectedESimPageName_ = ESimPageName.PROFILE_DISCOVERY; break; @@ -209,6 +218,19 @@ skipDiscovery: cellularSetup.ButtonState.HIDDEN, }; break; + case ESimUiState.CONFIRMATION_CODE_ENTRY: + buttonState = { + backward: cellularSetup.ButtonState.SHOWN_AND_ENABLED, + cancel: this.delegate.shouldShowCancelButton() ? + cellularSetup.ButtonState.SHOWN_AND_ENABLED : + cellularSetup.ButtonState.HIDDEN, + done: cellularSetup.ButtonState.SHOWN_AND_ENABLED, + next: cellularSetup.ButtonState.HIDDEN, + tryAgain: cellularSetup.ButtonState.HIDDEN, + skipDiscovery: cellularSetup.ButtonState.HIDDEN, + // TODO(crbug.com/1093185) Add a "Confirm" button state. + }; + break; case ESimUiState.PROFILE_SELECTION: buttonState = { backward: cellularSetup.ButtonState.HIDDEN,
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.js index e2c9783..339c815 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.js +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// #import {getESimManagerRemote} from './mojo_interface_provider.m.js'; +// #import {observeESimManager} from './mojo_interface_provider.m.js'; /** * @fileoverview Polymer behavior for observing ESimManagerObserver @@ -16,10 +16,7 @@ /** @override */ attached() { - this.observer_ = - new chromeos.cellularSetup.mojom.ESimManagerObserverReceiver(this); - cellular_setup.getESimManagerRemote().addObserver( - this.observer_.$.bindNewPipeAndPassRemote()); + cellular_setup.observeESimManager(this); }, // ESimManagerObserver methods. Override these in the implementation.
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js index c416b1c..5b79070 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js
@@ -14,6 +14,7 @@ cr.define('cellular_setup', function() { let cellularRemote = null; let eSimManagerRemote = null; + let isTesting = false; /** * @param {?chromeos.cellularSetup.mojom.CellularSetupRemote} @@ -21,6 +22,7 @@ */ /* #export */ function setCellularSetupRemoteForTesting(testCellularRemote) { cellularRemote = testCellularRemote; + isTesting = true; } /** @@ -42,6 +44,7 @@ */ /* #export */ function setESimManagerRemoteForTesting(testESimManagerRemote) { eSimManagerRemote = testESimManagerRemote; + isTesting = true; } /** @@ -57,11 +60,31 @@ return eSimManagerRemote; } + /** + * @param {!chromeos.cellularSetup.mojom.ESimManagerObserverInterface} + * observer + * @returns {?chromeos.cellularSetup.mojom.ESimManagerObserverReceiver} + */ + /* #export */ function observeESimManager(observer) { + if (isTesting) { + getESimManagerRemote().addObserver( + /** @type {!chromeos.cellularSetup.mojom.ESimManagerObserverRemote} */ + (observer)); + return null; + } + + const receiver = + new chromeos.cellularSetup.mojom.ESimManagerObserverReceiver(observer); + getESimManagerRemote().addObserver(receiver.$.bindNewPipeAndPassRemote()); + return receiver; + } + // #cr_define_end return { setCellularSetupRemoteForTesting, getCellularSetupRemote, setESimManagerRemoteForTesting, - getESimManagerRemote + getESimManagerRemote, + observeESimManager }; });
diff --git a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn index 60495ca..957ac95c8 100644 --- a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -454,6 +454,7 @@ deps = [ ":mojo_interface_provider.m", ":network_list_types.m", + "//third_party/polymer/v3_0/components-chromium/paper-spinner:paper-spinner-lite", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js/cr/ui:focus_row_behavior.m", ]
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_list_item.html b/ui/webui/resources/cr_components/chromeos/network/network_list_item.html index fb0256e..8a58ff8d7 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_list_item.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_list_item.html
@@ -1,6 +1,7 @@ <link rel="import" href="../../../html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> <link rel="import" href="../../../cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="../../../cr_elements/icons.html"> <link rel="import" href="../../../cr_elements/policy/cr_policy_indicator.html"> @@ -78,6 +79,12 @@ --iron-icon-fill-color: #1A73E8; margin-inline-end: 8px; } + + paper-spinner-lite { + height: 20px; + margin-inline-end: 16px; + width: 20px; + } </style> <div id="wrapper" focus-row-container class="layout horizontal center flex"> @@ -99,9 +106,11 @@ </network-icon> </template> <template is="dom-if" if="[[item.polymerIcon]]"> - <iron-icon icon="[[item.polymerIcon]]" class$="[[getItemClassName_(item)]]"></iron-icon> + <iron-icon icon="[[item.polymerIcon]]" + class$="[[getItemClassName_(item, item.customItemType]]"></iron-icon> </template> - <div id="divText" class$="layout horizontal flex [[getItemClassName_(item)]]"> + <div id="divText" class$="layout horizontal flex + [[getItemClassName_(item, item.customItemType)]]"> <div id="networkName" aria-hidden="true"> [[getItemName_(item)]] </div> @@ -135,14 +144,18 @@ </cr-icon-button> </div> </template> - <template is="dom-if" if="[[isESimPendingProfile_(item)]]" restamp> - <!-- TODO(crbug.com/1093185): Download profile when clicked. --> - <cr-button id="downloadButton" - aria-label$="[[getItemName_(item)]], $i18n{networkListItemDownload}"> + <template is="dom-if" if="[[isESimPendingProfile_(item, item.customItemType)]]" restamp> + <cr-button id="installButton" + aria-label$="[[getItemName_(item)]], $i18n{networkListItemDownload}" + on-click="onInstallButtonClick_"> <iron-icon icon="network:download"></iron-icon> $i18n{networkListItemDownload} </cr-button> </template> + <template is="dom-if" if="[[isESimInstallingProfile_(item, item.customItemType)]]" restamp> + <paper-spinner-lite active></paper-spinner-lite> + $i18n{networkListItemAddingProfile} + </template> </div> </div> </template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_list_item.js b/ui/webui/resources/cr_components/chromeos/network/network_list_item.js index af8d29d..f106d20 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_list_item.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_list_item.js
@@ -377,6 +377,15 @@ return this.i18n( 'networkListItemLabelESimPendingProfile', index, total, this.getItemName_()); + } else if (this.isESimInstallingProfile_()) { + if (this.subtitle_) { + return this.i18n( + 'networkListItemLabelESimPendingProfileWithProviderNameInstalling', + index, total, this.getItemName_(), this.subtitle_); + } + return this.i18n( + 'networkListItemLabelESimPendingProfileInstalling', index, total, + this.getItemName_()); } return this.i18n( 'networkListItemLabel', index, total, this.getItemName_()); @@ -495,6 +504,8 @@ if (this.isSubpageButtonVisible_(this.networkState, this.showButtons) && this.$$('#subpage-button') === this.shadowRoot.activeElement) { this.fireShowDetails_(event); + } else if (this.isESimPendingProfile_()) { + this.onInstallButtonClick_(); } else if (this.item.hasOwnProperty('customItemName')) { this.fire('custom-item-selected', this.item); } else { @@ -552,12 +563,17 @@ return this.isFocused ? 'polite' : 'off'; }, + /** @private */ + onInstallButtonClick_() { + this.fire('install-profile', {iccid: this.item.customData.iccid}); + }, + /** * @return {boolean} * @private */ isESimPendingProfile_() { - return this.item.hasOwnProperty('customItemType') && + return !!this.item && this.item.hasOwnProperty('customItemType') && this.item.customItemType === NetworkList.CustomItemType.ESIM_PENDING_PROFILE; }, @@ -569,4 +585,14 @@ getItemClassName_() { return this.isESimPendingProfile_() ? 'esim-pending-profile' : ''; }, + + /** + * @return {boolean} + * @private + */ + isESimInstallingProfile_() { + return !!this.item && this.item.hasOwnProperty('customItemType') && + this.item.customItemType === + NetworkList.CustomItemType.ESIM_INSTALLING_PROFILE; + }, });
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_list_types.js b/ui/webui/resources/cr_components/chromeos/network/network_list_types.js index b9b9fde..a873ff6 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_list_types.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_list_types.js
@@ -14,6 +14,7 @@ NetworkList.CustomItemType = { OOBE: 1, ESIM_PENDING_PROFILE: 2, + ESIM_INSTALLING_PROFILE: 3, }; /**
diff --git a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni index ed430a9..f1a7cbe 100644 --- a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni +++ b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
@@ -19,6 +19,7 @@ "cellular_setup.setCellularSetupRemoteForTesting|setCellularSetupRemoteForTesting", "cellular_setup.getESimManagerRemote|getESimManagerRemote", "cellular_setup.setESimManagerRemoteForTesting|setESimManagerRemoteForTesting", + "cellular_setup.observeESimManager|observeESimManager", "cellular_setup.getPendingESimProfiles|getPendingESimProfiles", "cellular_setup.CellularSetupDelegate|CellularSetupDelegate", "network_config.MojoInterfaceProvider|MojoInterfaceProvider", @@ -33,7 +34,7 @@ "ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_types.html|ButtonState,Button,ButtonBarState,CellularSetupPageName", "ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup_delegate.html|CellularSetupDelegate", "ui/webui/resources/cr_components/chromeos/cellular_setup/subflow_behavior.html|SubflowBehavior", - "ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.html|setCellularSetupRemoteForTesting,getCellularSetupRemote,setESimManagerRemoteForTesting,getESimManagerRemote", + "ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.html|setCellularSetupRemoteForTesting,getCellularSetupRemote,setESimManagerRemoteForTesting,getESimManagerRemote,observeESimManager", "ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_utils.html|getPendingESimProfiles", "ui/webui/resources/cr_components/chromeos/cellular_setup/esim_manager_listener_behavior.html|ESimManagerListenerBehavior", "ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html|CrPolicyNetworkBehaviorMojo",
diff --git a/weblayer/browser/android/javatests/skew/mb_config.pyl b/weblayer/browser/android/javatests/skew/mb_config.pyl index b77af3ca..da42c9e2 100644 --- a/weblayer/browser/android/javatests/skew/mb_config.pyl +++ b/weblayer/browser/android/javatests/skew/mb_config.pyl
@@ -67,7 +67,7 @@ }, 'release_bot': { - 'mixins': ['release', 'static'], + 'mixins': ['release', 'static', 'goma'], }, 'static': {
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc index ae92265..8e62033 100644 --- a/weblayer/browser/content_browser_client_impl.cc +++ b/weblayer/browser/content_browser_client_impl.cc
@@ -661,11 +661,26 @@ content::NavigationHandle* handle) { std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; + TabImpl* tab = TabImpl::FromWebContents(handle->GetWebContents()); + NavigationControllerImpl* navigation_controller = nullptr; + if (tab) { + navigation_controller = + static_cast<NavigationControllerImpl*>(tab->GetNavigationController()); + } if (handle->IsInMainFrame()) { NavigationUIDataImpl* navigation_ui_data = static_cast<NavigationUIDataImpl*>(handle->GetNavigationUIData()); + + NavigationImpl* navigation_impl = nullptr; + if (navigation_controller) { + navigation_impl = + navigation_controller->GetNavigationImplFromHandle(handle); + } + if ((!navigation_ui_data || !navigation_ui_data->disable_network_error_auto_reload()) && + (!navigation_impl || + !navigation_impl->disable_network_error_auto_reload()) && IsNetworkErrorAutoReloadEnabled()) { auto auto_reload_throttle = error_page::NetErrorAutoReloader::MaybeCreateThrottleFor(handle); @@ -688,11 +703,8 @@ // The next highest priority throttle *must* be this as it's responsible for // calling to NavigationController for certain events. - TabImpl* tab = TabImpl::FromWebContents(handle->GetWebContents()); if (tab) { - auto throttle = - static_cast<NavigationControllerImpl*>(tab->GetNavigationController()) - ->CreateNavigationThrottle(handle); + auto throttle = navigation_controller->CreateNavigationThrottle(handle); if (throttle) throttles.push_back(std::move(throttle)); }
diff --git a/weblayer/browser/errorpage_browsertest.cc b/weblayer/browser/errorpage_browsertest.cc index 58abe90e..362b6357 100644 --- a/weblayer/browser/errorpage_browsertest.cc +++ b/weblayer/browser/errorpage_browsertest.cc
@@ -72,9 +72,12 @@ WARN_UNUSED_RESULT { content::TestNavigationManager navigation(web_contents(), url); NavigationController::NavigateParams params; - params.disable_network_error_auto_reload = - disable_network_error_auto_reload; - shell()->tab()->GetNavigationController()->Navigate(url, params); + auto* navigation_controller = shell()->tab()->GetNavigationController(); + std::unique_ptr<DisableAutoReload> disable_auto_reload; + if (disable_network_error_auto_reload) + disable_auto_reload = + std::make_unique<DisableAutoReload>(navigation_controller); + navigation_controller->Navigate(url, params); navigation.WaitForNavigationFinished(); return navigation.was_successful(); } @@ -98,6 +101,23 @@ } private: + class DisableAutoReload : public NavigationObserver { + public: + explicit DisableAutoReload(NavigationController* controller) + : controller_(controller) { + controller_->AddObserver(this); + } + ~DisableAutoReload() override { controller_->RemoveObserver(this); } + + // NavigationObserver implementation: + void NavigationStarted(Navigation* navigation) override { + navigation->DisableNetworkErrorAutoReload(); + } + + private: + NavigationController* controller_; + }; + base::test::ScopedFeatureList feature_list_; };
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java index 48a8e3ef..4212397 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/NavigationImpl.java
@@ -193,6 +193,13 @@ return NavigationImplJni.get().isServedFromBackForwardCache(mNativeNavigationImpl); } + @Override + public void disableNetworkErrorAutoReload() { + if (!NavigationImplJni.get().disableNetworkErrorAutoReload(mNativeNavigationImpl)) { + throw new IllegalStateException(); + } + } + public void setIntentLaunched() { mIntentLaunched = true; } @@ -255,5 +262,6 @@ boolean isPageInitiated(long nativeNavigationImpl); boolean isReload(long nativeNavigationImpl); boolean isServedFromBackForwardCache(long nativeNavigationImpl); + boolean disableNetworkErrorAutoReload(long nativeNavigationImpl); } }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl index 00d369b0..9787b7e 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl
@@ -38,4 +38,5 @@ boolean isUserDecidingIntentLaunch() = 14; boolean isKnownProtocol() = 15; boolean isServedFromBackForwardCache() = 16; + void disableNetworkErrorAutoReload() = 17; }
diff --git a/weblayer/browser/navigation_controller_impl.cc b/weblayer/browser/navigation_controller_impl.cc index ccbf419..fa3b988 100644 --- a/weblayer/browser/navigation_controller_impl.cc +++ b/weblayer/browser/navigation_controller_impl.cc
@@ -302,11 +302,6 @@ std::make_unique<content::NavigationController::LoadURLParams>(url); load_params->should_replace_current_entry = params.should_replace_current_entry; - if (params.disable_network_error_auto_reload) { - auto data = std::make_unique<NavigationUIDataImpl>(); - data->set_disable_network_error_auto_reload(true); - load_params->navigation_ui_data = std::move(data); - } if (params.enable_auto_play) load_params->was_activated = content::mojom::WasActivatedOption::kYes; @@ -396,6 +391,7 @@ base::AutoReset<NavigationImpl*> auto_reset(&navigation_starting_, navigation); navigation->set_safe_to_set_request_headers(true); + navigation->set_safe_to_disable_network_error_auto_reload(true); #if defined(OS_ANDROID) // Desktop mode and per-navigation UA use the same mechanism and so don't @@ -434,6 +430,7 @@ observer.NavigationStarted(navigation); navigation->set_safe_to_set_user_agent(false); navigation->set_safe_to_set_request_headers(false); + navigation->set_safe_to_disable_network_error_auto_reload(false); } void NavigationControllerImpl::DidRedirectNavigation(
diff --git a/weblayer/browser/navigation_impl.cc b/weblayer/browser/navigation_impl.cc index ce04b0c..5634520 100644 --- a/weblayer/browser/navigation_impl.cc +++ b/weblayer/browser/navigation_impl.cc
@@ -94,6 +94,13 @@ return true; } +jboolean NavigationImpl::DisableNetworkErrorAutoReload(JNIEnv* env) { + if (!safe_to_disable_network_error_auto_reload_) + return false; + DisableNetworkErrorAutoReload(); + return true; +} + void NavigationImpl::SetResponse( std::unique_ptr<embedder_support::WebResourceResponse> response) { response_ = std::move(response); @@ -218,6 +225,11 @@ set_user_agent_string_called_ = true; } +void NavigationImpl::DisableNetworkErrorAutoReload() { + DCHECK(safe_to_disable_network_error_auto_reload_); + disable_network_error_auto_reload_ = true; +} + #if defined(OS_ANDROID) static jboolean JNI_NavigationImpl_IsValidRequestHeaderName( JNIEnv* env,
diff --git a/weblayer/browser/navigation_impl.h b/weblayer/browser/navigation_impl.h index 1898d5f..8b11be41 100644 --- a/weblayer/browser/navigation_impl.h +++ b/weblayer/browser/navigation_impl.h
@@ -49,10 +49,18 @@ safe_to_set_user_agent_ = value; } + void set_safe_to_disable_network_error_auto_reload(bool value) { + safe_to_disable_network_error_auto_reload_ = value; + } + void set_was_stopped() { was_stopped_ = true; } bool set_user_agent_string_called() { return set_user_agent_string_called_; } + bool disable_network_error_auto_reload() { + return disable_network_error_auto_reload_; + } + void SetParamsToLoadWhenSafe( std::unique_ptr<content::NavigationController::LoadURLParams> params); std::unique_ptr<content::NavigationController::LoadURLParams> @@ -83,6 +91,7 @@ jboolean IsServedFromBackForwardCache(JNIEnv* env) { return IsServedFromBackForwardCache(); } + jboolean DisableNetworkErrorAutoReload(JNIEnv* env); void SetResponse( std::unique_ptr<embedder_support::WebResourceResponse> response); @@ -107,6 +116,7 @@ void SetRequestHeader(const std::string& name, const std::string& value) override; void SetUserAgentString(const std::string& value) override; + void DisableNetworkErrorAutoReload() override; bool IsPageInitiated() override; bool IsReload() override; bool IsServedFromBackForwardCache() override; @@ -134,6 +144,11 @@ // Whether SetUserAgentString was called. bool set_user_agent_string_called_ = false; + // Whether DisableNetworkErrorAutoReload is allowed at this time. + bool safe_to_disable_network_error_auto_reload_ = false; + + bool disable_network_error_auto_reload_ = false; + #if defined(OS_ANDROID) base::android::ScopedJavaGlobalRef<jobject> java_navigation_; std::unique_ptr<embedder_support::WebResourceResponse> response_;
diff --git a/weblayer/public/java/org/chromium/weblayer/NavigateParams.java b/weblayer/public/java/org/chromium/weblayer/NavigateParams.java index 3d6a71f..0fc051ad 100644 --- a/weblayer/public/java/org/chromium/weblayer/NavigateParams.java +++ b/weblayer/public/java/org/chromium/weblayer/NavigateParams.java
@@ -64,7 +64,10 @@ /** * Disables auto-reload for this navigation if the network is down and comes back later. - * Auto-reload is enabled by default. + * Auto-reload is enabled by default. This is deprecated as of 89, instead use + * {@link Navigation#disableNetworkErrorAutoReload} which works for both embedder-initiated + * navigations and also user-initiated navigations (such as back or forward). Auto-reload + * is disabled if either method is called. */ @NonNull public Builder disableNetworkErrorAutoReload() {
diff --git a/weblayer/public/java/org/chromium/weblayer/Navigation.java b/weblayer/public/java/org/chromium/weblayer/Navigation.java index 61e078f..4b11aa66 100644 --- a/weblayer/public/java/org/chromium/weblayer/Navigation.java +++ b/weblayer/public/java/org/chromium/weblayer/Navigation.java
@@ -255,6 +255,28 @@ } /** + * Disables auto-reload for this navigation if the network is down and comes back later. + * Auto-reload is enabled by default. This method may only be called from + * {@link NavigationCallback.onNavigationStarted}. + * + * @throws IllegalStateException If not called during start. + * + * @since 89 + */ + public void disableNetworkErrorAutoReload() { + ThreadCheck.ensureOnUiThread(); + if (WebLayer.shouldPerformVersionChecks() + && WebLayer.getSupportedMajorVersionInternal() < 89) { + throw new UnsupportedOperationException(); + } + try { + mNavigationImpl.disableNetworkErrorAutoReload(); + } catch (RemoteException e) { + throw new APICallException(e); + } + } + + /** * Sets the user-agent string that applies to the current navigation. This user-agent is not * sticky, it applies to this navigation only (and any redirects or resources that are loaded). * This method may only be called from {@link NavigationCallback.onNavigationStarted}.
diff --git a/weblayer/public/navigation.h b/weblayer/public/navigation.h index 2f1f4d1..22729fc 100644 --- a/weblayer/public/navigation.h +++ b/weblayer/public/navigation.h
@@ -119,6 +119,11 @@ // SetRequestHeader(). virtual void SetUserAgentString(const std::string& value) = 0; + // Disables auto-reload for this navigation if the network is down and comes + // back later. Auto-reload is enabled by default. This function may only be + // called from NavigationObserver::NavigationStarted(). + virtual void DisableNetworkErrorAutoReload() = 0; + // Whether the navigation was initiated by the page. Examples of // page-initiated navigations include: // * <a> link click
diff --git a/weblayer/public/navigation_controller.h b/weblayer/public/navigation_controller.h index 56691c87..9216002 100644 --- a/weblayer/public/navigation_controller.h +++ b/weblayer/public/navigation_controller.h
@@ -19,7 +19,6 @@ // |NavigationController::LoadURLParams|. struct NavigateParams { bool should_replace_current_entry = false; - bool disable_network_error_auto_reload = false; bool enable_auto_play = false; };
diff --git a/weblayer/weblayer_module.gni b/weblayer/weblayer_module.gni index 98004e72..eeb2a50 100644 --- a/weblayer/weblayer_module.gni +++ b/weblayer/weblayer_module.gni
@@ -5,5 +5,4 @@ weblayer_module_desc = { name = "weblayer" android_manifest = "//weblayer/browser/java/AndroidManifest_monochrome.xml" - supports_isolated_split = true }