diff --git a/DEPS b/DEPS index 8a94133..7ee4eff 100644 --- a/DEPS +++ b/DEPS
@@ -213,7 +213,7 @@ # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:7528d700b89db0b6feb32be098d40597f738d3c7', + 'luci_go': 'git_revision:9c88febc5ab63469baf5aae05a74f8e419970ef3', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -245,19 +245,19 @@ # 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': 'a2672102702d7b11cbd70c465fceb3fb9e58f88f', + 'skia_revision': '83859e27c361fb5ceb17e6f71716f119d637c9ca', # 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': 'fe6e3df471e24517f098e874d505b1728c332915', + 'v8_revision': '9e79bc53ba16930f18d7fbef2bbdb0b807547888', # 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': '602b957b88365a9cd34ab73efca4c96675bbb149', + 'angle_revision': '706e44b06a46659c933603c2c7e99d603717bc5b', # 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': 'bca23447ad4667a7b79973569ab5d8d905d211ac', + 'swiftshader_revision': '78491358c250fc627cb02b8d66679dc4a18dc12c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -320,7 +320,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': 'f5cdbdfb498c834043f5426a2887af970ad4b188', + 'devtools_frontend_revision': '7adcfa6de39c286e829362323ae33295585cbf1d', # 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. @@ -663,7 +663,7 @@ Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248', 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'd3e8789ea703ef617c51a36afe8c5dd1348b1a74', + 'url': Var('chromium_git') + '/website.git' + '@' + '70ff5876887c72323938990ba71fa15011e31433', }, 'src/ios/third_party/earl_grey2/src': { @@ -1085,12 +1085,12 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'd35c8af9e3c5814d18ad0a820511b28f53cc69e6', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'e142875d49189d6d52a2e012b7d4a2a653ebbd69', 'condition': 'checkout_linux', }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd5862557d6a2ceef3f85092aa76682a4cdf2fc4e', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3bf9766110f60f8d328d6caac4792b594d2b7189', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1473,7 +1473,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '448ab50107d2f6382e413564e51e8130e92c4e09', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '33928bc89438655f0ab59f4fb8c56ae4a6aa2afa', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1551,7 +1551,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/android/aemu/release/linux-amd64', - 'version': 'Ea-MmVNtNTqZyinCufB9t1a9bhgxSk4eLHIfYMTuWnkC' + 'version': 'myq62o-lUjtKNg97vsknMMge-RUmPfb2nJciJoONW-UC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1570,7 +1570,7 @@ }, 'src/third_party/re2/src': - Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '611baecbcedc9cec1f46e38616b6d8880b676c03', + Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '0d39decb2f0adcbcb943fd31943fcd20398ebe4e', 'src/third_party/r8': { 'packages': [ @@ -1655,7 +1655,7 @@ 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '62d7d0c928c9a040dce96aa2f16c00e7e67d59cb', - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@a19b5047ffcafc95fcba3f39e53f229acca6debc', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@c8fe6cd6739fbb957e6768a978336eeb91674c2b', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1764,7 +1764,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@13bf51fd202bc3a8253df69f36b6b517fefa84c2', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3c094716117773987bee6aa2129b8ece65b365d0', 'condition': 'checkout_src_internal', }, @@ -1783,7 +1783,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/eche_app/app', - 'version': 'Qa5fQL-FhMVjngdj4mWHgB_HEYJHls_GgerHPU6RBWcC', + 'version': 'JgpkC-c8buxqr0xk2MuWo-fOWnb2w8hUm7nANUi75MEC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index fdc67e7d..2664f04 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -1167,7 +1167,7 @@ for s in ('bling-autoroll-builder', 'v8-ci-autoroll-builder', 'wpt-autoroller', 'chrome-weblayer-builder', 'lacros-version-skew-roller', 'skylab-test-cros-roller', - 'infra-try-recipes-tester') + 'infra-try-recipes-tester', 'lacros-tracking-roller') ) | set('%s@skia-public.iam.gserviceaccount.com' % s for s in ('chromium-autoroll', 'chromium-release-autoroll') ) | set('%s@skia-corp.google.com.iam.gserviceaccount.com' % s
diff --git a/android_webview/browser/aw_dark_mode.cc b/android_webview/browser/aw_dark_mode.cc index 24ca3d25..c39a948a 100644 --- a/android_webview/browser/aw_dark_mode.cc +++ b/android_webview/browser/aw_dark_mode.cc
@@ -66,7 +66,7 @@ blink::web_pref::WebPreferences* web_prefs, int force_dark_mode, int force_dark_behavior, - bool allow_algorithmic_darkening) { + bool algorithmic_darkening_allowed) { if (!sShouldEnableSimplifiedDarkMode) { PopulateWebPreferencesForPreT(web_prefs, force_dark_mode, force_dark_behavior); @@ -84,8 +84,8 @@ web_prefs->preferred_color_scheme = blink::mojom::PreferredColorScheme::kDark; } else if (prefers_dark_from_theme_) { - is_dark_mode_ = allow_algorithmic_darkening; - web_prefs->force_dark_mode_enabled = allow_algorithmic_darkening; + is_dark_mode_ = algorithmic_darkening_allowed; + web_prefs->force_dark_mode_enabled = algorithmic_darkening_allowed; } }
diff --git a/android_webview/browser/aw_dark_mode.h b/android_webview/browser/aw_dark_mode.h index fdd10c2..ebfbe2b8 100644 --- a/android_webview/browser/aw_dark_mode.h +++ b/android_webview/browser/aw_dark_mode.h
@@ -22,7 +22,7 @@ void PopulateWebPreferences(blink::web_pref::WebPreferences* web_prefs, int force_dark_mode, int force_dark_behavior, - bool allow_algorithmic_darkening); + bool algorithmic_darkening_allowed); void DetachFromJavaObject( JNIEnv* env,
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc index 3e58fbb..6d8242a 100644 --- a/android_webview/browser/aw_settings.cc +++ b/android_webview/browser/aw_settings.cc
@@ -509,7 +509,7 @@ aw_dark_mode->PopulateWebPreferences( web_prefs, Java_AwSettings_getForceDarkModeLocked(env, obj), Java_AwSettings_getForceDarkBehaviorLocked(env, obj), - Java_AwSettings_getAllowAlgorithmicDarkeningLocked(env, obj)); + Java_AwSettings_isAlgorithmicDarkeningAllowedLocked(env, obj)); } }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwSettings.java b/android_webview/java/src/org/chromium/android_webview/AwSettings.java index df69234d..c05880e 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwSettings.java +++ b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
@@ -69,7 +69,7 @@ @ForceDarkMode private int mForceDarkMode = ForceDarkMode.FORCE_DARK_AUTO; - private boolean mAllowAlgorithmicDarkening; + private boolean mAlgorithmicDarkeningAllowed; public static final int FORCE_DARK_ONLY = ForceDarkBehavior.FORCE_DARK_ONLY; public static final int MEDIA_QUERY_ONLY = ForceDarkBehavior.MEDIA_QUERY_ONLY; @@ -1694,22 +1694,22 @@ } } - public boolean getAllowAlgorithmicDarkening() { + public boolean isAlgorithmicDarkeningAllowed() { synchronized (mAwSettingsLock) { - return getAllowAlgorithmicDarkeningLocked(); + return isAlgorithmicDarkeningAllowedLocked(); } } @CalledByNative - private boolean getAllowAlgorithmicDarkeningLocked() { + private boolean isAlgorithmicDarkeningAllowedLocked() { assert Thread.holdsLock(mAwSettingsLock); - return mAllowAlgorithmicDarkening; + return mAlgorithmicDarkeningAllowed; } - public void setAllowAlgorithmicDarkening(boolean allow) { + public void setAlgorithmicDarkeningAllowed(boolean allow) { synchronized (mAwSettingsLock) { - if (mAllowAlgorithmicDarkening != allow) { - mAllowAlgorithmicDarkening = allow; + if (mAlgorithmicDarkeningAllowed != allow) { + mAlgorithmicDarkeningAllowed = allow; mEventHandler.updateWebkitPreferencesLocked(); } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwDarkModeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwDarkModeTest.java index 39ec167d..55471a0 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwDarkModeTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwDarkModeTest.java
@@ -143,7 +143,7 @@ // Check setForceDarkMode has noops, otherwise ForceDarkening will be turned off. mAwContents.getSettings().setForceDarkMode(AwSettings.FORCE_DARK_OFF); - mAwContents.getSettings().setAllowAlgorithmicDarkening(true); + mAwContents.getSettings().setAlgorithmicDarkeningAllowed(true); // Set force dark mode again to check no ordering issue. mAwContents.getSettings().setForceDarkMode(AwSettings.FORCE_DARK_OFF); @@ -162,7 +162,7 @@ // Check setForceDarkMode has noops, otherwise ForceDarkening will be turned off. mAwContents.getSettings().setForceDarkMode(AwSettings.FORCE_DARK_OFF); - mAwContents.getSettings().setAllowAlgorithmicDarkening(true); + mAwContents.getSettings().setAlgorithmicDarkeningAllowed(true); // Set force dark mode again to check no ordering issue. mAwContents.getSettings().setForceDarkMode(AwSettings.FORCE_DARK_OFF);
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 62a21f3..1df7f8eb2 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
@@ -210,6 +210,10 @@ interface HIDConnectionEvent : Event interface HID : EventTarget +# Window Controls Overlay API is not implemented on Android. +interface WindowControlsOverlay : EventTarget +interface WindowControlsOverlayGeometryChangeEvent : Event + [GLOBAL OBJECT] method openDatabase attribute eventSender # test only
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index dca0909..9fb054f 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -928,6 +928,8 @@ "style/scoped_light_mode_as_default.cc", "style/style_util.cc", "style/style_util.h", + "style/system_shadow.cc", + "style/system_shadow.h", "style/system_toast_style.cc", "style/system_toast_style.h", "system/accessibility/accessibility_feature_disable_dialog.cc",
diff --git a/ash/accessibility/accessibility_controller_impl.cc b/ash/accessibility/accessibility_controller_impl.cc index 1ad3b91..361ed7432 100644 --- a/ash/accessibility/accessibility_controller_impl.cc +++ b/ash/accessibility/accessibility_controller_impl.cc
@@ -2405,11 +2405,12 @@ void AccessibilityControllerImpl::UpdateDictationBubble( bool visible, DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) { + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) { DCHECK(dictation().enabled()); DCHECK(dictation_bubble_controller_); - dictation_bubble_controller_->UpdateBubble(visible, icon, text); + dictation_bubble_controller_->UpdateBubble(visible, icon, text, hints); } } // namespace ash
diff --git a/ash/accessibility/accessibility_controller_impl.h b/ash/accessibility/accessibility_controller_impl.h index 10f77f2..053d2b0 100644 --- a/ash/accessibility/accessibility_controller_impl.h +++ b/ash/accessibility/accessibility_controller_impl.h
@@ -452,7 +452,8 @@ void UpdateDictationBubble( bool visible, DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) override; + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) override; // SessionObserver: void OnSigninScreenPrefServiceInitialized(PrefService* prefs) override;
diff --git a/ash/app_list/views/continue_task_view.cc b/ash/app_list/views/continue_task_view.cc index 1845c2c5..6afdbb3 100644 --- a/ash/app_list/views/continue_task_view.cc +++ b/ash/app_list/views/continue_task_view.cc
@@ -16,6 +16,7 @@ #include "ash/public/cpp/style/color_provider.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/style/highlight_border.h" #include "ash/style/style_util.h" #include "base/bind.h" #include "base/strings/string_util.h" @@ -67,7 +68,7 @@ ContinueTaskView::ContinueTaskView(AppListViewDelegate* view_delegate, bool tablet_mode) - : view_delegate_(view_delegate) { + : view_delegate_(view_delegate), is_tablet_mode_(tablet_mode) { SetFocusBehavior(FocusBehavior::ALWAYS); SetCallback(base::BindRepeating(&ContinueTaskView::OnButtonPressed, base::Unretained(this))); @@ -90,12 +91,8 @@ StyleUtil::ConfigureInkDropAttributes( this, StyleUtil::kBaseColor | StyleUtil::kInkDropOpacity); - if (tablet_mode) { - SetBackground(views::CreateRoundedRectBackground( - ColorProvider::Get()->GetBaseLayerColor( - ColorProvider::BaseLayerType::kTransparent80), - GetCornerRadius(/*tablet_mode=*/true))); - } + + UpdateStyleForTabletMode(); views::BoxLayout* layout_manager = SetLayoutManager(std::make_unique<views::BoxLayout>( @@ -136,6 +133,7 @@ views::View::OnThemeChanged(); bubble_utils::ApplyStyle(title_, bubble_utils::LabelStyle::kBody); bubble_utils::ApplyStyle(subtitle_, bubble_utils::LabelStyle::kSubtitle); + UpdateStyleForTabletMode(); } gfx::Size ContinueTaskView::GetMaximumSize() const { @@ -297,6 +295,21 @@ context_menu_runner_->Cancel(); } +void ContinueTaskView::UpdateStyleForTabletMode() { + // Do nothing if the view is not in tablet mode. + if (!is_tablet_mode_) + return; + + SetBackground(views::CreateRoundedRectBackground( + ColorProvider::Get()->GetBaseLayerColor( + ColorProvider::BaseLayerType::kTransparent80), + GetCornerRadius(/*tablet_mode=*/true))); + SetBorder(std::make_unique<HighlightBorder>( + GetCornerRadius(/*tablet_mode=*/true), + HighlightBorder::Type::kHighlightBorder2, + /*use_light_colors=*/false)); +} + BEGIN_METADATA(ContinueTaskView, views::View) END_METADATA
diff --git a/ash/app_list/views/continue_task_view.h b/ash/app_list/views/continue_task_view.h index 737e987..490d7ec 100644 --- a/ash/app_list/views/continue_task_view.h +++ b/ash/app_list/views/continue_task_view.h
@@ -90,6 +90,10 @@ // Closes the context menu for this view if it is running. void CloseContextMenu(); + // Updates the background and the border if the ContinueTaskView is in tablet + // mode. + void UpdateStyleForTabletMode(); + // The index of this view within a |SearchResultContainerView| that holds it. absl::optional<int> index_in_container_; @@ -99,6 +103,8 @@ views::ImageView* icon_ = nullptr; SearchResult* result_ = nullptr; // Owned by SearchModel::SearchResults. + const bool is_tablet_mode_; + std::unique_ptr<ui::SimpleMenuModel> context_menu_model_; std::unique_ptr<views::MenuRunner> context_menu_runner_;
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 046c330..8cf977b 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -3474,6 +3474,10 @@ S </message> + <message name="IDS_ASH_CALENDAR_NO_EVENTS" desc="Text that appears on the event list when there are no events."> + Open in Google calendar + </message> + <!-- Power off menu --> <message name="IDS_ASH_POWER_BUTTON_MENU_POWER_OFF_BUTTON" desc="Text shown on power off button in power button menu."> Shut down
diff --git a/ash/ash_strings_grd/IDS_ASH_CALENDAR_NO_EVENTS.png.sha1 b/ash/ash_strings_grd/IDS_ASH_CALENDAR_NO_EVENTS.png.sha1 new file mode 100644 index 0000000..99217f8 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_CALENDAR_NO_EVENTS.png.sha1
@@ -0,0 +1 @@ +d8eed11d7af76ee7413e3db47a3336946a49a86e \ No newline at end of file
diff --git a/ash/components/arc/BUILD.gn b/ash/components/arc/BUILD.gn index bec3a0a..9c7667d 100644 --- a/ash/components/arc/BUILD.gn +++ b/ash/components/arc/BUILD.gn
@@ -306,6 +306,8 @@ "test/fake_policy_instance.h", "test/fake_power_instance.cc", "test/fake_power_instance.h", + "test/fake_privacy_items_instance.cc", + "test/fake_privacy_items_instance.h", "test/fake_process_instance.cc", "test/fake_process_instance.h", "test/fake_sharesheet_instance.cc",
diff --git a/ash/components/arc/test/fake_privacy_items_instance.cc b/ash/components/arc/test/fake_privacy_items_instance.cc new file mode 100644 index 0000000..7d0692e --- /dev/null +++ b/ash/components/arc/test/fake_privacy_items_instance.cc
@@ -0,0 +1,30 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/components/arc/test/fake_privacy_items_instance.h" + +#include <utility> + +namespace arc { + +FakePrivacyItemsInstance::FakePrivacyItemsInstance() = default; + +FakePrivacyItemsInstance::~FakePrivacyItemsInstance() = default; + +void FakePrivacyItemsInstance::Init( + mojo::PendingRemote<mojom::PrivacyItemsHost> host_remote, + InitCallback callback) { + host_remote_.reset(); + host_remote_.Bind(std::move(host_remote)); + std::move(callback).Run(); +} + +void FakePrivacyItemsInstance::OnStaticPrivacyIndicatorBoundsChanged( + int32_t display_id, + const std::vector<gfx::Rect>& bounds) { + last_bounds_display_id_ = display_id; + last_bounds_ = bounds; +} + +} // namespace arc
diff --git a/ash/components/arc/test/fake_privacy_items_instance.h b/ash/components/arc/test/fake_privacy_items_instance.h new file mode 100644 index 0000000..3b2aae5 --- /dev/null +++ b/ash/components/arc/test/fake_privacy_items_instance.h
@@ -0,0 +1,42 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_COMPONENTS_ARC_TEST_FAKE_PRIVACY_ITEMS_INSTANCE_H_ +#define ASH_COMPONENTS_ARC_TEST_FAKE_PRIVACY_ITEMS_INSTANCE_H_ + +#include "ash/components/arc/mojom/privacy_items.mojom.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "ui/display/display.h" + +namespace arc { + +class FakePrivacyItemsInstance : public mojom::PrivacyItemsInstance { + public: + FakePrivacyItemsInstance(); + + FakePrivacyItemsInstance(const FakePrivacyItemsInstance&) = delete; + FakePrivacyItemsInstance& operator=(const FakePrivacyItemsInstance&) = delete; + + ~FakePrivacyItemsInstance() override; + + int last_bounds_display_id() const { return last_bounds_display_id_; } + std::vector<gfx::Rect> last_bounds() const { return last_bounds_; } + + // mojom::PrivacyItemsInstance overrides: + void Init(mojo::PendingRemote<mojom::PrivacyItemsHost> host_remote, + InitCallback callback) override; + void OnStaticPrivacyIndicatorBoundsChanged( + int32_t display_id, + const std::vector<gfx::Rect>& bounds) override; + + private: + mojo::Remote<mojom::PrivacyItemsHost> host_remote_; + int32_t last_bounds_display_id_ = display::kInvalidDisplayId; + std::vector<gfx::Rect> last_bounds_; +}; + +} // namespace arc + +#endif // ASH_COMPONENTS_ARC_TEST_FAKE_PRIVACY_ITEMS_INSTANCE_H_
diff --git a/ash/components/fwupd/BUILD.gn b/ash/components/fwupd/BUILD.gn index ebaf724..601e019 100644 --- a/ash/components/fwupd/BUILD.gn +++ b/ash/components/fwupd/BUILD.gn
@@ -21,6 +21,8 @@ sources = [ "firmware_update_manager.cc", "firmware_update_manager.h", + "histogram_util.cc", + "histogram_util.h", ] }
diff --git a/ash/components/fwupd/firmware_update_manager.cc b/ash/components/fwupd/firmware_update_manager.cc index 3eb60e3..860dc074 100644 --- a/ash/components/fwupd/firmware_update_manager.cc +++ b/ash/components/fwupd/firmware_update_manager.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include <utility> +#include "ash/components/fwupd/histogram_util.h" #include "ash/public/cpp/fwupd_download_client.h" #include "ash/webui/firmware_update_ui/mojom/firmware_update.mojom.h" #include "base/base_paths.h" @@ -240,6 +241,10 @@ } } +void FirmwareUpdateManager::RecordDeviceMetrics(int num_devices) { + firmware_update::metrics::EmitDeviceCount(num_devices, is_first_response_); +} + void FirmwareUpdateManager::NotifyUpdateListObservers() { for (auto& observer : update_list_observers_) { observer->OnUpdateListChanged(mojo::Clone(updates_)); @@ -450,6 +455,8 @@ // Clear all cached updates prior to fetching the new update list. updates_.clear(); + RecordDeviceMetrics(devices->size()); + // Fire the observer with an empty list if there are no devices in the // response. if (devices->empty()) { @@ -464,7 +471,6 @@ } void FirmwareUpdateManager::ShowNotificationIfRequired() { - should_show_notification_ = false; for (const auto& update : updates_) { if (update->priority == firmware_update::mojom::UpdatePriority::kCritical && !base::Contains(devices_already_notified_, update->device_id)) { @@ -490,13 +496,19 @@ // Remove the pending device. devices_pending_update_.erase(device_id); - // Fire the observer if there are no devices pending updates. - if (!HasPendingUpdates()) { - if (should_show_notification_) { - ShowNotificationIfRequired(); - } - NotifyUpdateListObservers(); + if (HasPendingUpdates()) { + return; } + + // We only want to show the notification once, at startup. + if (is_first_response_) { + ShowNotificationIfRequired(); + } + + is_first_response_ = false; + + // Fire the observer since there are no remaining devices pending updates. + NotifyUpdateListObservers(); } void FirmwareUpdateManager::OnInstallResponse(bool success) {
diff --git a/ash/components/fwupd/firmware_update_manager.h b/ash/components/fwupd/firmware_update_manager.h index 5d40d41..fdd6be6 100644 --- a/ash/components/fwupd/firmware_update_manager.h +++ b/ash/components/fwupd/firmware_update_manager.h
@@ -169,6 +169,10 @@ // Call to notify observers that a new notification is needed. void NotifyCriticalFirmwareUpdateReceived(); + // Records the # of devices found at startup and whenever the device list + // is refreshed. + void RecordDeviceMetrics(int num_devices); + // Map of a device ID to `FwupdDevice` which is waiting for the list // of updates. base::flat_map<std::string, chromeos::FwupdDevice> devices_pending_update_; @@ -187,8 +191,9 @@ // The device update that is currently inflight. firmware_update::mojom::FirmwareUpdatePtr inflight_update_; - // We only want to show the notification once, at startup. - bool should_show_notification_ = true; + // Used to show the firmware update notification and to determine which + // metric to fire (Startup/Refresh). + bool is_first_response_ = true; // Whether or not fetching updates in inflight. bool is_fetching_updates_ = false;
diff --git a/ash/components/fwupd/firmware_update_manager_unittest.cc b/ash/components/fwupd/firmware_update_manager_unittest.cc index e4a6d483..21c7f16d 100644 --- a/ash/components/fwupd/firmware_update_manager_unittest.cc +++ b/ash/components/fwupd/firmware_update_manager_unittest.cc
@@ -19,6 +19,7 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "chromeos/dbus/fwupd/fwupd_client.h" @@ -209,7 +210,10 @@ return firmware_update_manager_->GetNumUpdatesForTesting(); } - void RequestDevices() { firmware_update_manager_->RequestDevices(); } + void RequestDevices() { + firmware_update_manager_->RequestDevices(); + base::RunLoop().RunUntilIdle(); + } void SetFakeUrlForTesting(const std::string& fake_url) { firmware_update_manager_->SetFakeUrlForTesting(fake_url); @@ -556,7 +560,6 @@ dbus_responses_.push_back(CreateOneUpdateResponse()); RequestDevices(); - base::RunLoop().RunUntilIdle(); // Expect cache to clear and only 1 updates now instead of 2. const std::vector<firmware_update::mojom::FirmwareUpdatePtr>& new_updates = @@ -762,4 +765,21 @@ SetupObserver(&update_observer); EXPECT_EQ(0, message_center_->notification_count()); } + +TEST_F(FirmwareUpdateManagerTest, DeviceCountMetric) { + base::HistogramTester histogram_tester; + EXPECT_CALL(*proxy_, DoCallMethodWithErrorResponse(_, _, _)) + .WillRepeatedly(Invoke(this, &FirmwareUpdateManagerTest::OnMethodCalled)); + dbus_responses_.push_back(CreateOneDeviceResponse()); + dbus_responses_.push_back(CreateOneUpdateResponse()); + dbus_responses_.push_back(CreateOneDeviceResponse()); + dbus_responses_.push_back(CreateOneUpdateResponse()); + FakeUpdateObserver update_observer; + SetupObserver(&update_observer); + histogram_tester.ExpectUniqueSample( + "ChromeOS.FirmwareUpdateUi.OnStartup.DeviceCount", 1, 1); + RequestDevices(); + histogram_tester.ExpectUniqueSample( + "ChromeOS.FirmwareUpdateUi.OnRefresh.DeviceCount", 1, 1); +} } // namespace ash
diff --git a/ash/components/fwupd/histogram_util.cc b/ash/components/fwupd/histogram_util.cc new file mode 100644 index 0000000..c3c86ff --- /dev/null +++ b/ash/components/fwupd/histogram_util.cc
@@ -0,0 +1,30 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/components/fwupd/histogram_util.h" + +#include <string> + +#include "base/metrics/histogram_functions.h" + +namespace { + +const char kHistogramName[] = "ChromeOS.FirmwareUpdateUi."; + +} // namespace +namespace ash { +namespace firmware_update { +namespace metrics { +void EmitDeviceCount(int num_devices, bool is_startup) { + base::UmaHistogramCounts100( + GetSourceStr(is_startup) + std::string(".DeviceCount"), num_devices); +} + +std::string GetSourceStr(bool is_startup) { + return std::string(kHistogramName) + + std::string(is_startup ? "OnStartup" : "OnRefresh"); +} +} // namespace metrics +} // namespace firmware_update +} // namespace ash
diff --git a/ash/components/fwupd/histogram_util.h b/ash/components/fwupd/histogram_util.h new file mode 100644 index 0000000..455d9c714 --- /dev/null +++ b/ash/components/fwupd/histogram_util.h
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_COMPONENTS_FWUPD_HISTOGRAM_UTIL_H_ +#define ASH_COMPONENTS_FWUPD_HISTOGRAM_UTIL_H_ + +#include <cstdint> +#include <string> + +namespace ash { +namespace firmware_update { +namespace metrics { + +void EmitDeviceCount(int num_devices, bool is_startup); + +std::string GetSourceStr(bool is_startup); + +} // namespace metrics +} // namespace firmware_update +} // namespace ash + +#endif // ASH_COMPONENTS_FWUPD_HISTOGRAM_UTIL_H_
diff --git a/ash/components/phonehub/proto/phonehub_api.proto b/ash/components/phonehub/proto/phonehub_api.proto index a01b102..423e7757 100644 --- a/ash/components/phonehub/proto/phonehub_api.proto +++ b/ash/components/phonehub/proto/phonehub_api.proto
@@ -100,6 +100,12 @@ WORK_PROFILE = 1; } +enum ProfileDisableReason { + DISABLE_REASON_UNKNOWN = 0; + DISABLE_REASON_NOT_SUPPORTED = 1; + DISABLE_REASON_DISABLED_BY_POLICY = 2; +} + enum DoNotDisturbCapability { DO_NOT_DISTURB_NORMAL = 0; DO_NOT_DISTURB_NOT_ALLOWED = 1; @@ -147,6 +153,7 @@ FindMyDeviceRingStatus ring_status = 9; ProfileType profile_type = 10; + ProfileDisableReason profile_disable_reason = 17; FindMyDeviceCapability find_my_device_capability = 11;
diff --git a/ash/public/cpp/accessibility_controller.h b/ash/public/cpp/accessibility_controller.h index f45a829..89b0397 100644 --- a/ash/public/cpp/accessibility_controller.h +++ b/ash/public/cpp/accessibility_controller.h
@@ -190,7 +190,8 @@ virtual void UpdateDictationBubble( bool visible, DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) = 0; + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) = 0; protected: AccessibilityController();
diff --git a/ash/style/system_shadow.cc b/ash/style/system_shadow.cc new file mode 100644 index 0000000..53cdbfe --- /dev/null +++ b/ash/style/system_shadow.cc
@@ -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. + +#include "ash/style/system_shadow.h" +#include "base/logging.h" +#include "base/notreached.h" + +namespace ash { + +SystemShadow::SystemShadow(Type type) : type_(type) { + // Note: Init function should be called before SetShadowStyle. + Init(GetElevationFromType(type_)); + // System shadow always use `kChromeOSSystemUI` as shadow style. + SetShadowStyle(gfx::ShadowStyle::kChromeOSSystemUI); +} + +SystemShadow::~SystemShadow() = default; + +int SystemShadow::GetElevationFromType(Type type) { + switch (type) { + case Type::kElevation4: + return 4; + case Type::kElevation8: + return 8; + case Type::kElevation12: + return 12; + case Type::kElevation16: + return 16; + case Type::kElevation24: + return 24; + } +} + +void SystemShadow::SetType(Type type) { + if (type_ == type) + return; + + type_ = type; + SetElevation(GetElevationFromType(type_)); +} + +} // namespace ash
diff --git a/ash/style/system_shadow.h b/ash/style/system_shadow.h new file mode 100644 index 0000000..4c3c4c9 --- /dev/null +++ b/ash/style/system_shadow.h
@@ -0,0 +1,46 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_STYLE_SYSTEM_SHADOW_H_ +#define ASH_STYLE_SYSTEM_SHADOW_H_ + +#include "ash/ash_export.h" +#include "ui/compositor_extra/shadow.h" + +namespace ash { + +// Shadow for Chrome OS System UI component. +class ASH_EXPORT SystemShadow : public ui::Shadow { + public: + // Shadow types of system UI components. The shadows with different elevations + // have different appearance. + enum class Type { + kElevation4, + kElevation8, + kElevation12, + kElevation16, + kElevation24, + }; + + explicit SystemShadow(Type type); + SystemShadow(const SystemShadow&) = delete; + SystemShadow& operator=(const SystemShadow&) = delete; + ~SystemShadow() override; + + // Get shadow elevation according to the given type. + static int GetElevationFromType(Type type); + + // Change shadow type and update shadow elevation and appearance. Note that to + // avoid inconsistency of shadow type and elevation. Always change system + // shadow elevation with `SetType` instead of `SetElevation`. + void SetType(Type type); + Type type() const { return type_; } + + private: + Type type_ = Type::kElevation4; +}; + +} // namespace ash + +#endif // ASH_STYLE_SYSTEM_SHADOW_H_
diff --git a/ash/system/accessibility/dictation_bubble_controller.cc b/ash/system/accessibility/dictation_bubble_controller.cc index 8f87a60..f33cb23 100644 --- a/ash/system/accessibility/dictation_bubble_controller.cc +++ b/ash/system/accessibility/dictation_bubble_controller.cc
@@ -32,13 +32,14 @@ void DictationBubbleController::UpdateBubble( bool visible, DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) { + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) { if (visible) { MaybeInitialize(); - Update(icon, text); + Update(icon, text, hints); widget_->Show(); } else { - Update(icon, text); + Update(icon, text, hints); if (widget_) { widget_->Hide(); } @@ -85,12 +86,13 @@ // Chrome tab. void DictationBubbleController::Update( DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) { + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) { DCHECK(dictation_bubble_view_); DCHECK(widget_); // Update `dictation_bubble_view_`. - dictation_bubble_view_->Update(icon, text); + dictation_bubble_view_->Update(icon, text, hints); // Update the bounds to fit entirely within the screen. gfx::Rect new_bounds = widget_->GetWindowBoundsInScreen();
diff --git a/ash/system/accessibility/dictation_bubble_controller.h b/ash/system/accessibility/dictation_bubble_controller.h index 5866db0b..d3cf84366 100644 --- a/ash/system/accessibility/dictation_bubble_controller.h +++ b/ash/system/accessibility/dictation_bubble_controller.h
@@ -42,7 +42,8 @@ // Updates the bubble's visibility and text content. void UpdateBubble(bool visible, DictationBubbleIconType icon, - const absl::optional<std::u16string>& text); + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints); // ui::InputMethodObserver: void OnFocus() override {} @@ -64,7 +65,8 @@ // Updates the view and widget. void Update(DictationBubbleIconType icon, - const absl::optional<std::u16string>& text); + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints); // Owned by views hierarchy. DictationBubbleView* dictation_bubble_view_ = nullptr;
diff --git a/ash/system/accessibility/dictation_bubble_controller_unittest.cc b/ash/system/accessibility/dictation_bubble_controller_unittest.cc index 69a97c6ab..b06466d 100644 --- a/ash/system/accessibility/dictation_bubble_controller_unittest.cc +++ b/ash/system/accessibility/dictation_bubble_controller_unittest.cc
@@ -40,15 +40,17 @@ } void Show(DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) { + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) { GetController()->UpdateBubble( - /*visible=*/true, /*icon=*/icon, /*text=*/text); + /*visible=*/true, /*icon=*/icon, /*text=*/text, /*hints=*/hints); } void Hide() { GetController()->UpdateBubble(/*visible=*/false, /*icon=*/DictationBubbleIconType::kHidden, - /*text=*/std::u16string()); + /*text=*/std::u16string(), + /*hints=*/std::vector<std::string>()); } DictationBubbleView* GetView() { @@ -89,8 +91,8 @@ return GetView()->GetLabelTextColorForTesting(); } - int GetVisibleHintsCount() { - return GetView()->GetVisibleHintsCountForTesting(); + std::vector<std::u16string> GetVisibleHints() { + return GetView()->GetVisibleHintsForTesting(); } private: @@ -100,7 +102,8 @@ TEST_F(DictationBubbleControllerTest, ShowText) { EXPECT_FALSE(GetView()); Show(DictationBubbleIconType::kHidden, - absl::optional<std::u16string>(u"Testing")); + absl::optional<std::u16string>(u"Testing"), + absl::optional<std::vector<std::string>>()); EXPECT_TRUE(GetView()); EXPECT_TRUE(IsBubbleVisible()); EXPECT_EQ(u"Testing", GetBubbleText()); @@ -113,7 +116,8 @@ TEST_F(DictationBubbleControllerTest, ShowStandbyImage) { EXPECT_FALSE(GetView()); - Show(DictationBubbleIconType::kStandby, absl::optional<std::u16string>()); + Show(DictationBubbleIconType::kStandby, absl::optional<std::u16string>(), + absl::optional<std::vector<std::string>>()); EXPECT_TRUE(GetView()); EXPECT_TRUE(IsBubbleVisible()); EXPECT_EQ(std::u16string(), GetBubbleText()); @@ -127,7 +131,8 @@ TEST_F(DictationBubbleControllerTest, ShowMacroSuccessImage) { EXPECT_FALSE(GetView()); Show(DictationBubbleIconType::kMacroSuccess, - absl::optional<std::u16string>(u"Macro successfull")); + absl::optional<std::u16string>(u"Macro successfull"), + absl::optional<std::vector<std::string>>()); EXPECT_TRUE(GetView()); EXPECT_TRUE(IsBubbleVisible()); EXPECT_EQ(u"Macro successfull", GetBubbleText()); @@ -141,7 +146,8 @@ TEST_F(DictationBubbleControllerTest, ShowMacroFailImage) { EXPECT_FALSE(GetView()); Show(DictationBubbleIconType::kMacroFail, - absl::optional<std::u16string>(u"Macro failed")); + absl::optional<std::u16string>(u"Macro failed"), + absl::optional<std::vector<std::string>>()); EXPECT_TRUE(GetView()); EXPECT_TRUE(IsBubbleVisible()); EXPECT_EQ(u"Macro failed", GetBubbleText()); @@ -166,7 +172,8 @@ // Show bubble UI. EXPECT_FALSE(GetView()); Show(DictationBubbleIconType::kHidden, - absl::optional<std::u16string>(u"Testing")); + absl::optional<std::u16string>(u"Testing"), + absl::optional<std::vector<std::string>>()); EXPECT_TRUE(GetView()); EXPECT_TRUE(IsBubbleVisible()); EXPECT_EQ(u"Testing", GetBubbleText()); @@ -190,11 +197,12 @@ TEST_F(DictationBubbleControllerTest, Hints) { EXPECT_FALSE(GetView()); - Show(DictationBubbleIconType::kStandby, absl::optional<std::u16string>()); + Show(DictationBubbleIconType::kStandby, absl::optional<std::u16string>(), + absl::optional<std::vector<std::string>>()); EXPECT_TRUE(GetView()); EXPECT_TRUE(IsBubbleVisible()); - EXPECT_EQ(0, GetVisibleHintsCount()); + EXPECT_TRUE(GetVisibleHints().size() == 0); HideAndCheckExpectations(); }
diff --git a/ash/system/accessibility/dictation_bubble_view.cc b/ash/system/accessibility/dictation_bubble_view.cc index 07fb055..7c862d6 100644 --- a/ash/system/accessibility/dictation_bubble_view.cc +++ b/ash/system/accessibility/dictation_bubble_view.cc
@@ -11,6 +11,7 @@ #include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/style/ash_color_provider.h" +#include "base/strings/utf_string_conversions.h" #include "cc/paint/skottie_wrapper.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -200,11 +201,16 @@ ~HintView() override = default; // Updates the text content and visibility of all labels in this view. - void Update(const std::vector<std::u16string>& hints) { + void Update(const absl::optional<std::vector<std::string>>& hints) { + if (hints.has_value()) + DCHECK(hints.value().size() <= 5); + for (size_t i = 0; i < labels_.size(); ++i) { - bool has_hint_for_index = i < hints.size(); + bool has_hint_for_index = hints.has_value() && (i < hints.value().size()); labels_[i]->SetVisible(has_hint_for_index ? true : false); - labels_[i]->SetText(has_hint_for_index ? hints[i] : std::u16string()); + labels_[i]->SetText(has_hint_for_index + ? base::UTF8ToUTF16(hints.value()[i]) + : std::u16string()); } SizeToPreferredSize(); } @@ -250,10 +256,12 @@ DictationBubbleView::~DictationBubbleView() = default; -void DictationBubbleView::Update(DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) { +void DictationBubbleView::Update( + DictationBubbleIconType icon, + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) { top_row_view_->Update(icon, text); - hint_view_->Update(std::vector<std::u16string>()); + hint_view_->Update(hints); SizeToContents(); } @@ -313,13 +321,14 @@ return top_row_view_->label_->GetEnabledColor(); } -int DictationBubbleView::GetVisibleHintsCountForTesting() { - int count = 0; +std::vector<std::u16string> DictationBubbleView::GetVisibleHintsForTesting() { + std::vector<std::u16string> hints; for (size_t i = 0; i < hint_view_->labels_.size(); ++i) { - if (hint_view_->labels_[i]->GetVisible()) - ++count; + views::Label* label = hint_view_->labels_[i]; + if (label->GetVisible()) + hints.push_back(label->GetText()); } - return count; + return hints; } BEGIN_METADATA(DictationBubbleView, views::View)
diff --git a/ash/system/accessibility/dictation_bubble_view.h b/ash/system/accessibility/dictation_bubble_view.h index 7c7436b..f02d615 100644 --- a/ash/system/accessibility/dictation_bubble_view.h +++ b/ash/system/accessibility/dictation_bubble_view.h
@@ -6,6 +6,7 @@ #define ASH_SYSTEM_ACCESSIBILITY_DICTATION_BUBBLE_VIEW_H_ #include <string> +#include <vector> #include "ash/ash_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -36,10 +37,11 @@ DictationBubbleView& operator=(const DictationBubbleView&) = delete; ~DictationBubbleView() override; - // Updates the visibility of all child views. Also updates the text content - // of `label_` and updates the size of this view. + // Updates the visibility of all child views, displays the icon/animation + // specified by `icon`, and updates text content and size of this view. void Update(DictationBubbleIconType icon, - const absl::optional<std::u16string>& text); + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints); void OnColorModeChanged(bool dark_mode_enabled); @@ -57,7 +59,7 @@ bool IsMacroFailedImageVisibleForTesting(); SkColor GetLabelBackgroundColorForTesting(); SkColor GetLabelTextColorForTesting(); - int GetVisibleHintsCountForTesting(); + std::vector<std::u16string> GetVisibleHintsForTesting(); private: friend class DictationBubbleControllerTest;
diff --git a/ash/system/holding_space/holding_space_animation_registry.cc b/ash/system/holding_space/holding_space_animation_registry.cc index f2aa63cad..dc9aad5 100644 --- a/ash/system/holding_space/holding_space_animation_registry.cc +++ b/ash/system/holding_space/holding_space_animation_registry.cc
@@ -125,7 +125,7 @@ HoldingSpaceProgressRingAnimation::Type type) { auto it = registry_->ring_animations_by_key().find(key); if (it != registry_->ring_animations_by_key().end() && - it->second.animation->type() != type) { + it->second->type() != type) { registry_->SetProgressRingAnimationForKey(key, nullptr); } } @@ -153,12 +153,8 @@ return; registry_->icon_animations_by_key() - .emplace(key, - AnimationWithSubscription<HoldingSpaceProgressIconAnimation>{ - .animation = - std::make_unique<HoldingSpaceProgressIconAnimation>(), - .subscription = base::CallbackListSubscription()}) - .first->second.animation->Start(); + .emplace(key, std::make_unique<HoldingSpaceProgressIconAnimation>()) + .first->second->Start(); NotifyIconAnimationChangedForKey(key); } @@ -171,29 +167,22 @@ HoldingSpaceProgressRingAnimation::Type type) { auto it = registry_->ring_animations_by_key().find(key); if (it != registry_->ring_animations_by_key().end() && - it->second.animation->type() == type) { + it->second->type() == type) { return; } auto animation = HoldingSpaceProgressRingAnimation::CreateOfType(type); - - auto subscription = - animation->AddAnimationUpdatedCallback(base::BindRepeating( - &ProgressIndicatorAnimationDelegate::OnRingAnimationUpdatedForKey, - base::Unretained(this), key, animation.get())); - - auto subscribed_animation = - AnimationWithSubscription<HoldingSpaceProgressRingAnimation>{ - .animation = std::move(animation), - .subscription = std::move(subscription)}; + animation->AddUnsafeAnimationUpdatedCallback(base::BindRepeating( + &ProgressIndicatorAnimationDelegate::OnRingAnimationUpdatedForKey, + base::Unretained(this), key, animation.get())); if (it == registry_->ring_animations_by_key().end()) { registry_->ring_animations_by_key() - .emplace(key, std::move(subscribed_animation)) - .first->second.animation->Start(); + .emplace(key, std::move(animation)) + .first->second->Start(); } else { - it->second = std::move(subscribed_animation); - it->second.animation->Start(); + it->second = std::move(animation); + it->second->Start(); } NotifyRingAnimationChangedForKey(key); @@ -208,7 +197,7 @@ return; auto animation_it = registry_->icon_animations_by_key().find(key); it->second.Notify(animation_it != registry_->icon_animations_by_key().end() - ? animation_it->second.animation.get() + ? animation_it->second.get() : nullptr); } @@ -221,7 +210,7 @@ return; auto animation_it = registry_->ring_animations_by_key().find(key); it->second.Notify(animation_it != registry_->ring_animations_by_key().end() - ? animation_it->second.animation.get() + ? animation_it->second.get() : nullptr); }
diff --git a/ash/system/holding_space/holding_space_progress_indicator_animation.cc b/ash/system/holding_space/holding_space_progress_indicator_animation.cc index 3f90236..7d50d79 100644 --- a/ash/system/holding_space/holding_space_progress_indicator_animation.cc +++ b/ash/system/holding_space/holding_space_progress_indicator_animation.cc
@@ -24,6 +24,11 @@ return animation_updated_callback_list_.Add(std::move(callback)); } +void HoldingSpaceProgressIndicatorAnimation::AddUnsafeAnimationUpdatedCallback( + base::RepeatingClosureList::CallbackType callback) { + animation_updated_callback_list_.AddUnsafe(std::move(callback)); +} + void HoldingSpaceProgressIndicatorAnimation::Start() { StartInternal(/*is_cyclic_restart=*/false); }
diff --git a/ash/system/holding_space/holding_space_progress_indicator_animation.h b/ash/system/holding_space/holding_space_progress_indicator_animation.h index 0551465..0d99f3b 100644 --- a/ash/system/holding_space/holding_space_progress_indicator_animation.h +++ b/ash/system/holding_space/holding_space_progress_indicator_animation.h
@@ -34,6 +34,14 @@ base::CallbackListSubscription AddAnimationUpdatedCallback( base::RepeatingClosureList::CallbackType callback); + // Adds the specified `callback` to be notified of animation updates. + // NOTE: Because no subscription is returned by which to remove `callback`, + // this method should only be used where the `callback` is guaranteed to live + // at least as long as `this`. When lifetime is in doubt, prefer the use of + // `AddAnimationUpdatedCallback()`. + void AddUnsafeAnimationUpdatedCallback( + base::RepeatingClosureList::CallbackType callback); + // Immediately starts this animation. void Start();
diff --git a/ash/system/progress_indicator/progress_indicator_animation_registry.cc b/ash/system/progress_indicator/progress_indicator_animation_registry.cc index 87abd684..030e71f 100644 --- a/ash/system/progress_indicator/progress_indicator_animation_registry.cc +++ b/ash/system/progress_indicator/progress_indicator_animation_registry.cc
@@ -12,10 +12,7 @@ // Type aliases ---------------------------------------------------------------- template <typename AnimationType> -using KeyedAnimationWithSubscriptionMap = - std::map<const void*, - ProgressIndicatorAnimationRegistry::AnimationWithSubscription< - AnimationType>>; +using KeyedAnimationMap = std::map<const void*, std::unique_ptr<AnimationType>>; template <typename CallbackListType> using KeyedAnimationChangedCallbackListMap = @@ -27,7 +24,7 @@ // that the associated animation has changed. template <typename AnimationType, typename CallbackListType> void NotifyAnimationChangedForKey( - KeyedAnimationWithSubscriptionMap<AnimationType>* animations_by_key, + KeyedAnimationMap<AnimationType>* animations_by_key, KeyedAnimationChangedCallbackListMap<CallbackListType>* animation_changed_callback_lists_by_key, const void* key) { @@ -36,7 +33,7 @@ return; auto animations_it = animations_by_key->find(key); callback_lists_it->second.Notify(animations_it != animations_by_key->end() - ? animations_it->second.animation.get() + ? animations_it->second.get() : nullptr); } @@ -81,10 +78,10 @@ // * `GetProgressRingAnimationForKey()` template <typename AnimationType> AnimationType* GetAnimationForKey( - KeyedAnimationWithSubscriptionMap<AnimationType>* animations_by_key, + KeyedAnimationMap<AnimationType>* animations_by_key, const void* key) { auto it = animations_by_key->find(key); - return it != animations_by_key->end() ? it->second.animation.get() : nullptr; + return it != animations_by_key->end() ? it->second.get() : nullptr; } // Implements: @@ -92,17 +89,14 @@ // * `SetProgressRingAnimationForKey()` template <typename AnimationType, typename CallbackListType> AnimationType* SetAnimationForKey( - KeyedAnimationWithSubscriptionMap<AnimationType>* animations_by_key, + KeyedAnimationMap<AnimationType>* animations_by_key, KeyedAnimationChangedCallbackListMap<CallbackListType>* animation_changed_callback_lists_by_key, const void* key, std::unique_ptr<AnimationType> animation) { AnimationType* animation_ptr = animation.get(); if (animation) { - (*animations_by_key)[key] = - ProgressIndicatorAnimationRegistry::AnimationWithSubscription< - AnimationType>{.animation = std::move(animation), - .subscription = base::CallbackListSubscription()}; + (*animations_by_key)[key] = std::move(animation); NotifyAnimationChangedForKey(animations_by_key, animation_changed_callback_lists_by_key, key); } else {
diff --git a/ash/system/progress_indicator/progress_indicator_animation_registry.h b/ash/system/progress_indicator/progress_indicator_animation_registry.h index 138935ca..6c7c195 100644 --- a/ash/system/progress_indicator/progress_indicator_animation_registry.h +++ b/ash/system/progress_indicator/progress_indicator_animation_registry.h
@@ -95,18 +95,9 @@ void EraseAllAnimationsForKeyIf( base::RepeatingCallback<bool(const void* key)> predicate); - // TODO(dmblack): Move to private after completing refactor of - // `ProgressIndicatorAnimationRegistry` and `HoldingSpaceAnimationRegistry`. - template <typename AnimationType> - struct AnimationWithSubscription { - std::unique_ptr<AnimationType> animation; - base::CallbackListSubscription subscription; - }; - // TODO(dmblack): Remove these methods after completing refactor of // `ProgressIndicatorAnimationRegistry` and `HoldingSpaceAnimationRegistry`. - std::map<const void*, - AnimationWithSubscription<HoldingSpaceProgressIconAnimation>>& + std::map<const void*, std::unique_ptr<HoldingSpaceProgressIconAnimation>>& icon_animations_by_key() { return icon_animations_by_key_; } @@ -114,8 +105,7 @@ icon_animation_changed_callback_lists_by_key() { return icon_animation_changed_callback_lists_by_key_; } - std::map<const void*, - AnimationWithSubscription<HoldingSpaceProgressRingAnimation>>& + std::map<const void*, std::unique_ptr<HoldingSpaceProgressRingAnimation>>& ring_animations_by_key() { return ring_animations_by_key_; } @@ -126,8 +116,7 @@ private: // Mapping of keys to their associated progress icon animations. - std::map<const void*, - AnimationWithSubscription<HoldingSpaceProgressIconAnimation>> + std::map<const void*, std::unique_ptr<HoldingSpaceProgressIconAnimation>> icon_animations_by_key_; // Mapping of keys to their associated icon animation changed callback lists. @@ -137,8 +126,7 @@ icon_animation_changed_callback_lists_by_key_; // Mapping of keys to their associated progress ring animations. - std::map<const void*, - AnimationWithSubscription<HoldingSpaceProgressRingAnimation>> + std::map<const void*, std::unique_ptr<HoldingSpaceProgressRingAnimation>> ring_animations_by_key_; // Mapping of keys to their associated ring animation changed callback lists.
diff --git a/ash/system/time/calendar_event_list_view.cc b/ash/system/time/calendar_event_list_view.cc index 98af72a..ee663b32 100644 --- a/ash/system/time/calendar_event_list_view.cc +++ b/ash/system/time/calendar_event_list_view.cc
@@ -4,8 +4,11 @@ #include "ash/system/time/calendar_event_list_view.h" +#include "ash/public/cpp/system_tray_client.h" +#include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_provider.h" +#include "ash/system/model/system_tray_model.h" #include "ash/system/time/calendar_utils.h" #include "ash/system/time/calendar_view_controller.h" #include "ash/system/tray/tray_popup_utils.h" @@ -18,7 +21,7 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/background.h" -#include "ui/views/controls/label.h" +#include "ui/views/controls/button/label_button.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/layout/box_layout.h" #include "ui/views/vector_icons.h" @@ -32,6 +35,39 @@ } // namespace +// A view that's displayed when the user selects a day cell from the calendar +// month view that has no events. Clicking on it opens Google calendar. +class CalendarEmptyEventListView : public views::LabelButton { + public: + explicit CalendarEmptyEventListView() + : views::LabelButton( + views::Button::PressedCallback(base::BindRepeating( + &CalendarEmptyEventListView::OpenCalendarDefault, + base::Unretained(this))), + l10n_util::GetStringUTF16(IDS_ASH_CALENDAR_NO_EVENTS)) { + SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_CENTER); + } + CalendarEmptyEventListView(const CalendarEmptyEventListView& other) = delete; + CalendarEmptyEventListView& operator=( + const CalendarEmptyEventListView& other) = delete; + ~CalendarEmptyEventListView() override = default; + + // views::View: + void OnThemeChanged() override { + views::View::OnThemeChanged(); + SetEnabledTextColors(calendar_utils::GetPrimaryTextColor()); + } + + // Callback that's invoked when the user clicks on "Open in Google calendar" + // in an empty event list. + void OpenCalendarDefault() { + GURL finalized_url; + bool opened_pwa = false; + Shell::Get()->system_tray_model()->client()->ShowCalendarEvent( + absl::nullopt, opened_pwa, finalized_url); + } +}; + CalendarEventListView::CalendarEventListView( CalendarViewController* calendar_view_controller) : calendar_view_controller_(calendar_view_controller), @@ -100,19 +136,30 @@ std::list<google_apis::calendar::CalendarEvent> events = calendar_view_controller_->SelectedDateEvents(); - // Sorts the event by start time. - events.sort([](google_apis::calendar::CalendarEvent& a, - google_apis::calendar::CalendarEvent& b) { - return a.start_time().date_time() < b.start_time().date_time(); - }); + if (events.size() > 0) { + // Sorts the event by start time. + events.sort([](google_apis::calendar::CalendarEvent& a, + google_apis::calendar::CalendarEvent& b) { + return a.start_time().date_time() < b.start_time().date_time(); + }); - for (const google_apis::calendar::CalendarEvent& event : events) { - auto* event_entry = content_view_->AddChildView( - std::make_unique<CalendarEventListItemView>(event)); + for (const google_apis::calendar::CalendarEvent& event : events) { + auto* event_entry = content_view_->AddChildView( + std::make_unique<CalendarEventListItemView>(event)); - // Needs to repaint the `content_view_`'s children. - event_entry->InvalidateLayout(); + // Needs to repaint the `content_view_`'s children. + event_entry->InvalidateLayout(); + } + + return; } + + // Show "Open in Google calendar" + CalendarEmptyEventListView* empty_list_view = content_view_->AddChildView( + std::make_unique<CalendarEmptyEventListView>()); + + // Needs to repaint the `content_view_`'s children. + empty_list_view->InvalidateLayout(); } BEGIN_METADATA(CalendarEventListView, views::View);
diff --git a/ash/system/time/calendar_event_list_view_unittest.cc b/ash/system/time/calendar_event_list_view_unittest.cc index 52e401b..24515086 100644 --- a/ash/system/time/calendar_event_list_view_unittest.cc +++ b/ash/system/time/calendar_event_list_view_unittest.cc
@@ -91,7 +91,9 @@ CreateEventListView(date); - EXPECT_EQ(0u, content_view()->children().size()); + // No events, so we see the empty list default. + EXPECT_EQ(1u, content_view()->children().size()); + EXPECT_EQ(u"Open in Google calendar", GetSummary(0)->GetText()); SetSelectedDate(date); @@ -110,7 +112,8 @@ SetSelectedDate(date + base::Days(2)); // 0 event on 20 Nov 2021. - EXPECT_EQ(0u, content_view()->children().size()); + EXPECT_EQ(1u, content_view()->children().size()); + EXPECT_EQ(u"Open in Google calendar", GetSummary(0)->GetText()); SetSelectedDate(date + base::Days(3));
diff --git a/ash/system/time/calendar_view_unittest.cc b/ash/system/time/calendar_view_unittest.cc index c425df2..57bde6b 100644 --- a/ash/system/time/calendar_view_unittest.cc +++ b/ash/system/time/calendar_view_unittest.cc
@@ -5,6 +5,7 @@ #include "ash/system/time/calendar_view.h" #include "ash/shell.h" +#include "ash/strings/grit/ash_strings.h" #include "ash/style/icon_button.h" #include "ash/system/time/calendar_event_list_view.h" #include "ash/system/time/calendar_month_view.h" @@ -17,6 +18,7 @@ #include "base/test/task_environment.h" #include "base/time/time.h" #include "base/time/time_override.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/views/controls/button/label_button.h" @@ -630,6 +632,12 @@ PressTab(); EXPECT_EQ(close_button(), focus_manager->GetFocusedView()); + // Goes to empty list view. + PressTab(); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_CALENDAR_NO_EVENTS), + static_cast<views::LabelButton*>(focus_manager->GetFocusedView()) + ->GetText()); + // Goes back to back button. PressTab();
diff --git a/ash/webui/personalization_app/BUILD.gn b/ash/webui/personalization_app/BUILD.gn index dd37e13b..55900716 100644 --- a/ash/webui/personalization_app/BUILD.gn +++ b/ash/webui/personalization_app/BUILD.gn
@@ -9,6 +9,7 @@ static_library("personalization_app") { sources = [ + "personalization_app_ambient_provider.h", "personalization_app_theme_provider.h", "personalization_app_ui.cc", "personalization_app_ui.h", @@ -48,6 +49,8 @@ source_set("browser_test_support") { testonly = true sources = [ + "test/fake_personalization_app_ambient_provider.cc", + "test/fake_personalization_app_ambient_provider.h", "test/fake_personalization_app_theme_provider.cc", "test/fake_personalization_app_theme_provider.h", "test/fake_personalization_app_user_provider.cc",
diff --git a/ash/webui/personalization_app/mojom/personalization_app.mojom b/ash/webui/personalization_app/mojom/personalization_app.mojom index 2b34b5c3..9763916 100644 --- a/ash/webui/personalization_app/mojom/personalization_app.mojom +++ b/ash/webui/personalization_app/mojom/personalization_app.mojom
@@ -280,3 +280,10 @@ // Select the downloaded profile image as the user image. SelectProfileImage(); }; + +// Provides APIs to expose Ambient mode settings. +// Used by the Personalization Hub. +interface AmbientProvider{ + // Boolean pref for whether ambient mode is enabled. + IsAmbientModeEnabled() => (bool enabled); +};
diff --git a/ash/webui/personalization_app/personalization_app_ambient_provider.h b/ash/webui/personalization_app/personalization_app_ambient_provider.h new file mode 100644 index 0000000..5fdf532 --- /dev/null +++ b/ash/webui/personalization_app/personalization_app_ambient_provider.h
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WEBUI_PERSONALIZATION_APP_PERSONALIZATION_APP_AMBIENT_PROVIDER_H_ +#define ASH_WEBUI_PERSONALIZATION_APP_PERSONALIZATION_APP_AMBIENT_PROVIDER_H_ + +#include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" + +namespace ash { + +class PersonalizationAppAmbientProvider + : public personalization_app::mojom::AmbientProvider { + public: + virtual void BindInterface( + mojo::PendingReceiver<personalization_app::mojom::AmbientProvider> + receiver) = 0; +}; + +} // namespace ash + +#endif // ASH_WEBUI_PERSONALIZATION_APP_PERSONALIZATION_APP_AMBIENT_PROVIDER_H_
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc index 0cad0fcd..2c09250 100644 --- a/ash/webui/personalization_app/personalization_app_ui.cc +++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -7,6 +7,7 @@ #include "ash/constants/ash_features.h" #include "ash/grit/ash_personalization_app_resources.h" #include "ash/grit/ash_personalization_app_resources_map.h" +#include "ash/webui/personalization_app/personalization_app_ambient_provider.h" #include "ash/webui/personalization_app/personalization_app_theme_provider.h" #include "ash/webui/personalization_app/personalization_app_url_constants.h" #include "ash/webui/personalization_app/personalization_app_user_provider.h" @@ -126,10 +127,12 @@ PersonalizationAppUI::PersonalizationAppUI( content::WebUI* web_ui, + std::unique_ptr<PersonalizationAppAmbientProvider> ambient_provider, std::unique_ptr<PersonalizationAppThemeProvider> theme_provider, std::unique_ptr<PersonalizationAppUserProvider> user_provider, std::unique_ptr<PersonalizationAppWallpaperProvider> wallpaper_provider) : ui::MojoWebUIController(web_ui), + ambient_provider_(std::move(ambient_provider)), theme_provider_(std::move(theme_provider)), user_provider_(std::move(user_provider)), wallpaper_provider_(std::move(wallpaper_provider)) { @@ -165,6 +168,12 @@ PersonalizationAppUI::~PersonalizationAppUI() = default; void PersonalizationAppUI::BindInterface( + mojo::PendingReceiver<personalization_app::mojom::AmbientProvider> + receiver) { + ambient_provider_->BindInterface(std::move(receiver)); +} + +void PersonalizationAppUI::BindInterface( mojo::PendingReceiver<personalization_app::mojom::ThemeProvider> receiver) { theme_provider_->BindInterface(std::move(receiver)); }
diff --git a/ash/webui/personalization_app/personalization_app_ui.h b/ash/webui/personalization_app/personalization_app_ui.h index 5893744..e45a5b8 100644 --- a/ash/webui/personalization_app/personalization_app_ui.h +++ b/ash/webui/personalization_app/personalization_app_ui.h
@@ -13,6 +13,7 @@ namespace ash { +class PersonalizationAppAmbientProvider; class PersonalizationAppThemeProvider; class PersonalizationAppWallpaperProvider; class PersonalizationAppUserProvider; @@ -21,6 +22,7 @@ public: PersonalizationAppUI( content::WebUI* web_ui, + std::unique_ptr<PersonalizationAppAmbientProvider> ambient_provider, std::unique_ptr<PersonalizationAppThemeProvider> theme_provider, std::unique_ptr<PersonalizationAppUserProvider> user_provider, std::unique_ptr<PersonalizationAppWallpaperProvider> wallpaper_provider); @@ -31,6 +33,10 @@ ~PersonalizationAppUI() override; void BindInterface( + mojo::PendingReceiver<personalization_app::mojom::AmbientProvider> + receiver); + + void BindInterface( mojo::PendingReceiver<personalization_app::mojom::ThemeProvider> receiver); @@ -42,6 +48,7 @@ receiver); private: + std::unique_ptr<PersonalizationAppAmbientProvider> ambient_provider_; std::unique_ptr<PersonalizationAppThemeProvider> theme_provider_; std::unique_ptr<PersonalizationAppUserProvider> user_provider_; std::unique_ptr<PersonalizationAppWallpaperProvider> wallpaper_provider_;
diff --git a/ash/webui/personalization_app/resources/BUILD.gn b/ash/webui/personalization_app/resources/BUILD.gn index b848c86..79a19de5 100644 --- a/ash/webui/personalization_app/resources/BUILD.gn +++ b/ash/webui/personalization_app/resources/BUILD.gn
@@ -48,7 +48,7 @@ "trusted/wallpaper/wallpaper_observer.ts", "trusted/wallpaper/wallpaper_reducers.ts", "trusted/wallpaper/wallpaper_state.ts", - "trusted/wallpaper/wallpaper_subpage.ts", + "trusted/wallpaper/index.ts", "untrusted/iframe_api.ts", "untrusted/setup.ts", @@ -83,6 +83,7 @@ "trusted/wallpaper/wallpaper_images_element.ts", "trusted/wallpaper/wallpaper_preview_element.ts", "trusted/wallpaper/wallpaper_selected_element.ts", + "trusted/wallpaper/wallpaper_subpage_element.ts", "untrusted/collections_grid.ts", "untrusted/images_grid.ts",
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_app.ts b/ash/webui/personalization_app/resources/trusted/personalization_app.ts index 8ed58e5..16fa214 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_app.ts +++ b/ash/webui/personalization_app/resources/trusted/personalization_app.ts
@@ -21,7 +21,7 @@ import './user_preview_element.js'; import './user/avatar_list_element.js'; import './user/user_subpage_element.js'; -import './wallpaper/wallpaper_subpage.js'; +import './wallpaper/index.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html index 151571f..fc2960e 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html +++ b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html
@@ -18,34 +18,6 @@ personalization-breadcrumb { grid-area: breadcrumb; } - #wallpaperContainer { - display: grid; - flex-grow: 1; - grid-template-areas: - '. leftspacer selected rightspacer .' - '. leftspacer . rightspacer .' - '. leftspacer imagegrid rightspacer .' - '. leftspacer . rightspacer .'; - grid-template-columns: 1fr 16px minmax(568px, 920px) 16px 1fr; - grid-template-rows: 172px 12px 1fr 12px; - position: relative; - width: 100%; - } - #leftspacer { - grid-area: leftspacer; - } - #rightspacer { - grid-area: rightspacer; - } - wallpaper-selected { - grid-area: selected; - } - wallpaper-collections, - wallpaper-images, - google-photos-collection, - local-images { - grid-area: imagegrid; - } personalization-toast { bottom: 16px; left: 16px; @@ -60,6 +32,9 @@ position: absolute; width: 100%; } + wallpaper-subpage { + flex-grow: 1; + } </style> <div id="container"> <!-- dwell-time is set to 200ms to populate history state more quickly while @@ -87,30 +62,8 @@ <user-subpage></user-subpage> </template> <template is="dom-if" if="[[shouldShowWallpaperSubpage_(path_)]]"> - <div id="wallpaperContainer"> - <!-- Prevent left margin from collapsing on narrow window in RTL --> - <div id="leftspacer"></div> - <wallpaper-selected path="[[path_]]" collection-id="[[queryParams_.id]]"> - </wallpaper-selected> - <!-- do not use hidden$ here - need to listen on property change in - these elements. --> - <wallpaper-collections hidden="[[!shouldShowCollections_(path_)]]"> - </wallpaper-collections> - <wallpaper-images collection-id="[[queryParams_.id]]" - hidden="[[!shouldShowCollectionImages_(path_)]]"></wallpaper-images> - <template is="dom-if" if="[[isGooglePhotosIntegrationEnabled_()]]"> - <google-photos-collection - album-id="[[queryParams_.googlePhotosAlbumId]]" - hidden="[[!shouldShowGooglePhotosCollection_(path_)]]"> - </google-photos-collection> - </template> - <local-images hidden="[[!shouldShowLocalCollection_(path_)]]"> - </local-images> - <!-- Prevent the right margin from collapsing when window gets very - narrow --> - <div id="rightspacer"></div> - <wallpaper-fullscreen></wallpaper-fullscreen> - </div> + <wallpaper-subpage path="[[path_]]" query-params="[[queryParams_]]"> + </wallpaper-subpage> </template> <personalization-toast></personalization-toast> </div>
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_router_element.ts b/ash/webui/personalization_app/resources/trusted/personalization_router_element.ts index 4b0386d..9581ac4 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_router_element.ts +++ b/ash/webui/personalization_app/resources/trusted/personalization_router_element.ts
@@ -104,39 +104,16 @@ this.setProperties({path_: path, queryParams_: queryParams}); } - private shouldShowCollections_(path: string): boolean { - return path === Paths.Collections; - } - - private shouldShowCollectionImages_(path: string): boolean { - return path === Paths.CollectionImages; - } - - private shouldShowGooglePhotosCollection_(path: string): boolean { - return path === Paths.GooglePhotosCollection; - } - - private shouldShowLocalCollection_(path: string): boolean { - return path === Paths.LocalCollection; - } - - /** - * Whether Google Photos integration is enabled. - */ - private isGooglePhotosIntegrationEnabled_(): boolean { - return loadTimeData.getBoolean('isGooglePhotosIntegrationEnabled'); - } - private shouldShowRootPage_(path: string|null): boolean { return isPersonalizationHubEnabled() && path === Paths.Root; } private shouldShowAmbientSubpage_(path: string|null): boolean { - return !!path?.startsWith(Paths.Ambient); + return isPersonalizationHubEnabled() && !!path?.startsWith(Paths.Ambient); } private shouldShowUserSubpage_(path: string|null): boolean { - return !!path?.startsWith(Paths.User); + return isPersonalizationHubEnabled() && !!path?.startsWith(Paths.User); } private shouldShowWallpaperSubpage_(path: string|null): boolean {
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/index.ts similarity index 96% rename from ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage.ts rename to ash/webui/personalization_app/resources/trusted/wallpaper/index.ts index 1ba3a917..2c679cf 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/index.ts
@@ -15,6 +15,7 @@ import './wallpaper_images_element.js'; import './wallpaper_preview_element.js'; import './wallpaper_selected_element.js'; +import './wallpaper_subpage_element.js'; import './styles.js'; import {onMessageReceived} from './untrusted_message_handler.js';
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html new file mode 100644 index 0000000..b94a8d0 --- /dev/null +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html
@@ -0,0 +1,57 @@ +<style> + #wallpaperContainer { + display: grid; + grid-template-areas: + '. leftspacer selected rightspacer .' + '. leftspacer . rightspacer .' + '. leftspacer imagegrid rightspacer .' + '. leftspacer . rightspacer .'; + grid-template-columns: 1fr 16px minmax(568px, 920px) 16px 1fr; + grid-template-rows: 172px 12px 1fr 12px; + height: 100%; + position: relative; + width: 100%; + } + + #leftspacer { + grid-area: leftspacer; + } + + #rightspacer { + grid-area: rightspacer; + } + + wallpaper-selected { + grid-area: selected; + } + + wallpaper-collections, + wallpaper-images, + google-photos-collection, + local-images { + grid-area: imagegrid; + } +</style> +<div id="wallpaperContainer"> + <!-- Prevent left margin from collapsing on narrow window in RTL --> + <div id="leftspacer"></div> + <wallpaper-selected path="[[path]]" collection-id="[[queryParams.id]]"> + </wallpaper-selected> + <!-- do not use hidden$ here - need to listen on property change in + these elements. --> + <wallpaper-collections hidden="[[!shouldShowCollections_(path)]]"> + </wallpaper-collections> + <wallpaper-images collection-id="[[queryParams.id]]" + hidden="[[!shouldShowCollectionImages_(path)]]"></wallpaper-images> + <template is="dom-if" if="[[isGooglePhotosIntegrationEnabled_()]]"> + <google-photos-collection album-id="[[queryParams.googlePhotosAlbumId]]" + hidden="[[!shouldShowGooglePhotosCollection_(path)]]"> + </google-photos-collection> + </template> + <local-images hidden="[[!shouldShowLocalCollection_(path)]]"> + </local-images> + <!-- Prevent the right margin from collapsing when window gets very + narrow --> + <div id="rightspacer"></div> + <wallpaper-fullscreen></wallpaper-fullscreen> +</div>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts new file mode 100644 index 0000000..7fc9275 --- /dev/null +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts
@@ -0,0 +1,56 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview This component displays the wallpaper section of the + * personalization SWA. + */ + +import {loadTimeData} from '//resources/js/load_time_data.m.js'; +import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {Paths} from '../personalization_router_element.js'; + +export class WallpaperSubpage extends PolymerElement { + static get is() { + return 'wallpaper-subpage'; + } + + static get template() { + return html`{__html_template__}`; + } + + static get properties() { + return {path: String, queryParams: Object}; + } + + path: string; + queryParams: Record<string, string>; + + private shouldShowCollections_(path: string): boolean { + return path === Paths.Collections; + } + + private shouldShowCollectionImages_(path: string): boolean { + return path === Paths.CollectionImages; + } + + private shouldShowGooglePhotosCollection_(path: string): boolean { + return this.isGooglePhotosIntegrationEnabled_() && + path === Paths.GooglePhotosCollection; + } + + private shouldShowLocalCollection_(path: string): boolean { + return path === Paths.LocalCollection; + } + + /** + * Whether Google Photos integration is enabled. + */ + private isGooglePhotosIntegrationEnabled_(): boolean { + return loadTimeData.getBoolean('isGooglePhotosIntegrationEnabled'); + } +} + +customElements.define(WallpaperSubpage.is, WallpaperSubpage);
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.cc b/ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.cc new file mode 100644 index 0000000..33cd764 --- /dev/null +++ b/ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.cc
@@ -0,0 +1,30 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.h" + +#include "ash/webui/personalization_app/mojom/personalization_app.mojom-forward.h" +#include "content/public/browser/web_ui.h" + +namespace ash { + +FakePersonalizationAppAmbientProvider::FakePersonalizationAppAmbientProvider( + content::WebUI* web_ui) {} + +FakePersonalizationAppAmbientProvider:: + ~FakePersonalizationAppAmbientProvider() = default; + +void FakePersonalizationAppAmbientProvider::BindInterface( + mojo::PendingReceiver<personalization_app::mojom::AmbientProvider> + receiver) { + ambient_receiver_.reset(); + ambient_receiver_.Bind(std::move(receiver)); +} + +void FakePersonalizationAppAmbientProvider::IsAmbientModeEnabled( + IsAmbientModeEnabledCallback callback) { + std::move(callback).Run(std::move(true)); +} + +} // namespace ash
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.h b/ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.h new file mode 100644 index 0000000..2ba6f52 --- /dev/null +++ b/ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.h
@@ -0,0 +1,49 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WEBUI_PERSONALIZATION_APP_TEST_FAKE_PERSONALIZATION_APP_AMBIENT_PROVIDER_H_ +#define ASH_WEBUI_PERSONALIZATION_APP_TEST_FAKE_PERSONALIZATION_APP_AMBIENT_PROVIDER_H_ + +#include "ash/webui/personalization_app/personalization_app_ambient_provider.h" + +#include <stdint.h> + +#include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" + +namespace content { +class WebUI; +} // namespace content + +namespace ash { + +class FakePersonalizationAppAmbientProvider + : public PersonalizationAppAmbientProvider { + public: + explicit FakePersonalizationAppAmbientProvider(content::WebUI* web_ui); + + FakePersonalizationAppAmbientProvider( + const FakePersonalizationAppAmbientProvider&) = delete; + FakePersonalizationAppAmbientProvider& operator=( + const FakePersonalizationAppAmbientProvider&) = delete; + + ~FakePersonalizationAppAmbientProvider() override; + + // PersonalizationAppAmbientProvider: + void BindInterface( + mojo::PendingReceiver<personalization_app::mojom::AmbientProvider> + receiver) override; + + // personalization_app::mojom::AmbientProvider + void IsAmbientModeEnabled(IsAmbientModeEnabledCallback callback) override; + + private: + mojo::Receiver<ash::personalization_app::mojom::AmbientProvider> + ambient_receiver_{this}; +}; + +} // namespace ash + +#endif // ASH_WEBUI_PERSONALIZATION_APP_TEST_FAKE_PERSONALIZATION_APP_AMBIENT_PROVIDER_H_
diff --git a/ash/webui/personalization_app/test/personalization_app_browsertest.js b/ash/webui/personalization_app/test/personalization_app_browsertest.js index bc36ef7..ef76aac5 100644 --- a/ash/webui/personalization_app/test/personalization_app_browsertest.js +++ b/ash/webui/personalization_app/test/personalization_app_browsertest.js
@@ -150,13 +150,22 @@ TEST_F('WallpaperSubpageBrowserTest', 'LoadsCollectionsUntrustedIframe', () => { const router = document.querySelector('personalization-router'); - assertTrue(!!router); + assertTrue(!!router, 'personalization-router should be top level element'); - const collections = router.shadowRoot.querySelector('wallpaper-collections'); - assertTrue(!!collections); + const wallpaperSubpage = router.shadowRoot.querySelector('wallpaper-subpage'); + assertTrue( + !!wallpaperSubpage, + 'wallpaper-subpage should be found under personalization-router'); + + const collections = + wallpaperSubpage.shadowRoot.querySelector('wallpaper-collections'); + assertTrue( + !!collections, + 'wallpaper-collections should be found under wallpaper-subpage'); + const iframe = collections.shadowRoot.getElementById('collections-iframe'); - assertTrue(!!iframe); + assertTrue(!!iframe, 'iframe with id collections-iframe should be visible'); assertEquals( 'chrome-untrusted://personalization/untrusted/collections.html',
diff --git a/ash/webui/personalization_app/test/personalization_app_browsertest_fixture.cc b/ash/webui/personalization_app/test/personalization_app_browsertest_fixture.cc index c0daa36..8925bcf 100644 --- a/ash/webui/personalization_app/test/personalization_app_browsertest_fixture.cc +++ b/ash/webui/personalization_app/test/personalization_app_browsertest_fixture.cc
@@ -8,6 +8,7 @@ #include "ash/webui/personalization_app/personalization_app_ui.h" #include "ash/webui/personalization_app/personalization_app_url_constants.h" +#include "ash/webui/personalization_app/test/fake_personalization_app_ambient_provider.h" #include "ash/webui/personalization_app/test/fake_personalization_app_theme_provider.h" #include "ash/webui/personalization_app/test/fake_personalization_app_user_provider.h" #include "ash/webui/personalization_app/test/fake_personalization_app_wallpaper_provider.h" @@ -16,6 +17,8 @@ std::unique_ptr<content::WebUIController> TestPersonalizationAppWebUIProvider::NewWebUI(content::WebUI* web_ui, const GURL& url) { + auto ambient_provider = + std::make_unique<ash::FakePersonalizationAppAmbientProvider>(web_ui); auto theme_provider = std::make_unique<FakePersonalizationAppThemeProvider>(web_ui); auto wallpaper_provider = @@ -23,8 +26,8 @@ auto user_provider = std::make_unique<ash::FakePersonalizationAppUserProvider>(web_ui); return std::make_unique<ash::PersonalizationAppUI>( - web_ui, std::move(theme_provider), std::move(user_provider), - std::move(wallpaper_provider)); + web_ui, std::move(ambient_provider), std::move(theme_provider), + std::move(user_provider), std::move(wallpaper_provider)); } void PersonalizationAppBrowserTestFixture::SetUpOnMainThread() {
diff --git a/ash/webui/shimless_rma/resources/BUILD.gn b/ash/webui/shimless_rma/resources/BUILD.gn index 0c87633..8a6907f 100644 --- a/ash/webui/shimless_rma/resources/BUILD.gn +++ b/ash/webui/shimless_rma/resources/BUILD.gn
@@ -37,6 +37,7 @@ "reimaging_provisioning_page.js", "repair_component_chip.js", "shimless_rma.js", + "shimless_rma_fonts_css.js", "shimless_rma_shared_css.js", "splash_screen.js", "wrapup_finalize_page.js",
diff --git a/ash/webui/shimless_rma/resources/calibration_component_chip.html b/ash/webui/shimless_rma/resources/calibration_component_chip.html index 17e686cf..9207f6f 100644 --- a/ash/webui/shimless_rma/resources/calibration_component_chip.html +++ b/ash/webui/shimless_rma/resources/calibration_component_chip.html
@@ -1,4 +1,4 @@ -<style include="cr-shared-style shimless-rma-shared"> +<style include="cr-shared-style shimless-rma-shared shimless-fonts"> :host { padding: 1px; } @@ -12,7 +12,12 @@ align-items: normal; border-radius: 4px; box-shadow: var(--cr-card-shadow); + color: var(--shimless-component-text-color); + font-family: var(--shimless-component-font-family); + font-size: var(--shimless-component-font-size); + font-weight: var(--shimless-medium-font-weight); height: 70px; + line-height: var(--shimless-component-line-height); margin-bottom: 20px; margin-inline-end: 10px; width: 190px;
diff --git a/ash/webui/shimless_rma/resources/calibration_component_chip.js b/ash/webui/shimless_rma/resources/calibration_component_chip.js index 62d71e7c..2e0e8ee 100644 --- a/ash/webui/shimless_rma/resources/calibration_component_chip.js +++ b/ash/webui/shimless_rma/resources/calibration_component_chip.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './shimless_rma_fonts_css.js'; import './shimless_rma_shared_css.js'; import './icons.js';
diff --git a/ash/webui/shimless_rma/resources/critical_error_page.html b/ash/webui/shimless_rma/resources/critical_error_page.html index 37d77eb..3862c23 100644 --- a/ash/webui/shimless_rma/resources/critical_error_page.html +++ b/ash/webui/shimless_rma/resources/critical_error_page.html
@@ -25,7 +25,7 @@ class="small-icon"> </iron-icon> <h1>[[i18n('criticalErrorTitleText')]]</h1> - <div>[[i18n('criticalErrorMessageText')]]</div> + <div class="instructions">[[i18n('criticalErrorMessageText')]]</div> <div id="writeProtectStatus">[[statusString_]]</div> <cr-button id="exitToLoginButton" on-click="onExitToLoginButtonClicked_" disabled="[[allButtonsDisabled]]">
diff --git a/ash/webui/shimless_rma/resources/index.html b/ash/webui/shimless_rma/resources/index.html index 52597ab3..43efdcb 100644 --- a/ash/webui/shimless_rma/resources/index.html +++ b/ash/webui/shimless_rma/resources/index.html
@@ -11,6 +11,7 @@ <shimless-rma></shimless-rma> <link rel="stylesheet" src="shimless_rma_shared_css.js"> + <link rel="stylesheet" src="shimless_rma_fonts_css.js"> <script type="module" src="shimless_rma.js"></script> <!-- Below mojo script required to run browser tests --> <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
diff --git a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html index f6a165ec..60b91572 100644 --- a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.html
@@ -1,4 +1,4 @@ -<style include="cr-shared-style shimless-rma-shared"> +<style include="cr-shared-style shimless-rma-shared shimless-fonts"> #dialogBody { overflow-wrap: anywhere; } @@ -8,7 +8,11 @@ } #inputValidationLabel { - color: var(--google-grey-600); + color: var(--shimless-hint-text-color); + font-family: var(--shimless-hint-font-family); + font-size: var(--shimless-hint-font-size); + font-weight: var(--shimless-medium-font-weight); + line-height: var(--shimless-hint-line-height); } :host([rsu-code-invalid_]) #inputValidationLabel { @@ -22,15 +26,24 @@ #inputContainer { width: 275px; } + + #rsuCodeDialogLink { + color: var(--cros-link-color); + text-decoration: none; + } </style> <base-page orientation="column"> <div slot="header"> <h1>[[i18n('rsuCodePageTitleText')]]</h1> - <div> + <div class="instructions"> <span inner-h-t-m-l="[[rsuInstructionsText_]]"></span> </div> <div id="inputContainer"> + <div id="inputValidationLabel"> + [[i18n('rsuCodeLabelText')]] + <span id="rsuCodeLengthLabel">[[rsuCodeLengthLabel_]]</span> + </div> <cr-input id="rsuCode" value="{{rsuCode_}}" @@ -39,10 +52,6 @@ auto-validate disabled="[[allButtonsDisabled]]"> </cr-input> - <div id="inputValidationLabel"> - [[i18n('rsuCodeLabelText')]] - <span id="rsuCodeLengthLabel">[[rsuCodeLengthLabel_]]</span> - </div> </div> </div> <div slot="body">
diff --git a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js index a2cbdc66..73bbb84 100644 --- a/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js +++ b/ash/webui/shimless_rma/resources/onboarding_enter_rsu_wp_disable_code_page.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './shimless_rma_fonts_css.js'; import './shimless_rma_shared_css.js'; import './base_page.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
diff --git a/ash/webui/shimless_rma/resources/onboarding_landing_page.html b/ash/webui/shimless_rma/resources/onboarding_landing_page.html index 35e3c437..ec5f143 100644 --- a/ash/webui/shimless_rma/resources/onboarding_landing_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_landing_page.html
@@ -8,7 +8,7 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('welcomeTitleText')]]</h1> - <div>[[i18n('beginRmaWarningText')]]</div> + <div class="instructions">[[i18n('beginRmaWarningText')]]</div> <div id="verificationMessage"> <paper-spinner-lite id="busyIcon" hidden$="[[!verificationInProgress_]]" active> @@ -17,15 +17,15 @@ icon="[[getVerificationIcon_(isCompliant_)]]" hidden$="[[verificationInProgress_]]" class="small-icon"> </iron-icon> - <span hidden$="[[!verificationInProgress_]]"> + <span hidden$="[[!verificationInProgress_]]" class="instructions"> [[i18n('validatingComponentsText')]] </span> <span hidden$="[[verificationInProgress_]]"> - <span hidden$="[[!isCompliant_]]"> + <span hidden$="[[!isCompliant_]]" class="instructions"> [[i18n('validatedComponentsSuccessText')]] </span> <span inner-h-t-m-l="[[verificationFailedMessage_]]" - hidden$="[[isCompliant_]]"> + hidden$="[[isCompliant_]]" class="instructions"> </span> </span> </div>
diff --git a/ash/webui/shimless_rma/resources/onboarding_network_page.html b/ash/webui/shimless_rma/resources/onboarding_network_page.html index e955619..5361ada 100644 --- a/ash/webui/shimless_rma/resources/onboarding_network_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_network_page.html
@@ -39,7 +39,7 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('connectNetworkTitleText')]]</h1> - <div>[[i18n('connectNetworkDescriptionText')]]</div> + <div class="instructions">[[i18n('connectNetworkDescriptionText')]]</div> </div> <div slot="body" id="container"> <network-list id="networkList" show-technology-badge
diff --git a/ash/webui/shimless_rma/resources/onboarding_select_components_page.html b/ash/webui/shimless_rma/resources/onboarding_select_components_page.html index 193dfe1a..c42bd3e 100644 --- a/ash/webui/shimless_rma/resources/onboarding_select_components_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_select_components_page.html
@@ -1,10 +1,14 @@ <style include="cr-shared-style shimless-rma-shared"> + #reworkFlowLink { + color: var(--cros-link-color); + text-decoration: none; + } </style> <base-page orientation="column"> <div slot="header"> <h1>[[i18n('selectComponentsTitleText')]]</h1> - <div> + <div class="instructions"> <span inner-h-t-m-l="[[reworkFlowLinkText_]]"></span> </div> </div>
diff --git a/ash/webui/shimless_rma/resources/onboarding_update_page.html b/ash/webui/shimless_rma/resources/onboarding_update_page.html index e1891cc1..7fe653b 100644 --- a/ash/webui/shimless_rma/resources/onboarding_update_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_update_page.html
@@ -13,21 +13,23 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('osUpdateTitleText')]]</h1> - <div hidden$="[[isCompliant_]]"> + <div hidden$="[[isCompliant_]]" class="instructions"> <div inner-h-t-m-l="[[verificationFailedMessage_]]"></div> <div>[[i18n('osUpdateUnqualifiedComponentsBottomText')]]</div> </div> - <div hidden$="[[!isCompliant_]]">[[updateNoticeMessage_]]</div> + <div hidden$="[[!isCompliant_]]" class="instructions"> + [[updateNoticeMessage_]] + </div> <div id="versionInfo"> <iron-icon id="updateIcon" class="small-icon" icon="[[getUpdateNoticeIcon_(updateAvailable_)]]"> </iron-icon> - [[currentVersionText_]] + <div class="instructions">[[currentVersionText_]]</div> </div> <div id="progressMessage"> <paper-spinner-lite hidden$="[[!updateInProgress_]]" active> </paper-spinner-lite> - [[updateProgressMessage_]] + <div class="instructions">[[updateProgressMessage_]]</div> </div> <p id="networkUnavailable" hidden$="[[networkAvailable]]"> [[i18n('onboardingUpdateConnectToInternet')]]
diff --git a/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html b/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html index 3a0d745b..2f0c548 100644 --- a/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_wait_for_manual_wp_disable_page.html
@@ -4,7 +4,7 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('manuallyDisableWpTitleText')]]</h1> - <div id="manuallyDisableHwwpInstructions"> + <div id="manuallyDisableHwwpInstructions" class="instructions"> [[i18n('manuallyDisableWpInstructionsText')]] </div> </div>
diff --git a/ash/webui/shimless_rma/resources/onboarding_wp_disable_complete_page.html b/ash/webui/shimless_rma/resources/onboarding_wp_disable_complete_page.html index a292935..7e2d5b0 100644 --- a/ash/webui/shimless_rma/resources/onboarding_wp_disable_complete_page.html +++ b/ash/webui/shimless_rma/resources/onboarding_wp_disable_complete_page.html
@@ -4,7 +4,9 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('wpDisableCompletePageTitleText')]]</h1> - <div id="writeProtectAction">[[actionString_]]</div> + <div id="writeProtectAction" class="instructions"> + [[actionString_]] + </div> </div> <div slot="body"> <!-- TODO(gavindodd): Replace with correct graphic -->
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html b/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html index b0a96887..36d2901 100644 --- a/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_calibration_failed_page.html
@@ -4,7 +4,9 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('calibrationFailedTitleText')]]</h1> - <div>[[i18n('calibrationFailedInstructionsText')]]</div> + <div class="instructions"> + [[i18n('calibrationFailedInstructionsText')]] + </div> <div> <cr-button id="retryCalibrationButton" class="cancel-button" on-click="onRetryCalibrationButtonClicked_"
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html b/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html index 9bd369be..9c72288 100644 --- a/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_calibration_run_page.html
@@ -4,7 +4,7 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('runCalibrationTitleText')]]</h1> - <div id="calibration"> + <div id="calibration" class="instructions"> <span>[[calibrationStatusMessage_]]</span> </div> </div>
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_setup_page.html b/ash/webui/shimless_rma/resources/reimaging_calibration_setup_page.html index 9c2a0ef9..c94d5d8 100644 --- a/ash/webui/shimless_rma/resources/reimaging_calibration_setup_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_calibration_setup_page.html
@@ -4,7 +4,7 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('setupCalibrationTitleText')]]</h1> - <div id="instructions"> + <div id="instructions" class="instructions"> <span>[[calibrationInstructions_]]</span> </div> </div>
diff --git a/ash/webui/shimless_rma/resources/reimaging_device_information_page.html b/ash/webui/shimless_rma/resources/reimaging_device_information_page.html index a2e92f1..1b4ea54 100644 --- a/ash/webui/shimless_rma/resources/reimaging_device_information_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_device_information_page.html
@@ -1,4 +1,4 @@ -<style include="cr-shared-style shimless-rma-shared"> +<style include="cr-shared-style shimless-rma-shared shimless-fonts"> .input-row { margin-bottom: 30px; } @@ -13,8 +13,12 @@ } .sku-warning { - color: gray; /* TODO(joonbug): Update cros colors */ + color: var(--shimless-warning-text-color); display: flex; + font-family: var(--shimless-warning-font-family); + font-size: var(--shimless-warning-font-size); + font-weight: var(--shimless-regular-font-weight); + line-height: var(--shimless-warning-line-height); max-width: 400px; } @@ -31,12 +35,22 @@ select { margin-inline-end: 20px; } + + .cr-form-field-label { + color: var(--shimless-hint-text-color); + font-family: var(--shimless-hint-font-family); + font-size: var(--shimless-hint-font-size); + font-weight: var(--shimless-medium-font-weight); + line-height: var(--shimless-hint-line-height); + } </style> <base-page orientation="column"> <div slot="header"> <h1>[[i18n('confirmDeviceInfoTitle')]]</h1> - <div>[[i18n('confirmDeviceInfoInstructions')]]</div> + <div class="instructions"> + [[i18n('confirmDeviceInfoInstructions')]] + </div> </div> <div slot="body"> <div class="input-row">
diff --git a/ash/webui/shimless_rma/resources/reimaging_device_information_page.js b/ash/webui/shimless_rma/resources/reimaging_device_information_page.js index b182db36..24e00c90 100644 --- a/ash/webui/shimless_rma/resources/reimaging_device_information_page.js +++ b/ash/webui/shimless_rma/resources/reimaging_device_information_page.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './shimless_rma_fonts_css.js'; import './shimless_rma_shared_css.js'; import './base_page.js'; import './icons.js';
diff --git a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html index 7415790..b21b195 100644 --- a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
@@ -4,7 +4,7 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('firmwareUpdatePageTitleText')]]</h1> - <div id="firmwareUpdateStatus">[[statusString_]]</div> + <div id="firmwareUpdateStatus" class="instructions">[[statusString_]]</div> </div> <div slot="body"> <!-- TODO(gavindodd): Replace with spinner -->
diff --git a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html index 1bc5762..7a5232e 100644 --- a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html
@@ -4,7 +4,9 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('provisioningPageTitleText')]]</h1> - <div id="provisioningDeviceStatus">[[statusString_]]</div> + <div id="provisioningDeviceStatus" class="instructions"> + [[statusString_]] + </div> <div> <cr-button id="retryProvisioningButton" class="cancel-button" on-click="onRetryProvsioningButtonClicked_"
diff --git a/ash/webui/shimless_rma/resources/repair_component_chip.html b/ash/webui/shimless_rma/resources/repair_component_chip.html index 463d60e..fc2e078 100644 --- a/ash/webui/shimless_rma/resources/repair_component_chip.html +++ b/ash/webui/shimless_rma/resources/repair_component_chip.html
@@ -1,4 +1,4 @@ -<style include="cr-shared-style shimless-rma-shared"> +<style include="cr-shared-style shimless-rma-shared shimless-fonts"> :host { padding: 1px; } @@ -12,7 +12,12 @@ align-items: normal; border-radius: 4px; box-shadow: var(--cr-card-shadow); + color: var(--shimless-component-text-color); + font-family: var(--shimless-component-font-family); + font-size: var(--shimless-component-font-size); + font-weight: var(--shimless-medium-font-weight); height: 70px; + line-height: var(--shimless-component-line-height); margin-bottom: 20px; margin-inline-end: 10px; width: 190px;
diff --git a/ash/webui/shimless_rma/resources/repair_component_chip.js b/ash/webui/shimless_rma/resources/repair_component_chip.js index 858527e..54c4e13 100644 --- a/ash/webui/shimless_rma/resources/repair_component_chip.js +++ b/ash/webui/shimless_rma/resources/repair_component_chip.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './shimless_rma_fonts_css.js'; import './shimless_rma_shared_css.js'; import './icons.js';
diff --git a/ash/webui/shimless_rma/resources/shimless_rma_fonts_css.html b/ash/webui/shimless_rma/resources/shimless_rma_fonts_css.html new file mode 100644 index 0000000..43fabbd --- /dev/null +++ b/ash/webui/shimless_rma/resources/shimless_rma_fonts_css.html
@@ -0,0 +1,39 @@ +<template> + <style> + :host { + --shimless-title-font-family: "Google Sans", Roboto, sans-serif; + --shimless-instructions-font-family: Roboto, sans-serif; + --shimless-component-font-family: Roboto, sans-serif; + --shimless-hint-font-family: Roboto, sans-serif; + --shimless-warning-font-family: Roboto, sans-serif; + --shimless-button-label-font-family: "Google Sans", Roboto, sans-serif; + --shimless-input-font-family: Roboto, sans-serif; + + --shimless-title-font-size: 28px; + --shimless-component-font-size: 14px; + --shimless-instructions-font-size: 14px; + --shimless-hint-font-size: 10px; + --shimless-warning-font-size: 12px; + --shimless-button-label-font-size: 16px; + --shimless-input-font-size: 13px; + + --shimless-title-line-height: 36px; + --shimless-instructions-line-height: 20px; + --shimless-component-line-height: 20px; + --shimless-hint-line-height: 10px; + --shimless-warning-line-height: 18px; + --shimless-button-label-line-height: 24px; + --shimless-input-line-height: 20px; + + --shimless-regular-font-weight: 400; + --shimless-medium-font-weight: 500; + + --shimless-title-text-color: var(--cros-text-color-primary); + --shimless-instructions-text-color: var(--cros-text-color-secondary); + --shimless-component-text-color: var(--cros-text-color-secondary); + --shimless-hint-text-color: var(--google-grey-600); + --shimless-warning-text-color: var(--cros-text-color-secondary); + --shimless-button-label-text-color: var(--cros-text-color-primary); + } + </style> +</template> \ No newline at end of file
diff --git a/ash/webui/shimless_rma/resources/shimless_rma_fonts_css.js b/ash/webui/shimless_rma/resources/shimless_rma_fonts_css.js new file mode 100644 index 0000000..5bf20ea2 --- /dev/null +++ b/ash/webui/shimless_rma/resources/shimless_rma_fonts_css.js
@@ -0,0 +1,11 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +const template = document.createElement('template'); +template.innerHTML = ` +<dom-module id="shimless-fonts">{__html_template__}</dom-module> +`; +document.body.appendChild(template.content.cloneNode(true)); \ No newline at end of file
diff --git a/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html b/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html index 8c7b038..9b6a260 100644 --- a/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html +++ b/ash/webui/shimless_rma/resources/shimless_rma_shared_css.html
@@ -5,13 +5,13 @@ <link rel="stylesheet" href="chrome://resources/cr_elements/md_select_css.html"> <template> - <style include="cr-shared-style md-select"> + <style include="cr-shared-style md-select shimless-fonts"> html { background-color: var(--cros-bg-color); } .indented-description { - color: gray; /* TODO(joonbug): update cros color */ + color: var(--shimless-instructions-text-color); padding: 0 0 0 48px; /* specify all to override */ } @@ -24,5 +24,28 @@ height: 300px; width: 300px; } + + h1 { + color: var(--shimless-title-text-color); + font-family: var(--shimless-title-font-family); + font-size: var(--shimless-title-font-size); + font-weight: var(--shimless-medium-font-weight); + line-height: var(--shimless-title-line-height); + } + + .instructions { + color: var(--shimless-instructions-text-color); + font-family: var(--shimless-instructions-font-family); + font-size: var(--shimless-instructions-font-size); + font-weight: var(--shimless-regular-font-weight); + line-height: var(--shimless-instructions-line-height); + } + + cr-input { + font-family: var(--shimless-input-font-family); + font-size: var(--shimless-input-font-size); + font-weight: var(--shimless-regular-font-weight); + line-height: var(--shimless-input-line-height); + } </style> </template>
diff --git a/ash/webui/shimless_rma/resources/shimless_rma_shared_css.js b/ash/webui/shimless_rma/resources/shimless_rma_shared_css.js index 86d1a0d..cb39fdd 100644 --- a/ash/webui/shimless_rma/resources/shimless_rma_shared_css.js +++ b/ash/webui/shimless_rma/resources/shimless_rma_shared_css.js
@@ -5,6 +5,7 @@ import 'chrome://resources/cr_elements/shared_style_css.m.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import './shimless_rma_fonts_css.js'; const template = document.createElement('template'); template.innerHTML = `
diff --git a/ash/webui/shimless_rma/resources/wrapup_finalize_page.html b/ash/webui/shimless_rma/resources/wrapup_finalize_page.html index 5156b10..0a58719 100644 --- a/ash/webui/shimless_rma/resources/wrapup_finalize_page.html +++ b/ash/webui/shimless_rma/resources/wrapup_finalize_page.html
@@ -4,7 +4,9 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('finalizePageTitleText')]]</h1> - <div id="finalizationMessage">[[finalizationMessage_]]</div> + <div id="finalizationMessage" class="instructions"> + [[finalizationMessage_]] + </div> <div> <cr-button id="retryFinalizationButton" class="cancel-button" on-click="onRetryFinalizationButtonClicked_"
diff --git a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html index f4c9534..58a3d221 100644 --- a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html +++ b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html
@@ -1,4 +1,4 @@ -<style include="cr-shared-style shimless-rma-shared"> +<style include="cr-shared-style shimless-rma-shared shimless-fonts"> cr-dialog::part(dialog) { width: 700px; } @@ -21,12 +21,20 @@ } .button-label { - color: black; + color: var(--shimless-button-label-text-color); + font-family: var(--shimless-button-label-font-family); + font-size: var(--shimless-button-label-font-size); + font-weight: var(--shimless-medium-font-weight); + line-height: var(--shimless-button-label-line-height); margin-bottom: 5px; } .button-description { - color: grey; + color: var(--shimless-instructions-text-color); + font-family: var(--shimless-instructions-font-family); + font-size: var(--shimless-instructions-font-size); + font-weight: var(--shimless-regular-font-weight); + line-height: var(--shimless-instructions-line-height); } .button-icon { @@ -54,7 +62,9 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('repairCompletedTitleText')]]</h1> - <div>[[i18n('repairCompletedDescriptionText')]]</div> + <div class="instructions"> + [[i18n('repairCompletedDescriptionText')]] + </div> <cr-button id="shutDownButton" on-click="onShutDownButtonClick_" disabled="[[allButtonsDisabled]]"> [[i18n('repairCompleteShutDownButtonText')]] @@ -134,7 +144,8 @@ <cr-button id="closeLogDialogButton" on-click="onCancelClick_"> [[i18n('rmaLogsCancelButtonText')]] </cr-button> - <cr-button id="rmaLogButton" on-click="onRmaLogButtonClick_"> + <cr-button id="rmaLogButton" class="text-button pill" + on-click="onRmaLogButtonClick_"> [[i18n('rmaLogsSaveToUsbButtonText')]] </cr-button> </div>
diff --git a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js index 8e71da1..f9701f4 100644 --- a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js +++ b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js
@@ -6,6 +6,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js'; import './base_page.js'; +import './shimless_rma_fonts_css.js'; import './shimless_rma_shared_css.js'; import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js';
diff --git a/ash/webui/shimless_rma/resources/wrapup_restock_page.html b/ash/webui/shimless_rma/resources/wrapup_restock_page.html index 38086de..358f37b 100644 --- a/ash/webui/shimless_rma/resources/wrapup_restock_page.html +++ b/ash/webui/shimless_rma/resources/wrapup_restock_page.html
@@ -4,7 +4,7 @@ <base-page orientation="column"> <div slot="header"> <h1>[[i18n('restockTitleText')]]</h1> - <div>[[i18n('restockInstructionsText')]]</div> + <div class="instructions">[[i18n('restockInstructionsText')]]</div> <cr-button id="continue" on-click="onRestockContinueButtonClicked_" disabled="[[allButtonsDisabled]]"> [[i18n('restockContinueButtonText')]]
diff --git a/ash/webui/shimless_rma/resources/wrapup_wait_for_manual_wp_enable_page.html b/ash/webui/shimless_rma/resources/wrapup_wait_for_manual_wp_enable_page.html index b71e268..376b2de4 100644 --- a/ash/webui/shimless_rma/resources/wrapup_wait_for_manual_wp_enable_page.html +++ b/ash/webui/shimless_rma/resources/wrapup_wait_for_manual_wp_enable_page.html
@@ -6,7 +6,7 @@ <h1>[[i18n('manuallyEnableWpTitleText')]]</h1> </div> <div slot="body"> - <div id="manuallyEnableHwwpInstructions"> + <div id="manuallyEnableHwwpInstructions" class="instructions"> [[getBodyText_(hwwpEnabled_)]] </div> </div>
diff --git a/ash/wm/desks/templates/desks_templates_unittest.cc b/ash/wm/desks/templates/desks_templates_unittest.cc index 17d0497..86ef352 100644 --- a/ash/wm/desks/templates/desks_templates_unittest.cc +++ b/ash/wm/desks/templates/desks_templates_unittest.cc
@@ -652,9 +652,6 @@ // This window should be hidden whenever the desk templates grid is open. auto test_window = CreateAppWindow(); - // This action should record deletions and grid shows in a UMA histogram. - base::HistogramTester histogram_tester; - OpenOverviewAndShowTemplatesGrid(); // The window is hidden because the desk templates grid is open. @@ -685,13 +682,6 @@ auto* save_template = GetSaveDeskAsTemplateButtonForRoot(Shell::GetPrimaryRootWindow()); EXPECT_TRUE(save_template->IsVisible()); - - // Assert that histogram metrics were recorded. - // note: deleting a template that doesn't exist counts as a delete according - // to the desks model hence expected_deletes being set to two. - const int expected_deletes = 2; - histogram_tester.ExpectTotalCount(kDeleteTemplateHistogramName, - expected_deletes); } // Tests that the save desk as template button is aligned with the first @@ -1728,8 +1718,248 @@ EXPECT_EQ(base::UTF8ToUTF16(template_name), name_view->GetText()); } +// Tests to verify that clicking the spacebar doesn't cause the name view to +// lose focus (since it's within a button), and that whitespaces are handled +// correctly. +TEST_F(DesksTemplatesTest, TemplateNameTestSpaces) { + auto test_window = CreateAppWindow(); + + const std::string template_name = "desk name"; + AddEntry(base::GUID::GenerateRandomV4(), template_name, base::Time::Now()); + + OpenOverviewAndShowTemplatesGrid(); + DesksTemplatesNameView* name_view = + GetItemViewFromTemplatesGrid(0)->name_view(); + + // Pressing spacebar does not cause `name_view` to lose focus. + ClickOnView(name_view); + SendKey(ui::VKEY_RIGHT); + SendKey(ui::VKEY_SPACE); + EXPECT_TRUE(name_view->HasFocus()); + EXPECT_EQ(base::UTF8ToUTF16(template_name) + u" ", name_view->GetText()); + + // Extra whitespace should be trimmed. + SendKey(ui::VKEY_HOME); + SendKey(ui::VKEY_SPACE); + SendKey(ui::VKEY_SPACE); + EXPECT_EQ(u" " + base::UTF8ToUTF16(template_name) + u" ", + name_view->GetText()); + SendKey(ui::VKEY_RETURN); + EXPECT_EQ(base::UTF8ToUTF16(template_name), name_view->GetText()); + + // A string consisting of just spaces is considered an empty string, and the + // name change is reverted. + EXPECT_FALSE(name_view->HasFocus()); + ClickOnView(name_view); + EXPECT_TRUE(name_view->HasFocus()); + SendKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); + SendKey(ui::VKEY_SPACE); + EXPECT_EQ(u" ", name_view->GetText()); + SendKey(ui::VKEY_RETURN); + EXPECT_EQ(base::UTF8ToUTF16(template_name), name_view->GetText()); +} + +// Tests that there is no crash after we use the keyboard to change the name of +// a template. Regression test for https://crbug.com/1279649. +TEST_F(DesksTemplatesTest, EditTemplateNameWithKeyboardNoCrash) { + AddEntry(base::GUID::GenerateRandomV4(), "a", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "b", base::Time::Now()); + + OpenOverviewAndShowTemplatesGrid(); + DesksTemplatesNameView* name_view = + GetItemViewFromTemplatesGrid(0)->name_view(); + + // Tab until we focus the name view of the first template item. + SendKey(ui::VKEY_TAB); + SendKey(ui::VKEY_TAB); + ASSERT_EQ(name_view, GetHighlightedView()); + + // Rename template "a" to template "d". + SendKey(ui::VKEY_RETURN); + SendKey(ui::VKEY_D); + SendKey(ui::VKEY_RETURN); + WaitForDesksTemplatesUI(); + + // Verify that there is no crash after we tab again. + SendKey(ui::VKEY_TAB); +} + +// Tests that there is no crash when leaving the template name view focused with +// a changed name during shutdown. Regression test for +// https://crbug.com/1281422. +TEST_F(DesksTemplatesTest, EditTemplateNameShutdownNoCrash) { + // The fade out animation of the desks templates grid must be enabled for this + // crash to have happened. + animation_scale_ = std::make_unique<ui::ScopedAnimationDurationScaleMode>( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + + AddEntry(base::GUID::GenerateRandomV4(), "a", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "b", base::Time::Now()); + + OpenOverviewAndShowTemplatesGrid(); + DesksTemplatesNameView* name_view = + GetItemViewFromTemplatesGrid(0)->name_view(); + + // Tab until we focus the name view of the first template item. + SendKey(ui::VKEY_TAB); + SendKey(ui::VKEY_TAB); + ASSERT_EQ(name_view, GetHighlightedView()); + + // Rename template "a" to template "ddd". + SendKey(ui::VKEY_RETURN); + SendKey(ui::VKEY_D); + SendKey(ui::VKEY_D); + SendKey(ui::VKEY_D); + + // Verify that there is no crash while the test tears down. +} + +// Tests that the hovering over the templates name shows the expected cursor. +TEST_F(DesksTemplatesTest, TemplatesNameHitTest) { + auto* cursor_manager = Shell::Get()->cursor_manager(); + + for (bool is_rtl : {true, false}) { + SCOPED_TRACE(is_rtl ? "rtl" : "ltr"); + base::i18n::SetRTLForTesting(is_rtl); + + AddEntry(base::GUID::GenerateRandomV4(), "a", base::Time::Now()); + + OpenOverviewAndShowTemplatesGrid(); + DesksTemplatesNameView* name_view = + GetItemViewFromTemplatesGrid(0)->name_view(); + const gfx::Rect name_view_bounds = name_view->GetBoundsInScreen(); + // Hover to a point just inside main edge. This will cover the case where + // the hit test logic is inverted. + const gfx::Point hover_point = + is_rtl ? name_view_bounds.right_center() + gfx::Vector2d(-2, 0) + : name_view_bounds.left_center() + gfx::Vector2d(2, 0); + + // Tests that the hover cursor is an IBeam. + GetEventGenerator()->MoveMouseTo(hover_point); + EXPECT_EQ(ui::mojom::CursorType::kIBeam, + cursor_manager->GetCursor().type()); + + // Exit overview for the next run. + ToggleOverview(); + } +} + +// Tests that accessibility overrides are set as expected. +TEST_F(DesksTemplatesTest, AccessibilityFocusAnnotatorInOverview) { + auto window = CreateTestWindow(gfx::Rect(100, 100)); + + ToggleOverview(); + WaitForDesksTemplatesUI(); + + auto* focus_widget = views::Widget::GetWidgetForNativeWindow( + GetOverviewSession()->GetOverviewFocusWindow()); + DCHECK(focus_widget); + + OverviewGrid* grid = GetOverviewSession()->grid_list()[0].get(); + auto* desk_widget = const_cast<views::Widget*>(grid->desks_widget()); + DCHECK(desk_widget); + + auto* save_widget = + GetSaveDeskAsTemplateButtonForRoot(Shell::GetPrimaryRootWindow()); + + // Overview items are in MRU order, so the expected order in the grid list is + // the reverse creation order. + auto* item_widget = GetOverviewItemForWindow(window.get())->item_widget(); + + // Order should be [focus_widget, save_widget, item_widget, desk_widget]. + CheckA11yOverrides("focus", focus_widget, desk_widget, save_widget); + CheckA11yOverrides("save", save_widget, focus_widget, item_widget); + CheckA11yOverrides("item", item_widget, save_widget, desk_widget); + CheckA11yOverrides("desk", desk_widget, item_widget, focus_widget); +} + +TEST_F(DesksTemplatesTest, LayoutItemsInLandscape) { + UpdateDisplay("800x600"); + + // Create a window and add four test entries. + auto test_window = CreateAppWindow(); + AddEntry(base::GUID::GenerateRandomV4(), "A_template", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "B_template", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "C_template", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "D_template", base::Time::Now()); + + OpenOverviewAndShowTemplatesGrid(); + + OverviewGrid* overview_grid = GetOverviewGridList()[0].get(); + views::Widget* grid_widget = overview_grid->desks_templates_grid_widget(); + const auto* templates_grid_view = + static_cast<DesksTemplatesGridView*>(grid_widget->GetContentsView()); + + // The grid has four items and one feedback button. + views::View::Views grid_views = templates_grid_view->children(); + ASSERT_EQ(5ul, grid_views.size()); + + // We expect the first three items to be laid out in one row. + EXPECT_EQ(grid_views[0]->bounds().y(), grid_views[1]->bounds().y()); + EXPECT_EQ(grid_views[0]->bounds().y(), grid_views[2]->bounds().y()); + // The fourth item goes in the second row. + EXPECT_NE(grid_views[0]->bounds().y(), grid_views[3]->bounds().y()); +} + +TEST_F(DesksTemplatesTest, LayoutItemsInPortrait) { + UpdateDisplay("600x800"); + + // Create a window and add four test entries. + auto test_window = CreateAppWindow(); + AddEntry(base::GUID::GenerateRandomV4(), "A_template", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "B_template", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "C_template", base::Time::Now()); + AddEntry(base::GUID::GenerateRandomV4(), "D_template", base::Time::Now()); + + OpenOverviewAndShowTemplatesGrid(); + + OverviewGrid* overview_grid = GetOverviewGridList()[0].get(); + views::Widget* grid_widget = overview_grid->desks_templates_grid_widget(); + const auto* templates_grid_view = + static_cast<DesksTemplatesGridView*>(grid_widget->GetContentsView()); + + // The grid has four items and one feedback button. + views::View::Views grid_views = templates_grid_view->children(); + ASSERT_EQ(5ul, grid_views.size()); + + // We expect the first two items to be laid out in one row. + EXPECT_EQ(grid_views[0]->bounds().y(), grid_views[1]->bounds().y()); + // And the last two items on the next row. + EXPECT_NE(grid_views[0]->bounds().y(), grid_views[2]->bounds().y()); + EXPECT_EQ(grid_views[2]->bounds().y(), grid_views[3]->bounds().y()); +} + +// Tests that there is no overlap with the shelf on our smallest supported +// resolution. +TEST_F(DesksTemplatesTest, ItemsDoNotOverlapShelf) { + // The smallest display resolution we support is 1087x675. + UpdateDisplay("1000x600"); + + // Create 6 entries to max out the grid. + for (const std::string& name : {"A", "B", "C", "D", "E", "F"}) + AddEntry(base::GUID::GenerateRandomV4(), name, base::Time::Now()); + + OpenOverviewAndShowTemplatesGrid(); + + OverviewGrid* overview_grid = GetOverviewGridList()[0].get(); + views::Widget* grid_widget = overview_grid->desks_templates_grid_widget(); + const auto* templates_grid_view = + static_cast<DesksTemplatesGridView*>(grid_widget->GetContentsView()); + + // The grid has six items and one feedback button. + views::View::Views grid_views = templates_grid_view->children(); + ASSERT_EQ(7ul, grid_views.size()); + + const gfx::Rect shelf_bounds = + GetPrimaryShelf()->shelf_widget()->GetWindowBoundsInScreen(); + + // Test that none of the grid items overlap with the shelf. + for (views::View* view : grid_views) + EXPECT_FALSE(view->GetBoundsInScreen().Intersects(shelf_bounds)); +} + // Tests that showing the overview records to the TemplateGrid histogram. -TEST_F(DesksTemplatesTest, RecordDesksTemplateGridShows) { +TEST_F(DesksTemplatesTest, RecordDesksTemplateGridShowMetric) { // Make sure that LoadTemplateHistogram is recorded. base::HistogramTester histogram_tester; @@ -1878,174 +2108,6 @@ kExpectedDialogShows); } -// Tests to verify that clicking the spacebar doesn't cause the name view to -// lose focus (since it's within a button), and that whitespaces are handled -// correctly. -TEST_F(DesksTemplatesTest, TemplateNameTestSpaces) { - auto test_window = CreateAppWindow(); - - const std::string template_name = "desk name"; - AddEntry(base::GUID::GenerateRandomV4(), template_name, base::Time::Now()); - - OpenOverviewAndShowTemplatesGrid(); - DesksTemplatesNameView* name_view = - GetItemViewFromTemplatesGrid(0)->name_view(); - - // Pressing spacebar does not cause `name_view` to lose focus. - ClickOnView(name_view); - SendKey(ui::VKEY_RIGHT); - SendKey(ui::VKEY_SPACE); - EXPECT_TRUE(name_view->HasFocus()); - EXPECT_EQ(base::UTF8ToUTF16(template_name) + u" ", name_view->GetText()); - - // Extra whitespace should be trimmed. - SendKey(ui::VKEY_HOME); - SendKey(ui::VKEY_SPACE); - SendKey(ui::VKEY_SPACE); - EXPECT_EQ(u" " + base::UTF8ToUTF16(template_name) + u" ", - name_view->GetText()); - SendKey(ui::VKEY_RETURN); - EXPECT_EQ(base::UTF8ToUTF16(template_name), name_view->GetText()); - - // A string consisting of just spaces is considered an empty string, and the - // name change is reverted. - EXPECT_FALSE(name_view->HasFocus()); - ClickOnView(name_view); - EXPECT_TRUE(name_view->HasFocus()); - SendKey(ui::VKEY_A, ui::EF_CONTROL_DOWN); - SendKey(ui::VKEY_SPACE); - EXPECT_EQ(u" ", name_view->GetText()); - SendKey(ui::VKEY_RETURN); - EXPECT_EQ(base::UTF8ToUTF16(template_name), name_view->GetText()); -} - -// Tests that there is no crash after we use the keyboard to change the name of -// a template. Regression test for https://crbug.com/1279649. -TEST_F(DesksTemplatesTest, EditTemplateNameWithKeyboardNoCrash) { - AddEntry(base::GUID::GenerateRandomV4(), "a", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "b", base::Time::Now()); - - OpenOverviewAndShowTemplatesGrid(); - DesksTemplatesNameView* name_view = - GetItemViewFromTemplatesGrid(0)->name_view(); - - // Tab until we focus the name view of the first template item. - SendKey(ui::VKEY_TAB); - SendKey(ui::VKEY_TAB); - ASSERT_EQ(name_view, GetHighlightedView()); - - // Rename template "a" to template "d". - SendKey(ui::VKEY_RETURN); - SendKey(ui::VKEY_D); - SendKey(ui::VKEY_RETURN); - WaitForDesksTemplatesUI(); - - // Verify that there is no crash after we tab again. - SendKey(ui::VKEY_TAB); -} - -// Tests that there is no crash when leaving the template name view focused with -// a changed name during shutdown. Regression test for -// https://crbug.com/1281422. -TEST_F(DesksTemplatesTest, EditTemplateNameShutdownNoCrash) { - // The fade out animation of the desks templates grid must be enabled for this - // crash to have happened. - animation_scale_ = std::make_unique<ui::ScopedAnimationDurationScaleMode>( - ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); - - AddEntry(base::GUID::GenerateRandomV4(), "a", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "b", base::Time::Now()); - - OpenOverviewAndShowTemplatesGrid(); - DesksTemplatesNameView* name_view = - GetItemViewFromTemplatesGrid(0)->name_view(); - - // Tab until we focus the name view of the first template item. - SendKey(ui::VKEY_TAB); - SendKey(ui::VKEY_TAB); - ASSERT_EQ(name_view, GetHighlightedView()); - - // Rename template "a" to template "ddd". - SendKey(ui::VKEY_RETURN); - SendKey(ui::VKEY_D); - SendKey(ui::VKEY_D); - SendKey(ui::VKEY_D); - - // Verify that there is no crash while the test tears down. -} - -// Tests that the hovering over the templates name shows the expected cursor. -TEST_F(DesksTemplatesTest, TemplatesNameHitTest) { - auto* cursor_manager = Shell::Get()->cursor_manager(); - - for (bool is_rtl : {true, false}) { - SCOPED_TRACE(is_rtl ? "rtl" : "ltr"); - base::i18n::SetRTLForTesting(is_rtl); - - AddEntry(base::GUID::GenerateRandomV4(), "a", base::Time::Now()); - - OpenOverviewAndShowTemplatesGrid(); - DesksTemplatesNameView* name_view = - GetItemViewFromTemplatesGrid(0)->name_view(); - const gfx::Rect name_view_bounds = name_view->GetBoundsInScreen(); - // Hover to a point just inside main edge. This will cover the case where - // the hit test logic is inverted. - const gfx::Point hover_point = - is_rtl ? name_view_bounds.right_center() + gfx::Vector2d(-2, 0) - : name_view_bounds.left_center() + gfx::Vector2d(2, 0); - - // Tests that the hover cursor is an IBeam. - GetEventGenerator()->MoveMouseTo(hover_point); - EXPECT_EQ(ui::mojom::CursorType::kIBeam, - cursor_manager->GetCursor().type()); - - // Exit overview for the next run. - ToggleOverview(); - } -} - -TEST_F(DesksTemplatesTest, UserTemplateCountRecordsCorrectly) { - // Record histogram. - base::HistogramTester histogram_tester; - - // Create three new templates through the UI. - for (unsigned long num_templates = 0; num_templates < 3; ++num_templates) { - // There are no saved template entries and one test window initially. - auto test_window = CreateAppWindow(); - - // Toggle overview if there isn't currently an overview. This is needed - // to save a template via the UI. - if (!GetOverviewSession()) { - ToggleOverview(); - WaitForDesksTemplatesUI(); - } - - // The `save_desk_as_template_widget` is visible when at least one window is - // open. - views::Widget* save_desk_as_template_widget = - GetSaveDeskAsTemplateButtonForRoot(Shell::GetPrimaryRootWindow()); - ASSERT_TRUE(save_desk_as_template_widget); - EXPECT_TRUE(save_desk_as_template_widget->GetContentsView()->GetVisible()); - - // Click on `save_desk_as_template_widget` button. - ClickOnView(save_desk_as_template_widget->GetContentsView()); - ASSERT_EQ(num_templates + 1, GetAllEntries().size()); - - // Expect that the Desk Templates grid is visible. - EXPECT_TRUE(GetOverviewGridList()[0]->IsShowingDesksTemplatesGrid()); - } - - OpenOverviewAndShowTemplatesGrid(); - - // Delete one of the templates which will iterate the histogram's second - // bucket. - DeleteTemplate(GetAllEntries()[0]->uuid(), /*expected_item_count=*/3); - - histogram_tester.ExpectBucketCount(kUserTemplateCountHistogramName, 1, 1); - histogram_tester.ExpectBucketCount(kUserTemplateCountHistogramName, 2, 2); - histogram_tester.ExpectBucketCount(kUserTemplateCountHistogramName, 3, 1); -} - // Tests that the window and tab counts are properly recorded in their // resepctive metrics. TEST_F(DesksTemplatesTest, SaveDeskRecordsWindowAndTabCountMetrics) { @@ -2104,122 +2166,51 @@ histogram_tester.ExpectBucketCount(kWindowAndTabCountHistogramName, 6, 1); } -// Tests that accessibility overrides are set as expected. -TEST_F(DesksTemplatesTest, AccessibilityFocusAnnotatorInOverview) { - auto window = CreateTestWindow(gfx::Rect(100, 100)); +// Tests that the user template count metric is recorded correctly. +TEST_F(DesksTemplatesTest, UserTemplateCountRecordsMetricCorrectly) { + // Record histogram. + base::HistogramTester histogram_tester; - ToggleOverview(); - WaitForDesksTemplatesUI(); + // Create three new templates through the UI. + for (unsigned long num_templates = 0; num_templates < 3; ++num_templates) { + // There are no saved template entries and one test window initially. + auto test_window = CreateAppWindow(); - auto* focus_widget = views::Widget::GetWidgetForNativeWindow( - GetOverviewSession()->GetOverviewFocusWindow()); - DCHECK(focus_widget); + // Toggle overview if there isn't currently an overview. This is needed + // to save a template via the UI. + if (!GetOverviewSession()) { + ToggleOverview(); + WaitForDesksTemplatesUI(); + } - OverviewGrid* grid = GetOverviewSession()->grid_list()[0].get(); - auto* desk_widget = const_cast<views::Widget*>(grid->desks_widget()); - DCHECK(desk_widget); + // The `save_desk_as_template_widget` is visible when at least one window is + // open. + views::Widget* save_desk_as_template_widget = + GetSaveDeskAsTemplateButtonForRoot(Shell::GetPrimaryRootWindow()); + ASSERT_TRUE(save_desk_as_template_widget); + EXPECT_TRUE(save_desk_as_template_widget->GetContentsView()->GetVisible()); - auto* save_widget = - GetSaveDeskAsTemplateButtonForRoot(Shell::GetPrimaryRootWindow()); + // Click on `save_desk_as_template_widget` button. + ClickOnView(save_desk_as_template_widget->GetContentsView()); + ASSERT_EQ(num_templates + 1, GetAllEntries().size()); - // Overview items are in MRU order, so the expected order in the grid list is - // the reverse creation order. - auto* item_widget = GetOverviewItemForWindow(window.get())->item_widget(); - - // Order should be [focus_widget, save_widget, item_widget, desk_widget]. - CheckA11yOverrides("focus", focus_widget, desk_widget, save_widget); - CheckA11yOverrides("save", save_widget, focus_widget, item_widget); - CheckA11yOverrides("item", item_widget, save_widget, desk_widget); - CheckA11yOverrides("desk", desk_widget, item_widget, focus_widget); -} - -TEST_F(DesksTemplatesTest, LayoutItemsInLandscape) { - UpdateDisplay("800x600"); - - // Create a window and add four test entries. - auto test_window = CreateAppWindow(); - AddEntry(base::GUID::GenerateRandomV4(), "A_template", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "B_template", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "C_template", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "D_template", base::Time::Now()); + // Expect that the Desk Templates grid is visible. + EXPECT_TRUE(GetOverviewGridList()[0]->IsShowingDesksTemplatesGrid()); + } OpenOverviewAndShowTemplatesGrid(); - OverviewGrid* overview_grid = GetOverviewGridList()[0].get(); - views::Widget* grid_widget = overview_grid->desks_templates_grid_widget(); - const auto* templates_grid_view = - static_cast<DesksTemplatesGridView*>(grid_widget->GetContentsView()); + // Delete one of the templates which will iterate the histogram's second + // bucket. + DeleteTemplate(GetAllEntries()[0]->uuid(), /*expected_item_count=*/3); - // The grid has four items and one feedback button. - views::View::Views grid_views = templates_grid_view->children(); - ASSERT_EQ(5ul, grid_views.size()); - - // We expect the first three items to be laid out in one row. - EXPECT_EQ(grid_views[0]->bounds().y(), grid_views[1]->bounds().y()); - EXPECT_EQ(grid_views[0]->bounds().y(), grid_views[2]->bounds().y()); - // The fourth item goes in the second row. - EXPECT_NE(grid_views[0]->bounds().y(), grid_views[3]->bounds().y()); -} - -TEST_F(DesksTemplatesTest, LayoutItemsInPortrait) { - UpdateDisplay("600x800"); - - // Create a window and add four test entries. - auto test_window = CreateAppWindow(); - AddEntry(base::GUID::GenerateRandomV4(), "A_template", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "B_template", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "C_template", base::Time::Now()); - AddEntry(base::GUID::GenerateRandomV4(), "D_template", base::Time::Now()); - - OpenOverviewAndShowTemplatesGrid(); - - OverviewGrid* overview_grid = GetOverviewGridList()[0].get(); - views::Widget* grid_widget = overview_grid->desks_templates_grid_widget(); - const auto* templates_grid_view = - static_cast<DesksTemplatesGridView*>(grid_widget->GetContentsView()); - - // The grid has four items and one feedback button. - views::View::Views grid_views = templates_grid_view->children(); - ASSERT_EQ(5ul, grid_views.size()); - - // We expect the first two items to be laid out in one row. - EXPECT_EQ(grid_views[0]->bounds().y(), grid_views[1]->bounds().y()); - // And the last two items on the next row. - EXPECT_NE(grid_views[0]->bounds().y(), grid_views[2]->bounds().y()); - EXPECT_EQ(grid_views[2]->bounds().y(), grid_views[3]->bounds().y()); -} - -// Tests that there is no overlap with the shelf on our smallest supported -// resolution. -TEST_F(DesksTemplatesTest, ItemsDoNotOverlapShelf) { - // The smallest display resolution we support is 1087x675. - UpdateDisplay("1000x600"); - - // Create 6 entries to max out the grid. - for (const std::string& name : {"A", "B", "C", "D", "E", "F"}) - AddEntry(base::GUID::GenerateRandomV4(), name, base::Time::Now()); - - OpenOverviewAndShowTemplatesGrid(); - - OverviewGrid* overview_grid = GetOverviewGridList()[0].get(); - views::Widget* grid_widget = overview_grid->desks_templates_grid_widget(); - const auto* templates_grid_view = - static_cast<DesksTemplatesGridView*>(grid_widget->GetContentsView()); - - // The grid has six items and one feedback button. - views::View::Views grid_views = templates_grid_view->children(); - ASSERT_EQ(7ul, grid_views.size()); - - const gfx::Rect shelf_bounds = - GetPrimaryShelf()->shelf_widget()->GetWindowBoundsInScreen(); - - // Test that none of the grid items overlap with the shelf. - for (views::View* view : grid_views) - EXPECT_FALSE(view->GetBoundsInScreen().Intersects(shelf_bounds)); + histogram_tester.ExpectBucketCount(kUserTemplateCountHistogramName, 1, 1); + histogram_tester.ExpectBucketCount(kUserTemplateCountHistogramName, 2, 2); + histogram_tester.ExpectBucketCount(kUserTemplateCountHistogramName, 3, 1); } // Tests record metrics when current template being replaced. -TEST_F(DesksTemplatesTest, ReplaceTemplate) { +TEST_F(DesksTemplatesTest, ReplaceTemplateMetric) { base::HistogramTester histogram_tester; UpdateDisplay("800x600,800x600");
diff --git a/base/BUILD.gn b/base/BUILD.gn index 8a3a284..fcf03a8 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3949,6 +3949,7 @@ "android/java/src/org/chromium/base/FeatureList.java", "android/java/src/org/chromium/base/Features.java", "android/java/src/org/chromium/base/FieldTrialList.java", + "android/java/src/org/chromium/base/FileUtils.java", "android/java/src/org/chromium/base/ImportantFileWriterAndroid.java", "android/java/src/org/chromium/base/IntStringCallback.java", "android/java/src/org/chromium/base/JNIUtils.java",
diff --git a/base/android/java/src/org/chromium/base/FileUtils.java b/base/android/java/src/org/chromium/base/FileUtils.java index db295e8..1c38298 100644 --- a/base/android/java/src/org/chromium/base/FileUtils.java +++ b/base/android/java/src/org/chromium/base/FileUtils.java
@@ -13,6 +13,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; @@ -26,6 +29,7 @@ /** * Helper methods for dealing with Files. */ +@JNINamespace("base::android") public class FileUtils { private static final String TAG = "FileUtils"; @@ -208,4 +212,22 @@ } return null; } + + /** + * Gets the canonicalised absolute pathname for |filePath|. Returns empty string if the path is + * invalid. This function can result in I/O so it can be slow. + * @param filePath Path of the file, has to be a file path instead of a content URI. + * @return canonicalised absolute pathname for |filePath|. + */ + public static String getAbsoluteFilePath(String filePath) { + return FileUtilsJni.get().getAbsoluteFilePath(filePath); + } + + @NativeMethods + public interface Natives { + /** + * Returns the canonicalised absolute pathname for |filePath|. + */ + String getAbsoluteFilePath(String filePath); + } }
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java index 95ddded..201cb315 100644 --- a/base/android/java/src/org/chromium/base/library_loader/Linker.java +++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -420,7 +420,14 @@ // nullified yet. With an invalid load address it is impossible to locate the RELRO // region in the current process. This could happen when the library loaded successfully // only after the fallback to no sharing. - return mRemoteLibInfo.mLoadAddress != 0; + // + // TODO(pasko): There is no need to check for |mLoadAddress| here because in the worst + // case the zero address will be ignored on the native side of the + // atomicReplaceRelroLocked(). The takeSharedRelrosFromBundle() relies on zero addresses + // being ignored in native anyway. It seems the only effect of removing this check here + // will be extra added samples to the RelroSharingStatus2 histogram. This will be a tiny + // bit smoother to do after M99. + return mLocalLibInfo.mLoadAddress != 0; } return false; }
diff --git a/base/android/linker/modern_linker_jni.cc b/base/android/linker/modern_linker_jni.cc index 4917fd22..9c4a19a 100644 --- a/base/android/linker/modern_linker_jni.cc +++ b/base/android/linker/modern_linker_jni.cc
@@ -524,7 +524,7 @@ return false; } - if (other_lib_info.load_address_ == 0) { + if (load_address_ == 0) { LOG_ERROR("Load address reset. Second attempt to load the library?"); s_relro_sharing_status = RelroSharingStatus::EXTERNAL_LOAD_ADDRESS_RESET; return false;
diff --git a/base/android/linker/modern_linker_jni.h b/base/android/linker/modern_linker_jni.h index e8a2d08..6b3eafb 100644 --- a/base/android/linker/modern_linker_jni.h +++ b/base/android/linker/modern_linker_jni.h
@@ -118,6 +118,7 @@ // unittest LoadLibrary() directly. bool CreateSharedRelroFdForTesting(); + void set_relro_fd_for_testing(int fd) { relro_fd_ = fd; } int get_relro_fd_for_testing() const { return relro_fd_; } size_t get_relro_start_for_testing() const { return relro_start_; } size_t get_load_size_for_testing() const { return load_size_; }
diff --git a/base/android/linker/modern_linker_unittest.cc b/base/android/linker/modern_linker_unittest.cc index c9a921a2..a932123 100644 --- a/base/android/linker/modern_linker_unittest.cc +++ b/base/android/linker/modern_linker_unittest.cc
@@ -239,6 +239,15 @@ lib_info.load_address() + lib_info.get_load_size_for_testing()); } +TEST_F(ModernLinkerTest, FindLibraryRangesWhenLoadAddressWasReset) { + NativeLibInfo other_lib_info = {0, 0}; + uintptr_t executable_start = reinterpret_cast<uintptr_t>(&__executable_start); + other_lib_info.set_load_address(executable_start); + other_lib_info.set_relro_fd_for_testing(123); + NativeLibInfo lib_info = {0, 0}; + EXPECT_FALSE(lib_info.CompareRelroAndReplaceItBy(other_lib_info)); +} + // Check that discovering RELRO segment address ranges and the DSO ranges agrees // with the method based on dl_iterate_phdr(3). The check is performed on the // test library, not on libmonochrome.
diff --git a/base/containers/vector_buffer.h b/base/containers/vector_buffer.h index b48365d9f..79aac63 100644 --- a/base/containers/vector_buffer.h +++ b/base/containers/vector_buffer.h
@@ -8,15 +8,12 @@ #include <stdlib.h> #include <string.h> -#include <ios> -#include <ostream> #include <type_traits> #include <utility> #include "base/check_op.h" #include "base/containers/util.h" #include "base/numerics/checked_math.h" -#include "build/build_config.h" namespace base { namespace internal { @@ -130,11 +127,7 @@ typename std::enable_if<base::is_trivially_copyable<T2>::value, int>::type = 0> static void MoveRange(T* from_begin, T* from_end, T* to) { - CHECK(!RangesOverlap(from_begin, from_end, to)) - // TODO(crbug.com/1172816): Remove logging once root cause is found. - << std::hex << "from_begin: 0x" << get_uintptr(from_begin) - << ", from_end: 0x" << get_uintptr(from_end) << ", to: 0x" - << get_uintptr(to); + CHECK(!RangesOverlap(from_begin, from_end, to)); memcpy( to, from_begin,
diff --git a/base/files/file_util_android.cc b/base/files/file_util_android.cc index b8b3b37..ca068ca 100644 --- a/base/files/file_util_android.cc +++ b/base/files/file_util_android.cc
@@ -4,10 +4,30 @@ #include "base/files/file_util.h" +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/base_jni_headers/FileUtils_jni.h" #include "base/files/file_path.h" #include "base/path_service.h" +using base::android::JavaParamRef; +using base::android::JavaRef; +using base::android::ScopedJavaLocalRef; + namespace base { +namespace android { + +static ScopedJavaLocalRef<jstring> JNI_FileUtils_GetAbsoluteFilePath( + JNIEnv* env, + const JavaParamRef<jstring>& j_file_path) { + base::FilePath file_path( + base::android::ConvertJavaStringToUTF8(env, j_file_path)); + base::FilePath absolute_file_path = MakeAbsoluteFilePath(file_path); + return base::android::ConvertUTF8ToJavaString(env, + absolute_file_path.value()); +} + +} // namespace android bool GetShmemTempDir(bool executable, base::FilePath* path) { return PathService::Get(base::DIR_CACHE, path);
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 2d1db51..8fa3de0c 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -2045,7 +2045,7 @@ } else { cflags = [ "-Os" ] + common_optimize_on_cflags } - } else if (is_chromeos_ash) { + } else if (is_chromeos) { # TODO(gbiv): This is partially favoring size over speed. CrOS exclusively # uses clang, and -Os in clang is more of a size-conscious -O2 than "size at # any cost" (AKA -Oz). It'd be nice to:
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index eeeb4e0e..9266f95 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -645,6 +645,7 @@ "java/res/layout/managed_by_menu_item.xml", "java/res/layout/material_tooltip.xml", "java/res/layout/multiline_spinner_item.xml", + "java/res/layout/mv_tiles_layout.xml", "java/res/layout/navigation_bubble.xml", "java/res/layout/navigation_sheet.xml", "java/res/layout/navigation_sheet_toolbar.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 02248db..5c7ab01 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1057,6 +1057,10 @@ "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSites.java", "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java", "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java", + "java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListCoordinator.java", + "java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListProperties.java", + "java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinder.java", + "java/src/org/chromium/chrome/browser/suggestions/tile/MvTilesLayout.java", "java/src/org/chromium/chrome/browser/suggestions/tile/SiteSectionViewHolder.java", "java/src/org/chromium/chrome/browser/suggestions/tile/SuggestionsTileView.java", "java/src/org/chromium/chrome/browser/suggestions/tile/Tile.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 5a3768a..baf0130d 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -193,6 +193,7 @@ "junit/src/org/chromium/chrome/browser/signin/SyncConsentActivityLauncherImplTest.java", "junit/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorMediatorTest.java", "junit/src/org/chromium/chrome/browser/suggestions/SuggestionsImageFetcherTest.java", + "junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinderUnitTest.java", "junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerFlowTest.java", "junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java", "junit/src/org/chromium/chrome/browser/survey/SurveyHttpClientBridgeUnitTest.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java index b8ecde3..8235e40 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/onboarding/BottomSheetOnboardingWithPopupCoordinator.java
@@ -36,6 +36,8 @@ private static final String SPLIT_ONBOARDING_SHOW_DIALOG_KEY = "split_onboarding_show_dialog"; private static final String SPLIT_ONBOARDING_ACCEPT_DIALOG_KEY = "split_onboarding_accept"; private static final String SPLIT_ONBOARDING_CLOSE_DIALOG_KEY = "split_onboarding_decline"; + private static final String SPLIT_ONBOARDING_TITLE_KEY = "split_onboarding_title"; + private static final String SPLIT_ONBOARDING_SUBTITLE_KEY = "split_onboarding_text"; // We have a bit more space in the dialog, so we add line spacing to make it easier to read the // terms. private static final float TERMS_LINE_SPACING_MULTIPLIER = 1.25f; @@ -96,9 +98,18 @@ ButtonCompat bottomSheetNoButton = mView.findViewById(R.id.button_init_not_ok); bottomSheetNoButton.setText(mStringMap.get(SPLIT_ONBOARDING_CLOSE_BOTTOMSHEET_KEY)); } - - updateTitleView(mView.findViewById(R.id.onboarding_try_assistant)); - updateSubtitleView(mView.findViewById(R.id.onboarding_subtitle)); + TextView titleView = mView.findViewById(R.id.onboarding_try_assistant); + if (mStringMap.containsKey(SPLIT_ONBOARDING_TITLE_KEY)) { + titleView.setText(mStringMap.get(SPLIT_ONBOARDING_TITLE_KEY)); + } else { + updateTitleView(titleView); + } + TextView subtitleView = mView.findViewById(R.id.onboarding_subtitle); + if (mStringMap.containsKey(SPLIT_ONBOARDING_SUBTITLE_KEY)) { + subtitleView.setText(mStringMap.get(SPLIT_ONBOARDING_SUBTITLE_KEY)); + } else { + updateSubtitleView(subtitleView); + } } private void showDialog(Callback<Integer> callback) {
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java index f9002c7..101109e 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java
@@ -421,8 +421,12 @@ String expectedConfirmDialogText = "Accept"; String expectedCloseDialogText = "Reject"; - coordinator.addEntryToStringMap("onboarding_title", expectedTitle); - coordinator.addEntryToStringMap("onboarding_text", expectedMessage); + // If both are provided, split_onboarding_* should take precedence + coordinator.addEntryToStringMap("onboarding_title", "Should be ignored"); + coordinator.addEntryToStringMap("onboarding_text", "Should be ignored"); + coordinator.addEntryToStringMap("split_onboarding_title", expectedTitle); + coordinator.addEntryToStringMap("split_onboarding_text", expectedMessage); + coordinator.addEntryToStringMap("terms_and_conditions", expectedTerms); coordinator.addEntryToStringMap("terms_and_conditions_url", expectedTermsUrl); coordinator.addEntryToStringMap( @@ -497,8 +501,12 @@ String expectedConfirmDialogText = "Accept"; String expectedCloseDialogText = "Reject"; - coordinator.addEntryToStringMap("onboarding_title", expectedTitle); - coordinator.addEntryToStringMap("onboarding_text", expectedMessage); + // If both are provided, split_onboarding_* should take precedence + coordinator.addEntryToStringMap("onboarding_title", "Should be ignored"); + coordinator.addEntryToStringMap("onboarding_text", "Should be ignored"); + coordinator.addEntryToStringMap("split_onboarding_title", expectedTitle); + coordinator.addEntryToStringMap("split_onboarding_text", expectedMessage); + coordinator.addEntryToStringMap("terms_and_conditions", expectedTerms); coordinator.addEntryToStringMap("terms_and_conditions_url", expectedTermsUrl); coordinator.addEntryToStringMap(
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewTest.java index 9ba6b9fe..01b680ce 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewTest.java
@@ -181,6 +181,22 @@ } @Override + public void setPriorityNotification(String feature) {} + + @Override + @Nullable + public String getPendingPriorityNotification() { + return null; + } + + @Override + public void registerPriorityNotificationHandler( + String feature, Runnable priorityNotificationHandler) {} + + @Override + public void unregisterPriorityNotificationHandler(String feature) {} + + @Override public boolean isInitialized() { return true; }
diff --git a/chrome/android/features/start_surface/internal/java/res/values/dimens.xml b/chrome/android/features/start_surface/internal/java/res/values/dimens.xml index 39c0b0e9..f6230564 100644 --- a/chrome/android/features/start_surface/internal/java/res/values/dimens.xml +++ b/chrome/android/features/start_surface/internal/java/res/values/dimens.xml
@@ -5,7 +5,7 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <dimen name="ss_bottom_bar_height">64dp</dimen> <dimen name="tasks_surface_body_top_margin">16dp</dimen> - <dimen name="mv_tiles_container_top_margin">14dp</dimen> + <dimen name="mv_tiles_container_top_margin">17dp</dimen> <dimen name="tab_switcher_title_top_margin">16dp</dimen> <dimen name="fake_search_box_top_margin">24dp</dimen> </resources>
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceMVTilesTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceMVTilesTest.java index bca4a63..7fe4494 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceMVTilesTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceMVTilesTest.java
@@ -49,9 +49,9 @@ import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.suggestions.SiteSuggestion; +import org.chromium.chrome.browser.suggestions.tile.MvTilesLayout; import org.chromium.chrome.browser.suggestions.tile.SuggestionsTileView; import org.chromium.chrome.browser.tab.TabLaunchType; -import org.chromium.chrome.browser.tasks.MvTilesLayout; import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index 59babfb..5b0e769 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -63,7 +63,6 @@ "java/res/layout/incognito_description_container_layout.xml", "java/res/layout/iph_drag_and_drop_dialog_layout.xml", "java/res/layout/large_message_card_item.xml", - "java/res/layout/mv_tiles_layout.xml", "java/res/layout/new_tab_tile_card_item.xml", "java/res/layout/price_card.xml", "java/res/layout/price_tracking_dialog_layout.xml", @@ -80,6 +79,7 @@ "java/res/layout/tab_selection_editor_layout.xml", "java/res/layout/tab_selection_editor_toolbar.xml", "java/res/layout/tab_strip_item.xml", + "java/res/layout/tasks_surface_search_box_layout.xml", "java/res/layout/tasks_view_layout.xml", "java/res/values/attrs.xml", "java/res/values/colors.xml", @@ -96,9 +96,6 @@ android_library("java") { sources = [ - "java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java", - "java/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinder.java", - "java/src/org/chromium/chrome/browser/tasks/MvTilesLayout.java", "java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java", "java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java", "java/src/org/chromium/chrome/browser/tasks/SingleTabView.java",
diff --git a/chrome/android/features/tab_ui/java/res/layout/mv_tiles_layout.xml b/chrome/android/features/tab_ui/java/res/layout/mv_tiles_layout.xml deleted file mode 100644 index 83707ef..0000000 --- a/chrome/android/features/tab_ui/java/res/layout/mv_tiles_layout.xml +++ /dev/null
@@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. --> - -<!-- A site suggestion tile. --> -<org.chromium.chrome.browser.tasks.MvTilesLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/mv_tiles_layout" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:orientation="horizontal"> -</org.chromium.chrome.browser.tasks.MvTilesLayout>
diff --git a/chrome/android/features/tab_ui/java/res/layout/tasks_surface_search_box_layout.xml b/chrome/android/features/tab_ui/java/res/layout/tasks_surface_search_box_layout.xml new file mode 100644 index 0000000..9cd0aca --- /dev/null +++ b/chrome/android/features/tab_ui/java/res/layout/tasks_surface_search_box_layout.xml
@@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2022 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<view xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/search_box" + class="org.chromium.chrome.browser.ntp.search.SearchBoxContainerView" + android:layout_width="match_parent" + android:layout_height="@dimen/ntp_search_box_height" + android:layout_marginTop="0dp" + android:layout_marginStart="12dp" + android:layout_marginEnd="12dp" + android:paddingStart="@dimen/search_box_start_padding" + android:paddingEnd="10dp" + android:background="@drawable/ntp_search_box" + android:gravity="center_vertical" + android:orientation="horizontal"> + + <!-- TODO(crbug.com/900912): Fix and remove lint ignore --> + <RelativeLayout + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" + android:layout_marginEnd="12dp" + android:gravity="center_vertical"> + <EditText + android:id="@+id/search_box_text" + style="@style/TextAppearance.TasksSurfaceSearchBoxText" + android:layout_width="match_parent" + android:layout_height="24dp" + android:background="@null" + android:ellipsize="end" + android:focusable="false" + android:focusableInTouchMode="false" + android:hint="@string/search_or_type_web_address" + android:inputType="text" + android:singleLine="true" + tools:ignore="Autofill,LabelFor" /> + </RelativeLayout> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/voice_search_button" + style="@style/LocationBarActionButton" + android:layout_width="20dp" + android:layout_height="20dp" + android:contentDescription="@string/accessibility_toolbar_btn_mic" + android:src="@drawable/btn_mic" /> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/lens_camera_button" + style="@style/LocationBarActionButton" + android:layout_width="20dp" + android:layout_height="20dp" + android:layout_marginStart="16dp" + android:contentDescription="@string/accessibility_btn_lens_camera" + android:src="@drawable/lens_camera_icon" + android:visibility="gone" /> +</view> \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml b/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml index f982ebb3..7ab8c88 100644 --- a/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml +++ b/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml
@@ -27,11 +27,9 @@ android:id="@+id/fake_search_box" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="2dp" - android:layout_marginEnd="2dp" android:orientation="vertical" app:layout_scrollFlags="scroll"> - <include layout="@layout/fake_search_box_layout"/> + <include layout="@layout/tasks_surface_search_box_layout"/> </LinearLayout> <FrameLayout android:id="@+id/query_tiles_container" android:layout_width="match_parent" @@ -43,14 +41,7 @@ app:layout_scrollFlags="scroll"> <include layout="@layout/query_tiles_layout" /> </FrameLayout> - <HorizontalScrollView android:id="@+id/mv_tiles_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:visibility="gone" - android:scrollbars="none" - app:layout_scrollFlags="scroll"> - <include layout="@layout/mv_tiles_layout" /> - </HorizontalScrollView> + <include layout="@layout/mv_tiles_layout" /> <LinearLayout android:id="@+id/tab_switcher_title" android:layout_width="match_parent"
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml index 1fd75ca..d6c2396 100644 --- a/chrome/android/features/tab_ui/java/res/values/dimens.xml +++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -75,4 +75,7 @@ <integer name="tab_thumbnail_placeholder_selected_color_alpha">38</integer> <integer name="tab_grid_hovered_card_background_color_alpha">128</integer> <integer name="tab_grid_hovered_card_background_selected_color_alpha">26</integer> + + <dimen name="tasks_surface_location_bar_url_text_size">18sp</dimen> + <dimen name="search_box_start_padding">16dp</dimen> </resources>
diff --git a/chrome/android/features/tab_ui/java/res/values/styles.xml b/chrome/android/features/tab_ui/java/res/values/styles.xml index 42f4227..ba6e661 100644 --- a/chrome/android/features/tab_ui/java/res/values/styles.xml +++ b/chrome/android/features/tab_ui/java/res/values/styles.xml
@@ -126,4 +126,9 @@ <item name="chipColor">@color/default_text_color_inverse</item> </style> + <style name="TextAppearance.TasksSurfaceSearchBoxText"> + <item name="android:textSize">@dimen/tasks_surface_location_bar_url_text_size</item> + <item name="android:textColorHint">@color/search_box_hint</item> + </style> + </resources>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java index 158393f..c921655 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java
@@ -29,9 +29,12 @@ import org.chromium.chrome.browser.query_tiles.QueryTileSection; import org.chromium.chrome.browser.query_tiles.QueryTileSection.QueryInfo; import org.chromium.chrome.browser.share.ShareDelegate; +import org.chromium.chrome.browser.suggestions.tile.MostVisitedListCoordinator; +import org.chromium.chrome.browser.suggestions.tile.MvTilesLayout; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.tasks.mv_tiles.MostVisitedTileNavigationDelegate; import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate.TabSwitcherType; import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher; @@ -62,8 +65,12 @@ private final Supplier<DynamicResourceLoader> mDynamicResourceLoaderSupplier; private final TabContentManager mTabContentManager; private final ModalDialogManager mModalDialogManager; + private final Activity mActivity; + private final Supplier<Tab> mParentTabSupplier; - /** This flag should be reset once {@link mMostVisitedList#destroyMVTiles()} is called. */ + /** + * This flag should be reset once {@link MostVisitedListCoordinator#destroyMVTiles} is called. + */ private boolean mIsMVTilesInitialized; /** {@see TabManagementDelegate#createTasksSurface} */ @@ -82,6 +89,7 @@ @NonNull Supplier<ShareDelegate> shareDelegateSupplier, @NonNull MultiWindowModeStateDispatcher multiWindowModeStateDispatcher, @NonNull ViewGroup rootView) { + mActivity = activity; mView = (TasksView) LayoutInflater.from(activity).inflate(R.layout.tasks_view_layout, null); mView.initialize(activityLifecycleDispatcher, parentTabSupplier.hasValue() && parentTabSupplier.get().isIncognito(), @@ -94,6 +102,7 @@ mDynamicResourceLoaderSupplier = dynamicResourceLoaderSupplier; mTabContentManager = tabContentManager; mModalDialogManager = modalDialogManager; + mParentTabSupplier = parentTabSupplier; if (tabSwitcherType == TabSwitcherType.CAROUSEL) { mTabSwitcher = TabManagementModuleProvider.getDelegate().createCarouselTabSwitcher( activity, activityLifecycleDispatcher, tabModelSelector, tabContentManager, @@ -130,8 +139,8 @@ if (hasMVTiles) { MvTilesLayout mvTilesLayout = mView.findViewById(R.id.mv_tiles_layout); - mMostVisitedList = new MostVisitedListCoordinator(activity, mvTilesLayout, - mPropertyModel, parentTabSupplier, snackbarManager, windowAndroid); + mMostVisitedList = new MostVisitedListCoordinator( + activity, mvTilesLayout, mPropertyModel, snackbarManager, windowAndroid); mMostVisitedList.initialize(); } if (hasQueryTiles) { @@ -152,7 +161,8 @@ public void initialize() { assert LibraryLoader.getInstance().isInitialized(); if (!mIsMVTilesInitialized && mMostVisitedList != null) { - mMostVisitedList.initWithNative(); + mMostVisitedList.initWithNative(new MostVisitedTileNavigationDelegate( + mActivity, Profile.getLastUsedRegularProfile(), mParentTabSupplier)); mIsMVTilesInitialized = true; } mMediator.initialize();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java index f46b181..0548e2f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java
@@ -4,7 +4,7 @@ package org.chromium.chrome.browser.tasks; -import static org.chromium.chrome.browser.tasks.MostVisitedListProperties.IS_VISIBLE; +import static org.chromium.chrome.browser.suggestions.tile.MostVisitedListProperties.IS_VISIBLE; import android.text.TextWatcher; import android.view.View;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/mv_tiles/MostVisitedTileNavigationDelegate.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/mv_tiles/MostVisitedTileNavigationDelegate.java new file mode 100644 index 0000000..ca661aa --- /dev/null +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/mv_tiles/MostVisitedTileNavigationDelegate.java
@@ -0,0 +1,97 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.mv_tiles; + +import android.app.Activity; + +import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; +import org.chromium.chrome.browser.offlinepages.RequestCoordinatorBridge; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.suggestions.SuggestionsMetrics; +import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.document.TabDelegate; +import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil; +import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.ui.base.PageTransition; +import org.chromium.ui.mojom.WindowOpenDisposition; + +/** + * Extension of {@link SuggestionsNavigationDelegate} with specific methods of MV tiles on Start + * Surface. + */ +public class MostVisitedTileNavigationDelegate extends SuggestionsNavigationDelegate { + private final Supplier<Tab> mParentTabSupplier; + private final TabDelegate mTabDelegate; + + /** + * Creates a new {@link MostVisitedTileNavigationDelegate}. + * @param activity The Android activity. + * @param profile The currently applicable profile. + * @param parentTabSupplier Supplies the StartSurface's parent tab. + */ + public MostVisitedTileNavigationDelegate( + Activity activity, Profile profile, Supplier<Tab> parentTabSupplier) { + super(activity, profile, /*host=*/null, /*tabModelSelector=*/null, /*tab=*/null); + mParentTabSupplier = parentTabSupplier; + mTabDelegate = new TabDelegate(false); + } + + @Override + public boolean isOpenInNewTabInGroupEnabled() { + return false; + } + + /** + * Opens the suggestions page without recording metrics. + * + * @param windowOpenDisposition How to open (new window, current tab, etc). + * @param url The url to navigate to. + */ + @Override + public void navigateToSuggestionUrl(int windowOpenDisposition, String url, boolean inGroup) { + assert !inGroup; + switch (windowOpenDisposition) { + case WindowOpenDisposition.CURRENT_TAB: + case WindowOpenDisposition.NEW_BACKGROUND_TAB: + ReturnToChromeExperimentsUtil.handleLoadUrlFromStartSurface( + new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK), + windowOpenDisposition + == org.chromium.ui.mojom.WindowOpenDisposition.NEW_BACKGROUND_TAB, + /*incognito=*/null, mParentTabSupplier.get()); + SuggestionsMetrics.recordTileTapped(); + break; + case WindowOpenDisposition.OFF_THE_RECORD: + ReturnToChromeExperimentsUtil.handleLoadUrlFromStartSurface( + new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK), true /*incognito*/, + mParentTabSupplier.get()); + break; + case WindowOpenDisposition.NEW_WINDOW: + openUrlInNewWindow(new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK)); + break; + case WindowOpenDisposition.SAVE_TO_DISK: + // TODO(crbug.com/1202321): Downloading toast is not shown maybe due to the + // webContent is null for start surface. + saveUrlForOffline(url); + break; + default: + assert false; + } + } + + private void saveUrlForOffline(String url) { + // TODO(crbug.com/1193816): Namespace shouldn't be NTP_SUGGESTIONS_NAMESPACE since it's + // not on NTP. + RequestCoordinatorBridge.getForProfile(Profile.getLastUsedRegularProfile()) + .savePageLater( + url, OfflinePageBridge.NTP_SUGGESTIONS_NAMESPACE, true /* userRequested */); + } + + private void openUrlInNewWindow(LoadUrlParams loadUrlParams) { + mTabDelegate.createTabInOtherWindow(loadUrlParams, mActivity, + mParentTabSupplier.get() == null ? -1 : mParentTabSupplier.get().getId()); + } +}
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni index 1c4817d2e..c2aba64 100644 --- a/chrome/android/features/tab_ui/tab_management_java_sources.gni +++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -6,9 +6,9 @@ "//chrome/android/features/start_surface/public/start_surface_public_java_sources.gni") public_tab_management_java_sources = [ - "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListProperties.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurface.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java", + "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/mv_tiles/MostVisitedTileNavigationDelegate.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialog.java", @@ -60,7 +60,6 @@ ] tab_management_junit_java_sources = [ - "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinderUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediatorUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java",
diff --git a/chrome/android/java/res/layout/bookmark_save_flow.xml b/chrome/android/java/res/layout/bookmark_save_flow.xml index 03d0de2..e46ef5b61 100644 --- a/chrome/android/java/res/layout/bookmark_save_flow.xml +++ b/chrome/android/java/res/layout/bookmark_save_flow.xml
@@ -90,14 +90,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" - android:layout_gravity="center_vertical" /> + android:layout_gravity="center_vertical" + android:importantForAccessibility="no" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" - android:orientation="vertical"> + android:orientation="vertical" + android:focusable="true"> <TextView android:id="@+id/notification_switch_title" android:text="@string/enable_price_tracking_menu_item"
diff --git a/chrome/android/java/res/layout/mv_tiles_layout.xml b/chrome/android/java/res/layout/mv_tiles_layout.xml new file mode 100644 index 0000000..1522daa --- /dev/null +++ b/chrome/android/java/res/layout/mv_tiles_layout.xml
@@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2022 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<!-- A site suggestion tile. --> +<HorizontalScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/mv_tiles_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" + android:scrollbars="none" + app:layout_scrollFlags="scroll"> + + <org.chromium.chrome.browser.suggestions.tile.MvTilesLayout + android:id="@+id/mv_tiles_layout" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:orientation="horizontal"> + </org.chromium.chrome.browser.suggestions.tile.MvTilesLayout> +</HorizontalScrollView> +
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 8adcebf7..8010ce0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -959,6 +959,7 @@ mLocaleManager.stopObservingPhoneChanges(); NavigationPredictorBridge.onPause(); + StartSurfaceUserData.getInstance().setUnusedTabRestoredAtStartup(false); super.onPauseWithNative(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index 744df5e..2a82493 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -110,6 +110,7 @@ add(ChromeFeatureList.TAB_GROUPS_FOR_TABLETS); add(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID); add(ChromeFeatureList.TAB_TO_GTS_ANIMATION); + add(ChromeFeatureList.TAB_STRIP_IMPROVEMENTS); add(ChromeFeatureList.THEME_REFACTOR_ANDROID); add(ChromeFeatureList.TOOLBAR_USE_HARDWARE_BITMAP_DRAW); add(ChromeFeatureList.USE_CHIME_ANDROID_SDK);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java index 19309b1..32a5093 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowCoordinator.java
@@ -13,7 +13,6 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import org.chromium.base.CallbackController; import org.chromium.base.lifetime.DestroyChecker; import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.task.PostTask; @@ -26,6 +25,7 @@ import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.content_public.browser.UiThreadTaskTraits; @@ -42,18 +42,15 @@ private final PropertyModelChangeProcessor<PropertyModel, ViewLookupCachingFrameLayout, PropertyKey> mChangeProcessor; private final DestroyChecker mDestroyChecker; + private final BottomSheetObserver mSheetObserver; - private CallbackController mCallbackController = new CallbackController(); private BottomSheetController mBottomSheetController; private BookmarkSaveFlowBottomSheetContent mBottomSheetContent; private BookmarkSaveFlowMediator mMediator; private View mBookmarkSaveFlowView; - private BookmarkModel mBookmarkModel; - - private boolean mClosedViaRunnable; - private UserEducationHelper mUserEducationHelper; + private boolean mClosedViaRunnable; /** * @param context The {@link Context} associated with this cooridnator. @@ -68,6 +65,15 @@ @NonNull UserEducationHelper userEducationHelper) { mContext = context; mBottomSheetController = bottomSheetController; + mSheetObserver = new EmptyBottomSheetObserver() { + @Override + public void onSheetContentChanged(BottomSheetContent newContent) { + if (newContent != mBottomSheetContent) { + destroy(); + } + } + }; + mBottomSheetController.addObserver(mSheetObserver); mUserEducationHelper = userEducationHelper; mBookmarkModel = new BookmarkModel(); mDestroyChecker = new DestroyChecker(); @@ -152,9 +158,8 @@ .build()); } - private void close() { - mDestroyChecker.checkNotDestroyed(); - + @VisibleForTesting + void close() { mClosedViaRunnable = true; mBottomSheetController.hideContent(mBottomSheetContent, true); } @@ -162,8 +167,7 @@ private void setupAutodismiss() { if (!BookmarkFeatures.isImprovedSaveFlowAutodismissEnabled()) return; - PostTask.postDelayedTask(UiThreadTaskTraits.USER_VISIBLE, - mCallbackController.makeCancelable(this::close), + PostTask.postDelayedTask(UiThreadTaskTraits.USER_VISIBLE, this::close, BookmarkFeatures.getImprovedSaveFlowAutodismissTimeMs()); } @@ -171,11 +175,12 @@ mDestroyChecker.checkNotDestroyed(); mDestroyChecker.destroy(); + mBottomSheetController.removeObserver(mSheetObserver); + // The bottom sheet was closed by a means other than one of the edit actions. if (mClosedViaRunnable) { RecordUserAction.record("MobileBookmark.SaveFlow.ClosedWithoutEditAction"); } - mCallbackController.destroy(); mMediator.destroy(); mMediator = null; @@ -212,9 +217,7 @@ } @Override - public void destroy() { - BookmarkSaveFlowCoordinator.this.destroy(); - } + public void destroy() {} @Override public int getPriority() { @@ -266,4 +269,8 @@ View getViewForTesting() { return mBookmarkSaveFlowView; } + + boolean getIsDestroyedForTesting() { + return mDestroyChecker.isDestroyed(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java index 063203f..edef6ece 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
@@ -13,6 +13,7 @@ import androidx.annotation.Nullable; import androidx.annotation.PluralsRes; import androidx.annotation.VisibleForTesting; +import androidx.vectordrawable.graphics.drawable.Animatable2Compat; import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; @@ -763,7 +764,16 @@ mPropertyModel.set( MessageBannerProperties.ICON_TINT_COLOR, MessageBannerProperties.TINT_NONE); drawable = drawable.mutate(); - ((AnimatedVectorDrawableCompat) drawable).start(); + final AnimatedVectorDrawableCompat animatedDrawable = + (AnimatedVectorDrawableCompat) drawable; + animatedDrawable.start(); + animatedDrawable.registerAnimationCallback(new Animatable2Compat.AnimationCallback() { + @Override + public void onAnimationEnd(Drawable drawable) { + if (mCurrentInfo == null || mCurrentInfo.icon != info.icon) return; + animatedDrawable.start(); + } + }); } mPropertyModel.set(MessageBannerProperties.ICON, drawable);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListCoordinator.java similarity index 62% rename from chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java rename to chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListCoordinator.java index 18e5ef5..9e2cf2b 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListCoordinator.java
@@ -2,46 +2,28 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.tasks; +package org.chromium.chrome.browser.suggestions.tile; import android.app.Activity; import android.view.ViewGroup; -import androidx.annotation.VisibleForTesting; - import org.chromium.base.Log; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; -import org.chromium.chrome.browser.offlinepages.RequestCoordinatorBridge; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.suggestions.ImageFetcher; import org.chromium.chrome.browser.suggestions.SuggestionsConfig; import org.chromium.chrome.browser.suggestions.SuggestionsDependencyFactory; -import org.chromium.chrome.browser.suggestions.SuggestionsMetrics; import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate; import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegateImpl; import org.chromium.chrome.browser.suggestions.mostvisited.MostVisitedSitesMetadataUtils; -import org.chromium.chrome.browser.suggestions.tile.SuggestionsTileView; -import org.chromium.chrome.browser.suggestions.tile.Tile; -import org.chromium.chrome.browser.suggestions.tile.TileGroup; -import org.chromium.chrome.browser.suggestions.tile.TileGroupDelegateImpl; -import org.chromium.chrome.browser.suggestions.tile.TileRenderer; -import org.chromium.chrome.browser.suggestions.tile.TileSectionType; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.tabmodel.document.TabDelegate; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; -import org.chromium.chrome.browser.ui.native_page.NativePageHost; -import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.ui.base.DeviceFormFactor; -import org.chromium.ui.base.PageTransition; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.mojom.WindowOpenDisposition; import java.io.IOException; import java.util.List; @@ -51,7 +33,7 @@ * * TODO(mattsimmons): Move logic and view manipulation into the mediator/viewbinder. (and add tests) */ -class MostVisitedListCoordinator implements TileGroup.Observer { +public class MostVisitedListCoordinator implements TileGroup.Observer { private static final String TAG = "TopSites"; public static final String CONTEXT_MENU_USER_ACTION_PREFIX = "Suggestions"; private static final String NEW_TAB_URL_HELP = "https://support.google.com/chrome/?p=new_tab"; @@ -60,10 +42,9 @@ // There's a limit of 12 in {@link MostVisitedSitesBridge#setObserver}. private static final int MAX_RESULTS = 12; private final Activity mActivity; - private WindowAndroid mWindowAndroid; + private final WindowAndroid mWindowAndroid; private final MvTilesLayout mMvTilesLayout; private final PropertyModelChangeProcessor mModelChangeProcessor; - private final Supplier<Tab> mParentTabSupplier; private final SnackbarManager mSnackbarManager; private TileGroup mTileGroup; private TileGroup.Delegate mTileGroupDelegate; @@ -76,14 +57,13 @@ private ImageFetcher mImageFetcher; public MostVisitedListCoordinator(Activity activity, MvTilesLayout mvTilesLayout, - PropertyModel propertyModel, Supplier<Tab> parentTabSupplier, - SnackbarManager snackbarManager, WindowAndroid windowAndroid) { + PropertyModel propertyModel, SnackbarManager snackbarManager, + WindowAndroid windowAndroid) { mActivity = activity; mWindowAndroid = windowAndroid; mMvTilesLayout = mvTilesLayout; mModelChangeProcessor = PropertyModelChangeProcessor.create( propertyModel, mMvTilesLayout, MostVisitedListViewBinder::bind); - mParentTabSupplier = parentTabSupplier; mSnackbarManager = snackbarManager; } @@ -94,7 +74,6 @@ // If it's a cold start and Instant Start is turned on, we render MV tiles placeholder here // pre-native. if (!mInitializationComplete - && ReturnToChromeExperimentsUtil.isStartSurfaceEnabled(mActivity) && TabUiFeatureUtilities.supportInstantStart( DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity), mActivity)) { try { @@ -115,8 +94,9 @@ * Called before the TasksSurface is showing to initialize MV tiles. * {@link MostVisitedListCoordinator#destroyMVTiles()} is called after the TasksSurface hides. */ - public void initWithNative() { + public void initWithNative(SuggestionsNavigationDelegate navigationDelegate) { Profile profile = Profile.getLastUsedRegularProfile(); + mNavigationDelegate = navigationDelegate; mImageFetcher = new ImageFetcher(profile); if (mRenderer == null) { // This function is never called in incognito mode. @@ -125,8 +105,6 @@ } else { mRenderer.setImageFetcher(mImageFetcher); } - mNavigationDelegate = new MostVisitedTileNavigationDelegate( - mActivity, profile, null, null, null, mParentTabSupplier); mSuggestionsUiDelegate = new MostVisitedSuggestionsUiDelegate( mNavigationDelegate, profile, mSnackbarManager); Runnable closeContextMenuCallback = mActivity::closeContextMenu; @@ -186,74 +164,6 @@ updateOfflineBadge(tile); } - private static class MostVisitedTileNavigationDelegate extends SuggestionsNavigationDelegate { - private Supplier<Tab> mParentTabSupplier; - private TabDelegate mTabDelegate; - - public MostVisitedTileNavigationDelegate(Activity activity, Profile profile, - NativePageHost host, TabModelSelector tabModelSelector, Tab tab, - Supplier<Tab> parentTabSupplier) { - super(activity, profile, host, tabModelSelector, tab); - mParentTabSupplier = parentTabSupplier; - mTabDelegate = new TabDelegate(false); - } - - @Override - public boolean isOpenInNewTabInGroupEnabled() { - return false; - } - - /** - * Opens the suggestions page without recording metrics. - * - * @param windowOpenDisposition How to open (new window, current tab, etc). - * @param url The url to navigate to. - */ - @Override - public void navigateToSuggestionUrl( - int windowOpenDisposition, String url, boolean inGroup) { - assert !inGroup; - switch (windowOpenDisposition) { - case WindowOpenDisposition.CURRENT_TAB: - case WindowOpenDisposition.NEW_BACKGROUND_TAB: - ReturnToChromeExperimentsUtil.handleLoadUrlFromStartSurface( - new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK), - windowOpenDisposition == WindowOpenDisposition.NEW_BACKGROUND_TAB, - /*incognito=*/null, mParentTabSupplier.get()); - SuggestionsMetrics.recordTileTapped(); - break; - case WindowOpenDisposition.OFF_THE_RECORD: - ReturnToChromeExperimentsUtil.handleLoadUrlFromStartSurface( - new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK), - true /*incognito*/, mParentTabSupplier.get()); - break; - case WindowOpenDisposition.NEW_WINDOW: - openUrlInNewWindow(new LoadUrlParams(url, PageTransition.AUTO_BOOKMARK)); - break; - case WindowOpenDisposition.SAVE_TO_DISK: - // TODO(crbug.com/1202321): Downloading toast is not shown maybe due to the - // webContent is null for start surface. - saveUrlForOffline(url); - break; - default: - assert false; - } - } - - private void saveUrlForOffline(String url) { - // TODO(crbug.com/1193816): Namespace shouldn't be NTP_SUGGESTIONS_NAMESPACE since it's - // not on NTP. - RequestCoordinatorBridge.getForProfile(Profile.getLastUsedRegularProfile()) - .savePageLater(url, OfflinePageBridge.NTP_SUGGESTIONS_NAMESPACE, - true /* userRequested */); - } - - private void openUrlInNewWindow(LoadUrlParams loadUrlParams) { - mTabDelegate.createTabInOtherWindow(loadUrlParams, mActivity, - mParentTabSupplier.get() == null ? -1 : mParentTabSupplier.get().getId()); - } - } - /** Called when the TasksSurface is hidden. */ public void destroyMVTiles() { mMvTilesLayout.destroy(); @@ -284,8 +194,7 @@ } } - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - boolean isMVTilesCleanedUp() { + public boolean isMVTilesCleanedUp() { return mTileGroupDelegate == null && mTileGroup == null; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListProperties.java similarity index 85% rename from chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListProperties.java rename to chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListProperties.java index b5b9af5..c2bce81 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListProperties.java
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.tasks; +package org.chromium.chrome.browser.suggestions.tile; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; /** View Properties related to displaying a most visited list. */ -final class MostVisitedListProperties { +public final class MostVisitedListProperties { private MostVisitedListProperties() {} public static final PropertyModel.WritableBooleanPropertyKey IS_VISIBLE =
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinder.java similarity index 81% rename from chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinder.java rename to chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinder.java index fdc2793..22cf2597 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinder.java
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.tasks; +package org.chromium.chrome.browser.suggestions.tile; -import static org.chromium.chrome.browser.tasks.MostVisitedListProperties.IS_VISIBLE; +import static org.chromium.chrome.browser.suggestions.tile.MostVisitedListProperties.IS_VISIBLE; import android.view.View; import android.view.ViewGroup;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MvTilesLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MvTilesLayout.java similarity index 96% rename from chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MvTilesLayout.java rename to chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MvTilesLayout.java index 1fbb90cc..a12cfe5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/MvTilesLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MvTilesLayout.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.tasks; +package org.chromium.chrome.browser.suggestions.tile; import android.content.Context; import android.content.res.Configuration; @@ -14,8 +14,6 @@ import androidx.annotation.VisibleForTesting; import org.chromium.chrome.browser.suggestions.SiteSuggestion; -import org.chromium.chrome.browser.suggestions.tile.SuggestionsTileView; -import org.chromium.chrome.browser.suggestions.tile.Tile; import org.chromium.components.browser_ui.widget.tile.TileView; /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java index 80753a32..9e28516 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkSaveFlowTest.java
@@ -28,6 +28,7 @@ import org.chromium.base.Callback; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeTabbedActivity; @@ -133,6 +134,21 @@ @Test @MediumTest + public void testBookmarkSaveFlow_DestroyAfterHidden() throws IOException { + TestThreadUtils.runOnUiThreadBlockingNoException(() -> { + BookmarkId id = addBookmark("Test bookmark", new GURL("http://a.com")); + mBookmarkSaveFlowCoordinator.show(id); + mBookmarkSaveFlowCoordinator.close(); + return null; + }); + CriteriaHelper.pollUiThread( + () + -> mBookmarkSaveFlowCoordinator.getIsDestroyedForTesting(), + "Save flow coordinator not destroyed."); + } + + @Test + @MediumTest @Feature({"RenderTest"}) public void testBookmarkSaveFlow_BookmarkMoved() throws IOException { TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java index 5b0d102a..1b62746a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
@@ -28,7 +28,6 @@ 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.FlakyTest; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.R; @@ -139,7 +138,6 @@ @Test @SmallTest - @FlakyTest(message = "crbug.com/1291515") public void testRefocusing() { for (int i = 0; i < 5; i++) { mOmnibox.requestFocus();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinderUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinderUnitTest.java similarity index 89% rename from chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinderUnitTest.java rename to chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinderUnitTest.java index af5f43b..71b6f4e 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/MostVisitedListViewBinderUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedListViewBinderUnitTest.java
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.tasks; +package org.chromium.chrome.browser.suggestions.tile; import static org.mockito.Mockito.verify; -import static org.chromium.chrome.browser.tasks.MostVisitedListProperties.IS_VISIBLE; +import static org.chromium.chrome.browser.suggestions.tile.MostVisitedListProperties.IS_VISIBLE; import android.view.View; import android.view.ViewGroup;
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index a38a1d4..c11476ed 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2319,6 +2319,7 @@ kDrawPredictedPointExperiment2Points3Ms, base::size(kDrawPredictedPointExperiment2Points3Ms), nullptr}}; +#if BUILDFLAG(IS_ANDROID) const FeatureEntry::FeatureParam kFedCmVariationAutoSignin[] = { {features::kFedCmAutoSigninFieldTrialParamName, "true"}}; const FeatureEntry::FeatureParam kFedCmVariationInterception[] = { @@ -2329,6 +2330,7 @@ {"- with FedCM HTTP filtering (very experimental)", kFedCmVariationInterception, base::size(kFedCmVariationInterception), nullptr}}; +#endif #if BUILDFLAG(IS_CHROMEOS_ASH) const FeatureEntry::Choice kForceControlFaceAeChoices[] = { @@ -5269,6 +5271,11 @@ flag_descriptions::kTabEngagementReportingDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kTabEngagementReportingAndroid)}, + {"enable-tab-strip-improvements", + flag_descriptions::kTabStripImprovementsAndroidName, + flag_descriptions::kTabStripImprovementsAndroidDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kTabStripImprovements)}, + {"enable-conditional-tabstrip", flag_descriptions::kConditionalTabStripAndroidName, flag_descriptions::kConditionalTabStripAndroidDescription, kOsAndroid, @@ -7099,11 +7106,13 @@ flag_descriptions::kMediaSessionWebRTCDescription, kOsAll, FEATURE_VALUE_TYPE(media::kMediaSessionWebRTC)}, +#if BUILDFLAG(IS_ANDROID) {"fedcm", flag_descriptions::kFedCmName, - flag_descriptions::kFedCmDescription, kOsAll, + flag_descriptions::kFedCmDescription, kOsAndroid, FEATURE_WITH_PARAMS_VALUE_TYPE(features::kFedCm, kFedCmFeatureVariations, "FedCmFeatureVariations")}, +#endif #if BUILDFLAG(IS_CHROMEOS_ASH) {"bluetooth-sessionized-metrics",
diff --git a/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc index 1c15c8d..b35e276 100644 --- a/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc +++ b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc
@@ -802,12 +802,21 @@ break; } - // Extract text. + // Extract text and hints. absl::optional<std::u16string> text; + absl::optional<std::vector<std::string>> hints; if (properties.text) text = base::UTF8ToUTF16(*properties.text); + // TODO(crbug.com/1252037): Convert string message IDs into ints. Then plumb + // vector<int> through and retrieve localized strings when populating + // the DictationBubbleView. + if (properties.hints) + hints = *properties.hints; + + if (hints.has_value() && hints.value().size() > 5) + return RespondNow(Error("Should not provide more than five hints.")); ash::AccessibilityController::Get()->UpdateDictationBubble(properties.visible, - icon, text); + icon, text, hints); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc b/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc index 013554f26..8c8171f7 100644 --- a/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc +++ b/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc
@@ -49,51 +49,37 @@ return RunExtensionTest("accessibility_private", {.custom_arg = subtest}); } - bool IsDictationBubbleVisible() { + DictationBubbleController* GetDictationBubbleController() { DictationBubbleController* controller = Shell::Get() ->accessibility_controller() ->GetDictationBubbleControllerForTest(); DCHECK(controller != nullptr); - return controller->widget_->IsVisible(); + return controller; + } + + bool IsDictationBubbleVisible() { + return GetDictationBubbleController()->widget_->IsVisible(); } std::u16string GetDictationBubbleText() { - DictationBubbleController* controller = - Shell::Get() - ->accessibility_controller() - ->GetDictationBubbleControllerForTest(); - DCHECK(controller != nullptr); - return controller->dictation_bubble_view_->GetTextForTesting(); + return GetDictationBubbleController() + ->dictation_bubble_view_->GetTextForTesting(); } bool IsDictationBubbleStandbyViewVisible() { - DictationBubbleController* controller = - Shell::Get() - ->accessibility_controller() - ->GetDictationBubbleControllerForTest(); - DCHECK(controller != nullptr); - return controller->dictation_bubble_view_->IsStandbyViewVisibleForTesting(); + return GetDictationBubbleController() + ->dictation_bubble_view_->IsStandbyViewVisibleForTesting(); } bool IsDictationBubbleMacroSucceededImageVisible() { - DictationBubbleController* controller = - Shell::Get() - ->accessibility_controller() - ->GetDictationBubbleControllerForTest(); - DCHECK(controller != nullptr); - return controller->dictation_bubble_view_ - ->IsMacroSucceededImageVisibleForTesting(); + return GetDictationBubbleController() + ->dictation_bubble_view_->IsMacroSucceededImageVisibleForTesting(); } bool IsDictationBubbleMacroFailedImageVisible() { - DictationBubbleController* controller = - Shell::Get() - ->accessibility_controller() - ->GetDictationBubbleControllerForTest(); - DCHECK(controller != nullptr); - return controller->dictation_bubble_view_ - ->IsMacroFailedImageVisibleForTesting(); + return GetDictationBubbleController() + ->dictation_bubble_view_->IsMacroFailedImageVisibleForTesting(); } DictationBubbleIconType GetDictationBubbleVisibleIcon() { @@ -110,6 +96,22 @@ return DictationBubbleIconType::kHidden; } + bool DictationBubbleHasVisibleHints( + const std::vector<std::u16string>& expected) { + std::vector<std::u16string> actual = + GetDictationBubbleController() + ->dictation_bubble_view_->GetVisibleHintsForTesting(); + if (expected.size() != actual.size()) + return false; + + for (size_t i = 0; i < expected.size(); ++i) { + if (expected[i] != actual[i]) + return false; + } + + return true; + } + private: base::test::ScopedFeatureList scoped_feature_list_; }; @@ -313,6 +315,28 @@ ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message(); } +IN_PROC_BROWSER_TEST_P(AccessibilityPrivateApiTest, + UpdateDictationBubbleWithHints) { + Shell::Get()->accessibility_controller()->dictation().SetEnabled(true); + ExtensionTestMessageListener show_listener("Some hints", /*will_reply=*/true); + ExtensionTestMessageListener no_hints_listener("No hints", + /*will_reply=*/false); + extensions::ResultCatcher result_catcher; + ASSERT_TRUE(RunSubtest("testUpdateDictationBubbleWithHints")) << message_; + + ASSERT_TRUE(show_listener.WaitUntilSatisfied()); + EXPECT_TRUE(IsDictationBubbleVisible()); + EXPECT_TRUE(DictationBubbleHasVisibleHints( + std::vector<std::u16string>{u"One", u"Two", u"Three"})); + show_listener.Reply("Continue"); + + ASSERT_TRUE(no_hints_listener.WaitUntilSatisfied()); + EXPECT_TRUE(IsDictationBubbleVisible()); + EXPECT_TRUE(DictationBubbleHasVisibleHints(std::vector<std::u16string>())); + + ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message(); +} + INSTANTIATE_TEST_SUITE_P(PersistentBackground, AccessibilityPrivateApiTest, ::testing::Values(ContextType::kPersistentBackground));
diff --git a/chrome/browser/ash/arc/privacy_items/OWNERS b/chrome/browser/ash/arc/privacy_items/OWNERS new file mode 100644 index 0000000..4545be7 --- /dev/null +++ b/chrome/browser/ash/arc/privacy_items/OWNERS
@@ -0,0 +1 @@ +jorgegil@google.com \ No newline at end of file
diff --git a/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.cc b/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.cc new file mode 100644 index 0000000..a9e5203 --- /dev/null +++ b/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.cc
@@ -0,0 +1,89 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.h" + +#include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h" +#include "ash/components/arc/session/arc_bridge_service.h" +#include "base/memory/singleton.h" + +namespace arc { + +namespace { + +// Singleton factory for ArcPrivacyItemsBridge. +class ArcPrivacyItemsBridgeFactory + : public internal::ArcBrowserContextKeyedServiceFactoryBase< + ArcPrivacyItemsBridge, + ArcPrivacyItemsBridgeFactory> { + public: + // Factory name used by ArcBrowserContextKeyedServiceFactoryBase. + static constexpr const char* kName = "ArcPrivacyItemsBridgeFactory"; + + static ArcPrivacyItemsBridgeFactory* GetInstance() { + return base::Singleton<ArcPrivacyItemsBridgeFactory>::get(); + } + + private: + friend base::DefaultSingletonTraits<ArcPrivacyItemsBridgeFactory>; + + ArcPrivacyItemsBridgeFactory() = default; + ~ArcPrivacyItemsBridgeFactory() override = default; +}; + +} // namespace + +// static +ArcPrivacyItemsBridge* ArcPrivacyItemsBridge::GetForBrowserContext( + content::BrowserContext* context) { + return ArcPrivacyItemsBridgeFactory::GetForBrowserContext(context); +} + +ArcPrivacyItemsBridge::ArcPrivacyItemsBridge(content::BrowserContext* context, + ArcBridgeService* bridge_service) + : arc_bridge_service_(bridge_service) { + DVLOG(2) << "ArcPrivacyItemsBridge::ArcPrivacyItemsBridge"; + arc_bridge_service_->privacy_items()->SetHost(this); + arc_bridge_service_->privacy_items()->AddObserver(this); +} + +ArcPrivacyItemsBridge::~ArcPrivacyItemsBridge() { + DVLOG(2) << "ArcPrivacyItemsBridge::~ArcPrivacyItemsBridge"; + arc_bridge_service_->privacy_items()->RemoveObserver(this); + arc_bridge_service_->privacy_items()->SetHost(nullptr); +} + +void ArcPrivacyItemsBridge::OnPrivacyItemsChanged( + std::vector<arc::mojom::PrivacyItemPtr> privacy_items) { + DVLOG(1) << "ArcPrivacyItemsBridge::OnPrivacyItemsChanged size=" + << privacy_items.size(); +} + +void ArcPrivacyItemsBridge::OnMicCameraIndicatorRequirementChanged(bool flag) { + DVLOG(1) << "ArcPrivacyItemsBridge::OnMicCameraIndicatorRequirementChanged " + "required=" + << flag; +} + +void ArcPrivacyItemsBridge::OnLocationIndicatorRequirementChanged(bool flag) { + DVLOG(1) << "ArcPrivacyItemsBridge::OnLocationIndicatorRequirementChanged " + "required=" + << flag; +} + +void ArcPrivacyItemsBridge::OnStaticPrivacyIndicatorBoundsChanged( + int32_t display_id, + std::vector<gfx::Rect> bounds) { + DVLOG(1) << "ArcPrivacyItemsBridge::OnStaticPrivacyIndicatorBoundsChanged"; + + auto* instance = + ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->privacy_items(), + OnStaticPrivacyIndicatorBoundsChanged); + if (!instance) + return; + + instance->OnStaticPrivacyIndicatorBoundsChanged(display_id, bounds); +} + +} // namespace arc
diff --git a/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.h b/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.h new file mode 100644 index 0000000..188aef7 --- /dev/null +++ b/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.h
@@ -0,0 +1,55 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_ARC_PRIVACY_ITEMS_ARC_PRIVACY_ITEMS_BRIDGE_H_ +#define CHROME_BROWSER_ASH_ARC_PRIVACY_ITEMS_ARC_PRIVACY_ITEMS_BRIDGE_H_ + +#include "ash/components/arc/mojom/privacy_items.mojom.h" +#include "ash/components/arc/session/connection_observer.h" +#include "components/keyed_service/core/keyed_service.h" + +namespace content { + +class BrowserContext; +} // namespace content + +namespace arc { + +class ArcBridgeService; + +class ArcPrivacyItemsBridge + : public KeyedService, + public ConnectionObserver<mojom::PrivacyItemsInstance>, + public mojom::PrivacyItemsHost { + public: + // Returns singleton instance for the given BrowserContext, + // or nullptr if the browser |context| is not allowed to use ARC. + static ArcPrivacyItemsBridge* GetForBrowserContext( + content::BrowserContext* context); + + ArcPrivacyItemsBridge(content::BrowserContext* context, + ArcBridgeService* bridge_service); + + ArcPrivacyItemsBridge(const ArcPrivacyItemsBridge&) = delete; + ArcPrivacyItemsBridge& operator=(const ArcPrivacyItemsBridge&) = delete; + + ~ArcPrivacyItemsBridge() override; + + // PrivacyItemsHost overrides. + void OnPrivacyItemsChanged( + std::vector<arc::mojom::PrivacyItemPtr> privacy_items) override; + void OnMicCameraIndicatorRequirementChanged(bool flag) override; + void OnLocationIndicatorRequirementChanged(bool flag) override; + + // PrivacyItemsInstance methods: + void OnStaticPrivacyIndicatorBoundsChanged(int32_t display_id, + std::vector<gfx::Rect> bounds); + + private: + ArcBridgeService* const arc_bridge_service_; +}; + +} // namespace arc + +#endif // CHROME_BROWSER_ASH_ARC_PRIVACY_ITEMS_ARC_PRIVACY_ITEMS_BRIDGE_H_
diff --git a/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge_unittest.cc b/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge_unittest.cc new file mode 100644 index 0000000..9ff9ebd8 --- /dev/null +++ b/chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge_unittest.cc
@@ -0,0 +1,58 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.h" +#include "ash/components/arc/session/arc_bridge_service.h" +#include "ash/components/arc/test/connection_holder_util.h" +#include "ash/components/arc/test/fake_privacy_items_instance.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace arc { + +class ArcPrivacyItemsBridgeTest : public testing::Test { + public: + ArcPrivacyItemsBridgeTest() = default; + ~ArcPrivacyItemsBridgeTest() override = default; + + void SetUp() override { + arc_bridge_service_ = std::make_unique<ArcBridgeService>(); + bridge_ = std::make_unique<ArcPrivacyItemsBridge>( + &testing_profile_, arc_bridge_service_.get()); + privacy_items_instance_ = std::make_unique<arc::FakePrivacyItemsInstance>(); + arc_bridge_service_->privacy_items()->SetInstance( + privacy_items_instance_.get()); + WaitForInstanceReady(arc_bridge_service_->privacy_items()); + } + + void TearDown() override { + arc_bridge_service_->privacy_items()->CloseInstance( + privacy_items_instance_.get()); + privacy_items_instance_.reset(); + bridge_.reset(); + arc_bridge_service_.reset(); + } + + ArcPrivacyItemsBridge* bridge() { return bridge_.get(); } + FakePrivacyItemsInstance* privacy_items_instance() { + return privacy_items_instance_.get(); + } + + private: + content::BrowserTaskEnvironment task_environment_; + TestingProfile testing_profile_; + std::unique_ptr<ArcBridgeService> arc_bridge_service_; + std::unique_ptr<ArcPrivacyItemsBridge> bridge_; + std::unique_ptr<FakePrivacyItemsInstance> privacy_items_instance_; +}; + +TEST_F(ArcPrivacyItemsBridgeTest, ChangingPrivacyBoundsForwardsToAndroid) { + std::vector<gfx::Rect> bounds; + bridge()->OnStaticPrivacyIndicatorBoundsChanged(5, bounds); + EXPECT_EQ(5, privacy_items_instance()->last_bounds_display_id()); + EXPECT_EQ(bounds, privacy_items_instance()->last_bounds()); +} + +} // namespace arc
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc index 0d18655..1069e98 100644 --- a/chrome/browser/ash/arc/session/arc_service_launcher.cc +++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -75,6 +75,7 @@ #include "chrome/browser/ash/arc/pip/arc_pip_bridge.h" #include "chrome/browser/ash/arc/policy/arc_policy_bridge.h" #include "chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.h" +#include "chrome/browser/ash/arc/privacy_items/arc_privacy_items_bridge.h" #include "chrome/browser/ash/arc/process/arc_process_service.h" #include "chrome/browser/ash/arc/screen_capture/arc_screen_capture_bridge.h" #include "chrome/browser/ash/arc/session/arc_demo_mode_preference_handler.h" @@ -237,6 +238,7 @@ ArcPowerBridge::GetForBrowserContext(profile)->SetUserIdHash( ash::ProfileHelper::GetUserIdHashFromProfile(profile)); ArcPrintSpoolerBridge::GetForBrowserContext(profile); + ArcPrivacyItemsBridge::GetForBrowserContext(profile); ArcProcessService::GetForBrowserContext(profile); ArcPropertyBridge::GetForBrowserContext(profile); ArcProvisionNotificationService::GetForBrowserContext(profile);
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn index ed3553d..70c3ab6 100644 --- a/chrome/browser/ash/crosapi/BUILD.gn +++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -273,6 +273,7 @@ "browser_version_service_ash_unittest.cc", "chrome_app_window_tracker_ash_unittest.cc", "crosapi_util_unittest.cc", + "dlp_ash_unittest.cc", "download_controller_ash_unittest.cc", "fake_migration_progress_tracker.h", "field_trial_service_ash_unittest.cc",
diff --git a/chrome/browser/ash/crosapi/dlp_ash.cc b/chrome/browser/ash/crosapi/dlp_ash.cc index dfcc04a..c104bda 100644 --- a/chrome/browser/ash/crosapi/dlp_ash.cc +++ b/chrome/browser/ash/crosapi/dlp_ash.cc
@@ -4,11 +4,14 @@ #include "chrome/browser/ash/crosapi/dlp_ash.h" +#include "ash/shell.h" +#include "base/check.h" #include "base/logging.h" #include "chrome/browser/ash/crosapi/window_util.h" #include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" #include "chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" +#include "content/public/browser/browser_thread.h" namespace crosapi { @@ -25,6 +28,8 @@ return policy::DlpRulesManager::Level::kBlock; case crosapi::mojom::DlpRestrictionLevel::kAllow: return policy::DlpRulesManager::Level::kAllow; + case crosapi::mojom::DlpRestrictionLevel::kNotSet: + return policy::DlpRulesManager::Level::kNotSet; } } @@ -50,6 +55,21 @@ return result; } +content::DesktopMediaID AreaToDesktopMediaID( + const mojom::ScreenShareAreaPtr& area) { + aura::Window* window = area->window_id.has_value() + ? GetShellSurfaceWindow(area->window_id.value()) + : ash::Shell::GetPrimaryRootWindow(); + if (!window) + return content::DesktopMediaID(); + + const content::DesktopMediaID::Type media_type = + area->window_id.has_value() ? content::DesktopMediaID::TYPE_WINDOW + : content::DesktopMediaID::TYPE_SCREEN; + + return content::DesktopMediaID::RegisterNativeWindow(media_type, window); +} + } // namespace DlpAsh::DlpAsh() = default; @@ -62,6 +82,7 @@ void DlpAsh::DlpRestrictionsUpdated(const std::string& window_id, mojom::DlpRestrictionSetPtr restrictions) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); aura::Window* window = GetShellSurfaceWindow(window_id); if (!window) { LOG(WARNING) << "Didn't find Lacros window with id: " << window_id; @@ -74,4 +95,84 @@ window, ConvertMojoToDlpContentRestrictionSet(restrictions)); } +void DlpAsh::CheckScreenShareRestriction( + mojom::ScreenShareAreaPtr area, + const std::u16string& application_title, + CheckScreenShareRestrictionCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const content::DesktopMediaID media_id = AreaToDesktopMediaID(area); + if (media_id.is_null()) { + std::move(callback).Run(/*allowed=*/true); + return; + } + + policy::DlpContentManagerAsh* dlp_content_manager = + policy::DlpContentManagerAsh::Get(); + DCHECK(dlp_content_manager); + dlp_content_manager->CheckScreenShareRestriction(media_id, application_title, + std::move(callback)); +} + +void DlpAsh::OnScreenShareStarted( + const std::string& label, + mojom::ScreenShareAreaPtr area, + const ::std::u16string& application_title, + ::mojo::PendingRemote<mojom::StateChangeDelegate> delegate) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const content::DesktopMediaID media_id = AreaToDesktopMediaID(area); + if (media_id.is_null()) + return; + + mojo::RemoteSetElementId id = + screen_share_remote_delegates_.Add(std::move(delegate)); + base::RepeatingCallback stop_callback = base::BindRepeating( + &DlpAsh::StopScreenShare, weak_ptr_factory_.GetWeakPtr(), id); + base::RepeatingCallback state_change_callback = base::BindRepeating( + &DlpAsh::ChangeScreenShareState, weak_ptr_factory_.GetWeakPtr(), id); + + policy::DlpContentManagerAsh* dlp_content_manager = + policy::DlpContentManagerAsh::Get(); + DCHECK(dlp_content_manager); + dlp_content_manager->OnScreenCaptureStarted( + label, {media_id}, application_title, std::move(stop_callback), + std::move(state_change_callback)); +} + +void DlpAsh::OnScreenShareStopped(const std::string& label, + mojom::ScreenShareAreaPtr area) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const content::DesktopMediaID media_id = AreaToDesktopMediaID(area); + if (media_id.is_null()) + return; + + policy::DlpContentManagerAsh* dlp_content_manager = + policy::DlpContentManagerAsh::Get(); + DCHECK(dlp_content_manager); + dlp_content_manager->OnScreenCaptureStopped(label, media_id); +} + +void DlpAsh::ChangeScreenShareState( + mojo::RemoteSetElementId id, + const content::DesktopMediaID& media_id, + blink::mojom::MediaStreamStateChange new_state) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!screen_share_remote_delegates_.Contains(id)) + return; + switch (new_state) { + case blink::mojom::MediaStreamStateChange::PAUSE: + screen_share_remote_delegates_.Get(id)->OnPause(); + break; + case blink::mojom::MediaStreamStateChange::PLAY: + screen_share_remote_delegates_.Get(id)->OnResume(); + break; + } +} + +void DlpAsh::StopScreenShare(mojo::RemoteSetElementId id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!screen_share_remote_delegates_.Contains(id)) + return; + screen_share_remote_delegates_.Get(id)->OnStop(); +} + } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/dlp_ash.h b/chrome/browser/ash/crosapi/dlp_ash.h index 7b9d212..ec27d36 100644 --- a/chrome/browser/ash/crosapi/dlp_ash.h +++ b/chrome/browser/ash/crosapi/dlp_ash.h
@@ -6,8 +6,11 @@ #define CHROME_BROWSER_ASH_CROSAPI_DLP_ASH_H_ #include "chromeos/crosapi/mojom/dlp.mojom.h" +#include "content/public/browser/desktop_media_id.h" +#include "content/public/browser/media_stream_request.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" namespace crosapi { @@ -26,9 +29,33 @@ void DlpRestrictionsUpdated( const std::string& window_id, mojom::DlpRestrictionSetPtr restrictions) override; + void CheckScreenShareRestriction( + mojom::ScreenShareAreaPtr area, + const std::u16string& application_title, + CheckScreenShareRestrictionCallback callback) override; + void OnScreenShareStarted( + const std::string& label, + mojom::ScreenShareAreaPtr area, + const ::std::u16string& application_title, + ::mojo::PendingRemote<mojom::StateChangeDelegate> delegate) override; + void OnScreenShareStopped(const std::string& label, + mojom::ScreenShareAreaPtr area) override; private: + // Callback to pass request to change screen share state to remote. + void ChangeScreenShareState(mojo::RemoteSetElementId id, + const content::DesktopMediaID& media_id, + blink::mojom::MediaStreamStateChange new_state); + + // Callback to pass request to stop screen share to remote. + void StopScreenShare(mojo::RemoteSetElementId id); + mojo::ReceiverSet<mojom::Dlp> receivers_; + mojo::RemoteSet<mojom::StateChangeDelegate> screen_share_remote_delegates_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<DlpAsh> weak_ptr_factory_{this}; }; } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/dlp_ash_unittest.cc b/chrome/browser/ash/crosapi/dlp_ash_unittest.cc new file mode 100644 index 0000000..d45297e --- /dev/null +++ b/chrome/browser/ash/crosapi/dlp_ash_unittest.cc
@@ -0,0 +1,200 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/crosapi/dlp_ash.h" + +#include "ash/test/ash_test_base.h" +#include "base/test/bind.h" +#include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" +#include "chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/window.h" + +namespace crosapi { + +namespace { + +const std::u16string kAppId = u"app_id"; +constexpr char kScreenShareLabel[] = "label"; + +class MockStateChangeDelegate : public mojom::StateChangeDelegate { + public: + MOCK_METHOD(void, OnPause, (), (override)); + MOCK_METHOD(void, OnResume, (), (override)); + MOCK_METHOD(void, OnStop, (), (override)); + + mojo::PendingRemote<mojom::StateChangeDelegate> BindAndGetRemote() { + DCHECK(!receiver_.is_bound()); + return receiver_.BindNewPipeAndPassRemote(); + } + + mojo::Receiver<mojom::StateChangeDelegate> receiver_{this}; +}; + +} // namespace + +class DlpAshTest : public ash::AshTestBase { + public: + DlpAsh* dlp_ash() { return &dlp_ash_; } + + private: + DlpAsh dlp_ash_; +}; + +TEST_F(DlpAshTest, CheckScreenShareRestrictionRootWindowAllowed) { + testing::StrictMock<policy::MockDlpContentManagerAsh> + mock_dlp_content_manager; + policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + &mock_dlp_content_manager); + EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) + .WillOnce([](const content::DesktopMediaID& media_id, + const std::u16string& application_title, + base::OnceCallback<void(bool)> callback) { + EXPECT_EQ(content::DesktopMediaID::TYPE_SCREEN, media_id.type); + EXPECT_EQ(kAppId, application_title); + std::move(callback).Run(/*should_proceed=*/true); + }); + + mojom::ScreenShareAreaPtr area = mojom::ScreenShareArea::New(); + base::RunLoop run_loop; + dlp_ash()->CheckScreenShareRestriction( + std::move(area), kAppId, base::BindLambdaForTesting([&](bool allowed) { + EXPECT_TRUE(allowed); + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_F(DlpAshTest, CheckScreenShareRestrictionRootWindowNotAllowed) { + testing::StrictMock<policy::MockDlpContentManagerAsh> + mock_dlp_content_manager; + policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + &mock_dlp_content_manager); + EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) + .WillOnce([](const content::DesktopMediaID& media_id, + const std::u16string& application_title, + base::OnceCallback<void(bool)> callback) { + EXPECT_EQ(content::DesktopMediaID::TYPE_SCREEN, media_id.type); + EXPECT_EQ(kAppId, application_title); + std::move(callback).Run(/*should_proceed=*/false); + }); + + mojom::ScreenShareAreaPtr area = mojom::ScreenShareArea::New(); + base::RunLoop run_loop; + dlp_ash()->CheckScreenShareRestriction( + std::move(area), kAppId, base::BindLambdaForTesting([&](bool allowed) { + EXPECT_FALSE(allowed); + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_F(DlpAshTest, CheckScreenShareRestrictionInvalidWindow) { + testing::StrictMock<policy::MockDlpContentManagerAsh> + mock_dlp_content_manager; + policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + &mock_dlp_content_manager); + + mojom::ScreenShareAreaPtr area = mojom::ScreenShareArea::New(); + area->window_id = "id"; + base::RunLoop run_loop; + dlp_ash()->CheckScreenShareRestriction( + std::move(area), kAppId, base::BindLambdaForTesting([&](bool allowed) { + EXPECT_TRUE(allowed); + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_F(DlpAshTest, ScreenShareStarted) { + testing::StrictMock<MockStateChangeDelegate> delegate; + testing::StrictMock<policy::MockDlpContentManagerAsh> + mock_dlp_content_manager; + policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + &mock_dlp_content_manager); + + base::RepeatingClosure stop_callback; + content::MediaStreamUI::StateChangeCallback state_change_callback; + content::DesktopMediaID media_id; + + EXPECT_CALL(mock_dlp_content_manager, OnScreenCaptureStarted) + .WillOnce( + [&](const std::string& label, + std::vector<content::DesktopMediaID> ids, + const std::u16string& application_title, + base::RepeatingClosure stop_cb, + content::MediaStreamUI::StateChangeCallback state_change_cb) { + EXPECT_EQ(kScreenShareLabel, label); + EXPECT_EQ(1u, ids.size()); + EXPECT_EQ(kAppId, application_title); + stop_callback = std::move(stop_cb); + state_change_callback = std::move(state_change_cb); + media_id = ids[0]; + EXPECT_EQ(content::DesktopMediaID::TYPE_SCREEN, media_id.type); + }); + + mojom::ScreenShareAreaPtr area = mojom::ScreenShareArea::New(); + + dlp_ash()->OnScreenShareStarted(kScreenShareLabel, std::move(area), kAppId, + delegate.BindAndGetRemote()); + + EXPECT_CALL(delegate, OnPause).Times(1); + state_change_callback.Run(media_id, + blink::mojom::MediaStreamStateChange::PAUSE); + + EXPECT_CALL(delegate, OnResume).Times(1); + state_change_callback.Run(media_id, + blink::mojom::MediaStreamStateChange::PLAY); + + EXPECT_CALL(delegate, OnStop).Times(1); + stop_callback.Run(); + + delegate.receiver_.FlushForTesting(); +} + +TEST_F(DlpAshTest, ScreenShareStartedInvalidWindow) { + testing::StrictMock<MockStateChangeDelegate> delegate; + testing::StrictMock<policy::MockDlpContentManagerAsh> + mock_dlp_content_manager; + policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + &mock_dlp_content_manager); + + mojom::ScreenShareAreaPtr area = mojom::ScreenShareArea::New(); + area->window_id = "id"; + dlp_ash()->OnScreenShareStarted(kScreenShareLabel, std::move(area), kAppId, + delegate.BindAndGetRemote()); + + delegate.receiver_.FlushForTesting(); +} + +TEST_F(DlpAshTest, ScreenShareStopped) { + testing::StrictMock<policy::MockDlpContentManagerAsh> + mock_dlp_content_manager; + policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + &mock_dlp_content_manager); + + EXPECT_CALL(mock_dlp_content_manager, OnScreenCaptureStopped) + .WillOnce([&](const std::string& label, + const content::DesktopMediaID& media_id) { + EXPECT_EQ(kScreenShareLabel, label); + EXPECT_EQ(content::DesktopMediaID::TYPE_SCREEN, media_id.type); + }); + + mojom::ScreenShareAreaPtr area = mojom::ScreenShareArea::New(); + dlp_ash()->OnScreenShareStopped(kScreenShareLabel, std::move(area)); +} + +TEST_F(DlpAshTest, ScreenShareStoppedInvalidWindow) { + testing::StrictMock<policy::MockDlpContentManagerAsh> + mock_dlp_content_manager; + policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + &mock_dlp_content_manager); + + mojom::ScreenShareAreaPtr area = mojom::ScreenShareArea::New(); + area->window_id = "id"; + dlp_ash()->OnScreenShareStopped(kScreenShareLabel, std::move(area)); +} + +} // namespace crosapi
diff --git a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc index 9bf2bde..c5632af 100644 --- a/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc +++ b/chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.cc
@@ -257,7 +257,8 @@ login_logout_reporter_ = ash::reporting::LoginLogoutReporter::Create( managed_session_service_.get()); user_added_removed_reporter_ = - std::make_unique<::reporting::UserAddedRemovedReporter>(); + ::reporting::UserAddedRemovedReporter::Create( + managed_session_service_.get()); metric_reporting_manager_ = reporting::MetricReportingManager::Create( managed_session_service_.get()); }
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.cc b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.cc index ebfd58e..03ea6a1 100644 --- a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.cc +++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.cc
@@ -251,16 +251,8 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); for (const content::DesktopMediaID& id : screen_capture_ids) { - auto screen_share_info = std::make_unique<ScreenShareInfo>( - label, id, application_title, stop_callback, state_change_callback); - DCHECK(std::find_if( - running_screen_shares_.begin(), running_screen_shares_.end(), - [&screen_share_info]( - const std::unique_ptr<ScreenShareInfo>& info) -> bool { - return info && *info == *screen_share_info; - }) == running_screen_shares_.end()); - - running_screen_shares_.push_back(std::move(screen_share_info)); + AddScreenShare(label, id, application_title, stop_callback, + state_change_callback); } CheckRunningScreenShares(); } @@ -292,122 +284,6 @@ g_dlp_content_manager = nullptr; } -DlpContentManagerAsh::ScreenShareInfo::ScreenShareInfo( - const std::string& label, - const content::DesktopMediaID& media_id, - const std::u16string& application_title, - base::OnceClosure stop_callback, - content::MediaStreamUI::StateChangeCallback state_change_callback) - : label_(label), - media_id_(media_id), - application_title_(application_title), - stop_callback_(std::move(stop_callback)), - state_change_callback_(std::move(state_change_callback)) {} - -DlpContentManagerAsh::ScreenShareInfo::~ScreenShareInfo() { - // Hide notifications if necessary. - HideNotifications(); -} - -bool DlpContentManagerAsh::ScreenShareInfo::operator==( - const DlpContentManagerAsh::ScreenShareInfo& other) const { - return label_ == other.label_ && media_id_ == other.media_id_; -} - -bool DlpContentManagerAsh::ScreenShareInfo::operator!=( - const DlpContentManagerAsh::ScreenShareInfo& other) const { - return !(*this == other); -} - -const content::DesktopMediaID& -DlpContentManagerAsh::ScreenShareInfo::GetMediaId() const { - return media_id_; -} - -const std::string& DlpContentManagerAsh::ScreenShareInfo::GetLabel() const { - return label_; -} - -const std::u16string& -DlpContentManagerAsh::ScreenShareInfo::GetApplicationTitle() const { - // TODO(crbug.com/1264793): Don't cache the application name, but compute it - // here. - return application_title_; -} - -bool DlpContentManagerAsh::ScreenShareInfo::IsRunning() const { - return state_ == State::kRunning; -} - -void DlpContentManagerAsh::ScreenShareInfo::Pause() { - DCHECK(state_ == State::kRunning); - state_change_callback_.Run(media_id_, - blink::mojom::MediaStreamStateChange::PAUSE); - state_ = State::kPaused; -} - -void DlpContentManagerAsh::ScreenShareInfo::Resume() { - DCHECK(state_ == State::kPaused); - state_change_callback_.Run(media_id_, - blink::mojom::MediaStreamStateChange::PLAY); - state_ = State::kRunning; -} - -void DlpContentManagerAsh::ScreenShareInfo::Stop() { - DCHECK(state_ != State::kStopped); - if (stop_callback_) { - std::move(stop_callback_).Run(); - state_ = State::kStopped; - } else { - NOTREACHED(); - } -} - -void DlpContentManagerAsh::ScreenShareInfo::MaybeUpdateNotifications() { - UpdatePausedNotification(/*show=*/state_ == State::kPaused); - UpdateResumedNotification(/*show=*/state_ == State::kRunning); -} - -void DlpContentManagerAsh::ScreenShareInfo::HideNotifications() { - UpdatePausedNotification(/*show=*/false); - UpdateResumedNotification(/*show=*/false); -} - -base::WeakPtr<DlpContentManagerAsh::ScreenShareInfo> -DlpContentManagerAsh::ScreenShareInfo::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -void DlpContentManagerAsh::ScreenShareInfo::UpdatePausedNotification( - bool show) { - if ((notification_state_ == NotificationState::kShowingPausedNotification) == - show) - return; - if (show) { - DCHECK(state_ == State::kPaused); - ShowDlpScreenSharePausedNotification(label_, application_title_); - notification_state_ = NotificationState::kShowingPausedNotification; - } else { - HideDlpScreenSharePausedNotification(label_); - notification_state_ = NotificationState::kNotShowingNotification; - } -} - -void DlpContentManagerAsh::ScreenShareInfo::UpdateResumedNotification( - bool show) { - if ((notification_state_ == NotificationState::kShowingResumedNotification) == - show) - return; - if (show) { - DCHECK(state_ == State::kRunning); - ShowDlpScreenShareResumedNotification(label_, application_title_); - notification_state_ = NotificationState::kShowingResumedNotification; - } else { - HideDlpScreenShareResumedNotification(label_); - notification_state_ = NotificationState::kNotShowingNotification; - } -} - DlpContentManagerAsh::VideoCaptureInfo::VideoCaptureInfo( const ScreenshotArea& area) : area(area) {} @@ -676,7 +552,7 @@ return info; } -DlpContentManagerAsh::ConfidentialContentsInfo +DlpContentManager::ConfidentialContentsInfo DlpContentManagerAsh::GetScreenShareConfidentialContentsInfo( const content::DesktopMediaID& media_id) const { if (media_id.type == content::DesktopMediaID::Type::TYPE_SCREEN) { @@ -761,70 +637,6 @@ } } -void DlpContentManagerAsh::RemoveScreenShare( - const std::string& label, - const content::DesktopMediaID& media_id) { - base::EraseIf( - running_screen_shares_, - [=](const std::unique_ptr<ScreenShareInfo>& screen_share_info) -> bool { - return screen_share_info->GetLabel() == label && - screen_share_info->GetMediaId() == media_id; - }); -} - -void DlpContentManagerAsh::CheckRunningScreenShares() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - for (std::unique_ptr<ScreenShareInfo>& screen_share : - running_screen_shares_) { - ConfidentialContentsInfo info = - GetScreenShareConfidentialContentsInfo(screen_share->GetMediaId()); - if (IsBlocked(info.restriction_info)) { - if (screen_share->IsRunning()) { - screen_share->Pause(); - MaybeReportEvent(info.restriction_info, - DlpRulesManager::Restriction::kScreenShare); - DlpBooleanHistogram(dlp::kScreenSharePausedOrResumedUMA, true); - screen_share->MaybeUpdateNotifications(); - } - continue; - } - if (is_screen_share_warning_mode_enabled_ && - IsWarn(info.restriction_info)) { - // Check which of the contents were already allowed and don't warn for - // those. - RemoveAllowedContents(info.confidential_contents, - DlpRulesManager::Restriction::kScreenShare); - if (info.confidential_contents.IsEmpty()) { - // The user already allowed all the visible content. - if (!screen_share->IsRunning()) { - screen_share->Resume(); - screen_share->MaybeUpdateNotifications(); - } - continue; - } - if (screen_share->IsRunning()) { - screen_share->Pause(); - screen_share->HideNotifications(); - } - // base::Unretained(this) is safe here because DlpContentManagerAsh is - // initialized as a singleton that's always available in the system. - warn_notifier_->ShowDlpScreenShareWarningDialog( - base::BindOnce(&DlpContentManagerAsh::OnDlpScreenShareWarnDialogReply, - base::Unretained(this), info.confidential_contents, - screen_share->GetWeakPtr()), - info.confidential_contents, screen_share->GetApplicationTitle()); - continue; - } - // No restrictions apply, only resume if necessary. - if (!screen_share->IsRunning()) { - screen_share->Resume(); - DlpBooleanHistogram(dlp::kScreenSharePausedOrResumedUMA, false); - screen_share->MaybeUpdateNotifications(); - } - } -} - // static base::TimeDelta DlpContentManagerAsh::GetPrivacyScreenOffDelayForTesting() { return kPrivacyScreenOffDelay; @@ -866,30 +678,6 @@ std::move(callback).Run(true); } -void DlpContentManagerAsh::OnDlpScreenShareWarnDialogReply( - const DlpConfidentialContents& confidential_contents, - base::WeakPtr<ScreenShareInfo> screen_share, - bool should_proceed) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (!screen_share) - // The screen share was stopped before the dialog was addressed, so no need - // to do anything. - return; - - if (should_proceed) { - screen_share->Resume(); - for (const auto& content : confidential_contents.GetContents()) { - user_allowed_contents_cache_.Cache( - content, DlpRulesManager::Restriction::kScreenShare); - } - screen_share->MaybeUpdateNotifications(); - } else { - screen_share->Stop(); - RemoveScreenShare(screen_share->GetLabel(), screen_share->GetMediaId()); - } -} - // ScopedDlpContentManagerAshForTesting ScopedDlpContentManagerAshForTesting::ScopedDlpContentManagerAshForTesting( DlpContentManagerAsh* test_dlp_content_manager) {
diff --git a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h index 7605b01..3a76769e 100644 --- a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h +++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h
@@ -79,15 +79,6 @@ virtual bool IsScreenCaptureRestricted( const content::DesktopMediaID& media_id); - // Checks whether screen sharing of content from the |media_id| source with - // application |application_name| is restricted or not advised. Depending on - // the result, calls |callback| and passes an indicator whether to proceed or - // not. - void CheckScreenShareRestriction( - const content::DesktopMediaID& media_id, - const std::u16string& application_title, - OnDlpRestrictionCheckedCallback callback) override; - // Called when video capturing for |area| is started. void OnVideoCaptureStarted(const ScreenshotArea& area); @@ -106,19 +97,20 @@ void CheckCaptureModeInitRestriction( ash::OnCaptureModeDlpRestrictionChecked callback); - // Called when screen capture is started. - // |state_change_callback| will be called when restricted content will appear - // or disappear in the captured area. + // DlpContentManager overrides: + void CheckScreenShareRestriction( + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + OnDlpRestrictionCheckedCallback callback) override; void OnScreenCaptureStarted( const std::string& label, std::vector<content::DesktopMediaID> screen_capture_ids, const std::u16string& application_title, base::RepeatingClosure stop_callback, - content::MediaStreamUI::StateChangeCallback state_change_callback); - - // Called when screen capture is stopped. + content::MediaStreamUI::StateChangeCallback state_change_callback) + override; void OnScreenCaptureStopped(const std::string& label, - const content::DesktopMediaID& media_id); + const content::DesktopMediaID& media_id) override; // Called when an updated restrictions are received for Lacros window. void OnWindowRestrictionChanged(aura::Window* window, @@ -139,74 +131,6 @@ friend class DlpContentTabHelper; friend class MockDlpContentManagerAsh; - // Used to keep track of running screen shares. - class ScreenShareInfo { - public: - ScreenShareInfo( - const std::string& label, - const content::DesktopMediaID& media_id, - const std::u16string& application_title, - base::OnceClosure stop_callback, - content::MediaStreamUI::StateChangeCallback state_change_callback); - ~ScreenShareInfo(); - - bool operator==(const ScreenShareInfo& other) const; - bool operator!=(const ScreenShareInfo& other) const; - - const content::DesktopMediaID& GetMediaId() const; - const std::string& GetLabel() const; - const std::u16string& GetApplicationTitle() const; - bool IsRunning() const; - - // Pauses a running screen share. - // No-op if the screen share is already paused. - void Pause(); - // Resumes a paused screen share. - // No-op if the screen share is already running. - void Resume(); - // Stops the screen share. Can only be called once. - void Stop(); - - // If necessary, hides or shows the paused/resumed notification for this - // screen share. The notification should be updated after changing the state - // from running to paused, or paused to running. - void MaybeUpdateNotifications(); - - // If shown, hides both the paused and resumed notification for this screen - // share. - void HideNotifications(); - - base::WeakPtr<ScreenShareInfo> GetWeakPtr(); - - private: - enum class NotificationState { - kNotShowingNotification, - kShowingPausedNotification, - kShowingResumedNotification - }; - enum class State { kRunning, kPaused, kStopped }; - // Shows (if |show| is true) or hides (if |show| is false) paused - // notification for this screen share. Does nothing if the notification is - // already in the required state. - void UpdatePausedNotification(bool show); - // Shows (if |show| is true) or hides (if |show| is false) resumed - // notification for this screen share. Does nothing if the notification is - // already in the required state. - void UpdateResumedNotification(bool show); - - std::string label_; - content::DesktopMediaID media_id_; - // TODO(crbug.com/1264793): Don't cache the application name. - std::u16string application_title_; - base::OnceClosure stop_callback_; - content::MediaStreamUI::StateChangeCallback state_change_callback_; - State state_ = State::kRunning; - NotificationState notification_state_ = - NotificationState::kNotShowingNotification; - - base::WeakPtrFactory<ScreenShareInfo> weak_factory_{this}; - }; - // Structure to keep track of a running video capture. struct VideoCaptureInfo { explicit VideoCaptureInfo(const ScreenshotArea& area); @@ -231,6 +155,8 @@ const DlpContentRestrictionSet& restriction_set) override; void OnVisibilityChanged(content::WebContents* web_contents) override; void RemoveFromConfidential(content::WebContents* web_contents) override; + ConfidentialContentsInfo GetScreenShareConfidentialContentsInfo( + const content::DesktopMediaID& media_id) const override; // Updates |on_screen_restrictions_| and calls // OnScreenRestrictionsChanged() if needed. @@ -255,24 +181,10 @@ const ScreenshotArea& area, DlpContentRestriction restriction) const; - // Returns which level, url, and information about visible confidential - // contents of screen share restriction that is currently enforced for - // |media_id|. - ConfidentialContentsInfo GetScreenShareConfidentialContentsInfo( - const content::DesktopMediaID& media_id) const; - // Checks and stops the running video capture if restricted content appeared // in the corresponding areas. void CheckRunningVideoCapture(); - // Removes screen share from |running_screen_shares_|. - void RemoveScreenShare(const std::string& label, - const content::DesktopMediaID& media_id); - - // Checks and stops the running screen shares if restricted content appeared - // in the corresponding areas. - void CheckRunningScreenShares(); - // Get the delay before switching privacy screen off. static base::TimeDelta GetPrivacyScreenOffDelayForTesting(); @@ -282,17 +194,6 @@ ConfidentialContentsInfo info, ash::OnCaptureModeDlpRestrictionChecked callback); - // Called back from Screen Share warning dialogs that are shown during the - // screen share. Passes along the user's response, reflected in the value of - // |should_proceed| along to |callback| which handles continuing or cancelling - // the action based on this response. In case that |should_proceed| is true, - // also saves the |confidential_contents| that were allowed to be shared by - // the user to avoid future warnings. - void OnDlpScreenShareWarnDialogReply( - const DlpConfidentialContents& confidential_contents, - base::WeakPtr<ScreenShareInfo> screen_share, - bool should_proceed); - // Map of window observers for the current confidential WebContents. base::flat_map<content::WebContents*, std::unique_ptr<DlpWindowObserver>> web_contents_window_observers_; @@ -309,9 +210,6 @@ // Information about the currently running video capture area if any. absl::optional<VideoCaptureInfo> running_video_capture_info_; - - // List of the currently running screen shares. - std::vector<std::unique_ptr<ScreenShareInfo>> running_screen_shares_; }; // Helper class to call SetDlpContentManagerAshForTesting and
diff --git a/chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h b/chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h index 8f73634..34c641a 100644 --- a/chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h +++ b/chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h
@@ -40,6 +40,18 @@ const std::u16string& application_title, OnDlpRestrictionCheckedCallback callback), (override)); + MOCK_METHOD(void, + OnScreenCaptureStarted, + (const std::string&, + std::vector<content::DesktopMediaID>, + const std::u16string&, + base::RepeatingClosure, + content::MediaStreamUI::StateChangeCallback), + (override)); + MOCK_METHOD(void, + OnScreenCaptureStopped, + (const std::string&, const content::DesktopMediaID&), + (override)); protected: void Init() override;
diff --git a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.cc b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.cc index 4eae3c5d..9efba1a 100644 --- a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.cc +++ b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.cc
@@ -4,33 +4,38 @@ #include "chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.h" -#include "base/logging.h" +#include <utility> + #include "base/memory/ptr_util.h" -#include "base/sequence_checker.h" -#include "base/task/bind_post_task.h" #include "chrome/browser/ash/login/users/chrome_user_manager.h" #include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part_chromeos.h" +#include "chrome/browser/policy/messaging_layer/proto/synced/add_remove_user_event.pb.h" +#include "components/reporting/proto/synced/record_constants.pb.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_names.h" namespace reporting { -UserAddedRemovedReporter::UserAddedRemovedReporter( - std::unique_ptr<UserEventReporterHelper> helper) - : helper_(std::move(helper)) { - ProcessRemoveUserCache(); - managed_session_observation_.Observe(&managed_session_service_); +// static +std::unique_ptr<UserAddedRemovedReporter> UserAddedRemovedReporter::Create( + policy::ManagedSessionService* managed_session_service) { + return base::WrapUnique( + new UserAddedRemovedReporter(std::make_unique<UserEventReporterHelper>( + Destination::ADDED_REMOVED_EVENTS), + managed_session_service)); } -UserAddedRemovedReporter::UserAddedRemovedReporter() - : helper_(std::make_unique<UserEventReporterHelper>( - Destination::ADDED_REMOVED_EVENTS)) { - ProcessRemoveUserCache(); - managed_session_observation_.Observe(&managed_session_service_); +// static +std::unique_ptr<UserAddedRemovedReporter> +UserAddedRemovedReporter::CreateForTesting( + std::unique_ptr<UserEventReporterHelper> helper, + policy::ManagedSessionService* managed_session_service) { + return base::WrapUnique( + new UserAddedRemovedReporter(std::move(helper), managed_session_service)); } UserAddedRemovedReporter::~UserAddedRemovedReporter() = default; @@ -120,4 +125,12 @@ user_manager->MarkReporterInitialized(); } + +UserAddedRemovedReporter::UserAddedRemovedReporter( + std::unique_ptr<UserEventReporterHelper> helper, + policy::ManagedSessionService* managed_session_service) + : helper_(std::move(helper)) { + ProcessRemoveUserCache(); + managed_session_observation_.Observe(managed_session_service); +} } // namespace reporting
diff --git a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.h b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.h index 8f65240..703f8798 100644 --- a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.h +++ b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.h
@@ -5,14 +5,14 @@ #ifndef CHROME_BROWSER_ASH_POLICY_REPORTING_USER_ADDED_REMOVED_USER_ADDED_REMOVED_REPORTER_H_ #define CHROME_BROWSER_ASH_POLICY_REPORTING_USER_ADDED_REMOVED_USER_ADDED_REMOVED_REPORTER_H_ +#include <memory> + #include "base/containers/flat_map.h" #include "base/scoped_observation.h" #include "chrome/browser/ash/policy/reporting/user_event_reporter_helper.h" #include "chrome/browser/ash/policy/status_collector/managed_session_service.h" -#include "chrome/browser/policy/messaging_layer/proto/synced/add_remove_user_event.pb.h" #include "chrome/browser/profiles/profile.h" #include "components/reporting/client/report_queue_provider.h" -#include "components/reporting/proto/synced/record_constants.pb.h" namespace reporting { @@ -23,11 +23,14 @@ class UserAddedRemovedReporter : public policy::ManagedSessionService::Observer { public: + // For prod. Uses the default implementation of UserEventReporterHelper. + static std::unique_ptr<UserAddedRemovedReporter> Create( + policy::ManagedSessionService* managed_session_service); + // For use in testing only. Allows user to pass in a test helper. - explicit UserAddedRemovedReporter( - std::unique_ptr<UserEventReporterHelper> helper); - // For prod. Uses the default implementation of UserEventReporterTestHelper. - UserAddedRemovedReporter(); + static std::unique_ptr<UserAddedRemovedReporter> CreateForTesting( + std::unique_ptr<UserEventReporterHelper> helper, + policy::ManagedSessionService* managed_session_service); UserAddedRemovedReporter(const UserAddedRemovedReporter& other) = delete; UserAddedRemovedReporter& operator=(const UserAddedRemovedReporter& other) = @@ -50,14 +53,16 @@ user_manager::UserRemovalReason reason) override; private: + UserAddedRemovedReporter( + std::unique_ptr<UserEventReporterHelper> helper, + policy::ManagedSessionService* managed_session_service); + std::unique_ptr<UserEventReporterHelper> helper_; // Maps a user's email to if they are affiliated. This is needed to determine // if their email may be reported. base::flat_map<AccountId, bool> users_to_be_deleted_; - policy::ManagedSessionService managed_session_service_; - base::ScopedObservation<policy::ManagedSessionService, policy::ManagedSessionService::Observer> managed_session_observation_{this};
diff --git a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_unittest.cc b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_unittest.cc index 9ae94b0..89829c2 100644 --- a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_unittest.cc +++ b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_unittest.cc
@@ -4,17 +4,26 @@ #include "chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter.h" +#include <memory> +#include <string> +#include <utility> + +#include "base/memory/weak_ptr.h" +#include "base/strings/string_piece.h" #include "base/test/task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ash/policy/status_collector/managed_session_service.h" #include "chrome/browser/ash/profiles/profile_helper.h" +#include "chrome/browser/policy/messaging_layer/proto/synced/add_remove_user_event.pb.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/power/fake_power_manager_client.h" -#include "components/policy/core/common/cloud/dm_token.h" #include "components/reporting/client/mock_report_queue.h" +#include "components/reporting/proto/synced/record_constants.pb.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_names.h" #include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" namespace reporting { @@ -81,34 +90,46 @@ delete mock_queue_; } - std::unique_ptr<TestingProfile> CreateRegularProfile( - base::StringPiece user_email) { + std::unique_ptr<TestingProfile> LoginRegularProfile( + base::StringPiece user_email, + policy::ManagedSessionService* managed_session_service) { const AccountId account_id = AccountId::FromUserEmail(std::string(user_email)); TestingProfile::Builder profile_builder; profile_builder.SetProfileName(account_id.GetUserEmail()); auto profile = profile_builder.Build(); - user_manager_->AddUser(account_id); + auto* const user = user_manager_->AddUser(account_id); user_manager_->LoginUser(account_id, true); + ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, + profile.get()); + managed_session_service->OnUserProfileLoaded(account_id); return profile; } - std::unique_ptr<TestingProfile> CreateGuestProfile() { + std::unique_ptr<TestingProfile> LoginGuestProfile( + policy::ManagedSessionService* managed_session_service) { TestingProfile::Builder profile_builder; auto profile = profile_builder.Build(); user_manager::User* user = user_manager_->AddGuestUser(); user_manager_->LoginUser(user->GetAccountId(), true); + ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, + profile.get()); + managed_session_service->OnUserProfileLoaded(user->GetAccountId()); return profile; } - std::unique_ptr<TestingProfile> CreateKioskProfile( - base::StringPiece user_email) { + std::unique_ptr<TestingProfile> LoginKioskProfile( + base::StringPiece user_email, + policy::ManagedSessionService* managed_session_service) { const AccountId account_id = AccountId::FromUserEmail(std::string(user_email)); TestingProfile::Builder profile_builder; auto profile = profile_builder.Build(); - user_manager_->AddKioskAppUser(account_id); + auto* const user = user_manager_->AddKioskAppUser(account_id); user_manager_->LoginUser(account_id, true); + ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, + profile.get()); + managed_session_service->OnUserProfileLoaded(account_id); return profile; } @@ -144,12 +165,18 @@ record.ParseFromString(std::string(record_string)); priority = event_priority; }); - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ true, /* user_new */ true)); - auto profile = CreateRegularProfile(user_email); - reporter.OnLogin(profile.get()); + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/true, /*user_new=*/true); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); + + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + LoginRegularProfile(user_email, managed_session_service.get()); EXPECT_THAT(priority, testing::Eq(::reporting::Priority::IMMEDIATE)); EXPECT_TRUE(record.has_event_timestamp_sec()); @@ -177,12 +204,17 @@ priority = event_priority; }); - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ false, /* user_new */ true)); + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/false, /*user_new=*/true); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); - auto profile = CreateRegularProfile(user_email); - reporter.OnLogin(profile.get()); + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + LoginRegularProfile(user_email, managed_session_service.get()); EXPECT_THAT(priority, testing::Eq(::reporting::Priority::IMMEDIATE)); EXPECT_TRUE(record.has_event_timestamp_sec()); @@ -200,18 +232,22 @@ nullptr, base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); auto mock_queue = weak_mock_queue_factory_->GetWeakPtr(); - - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ false, - /* report_user */ true, /* user_new */ true)); - - auto profile = CreateRegularProfile(user_email); - reporter.OnLogin(profile.get()); - reporter.OnUserToBeRemoved(account_id); - reporter.OnUserRemoved(account_id, - user_manager::UserRemovalReason::GAIA_REMOVED); - EXPECT_CALL(*mock_queue, AddRecord).Times(0); + + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/false, + /*report_user=*/true, /*user_new=*/true); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); + + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + auto profile = LoginRegularProfile(user_email, managed_session_service.get()); + managed_session_service->OnUserToBeRemoved(account_id); + managed_session_service->OnUserRemoved( + account_id, user_manager::UserRemovalReason::GAIA_REMOVED); } TEST_F(UserAddedRemovedReporterTest, TestExistingUserLogin) { @@ -221,15 +257,19 @@ nullptr, base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); auto mock_queue = weak_mock_queue_factory_->GetWeakPtr(); - - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ true, /* user_new */ false)); - - auto profile = CreateRegularProfile(user_email); - reporter.OnLogin(profile.get()); - EXPECT_CALL(*mock_queue, AddRecord).Times(0); + + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/true, /*user_new=*/false); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); + + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + LoginRegularProfile(user_email, managed_session_service.get()); } TEST_F(UserAddedRemovedReporterTest, TestGuestSessionLogsIn) { @@ -238,15 +278,19 @@ nullptr, base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); auto mock_queue = weak_mock_queue_factory_->GetWeakPtr(); - - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ true, /* user_new */ true)); - - auto profile = CreateGuestProfile(); - reporter.OnLogin(profile.get()); - EXPECT_CALL(*mock_queue, AddRecord).Times(0); + + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/true, /*user_new=*/true); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); + + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + LoginGuestProfile(managed_session_service.get()); } TEST_F(UserAddedRemovedReporterTest, TestKioskUserLogsIn) { @@ -258,15 +302,19 @@ nullptr, base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); auto mock_queue = weak_mock_queue_factory_->GetWeakPtr(); - - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ true, /* user_new */ true)); - - auto profile = CreateKioskProfile(user_email); - reporter.OnLogin(profile.get()); - EXPECT_CALL(*mock_queue, AddRecord).Times(0); + + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/true, /*user_new=*/true); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); + + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + LoginKioskProfile(user_email, managed_session_service.get()); } TEST_F(UserAddedRemovedReporterTest, TestAffiliatedUserRemoval) { @@ -290,14 +338,20 @@ priority = event_priority; }); - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ true, /* user_new */ true)); + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/true, /*user_new=*/false); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); - auto profile = CreateRegularProfile(user_email); - reporter.OnUserToBeRemoved(account_id); - reporter.OnUserRemoved(account_id, - user_manager::UserRemovalReason::GAIA_REMOVED); + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + auto profile = LoginRegularProfile(user_email, managed_session_service.get()); + managed_session_service->OnUserToBeRemoved(account_id); + managed_session_service->OnUserRemoved( + account_id, user_manager::UserRemovalReason::GAIA_REMOVED); EXPECT_THAT(priority, testing::Eq(::reporting::Priority::IMMEDIATE)); EXPECT_TRUE(record.has_event_timestamp_sec()); @@ -330,14 +384,20 @@ priority = event_priority; }); - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ false, /* user_new */ true)); + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/false, /*user_new=*/false); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); - auto profile = CreateRegularProfile(user_email); - reporter.OnUserToBeRemoved(account_id); - reporter.OnUserRemoved(account_id, - user_manager::UserRemovalReason::GAIA_REMOVED); + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + auto profile = LoginRegularProfile(user_email, managed_session_service.get()); + managed_session_service->OnUserToBeRemoved(account_id); + managed_session_service->OnUserRemoved( + account_id, user_manager::UserRemovalReason::GAIA_REMOVED); EXPECT_THAT(priority, testing::Eq(::reporting::Priority::IMMEDIATE)); EXPECT_TRUE(record.has_event_timestamp_sec()); @@ -356,16 +416,22 @@ nullptr, base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); auto mock_queue = weak_mock_queue_factory_->GetWeakPtr(); - - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ true, /* user_new */ true)); - auto profile = CreateKioskProfile(user_email); - reporter.OnUserToBeRemoved(account_id); - reporter.OnUserRemoved(account_id, - user_manager::UserRemovalReason::GAIA_REMOVED); - EXPECT_CALL(*mock_queue, AddRecord).Times(0); + + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/true, /*user_new=*/true); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); + + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); + + auto profile = LoginKioskProfile(user_email, managed_session_service.get()); + managed_session_service->OnUserToBeRemoved(account_id); + managed_session_service->OnUserRemoved( + account_id, user_manager::UserRemovalReason::GAIA_REMOVED); } TEST_F(UserAddedRemovedReporterTest, TestRemoteRemoval) { @@ -380,7 +446,6 @@ auto mock_queue = weak_mock_queue_factory_->GetWeakPtr(); ::reporting::UserAddedRemovedRecord record; - ::reporting::UserAddedRemovedRecord record_a; ::reporting::Priority priority; EXPECT_CALL(*mock_queue, AddRecord) .WillOnce( @@ -391,9 +456,15 @@ priority = event_priority; }); - UserAddedRemovedReporter reporter(std::make_unique<TestHelper>( - std::move(dummy_queue), mock_queue, /* report_event */ true, - /* report_user */ false, /* user_new */ true)); + auto test_helper = + std::make_unique<TestHelper>(std::move(dummy_queue), mock_queue, + /*report_event=*/true, + /*report_user=*/false, /*user_new=*/true); + auto managed_session_service = + std::make_unique<policy::ManagedSessionService>(); + + auto reporter = UserAddedRemovedReporter::CreateForTesting( + std::move(test_helper), managed_session_service.get()); EXPECT_THAT(priority, testing::Eq(::reporting::Priority::IMMEDIATE)); EXPECT_TRUE(record.has_event_timestamp_sec());
diff --git a/chrome/browser/ash/quick_pair/quick_pair_browser_delegate_impl.cc b/chrome/browser/ash/quick_pair/quick_pair_browser_delegate_impl.cc index aee3ac6..8abf041e 100644 --- a/chrome/browser/ash/quick_pair/quick_pair_browser_delegate_impl.cc +++ b/chrome/browser/ash/quick_pair/quick_pair_browser_delegate_impl.cc
@@ -77,10 +77,8 @@ } Profile* QuickPairBrowserDelegateImpl::GetActiveProfile() { - if (!user_manager::UserManager::Get()->IsUserLoggedIn()) { - NOTREACHED(); + if (!user_manager::UserManager::Get()->IsUserLoggedIn()) return nullptr; - } user_manager::User* active_user = user_manager::UserManager::Get()->GetActiveUser();
diff --git a/chrome/browser/ash/system_logs/network_health_source.cc b/chrome/browser/ash/system_logs/network_health_source.cc index bdc4421..a34d563 100644 --- a/chrome/browser/ash/system_logs/network_health_source.cc +++ b/chrome/browser/ash/system_logs/network_health_source.cc
@@ -51,7 +51,7 @@ << "\n"; output << "Signal Strength (Samples): ["; auto& samples = net->signal_strength_stats->samples; - for (int i = 0; i < samples.size(); i++) { + for (uint16_t i = 0; i < samples.size(); i++) { output << base::NumberToString(samples[i]); if (i < samples.size() - 1) output << ","; @@ -84,7 +84,7 @@ } std::ostringstream output; - for (int i = 0; i < problems.size(); i++) { + for (uint16_t i = 0; i < problems.size(); i++) { output << problems[i]; if (i != problems.size() - 1) output << ", ";
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc new file mode 100644 index 0000000..1d7ff0de --- /dev/null +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc
@@ -0,0 +1,31 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h" + +#include "ash/public/cpp/ambient/ambient_prefs.h" +#include "chrome/browser/profiles/profile.h" +#include "components/prefs/pref_service.h" + +PersonalizationAppAmbientProviderImpl::PersonalizationAppAmbientProviderImpl( + content::WebUI* web_ui) + : profile_(Profile::FromWebUI(web_ui)) {} + +PersonalizationAppAmbientProviderImpl:: + ~PersonalizationAppAmbientProviderImpl() = default; + +void PersonalizationAppAmbientProviderImpl::BindInterface( + mojo::PendingReceiver<ash::personalization_app::mojom::AmbientProvider> + receiver) { + ambient_receiver_.reset(); + ambient_receiver_.Bind(std::move(receiver)); +} + +void PersonalizationAppAmbientProviderImpl::IsAmbientModeEnabled( + IsAmbientModeEnabledCallback callback) { + PrefService* pref_service = profile_->GetPrefs(); + DCHECK(pref_service); + std::move(callback).Run( + pref_service->GetBoolean(ash::ambient::prefs::kAmbientModeEnabled)); +}
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h new file mode 100644 index 0000000..9e90db4 --- /dev/null +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h
@@ -0,0 +1,45 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_PERSONALIZATION_APP_AMBIENT_PROVIDER_IMPL_H_ +#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_PERSONALIZATION_APP_AMBIENT_PROVIDER_IMPL_H_ + +#include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" +#include "ash/webui/personalization_app/personalization_app_ambient_provider.h" +#include "content/public/browser/web_ui.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" + +class Profile; + +class PersonalizationAppAmbientProviderImpl + : public ash::PersonalizationAppAmbientProvider { + public: + explicit PersonalizationAppAmbientProviderImpl(content::WebUI* web_ui); + + PersonalizationAppAmbientProviderImpl( + const PersonalizationAppAmbientProviderImpl&) = delete; + PersonalizationAppAmbientProviderImpl& operator=( + const PersonalizationAppAmbientProviderImpl&) = delete; + + ~PersonalizationAppAmbientProviderImpl() override; + + void BindInterface( + mojo::PendingReceiver<ash::personalization_app::mojom::AmbientProvider> + receiver) override; + + // ash::personalization_app::mojom:AmbientProvider: + void IsAmbientModeEnabled(IsAmbientModeEnabledCallback callback) override; + + private: + mojo::Receiver<ash::personalization_app::mojom::AmbientProvider> + ambient_receiver_{this}; + + // Pointer to profile of user that opened personalization SWA. Not owned. + Profile* const profile_ = nullptr; +}; + +#endif // CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_PERSONALIZATION_APP_AMBIENT_PROVIDER_IMPL_H_
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl_unittest.cc new file mode 100644 index 0000000..087b66c --- /dev/null +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl_unittest.cc
@@ -0,0 +1,101 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h" + +#include <memory> + +#include "ash/constants/ash_features.h" +#include "ash/public/cpp/ambient/ambient_prefs.h" +#include "ash/webui/personalization_app/mojom/personalization_app.mojom.h" +#include "base/callback_helpers.h" +#include "base/test/bind.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_web_ui.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/webui/web_ui_util.h" + +namespace { + +constexpr char kFakeTestEmail[] = "fakeemail@example.com"; + +} // namespace + +class PersonalizationAppAmbientProviderImplTest : public testing::Test { + public: + PersonalizationAppAmbientProviderImplTest() + : profile_manager_(TestingBrowserProcess::GetGlobal()) {} + PersonalizationAppAmbientProviderImplTest( + const PersonalizationAppAmbientProviderImplTest&) = delete; + PersonalizationAppAmbientProviderImplTest& operator=( + const PersonalizationAppAmbientProviderImplTest&) = delete; + ~PersonalizationAppAmbientProviderImplTest() override = default; + + protected: + // testing::Test: + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + ash::features::kPersonalizationHub); + ASSERT_TRUE(profile_manager_.SetUp()); + profile_ = profile_manager_.CreateTestingProfile(kFakeTestEmail); + + web_contents_ = content::WebContents::Create( + content::WebContents::CreateParams(profile_)); + web_ui_.set_web_contents(web_contents_.get()); + + ambient_provider_ = + std::make_unique<PersonalizationAppAmbientProviderImpl>(&web_ui_); + + ambient_provider_->BindInterface( + ambient_provider_remote_.BindNewPipeAndPassReceiver()); + } + + TestingProfile* profile() { return profile_; } + + mojo::Remote<ash::personalization_app::mojom::AmbientProvider>& + ambient_provider_remote() { + return ambient_provider_remote_; + } + + private: + content::BrowserTaskEnvironment task_environment_; + TestingProfileManager profile_manager_; + content::TestWebUI web_ui_; + std::unique_ptr<content::WebContents> web_contents_; + TestingProfile* profile_; + mojo::Remote<ash::personalization_app::mojom::AmbientProvider> + ambient_provider_remote_; + std::unique_ptr<PersonalizationAppAmbientProviderImpl> ambient_provider_; + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(PersonalizationAppAmbientProviderImplTest, IsAmbientModeEnabled) { + PrefService* pref_service = profile()->GetPrefs(); + EXPECT_TRUE(pref_service); + pref_service->SetBoolean(ash::ambient::prefs::kAmbientModeEnabled, true); + bool called = false; + ambient_provider_remote()->IsAmbientModeEnabled( + base::BindLambdaForTesting([&called](bool enabled) { + called = true; + EXPECT_TRUE(enabled); + })); + ambient_provider_remote().FlushForTesting(); + EXPECT_TRUE(called); + + called = false; + pref_service->SetBoolean(ash::ambient::prefs::kAmbientModeEnabled, false); + ambient_provider_remote()->IsAmbientModeEnabled( + base::BindLambdaForTesting([&called](bool enabled) { + called = true; + EXPECT_FALSE(enabled); + })); + ambient_provider_remote().FlushForTesting(); + EXPECT_TRUE(called); +}
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index e28a62d..fcbfd13 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -985,6 +985,10 @@ if (ash::features::IsPersonalizationHubEnabled()) { RegisterWebUIControllerInterfaceBinder< + ash::personalization_app::mojom::AmbientProvider, + ash::PersonalizationAppUI>(map); + + RegisterWebUIControllerInterfaceBinder< ash::personalization_app::mojom::ThemeProvider, ash::PersonalizationAppUI>(map);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 3aec949..38acce8d 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -976,6 +976,8 @@ "../ash/arc/print_spooler/arc_print_spooler_util.h", "../ash/arc/print_spooler/print_session_impl.cc", "../ash/arc/print_spooler/print_session_impl.h", + "../ash/arc/privacy_items/arc_privacy_items_bridge.cc", + "../ash/arc/privacy_items/arc_privacy_items_bridge.h", "../ash/arc/process/arc_process.cc", "../ash/arc/process/arc_process.h", "../ash/arc/process/arc_process_service.cc", @@ -3203,6 +3205,8 @@ "../ash/web_applications/os_settings_web_app_info.h", "../ash/web_applications/os_url_handler_system_web_app_info.cc", "../ash/web_applications/os_url_handler_system_web_app_info.h", + "../ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.cc", + "../ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h", "../ash/web_applications/personalization_app/personalization_app_info.cc", "../ash/web_applications/personalization_app/personalization_app_info.h", "../ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc", @@ -3820,6 +3824,8 @@ "../ash/plugin_vm/fake_plugin_vm_features.h", "../ash/policy/core/user_policy_test_helper.cc", "../ash/policy/core/user_policy_test_helper.h", + "../ash/policy/dlp/mock_dlp_content_manager_ash.cc", + "../ash/policy/dlp/mock_dlp_content_manager_ash.h", "../ash/policy/handlers/fake_device_name_policy_handler.cc", "../ash/policy/handlers/fake_device_name_policy_handler.h", "../ash/policy/handlers/minimum_version_policy_test_helpers.cc", @@ -4002,6 +4008,7 @@ "../ash/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc", "../ash/arc/pip/arc_pip_bridge_unittest.cc", "../ash/arc/policy/arc_policy_bridge_unittest.cc", + "../ash/arc/privacy_items/arc_privacy_items_bridge_unittest.cc", "../ash/arc/process/arc_process_unittest.cc", "../ash/arc/session/arc_demo_mode_preference_handler_unittest.cc", "../ash/arc/session/arc_play_store_enabled_preference_handler_unittest.cc", @@ -4389,8 +4396,6 @@ "../ash/policy/core/user_cloud_policy_token_forwarder_unittest.cc", "../ash/policy/dlp/dlp_content_manager_ash_unittest.cc", "../ash/policy/dlp/dlp_files_controller_unittest.cc", - "../ash/policy/dlp/mock_dlp_content_manager_ash.cc", - "../ash/policy/dlp/mock_dlp_content_manager_ash.h", "../ash/policy/enrollment/account_status_check_fetcher_unittest.cc", "../ash/policy/enrollment/auto_enrollment_client_impl_unittest.cc", "../ash/policy/enrollment/device_cloud_policy_initializer_unittest.cc", @@ -4599,6 +4604,7 @@ "../ash/usb/cros_usb_detector_unittest.cc", "../ash/web_applications/help_app/help_app_discover_tab_notification_unittest.cc", "../ash/web_applications/help_app/help_app_notification_controller_unittest.cc", + "../ash/web_applications/personalization_app/personalization_app_ambient_provider_impl_unittest.cc", "../ash/web_applications/personalization_app/personalization_app_theme_provider_impl_unittest.cc", "../ash/web_applications/personalization_app/personalization_app_user_provider_impl_unittest.cc", "../ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc",
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.cc b/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.cc index 284ad24..0d14eb7 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.cc
@@ -153,8 +153,7 @@ DlpConfidentialContentsCache::DlpConfidentialContentsCache() : cache_size_limit_(kDefaultCacheSizeLimit), - task_runner_( - content::GetUIThreadTaskRunner(content::BrowserTaskTraits())) {} + task_runner_(base::SequencedTaskRunnerHandle::Get()) {} DlpConfidentialContentsCache::~DlpConfidentialContentsCache() = default;
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.h b/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.h index 861c0a51..c5eeb60 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_confidential_contents.h
@@ -166,7 +166,7 @@ const size_t cache_size_limit_; // Used to evict cache entries after the timeout. - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; }; } // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc index 86744970..87d5a301 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h" #include "chrome/browser/chromeos/policy/dlp/dlp_warn_notifier.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "url/gurl.h" @@ -139,6 +140,120 @@ warn_notifier_ = std::make_unique<DlpWarnNotifier>(); } +DlpContentManager::ScreenShareInfo::ScreenShareInfo( + const std::string& label, + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + base::OnceClosure stop_callback, + content::MediaStreamUI::StateChangeCallback state_change_callback) + : label_(label), + media_id_(media_id), + application_title_(application_title), + stop_callback_(std::move(stop_callback)), + state_change_callback_(std::move(state_change_callback)) {} + +DlpContentManager::ScreenShareInfo::~ScreenShareInfo() { + // Hide notifications if necessary. + HideNotifications(); +} + +bool DlpContentManager::ScreenShareInfo::operator==( + const DlpContentManager::ScreenShareInfo& other) const { + return label_ == other.label_ && media_id_ == other.media_id_; +} + +bool DlpContentManager::ScreenShareInfo::operator!=( + const DlpContentManager::ScreenShareInfo& other) const { + return !(*this == other); +} + +const content::DesktopMediaID& DlpContentManager::ScreenShareInfo::GetMediaId() + const { + return media_id_; +} + +const std::string& DlpContentManager::ScreenShareInfo::GetLabel() const { + return label_; +} + +const std::u16string& DlpContentManager::ScreenShareInfo::GetApplicationTitle() + const { + // TODO(crbug.com/1264793): Don't cache the application name, but compute it + // here. + return application_title_; +} + +bool DlpContentManager::ScreenShareInfo::IsRunning() const { + return state_ == State::kRunning; +} + +void DlpContentManager::ScreenShareInfo::Pause() { + DCHECK(state_ == State::kRunning); + state_change_callback_.Run(media_id_, + blink::mojom::MediaStreamStateChange::PAUSE); + state_ = State::kPaused; +} + +void DlpContentManager::ScreenShareInfo::Resume() { + DCHECK(state_ == State::kPaused); + state_change_callback_.Run(media_id_, + blink::mojom::MediaStreamStateChange::PLAY); + state_ = State::kRunning; +} + +void DlpContentManager::ScreenShareInfo::Stop() { + DCHECK(state_ != State::kStopped); + if (stop_callback_) { + std::move(stop_callback_).Run(); + state_ = State::kStopped; + } else { + NOTREACHED(); + } +} + +void DlpContentManager::ScreenShareInfo::MaybeUpdateNotifications() { + UpdatePausedNotification(/*show=*/state_ == State::kPaused); + UpdateResumedNotification(/*show=*/state_ == State::kRunning); +} + +void DlpContentManager::ScreenShareInfo::HideNotifications() { + UpdatePausedNotification(/*show=*/false); + UpdateResumedNotification(/*show=*/false); +} + +base::WeakPtr<DlpContentManager::ScreenShareInfo> +DlpContentManager::ScreenShareInfo::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +void DlpContentManager::ScreenShareInfo::UpdatePausedNotification(bool show) { + if ((notification_state_ == NotificationState::kShowingPausedNotification) == + show) + return; + if (show) { + DCHECK(state_ == State::kPaused); + ShowDlpScreenSharePausedNotification(label_, application_title_); + notification_state_ = NotificationState::kShowingPausedNotification; + } else { + HideDlpScreenSharePausedNotification(label_); + notification_state_ = NotificationState::kNotShowingNotification; + } +} + +void DlpContentManager::ScreenShareInfo::UpdateResumedNotification(bool show) { + if ((notification_state_ == NotificationState::kShowingResumedNotification) == + show) + return; + if (show) { + DCHECK(state_ == State::kRunning); + ShowDlpScreenShareResumedNotification(label_, application_title_); + notification_state_ = NotificationState::kShowingResumedNotification; + } else { + HideDlpScreenShareResumedNotification(label_); + notification_state_ = NotificationState::kNotShowingNotification; + } +} + void DlpContentManager::SetIsScreenShareWarningModeEnabledForTesting( bool is_enabled) { is_screen_share_warning_mode_enabled_ = is_enabled; @@ -273,6 +388,110 @@ std::move(callback).Run(true); } +void DlpContentManager::AddScreenShare( + const std::string& label, + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + base::RepeatingClosure stop_callback, + content::MediaStreamUI::StateChangeCallback state_change_callback) { + auto screen_share_info = std::make_unique<ScreenShareInfo>( + label, media_id, application_title, std::move(stop_callback), + state_change_callback); + DCHECK( + std::find_if(running_screen_shares_.begin(), running_screen_shares_.end(), + [&screen_share_info]( + const std::unique_ptr<ScreenShareInfo>& info) -> bool { + return info && *info == *screen_share_info; + }) == running_screen_shares_.end()); + + running_screen_shares_.push_back(std::move(screen_share_info)); +} + +void DlpContentManager::RemoveScreenShare( + const std::string& label, + const content::DesktopMediaID& media_id) { + base::EraseIf( + running_screen_shares_, + [=](const std::unique_ptr<ScreenShareInfo>& screen_share_info) -> bool { + return screen_share_info->GetLabel() == label && + screen_share_info->GetMediaId() == media_id; + }); +} + +void DlpContentManager::CheckRunningScreenShares() { + for (auto& screen_share : running_screen_shares_) { + ConfidentialContentsInfo info = + GetScreenShareConfidentialContentsInfo(screen_share->GetMediaId()); + if (IsBlocked(info.restriction_info)) { + if (screen_share->IsRunning()) { + screen_share->Pause(); + MaybeReportEvent(info.restriction_info, + DlpRulesManager::Restriction::kScreenShare); + DlpBooleanHistogram(dlp::kScreenSharePausedOrResumedUMA, true); + screen_share->MaybeUpdateNotifications(); + } + return; + } + if (is_screen_share_warning_mode_enabled_ && + IsWarn(info.restriction_info)) { + // Check which of the contents were already allowed and don't warn for + // those. + RemoveAllowedContents(info.confidential_contents, + DlpRulesManager::Restriction::kScreenShare); + if (info.confidential_contents.IsEmpty()) { + // The user already allowed all the visible content. + if (!screen_share->IsRunning()) { + screen_share->Resume(); + screen_share->MaybeUpdateNotifications(); + } + return; + } + if (screen_share->IsRunning()) { + screen_share->Pause(); + screen_share->HideNotifications(); + } + // base::Unretained(this) is safe here because DlpContentManager is + // initialized as a singleton that's always available in the system. + warn_notifier_->ShowDlpScreenShareWarningDialog( + base::BindOnce(&DlpContentManager::OnDlpScreenShareWarnDialogReply, + base::Unretained(this), info.confidential_contents, + screen_share->GetWeakPtr()), + info.confidential_contents, screen_share->GetApplicationTitle()); + return; + } + // No restrictions apply, only resume if necessary. + if (!screen_share->IsRunning()) { + screen_share->Resume(); + DlpBooleanHistogram(dlp::kScreenSharePausedOrResumedUMA, false); + screen_share->MaybeUpdateNotifications(); + } + } +} + +void DlpContentManager::OnDlpScreenShareWarnDialogReply( + const DlpConfidentialContents& confidential_contents, + base::WeakPtr<ScreenShareInfo> screen_share, + bool should_proceed) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (!screen_share) + // The screen share was stopped before the dialog was addressed, so no need + // to do anything. + return; + + if (should_proceed) { + screen_share->Resume(); + for (const auto& content : confidential_contents.GetContents()) { + user_allowed_contents_cache_.Cache( + content, DlpRulesManager::Restriction::kScreenShare); + } + screen_share->MaybeUpdateNotifications(); + } else { + screen_share->Stop(); + RemoveScreenShare(screen_share->GetLabel(), screen_share->GetMediaId()); + } +} + void DlpContentManager::OnDlpWarnDialogReply( const DlpConfidentialContents& confidential_contents, DlpRulesManager::Restriction restriction,
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h index d331eaa..375e1f06 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" #include "chrome/browser/chromeos/policy/dlp/dlp_warn_dialog.h" +#include "content/public/browser/media_stream_request.h" #include "url/gurl.h" namespace content { @@ -63,6 +64,21 @@ const std::u16string& application_title, OnDlpRestrictionCheckedCallback callback) = 0; + // Called when screen capture is started. + // |state_change_callback| will be called when restricted content will appear + // or disappear in the captured area. + virtual void OnScreenCaptureStarted( + const std::string& label, + std::vector<content::DesktopMediaID> screen_capture_ids, + const std::u16string& application_title, + base::RepeatingClosure stop_callback, + content::MediaStreamUI::StateChangeCallback state_change_callback) = 0; + + // Called when screen capture is stopped. + virtual void OnScreenCaptureStopped( + const std::string& label, + const content::DesktopMediaID& media_id) = 0; + protected: friend class DlpContentManagerTestHelper; @@ -72,6 +88,74 @@ std::unique_ptr<DlpWarnNotifier> warn_notifier); void ResetWarnNotifierForTesting(); + // Used to keep track of running screen shares. + class ScreenShareInfo { + public: + ScreenShareInfo( + const std::string& label, + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + base::OnceClosure stop_callback, + content::MediaStreamUI::StateChangeCallback state_change_callback); + ~ScreenShareInfo(); + + bool operator==(const ScreenShareInfo& other) const; + bool operator!=(const ScreenShareInfo& other) const; + + const content::DesktopMediaID& GetMediaId() const; + const std::string& GetLabel() const; + const std::u16string& GetApplicationTitle() const; + bool IsRunning() const; + + // Pauses a running screen share. + // No-op if the screen share is already paused. + void Pause(); + // Resumes a paused screen share. + // No-op if the screen share is already running. + void Resume(); + // Stops the screen share. Can only be called once. + void Stop(); + + // If necessary, hides or shows the paused/resumed notification for this + // screen share. The notification should be updated after changing the state + // from running to paused, or paused to running. + void MaybeUpdateNotifications(); + + // If shown, hides both the paused and resumed notification for this screen + // share. + void HideNotifications(); + + base::WeakPtr<ScreenShareInfo> GetWeakPtr(); + + private: + enum class NotificationState { + kNotShowingNotification, + kShowingPausedNotification, + kShowingResumedNotification + }; + enum class State { kRunning, kPaused, kStopped }; + // Shows (if |show| is true) or hides (if |show| is false) paused + // notification for this screen share. Does nothing if the notification is + // already in the required state. + void UpdatePausedNotification(bool show); + // Shows (if |show| is true) or hides (if |show| is false) resumed + // notification for this screen share. Does nothing if the notification is + // already in the required state. + void UpdateResumedNotification(bool show); + + std::string label_; + content::DesktopMediaID media_id_; + // TODO(crbug.com/1264793): Don't cache the application name. + std::u16string application_title_; + base::OnceClosure stop_callback_; + content::MediaStreamUI::StateChangeCallback state_change_callback_; + State state_ = State::kRunning; + NotificationState notification_state_ = + NotificationState::kNotShowingNotification; + + base::WeakPtrFactory<ScreenShareInfo> weak_factory_{this}; + }; + void SetIsScreenShareWarningModeEnabledForTesting(bool is_enabled); // Structure that relates a list of confidential contents to the @@ -127,6 +211,39 @@ ConfidentialContentsInfo info, OnDlpRestrictionCheckedCallback callback); + // Returns which level, url, and information about visible confidential + // contents of screen share restriction that is currently enforced for + // |media_id|. + virtual ConfidentialContentsInfo GetScreenShareConfidentialContentsInfo( + const content::DesktopMediaID& media_id) const = 0; + + // Adds screen share to be tracked in |running_screen_shares_|. + void AddScreenShare( + const std::string& label, + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + base::RepeatingClosure stop_callback, + content::MediaStreamUI::StateChangeCallback state_change_callback); + + // Removes screen share from |running_screen_shares_|. + void RemoveScreenShare(const std::string& label, + const content::DesktopMediaID& media_id); + + // Checks and stops the running screen shares if restricted content appeared + // in the corresponding areas. + void CheckRunningScreenShares(); + + // Called back from Screen Share warning dialogs that are shown during the + // screen share. Passes along the user's response, reflected in the value of + // |should_proceed| along to |callback| which handles continuing or cancelling + // the action based on this response. In case that |should_proceed| is true, + // also saves the |confidential_contents| that were allowed to be shared by + // the user to avoid future warnings. + void OnDlpScreenShareWarnDialogReply( + const DlpConfidentialContents& confidential_contents, + base::WeakPtr<ScreenShareInfo> screen_share, + bool should_proceed); + // Called back from warning dialogs. Passes along the user's response, // reflected in the value of |should_proceed| along to |callback| which // handles continuing or cancelling the action based on this response. In case @@ -161,6 +278,9 @@ // TODO(crbug.com/1264803): Change to DlpConfidentialContentsCache DlpConfidentialContentsCache user_allowed_contents_cache_; + // List of the currently running screen shares. + std::vector<std::unique_ptr<ScreenShareInfo>> running_screen_shares_; + raw_ptr<DlpReportingManager> reporting_manager_{nullptr}; std::unique_ptr<DlpWarnNotifier> warn_notifier_;
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.cc index 34d7cbe7..e3cbf2be 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h" +#include "base/containers/cxx20_erase.h" #include "chrome/browser/ui/lacros/window_utility.h" #include "chromeos/crosapi/mojom/dlp.mojom.h" #include "chromeos/lacros/lacros_service.h" @@ -27,8 +28,9 @@ case DlpRulesManager::Level::kBlock: return crosapi::mojom::DlpRestrictionLevel::kBlock; case DlpRulesManager::Level::kAllow: - case DlpRulesManager::Level::kNotSet: return crosapi::mojom::DlpRestrictionLevel::kAllow; + case DlpRulesManager::Level::kNotSet: + return crosapi::mojom::DlpRestrictionLevel::kNotSet; } } @@ -57,6 +59,18 @@ return result; } +crosapi::mojom::ScreenShareAreaPtr ConvertToScreenShareArea( + const content::DesktopMediaID& media_id) { + auto result = crosapi::mojom::ScreenShareArea::New(); + if (media_id.type == content::DesktopMediaID::Type::TYPE_SCREEN) { + return result; + } + DCHECK_EQ(media_id.type, content::DesktopMediaID::Type::TYPE_WINDOW); + aura::Window* window = content::DesktopMediaID::GetNativeWindowById(media_id); + result->window_id = lacros_window_utility::GetRootWindowUniqueId(window); + return result; +} + } // namespace // static @@ -74,10 +88,121 @@ GetScreenShareConfidentialContentsInfoForWebContents( media_id.web_contents_id), std::move(callback)); - } else { - // No restrictions apply. - // TODO(crbug.com/1278814): Pass the check to Ash to process there. + return; + } + chromeos::LacrosService* lacros_service = chromeos::LacrosService::Get(); + if (!lacros_service->IsAvailable<crosapi::mojom::Dlp>()) { + LOG(WARNING) << "DLP mojo service not available"; std::move(callback).Run(true); + return; + } + + int dlp_mojo_version = + lacros_service->GetInterfaceVersion(crosapi::mojom::Dlp::Uuid_); + if (dlp_mojo_version < int{crosapi::mojom::Dlp::MethodMinVersions:: + kCheckScreenShareRestrictionMinVersion}) { + LOG(WARNING) << "DLP mojo service version does not support screen share " + "restrictions"; + std::move(callback).Run(true); + return; + } + + lacros_service->GetRemote<crosapi::mojom::Dlp>()->CheckScreenShareRestriction( + ConvertToScreenShareArea(media_id), application_title, + std::move(callback)); +} + +void DlpContentManagerLacros::OnScreenCaptureStarted( + const std::string& label, + std::vector<content::DesktopMediaID> screen_capture_ids, + const std::u16string& application_title, + base::RepeatingClosure stop_callback, + content::MediaStreamUI::StateChangeCallback state_change_callback) { + for (const content::DesktopMediaID& media_id : screen_capture_ids) { + if (media_id.type == content::DesktopMediaID::Type::TYPE_WEB_CONTENTS) { + AddScreenShare(label, media_id, application_title, stop_callback, + state_change_callback); + } else { + chromeos::LacrosService* lacros_service = chromeos::LacrosService::Get(); + auto delegate = std::make_unique<ScreenShareStateChangeDelegate>( + label, media_id, state_change_callback, stop_callback); + if (lacros_service->IsAvailable<crosapi::mojom::Dlp>()) { + lacros_service->GetRemote<crosapi::mojom::Dlp>()->OnScreenShareStarted( + label, ConvertToScreenShareArea(media_id), application_title, + delegate->BindDelegate()); + running_remote_screen_shares_.push_back(std::move(delegate)); + } + } + } + CheckRunningScreenShares(); +} + +void DlpContentManagerLacros::OnScreenCaptureStopped( + const std::string& label, + const content::DesktopMediaID& media_id) { + if (media_id.type == content::DesktopMediaID::Type::TYPE_WEB_CONTENTS) { + RemoveScreenShare(label, media_id); + } else { + chromeos::LacrosService* lacros_service = chromeos::LacrosService::Get(); + if (lacros_service->IsAvailable<crosapi::mojom::Dlp>()) { + lacros_service->GetRemote<crosapi::mojom::Dlp>()->OnScreenShareStopped( + label, ConvertToScreenShareArea(media_id)); + } + base::EraseIf( + running_remote_screen_shares_, + [=](const std::unique_ptr< + DlpContentManagerLacros::ScreenShareStateChangeDelegate>& delegate) + -> bool { + return delegate->label() == label && delegate->media_id() == media_id; + }); + } +} + +DlpContentManagerLacros::ScreenShareStateChangeDelegate:: + ScreenShareStateChangeDelegate( + const std::string& label, + const content::DesktopMediaID& media_id, + content::MediaStreamUI::StateChangeCallback state_change_callback, + base::OnceClosure stop_callback) + : label_(label), + media_id_(media_id), + state_change_callback_(std::move(state_change_callback)), + stop_callback_(std::move(stop_callback)) {} + +DlpContentManagerLacros::ScreenShareStateChangeDelegate:: + ~ScreenShareStateChangeDelegate() = default; + +bool DlpContentManagerLacros::ScreenShareStateChangeDelegate::operator==( + const DlpContentManagerLacros::ScreenShareStateChangeDelegate& other) + const { + return label_ == other.label_ && media_id_ == other.media_id_; +} + +bool DlpContentManagerLacros::ScreenShareStateChangeDelegate::operator!=( + const DlpContentManagerLacros::ScreenShareStateChangeDelegate& other) + const { + return !(*this == other); +} + +mojo::PendingRemote<crosapi::mojom::StateChangeDelegate> +DlpContentManagerLacros::ScreenShareStateChangeDelegate::BindDelegate() { + return receiver_.BindNewPipeAndPassRemoteWithVersion(); +} + +void DlpContentManagerLacros::ScreenShareStateChangeDelegate::OnPause() { + state_change_callback_.Run(media_id_, + blink::mojom::MediaStreamStateChange::PAUSE); +} + +void DlpContentManagerLacros::ScreenShareStateChangeDelegate::OnResume() { + state_change_callback_.Run(media_id_, + blink::mojom::MediaStreamStateChange::PLAY); +} + +void DlpContentManagerLacros::ScreenShareStateChangeDelegate::OnStop() { + DCHECK(stop_callback_); + if (stop_callback_) { + std::move(stop_callback_).Run(); } } @@ -143,4 +268,15 @@ } } +DlpContentManager::ConfidentialContentsInfo +DlpContentManagerLacros::GetScreenShareConfidentialContentsInfo( + const content::DesktopMediaID& media_id) const { + if (media_id.type == content::DesktopMediaID::Type::TYPE_WEB_CONTENTS) { + return GetScreenShareConfidentialContentsInfoForWebContents( + media_id.web_contents_id); + } + NOTREACHED(); + return ConfidentialContentsInfo(); +} + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h index 750f575e..6864375 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h
@@ -9,7 +9,9 @@ #include "base/containers/flat_set.h" #include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" #include "chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.h" +#include "chromeos/crosapi/mojom/dlp.mojom.h" #include "content/public/browser/desktop_media_id.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "ui/aura/window_observer.h" namespace aura { @@ -31,19 +33,61 @@ // There will always be a single instance created on the first access. static DlpContentManagerLacros* Get(); - // Checks whether screen sharing of content from the |media_id| source with - // application |application_name| is restricted or not advised. Depending on - // the result, calls |callback| and passes an indicator whether to proceed or - // not. + // DlpContentManager overrides: void CheckScreenShareRestriction( const content::DesktopMediaID& media_id, const std::u16string& application_title, OnDlpRestrictionCheckedCallback callback) override; + void OnScreenCaptureStarted( + const std::string& label, + std::vector<content::DesktopMediaID> screen_capture_ids, + const std::u16string& application_title, + base::RepeatingClosure stop_callback, + content::MediaStreamUI::StateChangeCallback state_change_callback) + override; + void OnScreenCaptureStopped(const std::string& label, + const content::DesktopMediaID& media_id) override; private: friend class DlpContentManagerTestHelper; friend class DlpContentObserver; + // Class that tracks connection with screen share tracking in Ash. + class ScreenShareStateChangeDelegate + : public crosapi::mojom::StateChangeDelegate { + public: + ScreenShareStateChangeDelegate( + const std::string& label, + const content::DesktopMediaID& media_id, + content::MediaStreamUI::StateChangeCallback state_change_callback, + base::OnceClosure stop_callback); + ScreenShareStateChangeDelegate(const ScreenShareStateChangeDelegate&) = + delete; + ScreenShareStateChangeDelegate& operator=( + const ScreenShareStateChangeDelegate&) = delete; + ~ScreenShareStateChangeDelegate() override; + + bool operator==(const ScreenShareStateChangeDelegate& other) const; + bool operator!=(const ScreenShareStateChangeDelegate& other) const; + + mojo::PendingRemote<crosapi::mojom::StateChangeDelegate> BindDelegate(); + + // crosapi::mojom::StateChangeDelegate overrides: + void OnPause() override; + void OnResume() override; + void OnStop() override; + + const std::string& label() const { return label_; } + const content::DesktopMediaID& media_id() const { return media_id_; } + + private: + const std::string label_; + const content::DesktopMediaID media_id_; + content::MediaStreamUI::StateChangeCallback state_change_callback_; + base::OnceClosure stop_callback_; + mojo::Receiver<crosapi::mojom::StateChangeDelegate> receiver_{this}; + }; + DlpContentManagerLacros(); ~DlpContentManagerLacros() override; @@ -61,6 +105,10 @@ // needed. void UpdateRestrictions(aura::Window* window); + // DlpContentManager override: + ConfidentialContentsInfo GetScreenShareConfidentialContentsInfo( + const content::DesktopMediaID& media_id) const override; + // Tracks set of known confidential WebContents* for each Window*. base::flat_map<aura::Window*, base::flat_set<content::WebContents*>> window_webcontents_; @@ -68,6 +116,10 @@ // Tracks current restrictions applied to Window* based on visible // WebContents* belonging to Window*. base::flat_map<aura::Window*, DlpContentRestrictionSet> confidential_windows_; + + // List of currently running screen shares that are tracked remotely in Ash. + std::vector<std::unique_ptr<ScreenShareStateChangeDelegate>> + running_remote_screen_shares_; }; } // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros_browsertest.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros_browsertest.cc new file mode 100644 index 0000000..f0d564b --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros_browsertest.cc
@@ -0,0 +1,296 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h" + +#include "base/test/bind.h" +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager_test_helper.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/crosapi/mojom/dlp.mojom.h" +#include "chromeos/lacros/lacros_service.h" +#include "content/public/test/browser_test.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +namespace { + +const std::u16string kAppId = u"app_id"; +constexpr char kScreenShareLabel[] = "label"; + +// TODO(crbug.com/1291609): Mock Lacros side of crosapi instead when possible. +// This will allow these tests to be just unit_tests, not +// lacros_chrome_browsertests. +class MockDlpCrosapi : public crosapi::mojom::Dlp { + public: + MOCK_METHOD(void, + DlpRestrictionsUpdated, + (const std::string&, crosapi::mojom::DlpRestrictionSetPtr), + (override)); + MOCK_METHOD(void, + CheckScreenShareRestriction, + (crosapi::mojom::ScreenShareAreaPtr, + const std::u16string&, + CheckScreenShareRestrictionCallback), + (override)); + MOCK_METHOD(void, + OnScreenShareStarted, + (const std::string&, + crosapi::mojom::ScreenShareAreaPtr, + const ::std::u16string&, + ::mojo::PendingRemote<crosapi::mojom::StateChangeDelegate>), + (override)); + MOCK_METHOD(void, + OnScreenShareStopped, + (const std::string&, crosapi::mojom::ScreenShareAreaPtr), + (override)); +}; + +} // namespace + +class DlpContentManagerLacrosBrowserTest : public InProcessBrowserTest { + public: + // InProcessBrowserTest: + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + + // If DLP interface is not available on this version of ash-chrome, this + // test suite will no-op. + if (!IsServiceAvailable()) + return; + + test_helper_ = std::make_unique<DlpContentManagerTestHelper>(); + + // Replace the production DLP service with a mock for testing. + mojo::Remote<crosapi::mojom::Dlp>& remote = + chromeos::LacrosService::Get()->GetRemote<crosapi::mojom::Dlp>(); + remote.reset(); + receiver_.Bind(remote.BindNewPipeAndPassReceiver()); + } + + // Returns whether the DLP interface is available. It may + // not be available on earlier versions of ash-chrome. + bool IsServiceAvailable() const { + chromeos::LacrosService* lacros_service = chromeos::LacrosService::Get(); + return lacros_service && lacros_service->IsAvailable<crosapi::mojom::Dlp>(); + } + + void SetDlpInterfaceVersion(int version) { + crosapi::mojom::BrowserInitParamsPtr init_params = + chromeos::LacrosService::Get()->init_params()->Clone(); + init_params->interface_versions.value()[crosapi::mojom::Dlp::Uuid_] = + version; + chromeos::LacrosService::Get()->SetInitParamsForTests( + std::move(init_params)); + } + + DlpContentManagerLacros* manager() { + return static_cast<DlpContentManagerLacros*>( + test_helper_->GetContentManager()); + } + + testing::StrictMock<MockDlpCrosapi>& service() { return service_; } + + private: + testing::StrictMock<MockDlpCrosapi> service_; + mojo::Receiver<crosapi::mojom::Dlp> receiver_{&service_}; + std::unique_ptr<DlpContentManagerTestHelper> test_helper_; +}; + +IN_PROC_BROWSER_TEST_F( + DlpContentManagerLacrosBrowserTest, + CheckScreenShareRestrictionFullScreenNotSupportedVersion) { + // If DLP interface is not available on this version of ash-chrome, this test + // suite will no-op. + if (!IsServiceAvailable()) + return; + + SetDlpInterfaceVersion(0); + + // No call to mojo remote should happen in this case (ensured by StrictMock). + // The request is just silently allowed. + base::RunLoop run_loop; + manager()->CheckScreenShareRestriction( + content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, + content::DesktopMediaID::kFakeId), + kAppId, base::BindLambdaForTesting([&](bool allowed) { + EXPECT_TRUE(allowed); + run_loop.Quit(); + })); + run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_F(DlpContentManagerLacrosBrowserTest, + CheckScreenShareRestrictionFullScreenAllowed) { + // If DLP interface is not available on this version of ash-chrome, this test + // suite will no-op. + if (!IsServiceAvailable()) + return; + + SetDlpInterfaceVersion(service().Version_); + + EXPECT_CALL(service(), CheckScreenShareRestriction) + .WillOnce([](crosapi::mojom::ScreenShareAreaPtr area, + const std::u16string& application_title, + base::OnceCallback<void(bool)> callback) { + EXPECT_FALSE(area->window_id.has_value()); + EXPECT_EQ(kAppId, application_title); + std::move(callback).Run(/*should_proceed=*/true); + }); + + base::RunLoop run_loop; + manager()->CheckScreenShareRestriction( + content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, + content::DesktopMediaID::kFakeId), + kAppId, base::BindLambdaForTesting([&](bool allowed) { + EXPECT_TRUE(allowed); + run_loop.Quit(); + })); + run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_F(DlpContentManagerLacrosBrowserTest, + CheckScreenShareRestrictionFullScreenNotAllowed) { + // If DLP interface is not available on this version of ash-chrome, this test + // suite will no-op. + if (!IsServiceAvailable()) + return; + + SetDlpInterfaceVersion(service().Version_); + + EXPECT_CALL(service(), CheckScreenShareRestriction) + .WillOnce([](crosapi::mojom::ScreenShareAreaPtr area, + const std::u16string& application_title, + base::OnceCallback<void(bool)> callback) { + EXPECT_FALSE(area->window_id.has_value()); + EXPECT_EQ(kAppId, application_title); + std::move(callback).Run(/*should_proceed=*/false); + }); + + base::RunLoop run_loop; + manager()->CheckScreenShareRestriction( + content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, + content::DesktopMediaID::kFakeId), + kAppId, base::BindLambdaForTesting([&](bool allowed) { + EXPECT_FALSE(allowed); + run_loop.Quit(); + })); + run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_F(DlpContentManagerLacrosBrowserTest, + ScreenShareStartedStop) { + // If DLP interface is not available on this version of ash-chrome, this test + // suite will no-op. + if (!IsServiceAvailable()) + return; + + SetDlpInterfaceVersion(service().Version_); + + // Setup callback on remote service. + base::RunLoop bound_loop; + ::mojo::PendingRemote<crosapi::mojom::StateChangeDelegate> pending_delegate; + EXPECT_CALL(service(), OnScreenShareStarted) + .WillOnce([&](const std::string& label, + crosapi::mojom::ScreenShareAreaPtr area, + const std::u16string& application_title, + ::mojo::PendingRemote<crosapi::mojom::StateChangeDelegate> + delegate) { + EXPECT_EQ(kScreenShareLabel, label); + EXPECT_FALSE(area->window_id.has_value()); + EXPECT_EQ(kAppId, application_title); + pending_delegate = std::move(delegate); + bound_loop.Quit(); + }); + + // Call DLP manager and expect stop callback. + base::RunLoop stopped_run_loop; + manager()->OnScreenCaptureStarted( + kScreenShareLabel, + {content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, + content::DesktopMediaID::kFakeId)}, + kAppId, base::BindLambdaForTesting([&]() { stopped_run_loop.Quit(); }), + base::DoNothing()); + + // Bind remote delegate. + bound_loop.Run(); + mojo::Remote<crosapi::mojom::StateChangeDelegate> remote_delegate( + std::move(pending_delegate)); + EXPECT_TRUE(remote_delegate); + + // Request remote delegate to stop. + remote_delegate->OnStop(); + + // Wait for stop callback. + stopped_run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_F(DlpContentManagerLacrosBrowserTest, + ScreenShareStartedPauseAndResume) { + // If DLP interface is not available on this version of ash-chrome, this test + // suite will no-op. + if (!IsServiceAvailable()) + return; + + SetDlpInterfaceVersion(service().Version_); + + // Setup callback on remote service. + base::RunLoop bound_loop; + ::mojo::PendingRemote<crosapi::mojom::StateChangeDelegate> pending_delegate; + EXPECT_CALL(service(), OnScreenShareStarted) + .WillOnce([&](const std::string& label, + crosapi::mojom::ScreenShareAreaPtr area, + const std::u16string& application_title, + ::mojo::PendingRemote<crosapi::mojom::StateChangeDelegate> + delegate) { + EXPECT_EQ(kScreenShareLabel, label); + EXPECT_FALSE(area->window_id.has_value()); + EXPECT_EQ(kAppId, application_title); + pending_delegate = std::move(delegate); + bound_loop.Quit(); + }); + + // Call DLP manager and expect state change callbacks. + base::RunLoop paused_run_loop; + base::RunLoop resumed_run_loop; + content::DesktopMediaID media_id(content::DesktopMediaID::TYPE_SCREEN, + content::DesktopMediaID::kFakeId); + manager()->OnScreenCaptureStarted( + kScreenShareLabel, {media_id}, kAppId, base::DoNothing(), + base::BindLambdaForTesting( + [&](const content::DesktopMediaID& in_media_id, + blink::mojom::MediaStreamStateChange new_state) { + EXPECT_EQ(media_id, in_media_id); + if (new_state == blink::mojom::MediaStreamStateChange::PAUSE) { + paused_run_loop.Quit(); + } else if (new_state == + blink::mojom::MediaStreamStateChange::PLAY) { + resumed_run_loop.Quit(); + } else { + NOTREACHED(); + } + })); + + // Bind remote delegate. + bound_loop.Run(); + mojo::Remote<crosapi::mojom::StateChangeDelegate> remote_delegate( + std::move(pending_delegate)); + EXPECT_TRUE(remote_delegate); + + // Request remote delegate to pause. + remote_delegate->OnPause(); + + // Wait for stop callback. + paused_run_loop.Run(); + + // Request remote delegate to resume. + remote_delegate->OnResume(); + + // Wait for stop callback. + resumed_run_loop.Run(); +} + +} // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h b/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h index e773f8a..002ee56 100644 --- a/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h +++ b/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h
@@ -26,10 +26,26 @@ MOCK_METHOD(void, OnVisibilityChanged, (content::WebContents*), (override)); MOCK_METHOD(void, CheckScreenShareRestriction, - (const content::DesktopMediaID& media_id, - const std::u16string& application_title, - OnDlpRestrictionCheckedCallback callback), + (const content::DesktopMediaID&, + const std::u16string&, + OnDlpRestrictionCheckedCallback), (override)); + MOCK_METHOD(void, + OnScreenCaptureStarted, + (const std::string&, + std::vector<content::DesktopMediaID>, + const std::u16string&, + base::RepeatingClosure, + content::MediaStreamUI::StateChangeCallback), + (override)); + MOCK_METHOD(void, + OnScreenCaptureStopped, + (const std::string&, const content::DesktopMediaID&), + (override)); + MOCK_METHOD(ConfidentialContentsInfo, + GetScreenShareConfidentialContentsInfo, + (const content::DesktopMediaID&), + (const override)); }; } // namespace policy
diff --git a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc index 2fcead3..cdcec1c6 100644 --- a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc +++ b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc
@@ -52,10 +52,6 @@ host == chrome::kChromeUIPasswordManagerInternalsHost || host == chrome::kChromeUIPolicyHost || host == chrome::kChromeUIPredictorsHost || - // TODO(crbug.com/1202165): Remove when new quota-internals page is - // done. - host == chrome::kChromeUIQuotaInternalsHost || - host == content::kChromeUIQuotaInternals2Host || host == chrome::kChromeUISandboxHost || host == chrome::kChromeUISignInInternalsHost || host == chrome::kChromeUISiteEngagementHost || @@ -74,6 +70,7 @@ host == content::kChromeUIMediaInternalsHost || host == content::kChromeUINetworkErrorsListingHost || host == content::kChromeUIProcessInternalsHost || + host == content::kChromeUIQuotaInternalsHost || host == content::kChromeUIServiceWorkerInternalsHost || host == content::kChromeUIUkmHost || host == content::kChromeUIWebRTCInternalsHost;
diff --git a/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc b/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc index d5c7070..ec1d33d 100644 --- a/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc +++ b/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc
@@ -99,6 +99,9 @@ #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) return "Linux"; #endif +#if BUILDFLAG(IS_FUCHSIA) + return "Fuchsia"; +#endif } } // namespace
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index ea15a0d..3faebe4 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2750,6 +2750,11 @@ "expiry_milestone": 93 }, { + "name": "enable-tab-strip-improvements", + "owners": [ "skavuluru", "clank-app-team@google.com" ], + "expiry_milestone": 105 + }, + { "name": "enable-tab-switcher-on-return", "owners": [ "memex-team@google.com" ], "expiry_milestone": 100 @@ -3880,12 +3885,12 @@ { "name": "messages-for-android-chrome-survey", "owners": [ "pavely", "aishwaryarj" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "messages-for-android-infrastructure", "owners": [ "pavely", "lazzzis" ], - "expiry_milestone": 102 + "expiry_milestone": 105 }, { "name": "messages-for-android-instant-apps", @@ -3900,17 +3905,17 @@ { "name": "messages-for-android-notification-blocked", "owners": [ "pavely", "lazzzis" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "messages-for-android-passwords", "owners": [ "pavely", "lazzzis" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "messages-for-android-permission-update", "owners": [ "pavely", "lazzzis" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "messages-for-android-popup-blocked", @@ -3920,7 +3925,7 @@ { "name": "messages-for-android-pwa-install", "owners": [ "pavely", "lazzzis" ], - "expiry_milestone": 101 + "expiry_milestone": 105 }, { "name": "messages-for-android-reader-mode", @@ -3935,7 +3940,7 @@ { "name": "messages-for-android-save-card", "owners": [ "pavely", "lazzzis" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "messages-for-android-sync-error", @@ -3945,7 +3950,7 @@ { "name": "messages-for-android-update-password", "owners": [ "pavely", "lazzzis" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "metal",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 4af113a..2dc0ed1 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3486,6 +3486,11 @@ const char kTabGroupsForTabletsName[] = "Tab groups on tablets"; const char kTabGroupsForTabletsDescription[] = "Enable tab groups on tablets."; +const char kTabStripImprovementsAndroidName[] = + "Tab strip improvements for Android."; +const char kTabStripImprovementsAndroidDescription[] = + "Enables scrollable tab strip with tab group indicators."; + const char kThemeRefactorAndroidName[] = "Theme refactor on Android"; const char kThemeRefactorAndroidDescription[] = "Enables the theme refactoring on Android.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index cbe49fb..75ebf9c 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1387,6 +1387,9 @@ extern const char kTabSearchFuzzySearchName[]; extern const char kTabSearchFuzzySearchDescription[]; +extern const char kTabStripImprovementsAndroidName[]; +extern const char kTabStripImprovementsAndroidDescription[]; + extern const char kTailoredSecurityIntegrationName[]; extern const char kTailoredSecurityIntegrationDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 1df9faf9..cc11dc6 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -277,6 +277,7 @@ &kTabGroupsForTablets, &kTabGridLayoutAndroid, &kTabReparenting, + &kTabStripImprovements, &kTabSwitcherOnReturn, &kTabToGTSAnimation, &kTestDefaultDisabled, @@ -770,6 +771,9 @@ const base::Feature kTabReparenting{"TabReparenting", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kTabStripImprovements{"TabStripImprovements", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kTabSwitcherOnReturn{"TabSwitcherOnReturn", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 66afd848..2c769b6 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -146,6 +146,7 @@ extern const base::Feature kTabGroupsForTablets; extern const base::Feature kTabGridLayoutAndroid; extern const base::Feature kTabReparenting; +extern const base::Feature kTabStripImprovements; extern const base::Feature kTabSwitcherOnReturn; extern const base::Feature kTabToGTSAnimation; extern const base::Feature kTestDefaultDisabled;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java index 27e08ce..b5d3b92d 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -103,6 +103,7 @@ .put(ChromeFeatureList.FEED_LOADING_PLACEHOLDER, false) .put(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS, false) .put(ChromeFeatureList.TAB_GROUPS_FOR_TABLETS, false) + .put(ChromeFeatureList.TAB_STRIP_IMPROVEMENTS, false) .build(); /**
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 5074b147..38276e7 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -506,6 +506,7 @@ public static final String TAB_REPARENTING = "TabReparenting"; public static final String TAB_SWITCHER_ON_RETURN = "TabSwitcherOnReturn"; public static final String TAB_TO_GTS_ANIMATION = "TabToGTSAnimation"; + public static final String TAB_STRIP_IMPROVEMENTS = "TabStripImprovements"; public static final String TEST_DEFAULT_DISABLED = "TestDefaultDisabled"; public static final String TEST_DEFAULT_ENABLED = "TestDefaultEnabled"; public static final String THEME_REFACTOR_ANDROID = "ThemeRefactorAndroid";
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc similarity index 87% rename from extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc rename to chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc index 494d5453..1a1e483 100644 --- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc +++ b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc
@@ -2,14 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/base_paths.h" #include "base/bind.h" -#include "base/files/file_util.h" +#include "base/files/file_path.h" #include "base/location.h" -#include "base/memory/ptr_util.h" -#include "base/path_service.h" #include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" #include "base/test/test_timeouts.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -17,16 +13,13 @@ #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/guest_view/browser/guest_view_manager_delegate.h" #include "components/guest_view/browser/test_guest_view_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_widget_host_view.h" -#include "content/public/common/content_features.h" -#include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "extensions/browser/api/extensions_api_client.h" -#include "extensions/browser/extension_registry.h" -#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h" #include "extensions/common/constants.h" @@ -35,20 +28,17 @@ #include "third_party/blink/public/common/input/web_pointer_properties.h" using guest_view::GuestViewManager; -using guest_view::GuestViewManagerDelegate; using guest_view::TestGuestViewManager; -using guest_view::TestGuestViewManagerFactory; namespace extensions { -// Counts the number of URL requests made for a given URL. -class MimeHandlerViewTest : public ExtensionApiTest { +class ChromeMimeHandlerViewInteractiveUITest : public ExtensionApiTest { public: - MimeHandlerViewTest() { + ChromeMimeHandlerViewInteractiveUITest() { GuestViewManager::set_factory_for_testing(&factory_); } - ~MimeHandlerViewTest() override {} + ~ChromeMimeHandlerViewInteractiveUITest() override = default; void SetUpOnMainThread() override { ExtensionApiTest::SetUpOnMainThread(); @@ -111,8 +101,7 @@ } private: - TestGuestViewManagerFactory factory_; - base::test::ScopedFeatureList scoped_feature_list_; + guest_view::TestGuestViewManagerFactory factory_; }; // Test is flaky on Linux. https://crbug.com/877627 @@ -121,7 +110,8 @@ #else #define MAYBE_Fullscreen Fullscreen #endif -IN_PROC_BROWSER_TEST_F(MimeHandlerViewTest, MAYBE_Fullscreen) { +IN_PROC_BROWSER_TEST_F(ChromeMimeHandlerViewInteractiveUITest, + MAYBE_Fullscreen) { RunTest("testFullscreen.csv"); } @@ -148,7 +138,8 @@ #else #define MAYBE_EscapeExitsFullscreen EscapeExitsFullscreen #endif -IN_PROC_BROWSER_TEST_F(MimeHandlerViewTest, MAYBE_EscapeExitsFullscreen) { +IN_PROC_BROWSER_TEST_F(ChromeMimeHandlerViewInteractiveUITest, + MAYBE_EscapeExitsFullscreen) { // Use the testing subclass of MimeHandlerViewGuest. GetGuestViewManager()->RegisterTestGuestViewType<MimeHandlerViewGuest>( base::BindRepeating(&TestMimeHandlerViewGuest::Create));
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc index 1e81a6d8..3519bae 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -57,10 +57,13 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/shell.h" -#include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" -#include "ui/base/ui_base_features.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" +#include "ui/base/ui_base_features.h" +#endif // BUILDFLAG(IS_CHROMEOS) + #if BUILDFLAG(IS_MAC) #include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h" #endif // BUILDFLAG(IS_MAC) @@ -281,6 +284,7 @@ blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE && kIsLoopbackAudioSupported; +#if BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS_ASH) const content::DesktopMediaID screen_id = content::DesktopMediaID::RegisterNativeWindow( @@ -288,21 +292,26 @@ primary_root_window_for_testing_ ? primary_root_window_for_testing_ : ash::Shell::Get()->GetPrimaryRootWindow()); +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + const content::DesktopMediaID screen_id = content::DesktopMediaID( + content::DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + // base::Unretained(this) is safe because DesktopCaptureAccessHandler is owned // by MediaCaptureDevicesDispatcher, which is a lazy singleton which is // destroyed when the browser process terminates. - policy::DlpContentManagerAsh::Get()->CheckScreenShareRestriction( + policy::DlpContentManager::Get()->CheckScreenShareRestriction( screen_id, GetApplicationTitle(web_contents, extension), base::BindOnce(&DesktopCaptureAccessHandler::OnDlpRestrictionChecked, base::Unretained(this), web_contents->GetWeakPtr(), std::move(pending_request), screen_id, capture_audio)); return; -#else // BUILDFLAG(IS_CHROMEOS_ASH) +#else // BUILDFLAG(IS_CHROMEOS) const content::DesktopMediaID screen_id = content::DesktopMediaID( content::DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId); AcceptRequest(web_contents, std::move(pending_request), screen_id, capture_audio); -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) +#endif // !BUILDFLAG(IS_CHROMEOS) } bool DesktopCaptureAccessHandler::SupportsStreamType( @@ -451,21 +460,21 @@ return; } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) // base::Unretained(this) is safe because DesktopCaptureAccessHandler is owned // by MediaCaptureDevicesDispatcher, which is a lazy singleton which is // destroyed when the browser process terminates. - policy::DlpContentManagerAsh::Get()->CheckScreenShareRestriction( + policy::DlpContentManager::Get()->CheckScreenShareRestriction( media_id, pending_request->application_title, base::BindOnce(&DesktopCaptureAccessHandler::OnDlpRestrictionChecked, base::Unretained(this), web_contents->GetWeakPtr(), std::move(pending_request), media_id, ShouldCaptureAudio(media_id, request))); -#else // BUILDFLAG(IS_CHROMEOS_ASH) +#else // BUILDFLAG(IS_CHROMEOS) AcceptRequest(web_contents, std::move(pending_request), media_id, ShouldCaptureAudio(media_id, request)); -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) +#endif // !BUILDFLAG(IS_CHROMEOS) } void DesktopCaptureAccessHandler::ProcessChangeSourceRequest( @@ -608,20 +617,20 @@ blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, /*ui=*/nullptr); } else { -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) // base::Unretained(this) is safe because DesktopCaptureAccessHandler is // owned by MediaCaptureDevicesDispatcher, which is a lazy singleton which // is destroyed when the browser process terminates. - policy::DlpContentManagerAsh::Get()->CheckScreenShareRestriction( + policy::DlpContentManager::Get()->CheckScreenShareRestriction( media_id, application_title, base::BindOnce(&DesktopCaptureAccessHandler::OnDlpRestrictionChecked, base::Unretained(this), web_contents->GetWeakPtr(), std::move(pending_request), media_id, media_id.audio_share)); -#else // BUILDFLAG(IS_CHROMEOS_ASH) +#else // BUILDFLAG(IS_CHROMEOS) AcceptRequest(web_contents, std::move(pending_request), media_id, media_id.audio_share); -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) +#endif // !BUILDFLAG(IS_CHROMEOS) } if (!queue.empty()) ProcessQueuedAccessRequest(queue, web_contents); @@ -675,7 +684,7 @@ .Run(devices, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) void DesktopCaptureAccessHandler::OnDlpRestrictionChecked( base::WeakPtr<content::WebContents> web_contents, std::unique_ptr<PendingAccessRequest> pending_request, @@ -701,4 +710,4 @@ AcceptRequest(web_contents.get(), std::move(pending_request), media_id, capture_audio); } -#endif +#endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.h b/chrome/browser/media/webrtc/desktop_capture_access_handler.h index e2554b0..35116048 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.h +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.h
@@ -9,7 +9,6 @@ #include <string> #include <utility> -#include "build/chromeos_buildflags.h" #include "chrome/browser/media/capture_access_handler_base.h" #include "chrome/browser/media/media_access_handler.h" #include "chrome/browser/media/webrtc/desktop_media_list.h" @@ -19,11 +18,11 @@ #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/media_stream_request.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) namespace aura { class Window; } -#endif +#endif // BUILDFLAG(IS_CHROMEOS) namespace extensions { class Extension; @@ -105,7 +104,7 @@ WebContentsCollection web_contents_collection_; -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) // Called back after checking Data Leak Prevention (DLP) restrictions. void OnDlpRestrictionChecked( base::WeakPtr<content::WebContents> web_contents, @@ -115,7 +114,7 @@ bool is_dlp_allowed); aura::Window* primary_root_window_for_testing_ = nullptr; -#endif +#endif // BUILDFLAG(IS_CHROMEOS) }; #endif // CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_CAPTURE_ACCESS_HANDLER_H_
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc index 7e0dabe..3fe8b3b 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc
@@ -12,7 +12,6 @@ #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" @@ -31,10 +30,10 @@ #include "third_party/blink/public/common/mediastream/media_stream_request.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h" +#if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h" #include "ui/aura/window.h" -#endif +#endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_MAC) #include "base/test/scoped_feature_list.h" @@ -156,11 +155,11 @@ return access_handler_->pending_requests_; } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) void SetPrimaryRootWindow(aura::Window* window) { access_handler_->primary_root_window_for_testing_ = window; } -#endif +#endif // BUILDFLAG(IS_CHROMEOS) protected: raw_ptr<FakeDesktopMediaPickerFactory> picker_factory_; @@ -369,12 +368,12 @@ extensions::ExtensionBuilder extensionBuilder(kComponentExtension); extensionBuilder.SetLocation(extensions::mojom::ManifestLocation::kComponent); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) std::unique_ptr<aura::Window> primary_root_window = std::make_unique<aura::Window>(/*delegate=*/nullptr); primary_root_window->Init(ui::LAYER_NOT_DRAWN); SetPrimaryRootWindow(primary_root_window.get()); -#endif +#endif // BUILDFLAG(IS_CHROMEOS) blink::mojom::MediaStreamRequestResult result; blink::MediaStreamDevices devices; @@ -387,11 +386,11 @@ EXPECT_EQ(1u, devices.size()); } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) TEST_F(DesktopCaptureAccessHandlerTest, ScreenCaptureAccessDlpRestricted) { // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .WillOnce([&](const content::DesktopMediaID& media_id, @@ -424,8 +423,8 @@ TEST_F(DesktopCaptureAccessHandlerTest, ScreenCaptureAccessDlpNotRestricted) { // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .WillOnce([&](const content::DesktopMediaID& media_id, @@ -459,8 +458,8 @@ TEST_F(DesktopCaptureAccessHandlerTest, ScreenCaptureAccessDlpWebContentsDestroyed) { // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .Times(1) @@ -495,8 +494,8 @@ TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpRestricted) { // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .Times(1) @@ -528,8 +527,8 @@ TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpNotRestricted) { // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .Times(1) @@ -561,8 +560,8 @@ TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpRestricted) { // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .Times(1) @@ -585,8 +584,8 @@ TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpNotRestricted) { // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .Times(1) @@ -606,4 +605,4 @@ EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result); EXPECT_EQ(1u, devices.size()); } -#endif +#endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/media/webrtc/media_stream_capture_indicator.cc b/chrome/browser/media/webrtc/media_stream_capture_indicator.cc index 843fbb3..f5a5d87 100644 --- a/chrome/browser/media/webrtc/media_stream_capture_indicator.cc +++ b/chrome/browser/media/webrtc/media_stream_capture_indicator.cc
@@ -15,7 +15,6 @@ #include "base/containers/contains.h" #include "base/notreached.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/chrome_content_settings_utils.h" @@ -47,8 +46,8 @@ #include "extensions/common/extension.h" #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" +#if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" #endif using content::BrowserThread; @@ -241,8 +240,8 @@ ui_ ? base::OnceClosure() : stop_callback); } -#if BUILDFLAG(IS_CHROMEOS_ASH) - policy::DlpContentManagerAsh::Get()->OnScreenCaptureStarted( +#if BUILDFLAG(IS_CHROMEOS) + policy::DlpContentManager::Get()->OnScreenCaptureStarted( label, screen_capture_ids, application_title_, stop_callback, state_change_callback); #endif @@ -258,9 +257,8 @@ void OnDeviceStopped(const std::string& label, const content::DesktopMediaID& media_id) override { -#if BUILDFLAG(IS_CHROMEOS_ASH) - policy::DlpContentManagerAsh::Get()->OnScreenCaptureStopped(label, - media_id); +#if BUILDFLAG(IS_CHROMEOS) + policy::DlpContentManager::Get()->OnScreenCaptureStopped(label, media_id); #endif }
diff --git a/chrome/browser/media/webrtc/tab_capture_access_handler.cc b/chrome/browser/media/webrtc/tab_capture_access_handler.cc index 49a2cebd..dab415f 100644 --- a/chrome/browser/media/webrtc/tab_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/tab_capture_access_handler.cc
@@ -8,7 +8,6 @@ #include <utility> #include "base/bind.h" -#include "build/chromeos_buildflags.h" #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" #include "chrome/browser/media/webrtc/capture_policy_utils.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" @@ -24,9 +23,9 @@ #include "extensions/common/permissions/permissions_data.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" +#endif // BUILDFLAG(IS_CHROMEOS) namespace { // This helper class is designed to live as long as the capture, and is used @@ -172,7 +171,7 @@ const bool is_allowlisted_extension = IsExtensionAllowedForScreenCapture(extension); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) if (request.video_type == blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE) { // Use extension name as title for extensions and host/origin for drive-by @@ -189,7 +188,7 @@ // base::Unretained(this) is safe because TabCaptureAccessHandler is owned // by MediaCaptureDevicesDispatcher, which is a lazy singleton which is // destroyed when the browser process terminates. - policy::DlpContentManagerAsh::Get()->CheckScreenShareRestriction( + policy::DlpContentManager::Get()->CheckScreenShareRestriction( media_id, application_title, base::BindOnce( &TabCaptureAccessHandler::OnDlpRestrictionChecked, @@ -201,7 +200,7 @@ std::move(media_ui))); return; } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) AcceptRequest(web_contents, request, std::move(callback), is_allowlisted_extension, std::move(media_ui)); @@ -226,7 +225,7 @@ std::move(ui)); } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) void TabCaptureAccessHandler::OnDlpRestrictionChecked( base::WeakPtr<content::WebContents> web_contents, std::unique_ptr<PendingAccessRequest> pending_request, @@ -250,4 +249,4 @@ /*ui=*/nullptr); } } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/media/webrtc/tab_capture_access_handler.h b/chrome/browser/media/webrtc/tab_capture_access_handler.h index 1d2d527..5ef33b8 100644 --- a/chrome/browser/media/webrtc/tab_capture_access_handler.h +++ b/chrome/browser/media/webrtc/tab_capture_access_handler.h
@@ -43,7 +43,7 @@ bool is_allowlisted_extension, std::unique_ptr<MediaStreamUI> media_ui); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) // Called back after checking Data Leak Prevention (DLP) restrictions. void OnDlpRestrictionChecked( base::WeakPtr<content::WebContents> web_contents, @@ -51,7 +51,7 @@ std::unique_ptr<MediaStreamUI> media_ui, bool is_dlp_allowed); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // BUILDFLAG(IS_CHROMEOS) }; #endif // CHROME_BROWSER_MEDIA_WEBRTC_TAB_CAPTURE_ACCESS_HANDLER_H_
diff --git a/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc b/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc index de40027..f9406de 100644 --- a/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/tab_capture_access_handler_unittest.cc
@@ -11,7 +11,6 @@ #include "base/bind.h" #include "base/run_loop.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" #include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" @@ -23,10 +22,10 @@ #include "third_party/blink/public/common/mediastream/media_stream_request.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" -#include "chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h" -#endif +#if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" +#include "chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h" +#endif // BUILDFLAG(IS_CHROMEOS) namespace { constexpr char kOrigin[] = "https://origin/"; @@ -114,7 +113,7 @@ devices[0].type); } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS) TEST_F(TabCaptureAccessHandlerTest, DlpRestricted) { const content::DesktopMediaID source( content::DesktopMediaID::TYPE_WEB_CONTENTS, @@ -124,8 +123,8 @@ web_contents()->GetMainFrame()->GetRoutingID())); // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .WillOnce([](const content::DesktopMediaID& media_id, @@ -155,8 +154,8 @@ web_contents()->GetMainFrame()->GetRoutingID())); // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .WillOnce([](const content::DesktopMediaID& media_id, @@ -186,8 +185,8 @@ web_contents()->GetMainFrame()->GetRoutingID())); // Setup Data Leak Prevention restriction. - policy::MockDlpContentManagerAsh mock_dlp_content_manager; - policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager( + policy::MockDlpContentManager mock_dlp_content_manager; + policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .WillOnce([&](const content::DesktopMediaID& media_id, @@ -208,4 +207,4 @@ EXPECT_EQ(kInvalidResult, result); EXPECT_EQ(0u, devices.size()); } -#endif +#endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc b/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc index b2c10b9..5604d443 100644 --- a/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc +++ b/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc
@@ -486,6 +486,43 @@ EXPECT_FALSE(GetContentAnnotationsForURL(url).has_value()); } +IN_PROC_BROWSER_TEST_F(PageContentAnnotationsServiceNoHistoryTest, + ModelExecutesAndUsesCachedResult) { + { + base::HistogramTester histogram_tester; + + GURL url(embedded_test_server()->GetURL("a.com", "/hello.html")); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PageContentAnnotationsService.ContentAnnotated", 1); + + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached", + false, 1); + } + { + base::HistogramTester histogram_tester; + GURL url2(embedded_test_server()->GetURL("a.com", "/hello.html")); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url2)); + + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PageContentAnnotationsService.ContentAnnotated", 1); + + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PageContentAnnotationsService.ContentAnnotated", + true, 1); + + base::RunLoop().RunUntilIdle(); + + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached", + true, 1); + } +} + class PageContentAnnotationsServiceBatchVisitTest : public PageContentAnnotationsServiceNoHistoryTest { public: @@ -530,6 +567,11 @@ base::RunLoop().RunUntilIdle(); + // The cache is missed because we are batching requests. The cache check + // happens before adding a visit annotation request to the batch. + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached", + false, 2); histogram_tester.ExpectUniqueSample( "PageContentAnnotations.AnnotateVisit.BatchAnnotationStarted", true, 1); @@ -598,6 +640,10 @@ histogram_tester.ExpectUniqueSample( "PageContentAnnotations.AnnotateVisit.QueueFullVisitDropped", true, 1); + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached", + false, 4); + histogram_tester.ExpectTotalCount( "OptimizationGuide.PageContentAnnotationsService." "ContentAnnotationsStorageStatus",
diff --git a/chrome/browser/renderer_host/chrome_extension_message_filter.cc b/chrome/browser/renderer_host/chrome_extension_message_filter.cc index a0c4160..a0e748d 100644 --- a/chrome/browser/renderer_host/chrome_extension_message_filter.cc +++ b/chrome/browser/renderer_host/chrome_extension_message_filter.cc
@@ -26,9 +26,9 @@ #include "content/public/browser/browser_task_traits.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" +#include "extensions/browser/l10n_file_util.h" #include "extensions/common/extension_messages.h" #include "extensions/common/extension_set.h" -#include "extensions/common/file_util.h" #include "extensions/common/manifest_handlers/default_locale_handler.h" #include "extensions/common/manifest_handlers/shared_module_info.h" #include "extensions/common/message_bundle.h" @@ -129,8 +129,8 @@ if (default_locale.empty()) { // A little optimization: send the answer here to avoid an extra thread hop. std::unique_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map( - extensions::file_util::LoadNonLocalizedMessageBundleSubstitutionMap( - extension_id)); + extensions::l10n_file_util:: + LoadNonLocalizedMessageBundleSubstitutionMap(extension_id)); ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg, *dictionary_map); Send(reply_msg); @@ -173,7 +173,7 @@ extension_l10n_util::GzippedMessagesPermission gzip_permission, IPC::Message* reply_msg) { std::unique_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map( - extensions::file_util::LoadMessageBundleSubstitutionMapFromPaths( + extensions::l10n_file_util::LoadMessageBundleSubstitutionMapFromPaths( extension_paths, main_extension_id, default_locale, gzip_permission)); ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg,
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index fc2045d..5d73e76 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -144,7 +144,6 @@ "new_tab_page_instant:closure_compile", "ntp4:closure_compile", "omnibox:closure_compile", - "quota_internals:closure_compile", "settings:closure_compile", "sync_file_system_internals:closure_compile", "usb_internals:closure_compile", @@ -316,7 +315,6 @@ "$root_gen_dir/chrome/invalidations_resources.pak", "$root_gen_dir/chrome/net_internals_resources.pak", "$root_gen_dir/chrome/omnibox_resources.pak", - "$root_gen_dir/chrome/quota_internals_resources.pak", "$root_gen_dir/chrome/usb_internals_resources.pak", "$root_gen_dir/chrome/webrtc_logs_resources.pak", "$root_gen_dir/components/dev_ui_components_resources.pak", @@ -335,7 +333,6 @@ "//chrome/browser/resources/media:webrtc_logs_resources", "//chrome/browser/resources/net_internals:resources", "//chrome/browser/resources/omnibox:resources", - "//chrome/browser/resources/quota_internals:resources", "//chrome/browser/resources/usb_internals:resources", "//components/download/resources/download_internals:resources", "//components/resources:dev_ui_components_resources",
diff --git a/chrome/browser/resources/chromeos/arc_support/OWNERS b/chrome/browser/resources/chromeos/arc_support/OWNERS index e844cda..73a4704 100644 --- a/chrome/browser/resources/chromeos/arc_support/OWNERS +++ b/chrome/browser/resources/chromeos/arc_support/OWNERS
@@ -1,2 +1,6 @@ -lgcheng@chromium.org +lgcheng@google.com mhasank@chromium.org + +per-file recommend_app_list_view.*=rrsilva@google.com +per-file recommend_app_list_view.*=rsorokin@chromium.org +per-file recommend_app_list_view.*=tellier@google.com \ No newline at end of file
diff --git a/chrome/browser/resources/gaia_auth_host/authenticator.js b/chrome/browser/resources/gaia_auth_host/authenticator.js index 32f32a7..680f87e 100644 --- a/chrome/browser/resources/gaia_auth_host/authenticator.js +++ b/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -342,6 +342,11 @@ this.syncTrustedVaultKeys_ = msg.value; }, 'closeView'(msg) { + // We need to resend the message to make sure it comes after the API + // 'confirm' call. The API calls go via different channel. + window.postMessage({method: 'resendCloseView'}, window.origin); + }, + 'resendCloseView'(msg) { if (!this.enableCloseView_) { return; } @@ -949,7 +954,7 @@ * Returns true if given HTML5 message is received from the webview element. * @param {Object} e Payload of the received HTML5 message. */ - isGaiaMessage(e) { + isGaiaMessage_(e) { if (!this.isWebviewEvent_(e)) { return false; } @@ -968,12 +973,28 @@ } /** + * Returns true if given HTML5 message is received from the current window. + * @param {Object} e Payload of the received HTML5 message. + */ + isSelfMessage_(e) { + if (e.origin !== window.origin) { + return false; + } + + if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) { + return false; + } + + return true; + } + + /** * Invoked when an HTML5 message is received from the webview element. * @param {Object} e Payload of the received HTML5 message. * @private */ onMessageFromWebview_(e) { - if (!this.isGaiaMessage(e)) { + if (!this.isGaiaMessage_(e) && !this.isSelfMessage_(e)) { return; }
diff --git a/chrome/browser/resources/inline_login/arc_account_picker_app.html b/chrome/browser/resources/inline_login/arc_account_picker_app.html index b6920f8..0a347e885 100644 --- a/chrome/browser/resources/inline_login/arc_account_picker_app.html +++ b/chrome/browser/resources/inline_login/arc_account_picker_app.html
@@ -83,7 +83,7 @@ <p class="secondary">$i18nRaw{accountManagerDialogArcAccountPickerBody}</p> <template is="dom-repeat" id="accountsContainer" items="[[accounts]]"> - <div class="account-item"> + <div class="account-item" on-click="makeAvailableInArc_"> <div class="account-icon" style="background-image: [[getIconImageSet_(item.image)]]"> </div>
diff --git a/chrome/browser/resources/inline_login/arc_account_picker_app.js b/chrome/browser/resources/inline_login/arc_account_picker_app.js index a3f94b1..91eb33e6 100644 --- a/chrome/browser/resources/inline_login/arc_account_picker_app.js +++ b/chrome/browser/resources/inline_login/arc_account_picker_app.js
@@ -7,6 +7,7 @@ import {getImage} from '//resources/js/icon.js'; import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Account} from './inline_login_browser_proxy.js'; +import {InlineLoginBrowserProxyImpl} from './inline_login_browser_proxy.js'; /** @polymer */ class ArcAccountPickerAppElement extends PolymerElement { @@ -56,6 +57,15 @@ addAccount_() { this.dispatchEvent(new CustomEvent('add-account')); } + + /** + * @param {!{model: !{item: Account}, target: !Element}} event + * @private + */ + makeAvailableInArc_(event) { + InlineLoginBrowserProxyImpl.getInstance().makeAvailableInArc( + event.model.item); + } } customElements.define(
diff --git a/chrome/browser/resources/inline_login/inline_login_browser_proxy.js b/chrome/browser/resources/inline_login/inline_login_browser_proxy.js index 8300b91..0420c55d 100644 --- a/chrome/browser/resources/inline_login/inline_login_browser_proxy.js +++ b/chrome/browser/resources/inline_login/inline_login_browser_proxy.js
@@ -76,6 +76,11 @@ skipWelcomePage(skip) {} /** + * @param {Account} account + */ + makeAvailableInArc(account) {} + + /** * Send 'getAccountsNotAvailableInArc' message to the handler. The promise * will be resolved with the list of accounts that are not available in ARC. * @return {Promise<Array<Account>>} @@ -148,6 +153,11 @@ } /** @override */ + makeAvailableInArc(account) { + chrome.send('makeAvailableInArc', [account]); + } + + /** @override */ getDialogArguments() { return chrome.getVariableValue('dialogArguments'); }
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn index 5a16fe7..15208628 100644 --- a/chrome/browser/resources/print_preview/BUILD.gn +++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -40,8 +40,13 @@ generate_grd("build_grd") { input_files = [ "print_preview.html" ] - input_files_base_dir = rebase_path(".", "//") - deps = [ "../pdf:build_print_preview_grdp" ] + input_files_base_dir = + rebase_path("$target_gen_dir/$preprocess_folder", root_build_dir) + deps = [ + ":preprocess_html", + "../pdf:build_print_preview_grdp", + ] + grdp_files = [ "$root_gen_dir/chrome/browser/resources/pdf/print_preview_pdf_resources.grdp" ] if (optimize_webui) { deps += [ ":build" ] @@ -59,6 +64,12 @@ js_files = web_component_files } +preprocess_if_expr("preprocess_html") { + in_folder = "./" + out_folder = "$target_gen_dir/$preprocess_folder" + in_files = [ "print_preview.html" ] +} + preprocess_if_expr("preprocess") { in_folder = "./" out_folder = "$target_gen_dir/$preprocess_folder"
diff --git a/chrome/browser/resources/print_preview/print_preview.html b/chrome/browser/resources/print_preview/print_preview.html index da49aa1..c4620d22a 100644 --- a/chrome/browser/resources/print_preview/print_preview.html +++ b/chrome/browser/resources/print_preview/print_preview.html
@@ -55,6 +55,10 @@ <print-preview-app></print-preview-app> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> +<if expr="chromeos_ash"> + <link rel="stylesheet" + href="chrome://resources/chromeos/colors/cros_styles.css"> +</if> <script type="module" src="print_preview.js"></script> </body> </html>
diff --git a/chrome/browser/resources/quota_internals/BUILD.gn b/chrome/browser/resources/quota_internals/BUILD.gn deleted file mode 100644 index 3211b6a4..0000000 --- a/chrome/browser/resources/quota_internals/BUILD.gn +++ /dev/null
@@ -1,58 +0,0 @@ -# Copyright 2019 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("//chrome/common/features.gni") -import("//third_party/closure_compiler/compile_js.gni") -import("//tools/grit/grit_rule.gni") -import("//ui/webui/resources/tools/generate_grd.gni") - -generate_grd("build_grd") { - grd_prefix = "quota_internals" - out_grd = "$target_gen_dir/${grd_prefix}_resources.grd" - input_files = [ - "event_handler.js", - "main.css", - "main.html", - "message_dispatcher.js", - ] - input_files_base_dir = rebase_path(".", "//") -} - -js_type_check("closure_compile") { - deps = [ - ":event_handler", - ":message_dispatcher", - ] -} - -js_library("event_handler") { - deps = [ - ":message_dispatcher", - "//ui/webui/resources/js:cr.m", - "//ui/webui/resources/js:util.m", - "//ui/webui/resources/js/cr:ui.m", - "//ui/webui/resources/js/cr/ui:tabs", - "//ui/webui/resources/js/cr/ui:tree", - ] -} - -js_library("message_dispatcher") { -} - -grit("resources") { - defines = chrome_grit_defines - - # These arguments are needed since the grd is generated at build time. - enable_input_discovery_for_gn_analyze = false - source = "$target_gen_dir/quota_internals_resources.grd" - deps = [ ":build_grd" ] - - outputs = [ - "grit/quota_internals_resources.h", - "grit/quota_internals_resources_map.cc", - "grit/quota_internals_resources_map.h", - "quota_internals_resources.pak", - ] - output_dir = "$root_gen_dir/chrome" -}
diff --git a/chrome/browser/resources/quota_internals/DIR_METADATA b/chrome/browser/resources/quota_internals/DIR_METADATA deleted file mode 100644 index d669a4a..0000000 --- a/chrome/browser/resources/quota_internals/DIR_METADATA +++ /dev/null
@@ -1,4 +0,0 @@ -monorail: { - component: "Blink>Storage>Quota" -} -team_email: "storage-dev@chromium.org"
diff --git a/chrome/browser/resources/quota_internals/OWNERS b/chrome/browser/resources/quota_internals/OWNERS deleted file mode 100644 index a61a714..0000000 --- a/chrome/browser/resources/quota_internals/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://storage/browser/quota/OWNERS
diff --git a/chrome/browser/resources/quota_internals/event_handler.js b/chrome/browser/resources/quota_internals/event_handler.js deleted file mode 100644 index c267293..0000000 --- a/chrome/browser/resources/quota_internals/event_handler.js +++ /dev/null
@@ -1,495 +0,0 @@ -// Copyright (c) 2011 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 {addWebUIListener} from 'chrome://resources/js/cr.m.js'; -import {decorate} from 'chrome://resources/js/cr/ui.m.js'; -import {TabBox} from 'chrome://resources/js/cr/ui/tabs.js'; -import {Tree, TreeItem} from 'chrome://resources/js/cr/ui/tree.js'; -import {$} from 'chrome://resources/js/util.m.js'; - -import {requestInfo, triggerStoragePressure} from './message_dispatcher.js'; - -/** - * @param {Object} object Object to be checked. - * @return {boolean} true if |object| is {}. - * @private - */ -function isEmptyObject_(object) { - for (const i in object) { - return false; - } - return true; -} - -/** - * Copy properties from |source| to |destination|. - * @param {Object} source Source of the copy. - * @param {Object} destination Destination of the copy. - * @return {Object} |destination|. - * @private - */ -function copyAttributes_(source, destination) { - for (const i in source) { - destination[i] = source[i]; - } - return destination; -} - -/** - * Returns 'N/A' (Not Available) text if |value| is undefined. - * @param {*} value Object to print. - * @return {string} 'N/A' or ''. - * @private - */ -function checkIfAvailable_(value) { - return value === undefined ? 'N/A' : ''; -} - -/** - * Returns |value| itself if |value| is not undefined, - * else returns 'N/A' text. - * @param {?string} value String to print. - * @return {string} 'N/A' or |value|. - * @private - */ -function stringToText_(value) { - return checkIfAvailable_(value) || /** @type {string} */ (value); -} - -/** - * Separates |value| into segments. - * The length of first segment is at most |maxLength|. - * Length of other following segments are just |maxLength|. - * e.g. separateBackward_('abcdefghijk', 4) == ['abc','defg','hijk']; - * @param {string} value String to be separated. - * @param {number} maxLength Max length of segments. - * @return {Array<string>} Array of segments. - * @private - */ -function separateBackward_(value, maxLength) { - const result = []; - while (value.length > maxLength) { - result.unshift(value.slice(-3)); - value = value.slice(0, -3); - } - result.unshift(value); - return result; -} - -/** - * Returns formatted string from number as number of bytes. - * e.g. numBytesToText(123456789) = '123.45 MB (123,456,789 B)'. - * If |value| is undefined, this function returns 'N/A'. - * @param {?number} value Number to print. - * @return {string} 'N/A' or formatted |value|. - * @private - */ -function numBytesToText_(value) { - let result = checkIfAvailable_(value); - if (result) { - return result; - } - - const segments = separateBackward_(value.toString(), 3); - result = segments.join(',') + ' B'; - - if (segments.length > 1) { - const UNIT = [' B', ' KB', ' MB', ' GB', ' TB', ' PB']; - result = segments[0] + '.' + segments[1].slice(0, 2) + - UNIT[Math.min(segments.length, UNIT.length) - 1] + ' (' + result + ')'; - } - - return result; -} - -/** - * Return formatted date |value| if |value| is not undefined. - * If |value| is undefined, this function returns 'N/A'. - * @param {?number} value Number of milliseconds since - * UNIX epoch time (0:00, Jan 1, 1970, UTC). - * @return {string} Formatted text of date or 'N/A'. - * @private - */ -function dateToText(value) { - let result = checkIfAvailable_(value); - if (result) { - return result; - } - - const time = new Date(value); - const now = new Date(); - const delta = Date.now() - value; - - const SECOND = 1000; - const MINUTE = 60 * SECOND; - const HOUR = 60 * MINUTE; - const DAY = 23 * HOUR; - const WEEK = 7 * DAY; - - const SHOW_SECOND = 5 * MINUTE; - const SHOW_MINUTE = 5 * HOUR; - const SHOW_HOUR = 3 * DAY; - const SHOW_DAY = 2 * WEEK; - const SHOW_WEEK = 3 * 30 * DAY; - - if (delta < 0) { - result = 'access from future '; - } else if (delta < SHOW_SECOND) { - result = Math.ceil(delta / SECOND) + ' sec ago '; - } else if (delta < SHOW_MINUTE) { - result = Math.ceil(delta / MINUTE) + ' min ago '; - } else if (delta < SHOW_HOUR) { - result = Math.ceil(delta / HOUR) + ' hr ago '; - } else if (delta < SHOW_WEEK) { - result = Math.ceil(delta / DAY) + ' day ago '; - } - - result += '(' + time.toString() + ')'; - return result; -} - -/** - * Available disk space. - * @type {number|undefined} - */ -let availableSpace = undefined; - -/** - * Root of the quota data tree, - * holding userdata as |treeViewObject.detail|. - * @type {Tree} - */ -let treeViewObject; - -/** - * Key-value styled statistics data. - * This WebUI does not touch contents, just show. - * The value is hold as |statistics[key].detail|. - * @type {Object<string,Element>} - */ -const statistics = {}; - -/** - * Initialize and return |treeViewObject|. - * @return {!Tree} Initialized |treeViewObject|. - */ -function getTreeViewObject() { - if (!treeViewObject) { - treeViewObject = /** @type {!Tree} */ ($('tree-view')); - decorate(treeViewObject, Tree); - treeViewObject.detail = {payload: {}, children: {}}; - treeViewObject.addEventListener('change', updateDescription); - } - return treeViewObject; -} - -/** - * Initialize and return a tree item, that represents specified storage type. - * @param {!string} type Storage type. - * @return {TreeItem} Initialized |storageObject|. - */ -function getStorageObject(type) { - const treeViewObject = getTreeViewObject(); - let storageObject = treeViewObject.detail.children[type]; - if (!storageObject) { - storageObject = - new TreeItem({label: type, detail: {payload: {}, children: {}}}); - storageObject.mayHaveChildren_ = true; - treeViewObject.detail.children[type] = storageObject; - treeViewObject.add(storageObject); - } - return storageObject; -} - -/** - * Initialize and return a tree item, that represents specified - * storage type and hostname. - * @param {!string} type Storage type. - * @param {!string} host Hostname. - * @return {TreeItem} Initialized |hostObject|. - */ -function getHostObject(type, host) { - const storageObject = getStorageObject(type); - let hostObject = storageObject.detail.children[host]; - if (!hostObject) { - hostObject = - new TreeItem({label: host, detail: {payload: {}, children: {}}}); - hostObject.mayHaveChildren_ = true; - storageObject.detail.children[host] = hostObject; - storageObject.add(hostObject); - } - return hostObject; -} - -/** - * Initialize and return a tree item, that represents specified - * storage type, hostname and origin url. - * @param {!string} type Storage type. - * @param {!string} host Hostname. - * @param {!string} origin Origin URL. - * @return {TreeItem} Initialized |originObject|. - */ -function getOriginObject(type, host, origin) { - const hostObject = getHostObject(type, host); - let originObject = hostObject.detail.children[origin]; - if (!originObject) { - originObject = - new TreeItem({label: origin, detail: {payload: {}, children: {}}}); - originObject.mayHaveChildren_ = false; - hostObject.detail.children[origin] = originObject; - hostObject.add(originObject); - } - return originObject; -} - -/** @param {number} space Total available disk space. */ -function handleAvailableSpace(space) { - availableSpace = space; - $('diskspace-entry').textContent = numBytesToText_(availableSpace); -} - -/** - * |data| contains a record which has: - * |type|: - * Storage type, that is either 'temporary' or 'persistent'. - * |usage|: - * Total storage usage of all hosts. - * |unlimitedUsage|: - * Total storage usage of unlimited-quota origins. - * |quota|: - * Total quota of the storage. - * - * |usage|, |unlimitedUsage| and |quota| can be missing, - * and some additional fields can be included. - * @param {!{ - * type: string, - * usage: ?number, - * unlimitedUsage: ?number, - * quota: ?string - * }} data - */ -function handleGlobalInfo(data) { - const storageObject = getStorageObject(data.type); - copyAttributes_(data, storageObject.detail.payload); - storageObject.reveal(); - if (getTreeViewObject().selectedItem == storageObject) { - updateDescription(); - } -} - -/** - * |dataArray| contains records which have: - * |host|: - * Hostname of the entry. (e.g. 'example.com') - * |type|: - * Storage type. 'temporary' or 'persistent' - * |usage|: - * Total storage usage of the host. - * |quota|: - * Per-host quota. - * - * |usage| and |quota| can be missing, - * and some additional fields can be included. - * @param {!Array<{ - * host: string, - * type: string, - * usage: ?number, - * quota: ?number - * }>} dataArray - */ -function handlePerHostInfo(dataArray) { - for (let i = 0; i < dataArray.length; ++i) { - const data = dataArray[i]; - const hostObject = getHostObject(data.type, data.host); - copyAttributes_(data, hostObject.detail.payload); - hostObject.reveal(); - if (getTreeViewObject().selectedItem == hostObject) { - updateDescription(); - } - } -} - -/** - * |dataArray| contains records which have: - * |origin|: - * Origin URL of the entry. - * |type|: - * Storage type of the entry. 'temporary' or 'persistent'. - * |host|: - * Hostname of the entry. - * |usedCount|: - * Used count of the storage from the origin. - * |lastAccessTime|: - * Last storage access time from the origin. - * Number of milliseconds since UNIX epoch (Jan 1, 1970, 0:00:00 UTC). - * |lastModifiedTime|: - * Last modified time of the storage from the origin. - * Number of milliseconds since UNIX epoch. - * - * |usedCount|, |lastAccessTime| and |lastModifiedTime| can be missing, - * and some additional fields can be included. - * @param {!Array<!{ - * origin: string, - * type: string, - * host: string, - * usedCount: ?number, - * lastAccessTime: ?number, - * lastModifiedTime: ?number - * }>} dataArray - */ -function handlePerOriginInfo(dataArray) { - for (let i = 0; i < dataArray.length; ++i) { - const data = dataArray[i]; - const originObject = getOriginObject(data.type, data.host, data.origin); - copyAttributes_(data, originObject.detail.payload); - originObject.reveal(); - if (getTreeViewObject().selectedItem == originObject) { - updateDescription(); - } - } -} - -/** - * |data| contains misc statistics data as dictionary. - * @param {!Object} data - */ -function handleStatistics(data) { - for (const key in data) { - let entry = statistics[key]; - if (!entry) { - const template = document.querySelector('#table-row-template'); - entry = template.content.cloneNode(true).querySelector('tr'); - $('stat-entries').appendChild(entry); - statistics[key] = entry; - } - entry.detail = data[key]; - - entry.querySelectorAll('td')[0].textContent = stringToText_(key); - entry.querySelectorAll('td')[1].textContent = stringToText_(entry.detail); - } -} - -/** - * @param {!{isStoragePressureEnabled: boolean}} data Contains a boolean - * representing whether or not to show the storage pressure UI. - */ -function handleStoragePressureFlagInfo(data) { - $('storage-pressure-loading').hidden = true; - if (data.isStoragePressureEnabled) { - $('storage-pressure-outer').hidden = false; - } else { - $('storage-pressure-disabled').hidden = false; - } -} - -/** - * Update description on 'tree-item-description' field with - * selected item in tree view. - */ -function updateDescription() { - const item = getTreeViewObject().selectedItem; - const tbody = $('tree-item-description'); - tbody.innerHTML = trustedTypes.emptyHTML; - - if (item) { - const keyAndLabel = [ - ['type', 'Storage Type'], ['host', 'Host Name'], ['origin', 'Origin URL'], - ['usage', 'Total Storage Usage', numBytesToText_], - ['unlimitedUsage', 'Usage of Unlimited Origins', numBytesToText_], - ['quota', 'Quota', numBytesToText_], ['usedCount', 'Used count'], - ['lastAccessTime', 'Last Access Time', dateToText], - ['lastModifiedTime', 'Last Modified Time', dateToText] - ]; - for (let i = 0; i < keyAndLabel.length; ++i) { - const key = keyAndLabel[i][0]; - const label = keyAndLabel[i][1]; - const entry = item.detail.payload[key]; - if (entry === undefined) { - continue; - } - - const normalize = keyAndLabel[i][2] || stringToText_; - - const template = document.querySelector('#table-row-template'); - const row = template.content.cloneNode(true).querySelector('tr'); - row.querySelectorAll('td')[0].textContent = label; - row.querySelectorAll('td')[1].textContent = normalize(entry); - tbody.appendChild(row); - } - } -} - -/** - * Dump |treeViewObject| or subtree to a object. - * @param {(Tree|TreeItem)=} opt_treeitem - * @return {Object} Dump result object from |treeViewObject|. - */ -function dumpTreeToObj(opt_treeitem) { - const treeitem = opt_treeitem || getTreeViewObject(); - const res = {}; - res.payload = treeitem.detail.payload; - res.children = []; - for (const i in treeitem.detail.children) { - const child = treeitem.detail.children[i]; - res.children.push(dumpTreeToObj(child)); - } - - if (isEmptyObject_(res.payload)) { - delete res.payload; - } - - if (res.children.length == 0) { - delete res.children; - } - return res; -} - -/** - * Dump |statistics| to a object. - * @return {Object} Dump result object from |statistics|. - */ -function dumpStatisticsToObj() { - const result = {}; - for (const key in statistics) { - result[key] = statistics[key].detail; - } - return result; -} - -/** - * Event handler for 'dump-button' 'click'ed. - * Dump and show all data from WebUI page to 'dump-field' element. - */ -function dump() { - const separator = '========\n'; - - $('dump-field').textContent = separator + 'Summary\n' + separator + - JSON.stringify({availableSpace: availableSpace}, null, 2) + '\n' + - separator + 'Usage And Quota\n' + separator + - JSON.stringify(dumpTreeToObj(), null, 2) + '\n' + separator + - 'Misc Statistics\n' + separator + - JSON.stringify(dumpStatisticsToObj(), null, 2); -} - -function onLoad() { - decorate('tabbox', TabBox); - - addWebUIListener('AvailableSpaceUpdated', handleAvailableSpace); - addWebUIListener('GlobalInfoUpdated', handleGlobalInfo); - addWebUIListener('PerHostInfoUpdated', handlePerHostInfo); - addWebUIListener('PerOriginInfoUpdated', handlePerOriginInfo); - addWebUIListener('StatisticsUpdated', handleStatistics); - addWebUIListener('StoragePressureFlagUpdated', handleStoragePressureFlagInfo); - - requestInfo(); - - $('refresh-button').addEventListener('click', requestInfo, false); - $('dump-button').addEventListener('click', dump, false); - $('trigger-notification').addEventListener('click', () => { - const origin = $('storage-pressure-origin').value; - triggerStoragePressure(origin); - }, false); -} - -document.addEventListener('DOMContentLoaded', onLoad, false);
diff --git a/chrome/browser/resources/quota_internals/main.css b/chrome/browser/resources/quota_internals/main.css deleted file mode 100644 index 3afbeb6e..0000000 --- a/chrome/browser/resources/quota_internals/main.css +++ /dev/null
@@ -1,31 +0,0 @@ -/* Copyright (c) 2012 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. */ - -th, -td { - padding-inline-end: 0.5em; - padding-inline-start: 0.5em; - text-align: center; -} - -#tree-view-container { - float: left; - min-width: 15em; - width: 20%; -} - -tr:nth-child(odd) { - background: rgb(238, 238, 255); -} - -.tree-item:not([may-have-children]) > .tree-row > .tree-label-icon { - background-image: url(chrome://resources/images/icon_file.png); -} - -.pressure { - margin: 10px 0; -} -#storage-pressure-origin { - min-width: 20em; -}
diff --git a/chrome/browser/resources/quota_internals/main.html b/chrome/browser/resources/quota_internals/main.html deleted file mode 100644 index 87a17f4..0000000 --- a/chrome/browser/resources/quota_internals/main.html +++ /dev/null
@@ -1,95 +0,0 @@ -<!doctype html> -<!-- -Copyright (c) 2011 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 dir="ltr" lang="en"> -<title>Quota Internals</title> -<meta charset="utf-8"> -<link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> -<link rel="stylesheet" href="main.css"> - -<link rel="stylesheet" href="chrome://resources/css/tabs.css"> -<link rel="stylesheet" href="chrome://resources/css/tree.css"> - -<script type="module" src="event_handler.js"></script> - -<body> - -<tabbox> - <tabs> - <tab>Summary</tab> - <tab>Usage & Quota</tab> - <tab>Raw Data Dump</tab> - </tabs> - <tabpanels> - <tabpanel> - <!-- Summary --> - <h2>Summary</h2> - - <template id="table-row-template"> - <tr> - <td></td> - <td></td> - </tr> - </template> - - <table> - <tbody> - <tr> - <td>Free disk space for the profile directory.</td> - <td id="diskspace-entry">N/A</td> - </tr> - </tbody> - </table> - <h2>Misc Statistics</h2> - <table> - <tbody id="stat-entries" class="entries"></tbody> - </table> - <div id="storage-pressure-section"> - <h2>Test Storage Pressure Behavior</h2> - <div id="storage-pressure-loading"> - Loading... - </div> - <div id="storage-pressure-outer" hidden> - <div class="pressure"> - Origin to test: - <input id="storage-pressure-origin" - value="https://www.example.com"> - </div> - <div class="pressure"> - <button id="trigger-notification"> - Trigger Storage Pressure Notification - </button> - </div> - </div> - <div id="storage-pressure-disabled" hidden> - Storage Pressure feature disabled. - </div> - </div> - </tabpanel> - - <tabpanel> - <!-- Usage and Quota --> - <h2>Usage and Quota Database Browser</h2> - <div id="tree-view-container"> - <button id="refresh-button">Refresh</button> - <tree id="tree-view"></tree> - </div> - <table> - <thead></thead> - <tbody id="tree-item-description"></tbody> - </table> - </tabpanel> - - <tabpanel> - <!-- Raw Data Dump --> - <button id="dump-button">Dump Raw Data</button> - <pre id="dump-field"></pre> - </tabpanel> - </tabpanels> -</tabbox> - -</body> -</html>
diff --git a/chrome/browser/resources/quota_internals/message_dispatcher.js b/chrome/browser/resources/quota_internals/message_dispatcher.js deleted file mode 100644 index dd452be..0000000 --- a/chrome/browser/resources/quota_internals/message_dispatcher.js +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * Bridge between the browser and the page. - * In this file: - * * define interface to request data from the browser. - */ - -/** Post requestInfo message to Browser. */ -export function requestInfo() { - chrome.send('requestInfo'); -} - -/** - * Post triggerStoragePressure message to Browser. - * @param {string} origin - */ -export function triggerStoragePressure(origin) { - chrome.send('triggerStoragePressure', [origin]); -}
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java index 84878253..4273478f 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
@@ -316,6 +316,8 @@ FeatureConstants.IPH_SHARE_SCREENSHOT_FEATURE); return new FirstPartyOptionBuilder(ContentType.LINK_PAGE_VISIBLE, ContentType.TEXT, ContentType.HIGHLIGHTED_TEXT, ContentType.IMAGE) + .setDetailedContentTypesToDisableFor( + DetailedContentType.LIGHTWEIGHT_REACTION, DetailedContentType.WEB_NOTES) .setIcon(R.drawable.screenshot, R.string.sharing_screenshot) .setFeatureNameForMetrics("SharingHubAndroid.ScreenshotSelected") .setDisableForMultiWindow(true) @@ -335,6 +337,8 @@ private FirstPartyOption createLongScreenshotsFirstPartyOption() { return new FirstPartyOptionBuilder(ContentType.LINK_PAGE_VISIBLE, ContentType.TEXT, ContentType.HIGHLIGHTED_TEXT, ContentType.IMAGE) + .setDetailedContentTypesToDisableFor( + DetailedContentType.LIGHTWEIGHT_REACTION, DetailedContentType.WEB_NOTES) .setIcon(R.drawable.long_screenshot, R.string.sharing_long_screenshot) .setFeatureNameForMetrics("SharingHubAndroid.LongScreenshotSelected") .setDisableForMultiWindow(true) @@ -411,6 +415,8 @@ private FirstPartyOption createSendTabToSelfFirstPartyOption() { return new FirstPartyOptionBuilder( ContentType.LINK_PAGE_VISIBLE, ContentType.LINK_PAGE_NOT_VISIBLE, ContentType.IMAGE) + .setDetailedContentTypesToDisableFor( + DetailedContentType.LIGHTWEIGHT_REACTION, DetailedContentType.WEB_NOTES) .setIcon(R.drawable.send_tab, R.string.send_tab_to_self_share_activity_title) .setFeatureNameForMetrics("SharingHubAndroid.SendTabToSelfSelected") .setOnClickCallback((view) -> { @@ -430,6 +436,8 @@ private FirstPartyOption createQrCodeFirstPartyOption() { return new FirstPartyOptionBuilder( ContentType.LINK_PAGE_VISIBLE, ContentType.LINK_PAGE_NOT_VISIBLE, ContentType.IMAGE) + .setDetailedContentTypesToDisableFor( + DetailedContentType.LIGHTWEIGHT_REACTION, DetailedContentType.WEB_NOTES) .setIcon(R.drawable.qr_code, R.string.qr_code_share_icon_label) .setFeatureNameForMetrics("SharingHubAndroid.QRCodeSelected") .setOnClickCallback((view) -> { @@ -472,6 +480,8 @@ private FirstPartyOption createLightweightReactionsFirstPartyOption() { return new FirstPartyOptionBuilder(ContentType.LINK_PAGE_VISIBLE, ContentType.TEXT, ContentType.HIGHLIGHTED_TEXT, ContentType.IMAGE) + .setDetailedContentTypesToDisableFor( + DetailedContentType.LIGHTWEIGHT_REACTION, DetailedContentType.WEB_NOTES) .setIcon(R.drawable.lightweight_reactions_icon, R.string.sharing_lightweight_reactions) .setFeatureNameForMetrics("SharingHubAndroid.LightweightReactions")
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java index b151179f..c480ba8 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
@@ -354,20 +354,37 @@ @Test @MediumTest + public void getPropertyModels_webnotes_filtersByDetailedContentType() { + setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, + /*printingEnabled=*/true, LinkGeneration.MAX); + List<PropertyModel> propertyModels = + mChromeProvidedSharingOptionsProvider.getPropertyModels( + ImmutableSet.of(ContentType.IMAGE), DetailedContentType.WEB_NOTES, + /*isMultiWindow=*/false); + + List<String> expectedModels = + ImmutableList.<String>builder() + .add(mActivity.getResources().getString(R.string.sharing_copy_image)) + .add(mActivity.getResources().getString(R.string.sharing_save_image)) + .build(); + + assertCorrectModelsAreInTheRightOrder(propertyModels, expectedModels); + } + + @Test + @MediumTest @Features.EnableFeatures({ChromeFeatureList.LIGHTWEIGHT_REACTIONS}) public void getPropertyModels_lightweightReactions_filtersByDetailedContentType() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/true, LinkGeneration.MAX); List<PropertyModel> propertyModels = mChromeProvidedSharingOptionsProvider.getPropertyModels( - ImmutableSet.of(ContentType.IMAGE_AND_LINK), + ImmutableSet.of(ContentType.IMAGE), DetailedContentType.LIGHTWEIGHT_REACTION, /*isMultiWindow=*/false); - List<String> expectedModels = new ArrayList<>(); - expectedModels.add(mActivity.getResources().getString(R.string.sharing_copy_image)); - - assertCorrectModelsAreInTheRightOrder(propertyModels, expectedModels); + assertCorrectModelsAreInTheRightOrder(propertyModels, + ImmutableList.of(mActivity.getResources().getString(R.string.sharing_copy_image))); } @Test
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index e1cf8da..6642a3b7 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -96,7 +96,7 @@ // changed default theme assets, if you need themes to recreate their generated // images (which are cached), if you changed how missing values are // generated, or if you changed any constants. -const int kThemePackVersion = 79; +const int kThemePackVersion = 80; // IDs that are in the DataPack won't clash with the positive integer // uint16_t. kHeaderID should always have the maximum value because we want the @@ -1061,6 +1061,8 @@ kColorTabForegroundActiveFrameActive}, {TP::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_INACTIVE, kColorTabForegroundActiveFrameInactive}, + {TP::COLOR_TAB_THROBBER_SPINNING, ui::kColorThrobber}, + {TP::COLOR_TAB_THROBBER_WAITING, ui::kColorThrobberPreconnect}, {TP::COLOR_TOOLBAR, kColorToolbar}, {TP::COLOR_TOOLBAR_TEXT, kColorToolbarText}, }; @@ -1517,9 +1519,20 @@ SetColorIfUnspecified(TP::COLOR_TOOLBAR_TEXT, toolbar_text_color); } SkColor toolbar_button_icon_color; + color_utils::HSL button_tint; if (GetColor(TP::COLOR_TOOLBAR_BUTTON_ICON, &toolbar_button_icon_color)) { SetColor(TP::COLOR_TOOLBAR_BUTTON_ICON_HOVERED, toolbar_button_icon_color); SetColor(TP::COLOR_TOOLBAR_BUTTON_ICON_PRESSED, toolbar_button_icon_color); + SetColor(TP::COLOR_TAB_THROBBER_SPINNING, toolbar_button_icon_color); + SetColor(TP::COLOR_TAB_THROBBER_WAITING, toolbar_button_icon_color); + } else if (GetTint(TP::TINT_BUTTONS, &button_tint)) { + // Duplicate how COLOR_TOOLBAR_BUTTON_ICON will be computed. + // TODO(pkasting): Should this code be shared with + // ThemeHelper::GetDefaultColor() somehow? + const SkColor button_color = + color_utils::HSLShift(gfx::kChromeIconGrey, button_tint); + SetColor(TP::COLOR_TAB_THROBBER_SPINNING, button_color); + SetColor(TP::COLOR_TAB_THROBBER_WAITING, button_color); } SkColor toolbar_text_color; if (GetColor(TP::COLOR_TOOLBAR_TEXT, &toolbar_text_color)) {
diff --git a/chrome/browser/themes/theme_helper.cc b/chrome/browser/themes/theme_helper.cc index 088df4a7..9cb0a6d 100644 --- a/chrome/browser/themes/theme_helper.cc +++ b/chrome/browser/themes/theme_helper.cc
@@ -419,32 +419,6 @@ case TP::COLOR_NTP_TEXT_LIGHT: return IncreaseLightness( GetColor(TP::COLOR_NTP_TEXT, incognito, theme_supplier), 0.40); - case TP::COLOR_TAB_THROBBER_SPINNING: - case TP::COLOR_TAB_THROBBER_WAITING: { - // Similar to the code in BrowserThemeProvider::HasCustomColor(), here we - // decide the toolbar button icon has a custom color if the theme supplier - // has explicitly specified it or a TINT_BUTTONS value. Unlike that code, - // this does not consider TINT_BUTTONS to have been customized just - // because it differs from {-1, -1, -1}. The effect is that for the - // default light/dark/incognito themes, or custom themes which use the - // default toolbar button colors, the default throbber colors will be - // used; otherwise the throbber will be colored to match the toolbar - // buttons to guarantee visibility. - bool has_custom_color = false; - const SkColor button_color = - GetColor(TP::COLOR_TOOLBAR_BUTTON_ICON, incognito, theme_supplier, - &has_custom_color); - color_utils::HSL hsl; - return (has_custom_color || - (theme_supplier && - theme_supplier->GetTint(TP::TINT_BUTTONS, &hsl))) - ? button_color - : ui::GetAuraColor( - id == TP::COLOR_TAB_THROBBER_SPINNING - ? ui::NativeTheme::kColorId_ThrobberSpinningColor - : ui::NativeTheme::kColorId_ThrobberWaitingColor, - ui::NativeTheme::GetInstanceForNativeUi()); - } case TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE: case TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_INACTIVE: { return GetColor(id == TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h index 5bfc126..8666884 100644 --- a/chrome/browser/themes/theme_properties.h +++ b/chrome/browser/themes/theme_properties.h
@@ -161,8 +161,8 @@ COLOR_TAB_FOREGROUND_ACTIVE_FRAME_INACTIVE_INCOGNITO, // The throbber colors for tabs or anything on a toolbar (currently, only - // the download shelf). If you're adding a throbber elsewhere, such as in - // a dialog or bubble, you likely want ui::kColorThrobber. + // the download shelf). Do not use directly; only for use inside + // browser_theme_pack.cc. COLOR_TAB_THROBBER_SPINNING, COLOR_TAB_THROBBER_WAITING,
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc index 7ae009e5..85c62853 100644 --- a/chrome/browser/themes/theme_service_unittest.cc +++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -78,11 +78,13 @@ std::string ColorIdToString(int id) { #define E(color_id, theme_property_id, ...) \ {theme_property_id, #theme_property_id}, +#define E_CPONLY(color_id) static constexpr const auto kMap = base::MakeFixedFlatMap<int, const char*>({CHROME_COLOR_IDS}); #undef E +#undef E_CPONLY constexpr char kPrefix[] = "ThemeProperties::"; std::string id_str = kMap.find(id)->second; @@ -327,8 +329,10 @@ }; #define E(color_id, theme_property_id, ...) theme_property_id, +#define E_CPONLY(color_id) static constexpr int kTestIdValues[] = {CHROME_COLOR_IDS}; #undef E +#undef E_CPONLY INSTANTIATE_TEST_SUITE_P( ,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index adaaca0..bd379a58 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -300,14 +300,6 @@ "webui/predictors/predictors_ui.h", "webui/prefs_internals_source.cc", "webui/prefs_internals_source.h", - "webui/quota_internals/quota_internals_handler.cc", - "webui/quota_internals/quota_internals_handler.h", - "webui/quota_internals/quota_internals_proxy.cc", - "webui/quota_internals/quota_internals_proxy.h", - "webui/quota_internals/quota_internals_types.cc", - "webui/quota_internals/quota_internals_types.h", - "webui/quota_internals/quota_internals_ui.cc", - "webui/quota_internals/quota_internals_ui.h", "webui/segmentation_internals/segmentation_internals_page_handler_impl.cc", "webui/segmentation_internals/segmentation_internals_page_handler_impl.h", "webui/segmentation_internals/segmentation_internals_ui.cc", @@ -422,7 +414,6 @@ "//chrome/browser/resources/media:webrtc_logs_resources", "//chrome/browser/resources/net_internals:resources", "//chrome/browser/resources/omnibox:resources", - "//chrome/browser/resources/quota_internals:resources", "//chrome/browser/resources/usb_internals:resources", "//chrome/browser/safe_browsing", "//chrome/browser/ui/webui/bluetooth_internals",
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java index f62e567..adeda4e 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarLayout.java
@@ -840,6 +840,14 @@ } /** + * Returns whether there are any ongoing animations. + */ + @VisibleForTesting + public boolean isAnimationRunningForTesting() { + return false; + } + + /** * Sets the toolbar hairline color, if the toolbar has a hairline below it. * @param toolbarColor The toolbar color to base the hairline color on. */
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 782ec897..4b2c9e7 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -2869,4 +2869,11 @@ return getResources().getDimensionPixelSize(R.dimen.location_bar_lateral_padding) - getResources().getDimensionPixelSize(R.dimen.fake_search_box_lateral_padding); } + + @Override + @VisibleForTesting + public boolean isAnimationRunningForTesting() { + return mUrlFocusChangeInProgress || mBrandColorTransitionActive + || mOptionalButtonAnimationRunning; + } }
diff --git a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc index 83a72520..ab143db 100644 --- a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc +++ b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.cc
@@ -108,4 +108,5 @@ void FakeAccessibilityController::UpdateDictationBubble( bool visible, ash::DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) {} + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) {}
diff --git a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h index 29a53c62..b52ac46 100644 --- a/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h +++ b/chrome/browser/ui/ash/accessibility/fake_accessibility_controller.h
@@ -70,7 +70,8 @@ void UpdateDictationBubble( bool visible, ash::DictationBubbleIconType icon, - const absl::optional<std::u16string>& text) override; + const absl::optional<std::u16string>& text, + const absl::optional<std::vector<std::string>>& hints) override; private: bool was_client_set_ = false;
diff --git a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc index b8b5f15b..89e4074 100644 --- a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc +++ b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc
@@ -19,6 +19,7 @@ #include "components/services/app_service/public/mojom/types.mojom.h" #include "extensions/common/constants.h" #include "ui/aura/client/aura_constants.h" +#include "ui/views/widget/native_widget_aura.h" BrowserAppShelfItemController::BrowserAppShelfItemController( const ash::ShelfID& shelf_id, @@ -31,7 +32,9 @@ // Registers all running instances that started before this shelf item was // created, for example if a running app is later pinned to the shelf. registry_.NotifyExistingInstances(this); - LoadAppMenuIcon(); + LoadIcon(extension_misc::EXTENSION_ICON_BITTY, + base::BindOnce(&BrowserAppShelfItemController::OnLoadBittyIcon, + weak_ptr_factory_.GetWeakPtr())); } BrowserAppShelfItemController::~BrowserAppShelfItemController() = default; @@ -88,13 +91,13 @@ const apps::BrowserWindowInstance* instance = registry_.GetBrowserWindowInstanceById(id); DCHECK(instance); - items.push_back({command_id, instance->window->GetTitle(), menu_icon_}); + items.push_back({command_id, instance->window->GetTitle(), bitty_icon_}); } else { const apps::BrowserAppInstance* instance = registry_.GetAppInstanceById(id); DCHECK(instance); items.push_back( - {command_id, base::UTF8ToUTF16(instance->title), menu_icon_}); + {command_id, base::UTF8ToUTF16(instance->title), bitty_icon_}); } } return items; @@ -132,6 +135,12 @@ // Only handle Lacros browser windows. return; } + + if (!(bitty_icon_.isNull() || medium_icon_.isNull())) { + views::NativeWidgetAura::AssignIconToAuraWindow(instance.window, + bitty_icon_, medium_icon_); + } + int command = ++last_command_id_; command_to_instance_map_[command] = instance.id; } @@ -152,6 +161,12 @@ if (shelf_id().app_id != instance.app_id) { return; } + + if (!(bitty_icon_.isNull() || medium_icon_.isNull())) { + views::NativeWidgetAura::AssignIconToAuraWindow(instance.window, + bitty_icon_, medium_icon_); + } + int command = ++last_command_id_; command_to_instance_map_[command] = instance.id; } @@ -201,7 +216,8 @@ return it->first; } -void BrowserAppShelfItemController::LoadAppMenuIcon() { +void BrowserAppShelfItemController::LoadIcon(int32_t size_hint_in_dip, + apps::LoadIconCallback callback) { const std::string& app_id = shelf_id().app_id; auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); auto app_type = proxy->AppRegistryCache().GetAppType(app_id); @@ -210,25 +226,53 @@ apps::ConvertMojomAppTypToAppType(app_type), app_id, apps::IconType::kStandard, // matches favicon size - /* size_hint_in_dip= */ extension_misc::EXTENSION_ICON_BITTY, - /* allow_placeholder_icon= */ false, - base::BindOnce(&BrowserAppShelfItemController::OnLoadAppMenuIcon, - weak_ptr_factory_.GetWeakPtr())); + /* size_hint_in_dip= */ size_hint_in_dip, + /* allow_placeholder_icon= */ false, std::move(callback)); } else { icon_loader_releaser_ = proxy->LoadIcon( app_type, app_id, apps::mojom::IconType::kStandard, // matches favicon size - /* size_hint_in_dip= */ extension_misc::EXTENSION_ICON_BITTY, + /* size_hint_in_dip= */ size_hint_in_dip, /* allow_placeholder_icon= */ false, - apps::MojomIconValueToIconValueCallback( - base::BindOnce(&BrowserAppShelfItemController::OnLoadAppMenuIcon, - weak_ptr_factory_.GetWeakPtr()))); + apps::MojomIconValueToIconValueCallback(std::move(callback))); } } -void BrowserAppShelfItemController::OnLoadAppMenuIcon( +void BrowserAppShelfItemController::OnLoadMediumIcon( apps::IconValuePtr icon_value) { if (icon_value && icon_value->icon_type == apps::IconType::kStandard) { - menu_icon_ = icon_value->uncompressed; + medium_icon_ = icon_value->uncompressed; + + // At this point, we have loaded both icons needed to assign an icon to the + // Lacros and Ash windows, so we can assign the icons to the instances that + // have already been created. + std::string app_id = shelf_id().app_id; + if (app_id == extension_misc::kLacrosAppId) { + for (auto* instance : registry_.GetLacrosBrowserWindowInstances()) { + views::NativeWidgetAura::AssignIconToAuraWindow( + instance->window, bitty_icon_, medium_icon_); + } + } else { + for (auto* instance : registry_.SelectAppInstances( + [&app_id](const apps::BrowserAppInstance& instance) { + return instance.type == + apps::BrowserAppInstance::Type::kAppWindow && + app_id == instance.app_id; + })) { + views::NativeWidgetAura::AssignIconToAuraWindow( + instance->window, bitty_icon_, medium_icon_); + } + } + } +} + +void BrowserAppShelfItemController::OnLoadBittyIcon( + apps::IconValuePtr icon_value) { + if (icon_value && icon_value->icon_type == apps::IconType::kStandard) { + bitty_icon_ = icon_value->uncompressed; + BrowserAppShelfItemController::LoadIcon( + extension_misc::EXTENSION_ICON_MEDIUM, + base::BindOnce(&BrowserAppShelfItemController::OnLoadMediumIcon, + weak_ptr_factory_.GetWeakPtr())); } }
diff --git a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.h b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.h index 4574027..f27aa41 100644 --- a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.h +++ b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.h
@@ -71,8 +71,9 @@ // Gets the command ID for this item. The item must exist. int GetInstanceCommand(const base::UnguessableToken& id); - void LoadAppMenuIcon(); - void OnLoadAppMenuIcon(apps::IconValuePtr icon_value); + void LoadIcon(int32_t size_hint_in_dip, apps::LoadIconCallback callback); + void OnLoadMediumIcon(apps::IconValuePtr icon_value); + void OnLoadBittyIcon(apps::IconValuePtr icon_value); Profile* profile_; apps::BrowserAppInstanceRegistry& registry_; @@ -82,7 +83,8 @@ std::unique_ptr<ShelfContextMenu> context_menu_; std::unique_ptr<apps::IconLoader::Releaser> icon_loader_releaser_; - gfx::ImageSkia menu_icon_; + gfx::ImageSkia medium_icon_; + gfx::ImageSkia bitty_icon_; // Map of app menu item command IDs to instance IDs, used to maintain a stable // association of instances to command IDs and to order the items by launch
diff --git a/chrome/browser/ui/color/BUILD.gn b/chrome/browser/ui/color/BUILD.gn index 08e8c46..6e1aa7cd 100644 --- a/chrome/browser/ui/color/BUILD.gn +++ b/chrome/browser/ui/color/BUILD.gn
@@ -12,6 +12,8 @@ source_set("mixers") { sources = [ + "autofill_color_mixer.cc", + "autofill_color_mixer.h", "chrome_color_mixer.cc", "chrome_color_mixer.h", "chrome_color_mixers.cc", @@ -26,6 +28,7 @@ deps = [ ":color_headers", + "//build:branding_buildflags", "//ui/color:color", "//ui/color:mixers", ]
diff --git a/chrome/browser/ui/color/autofill_color_mixer.cc b/chrome/browser/ui/color/autofill_color_mixer.cc new file mode 100644 index 0000000..324427ce --- /dev/null +++ b/chrome/browser/ui/color/autofill_color_mixer.cc
@@ -0,0 +1,27 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/color/autofill_color_mixer.h" + +#include "build/branding_buildflags.h" +#include "chrome/browser/ui/color/chrome_color_id.h" +#include "ui/color/color_id.h" +#include "ui/color/color_mixer.h" +#include "ui/color/color_provider.h" +#include "ui/color/color_provider_manager.h" +#include "ui/color/color_recipe.h" +#include "ui/color/color_transform.h" +#include "ui/gfx/color_palette.h" + +void AddAutofillColorMixer(ui::ColorProvider* provider, + const ui::ColorProviderManager::Key& key) { +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + ui::ColorMixer& mixer = provider->AddMixer(); + + const bool dark_mode = + key.color_mode == ui::ColorProviderManager::ColorMode::kDark; + mixer[kColorGooglePayLogo] = {dark_mode ? SK_ColorWHITE + : gfx::kGoogleGrey700}; +#endif +}
diff --git a/chrome/browser/ui/color/autofill_color_mixer.h b/chrome/browser/ui/color/autofill_color_mixer.h new file mode 100644 index 0000000..8868d20e --- /dev/null +++ b/chrome/browser/ui/color/autofill_color_mixer.h
@@ -0,0 +1,19 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_COLOR_AUTOFILL_COLOR_MIXER_H_ +#define CHROME_BROWSER_UI_COLOR_AUTOFILL_COLOR_MIXER_H_ + +#include "ui/color/color_provider_manager.h" + +namespace ui { +class ColorProvider; +} + +// Adds a color mixer that contains recipes for autofill colors to |provider| +// with |key|. +void AddAutofillColorMixer(ui::ColorProvider* provider, + const ui::ColorProviderManager::Key& key); + +#endif // CHROME_BROWSER_UI_COLOR_AUTOFILL_COLOR_MIXER_H_
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h index 2212fd6..7bb3724d 100644 --- a/chrome/browser/ui/color/chrome_color_id.h +++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -20,6 +20,8 @@ ThemeProperties::COLOR_DOWNLOAD_SHELF_BUTTON_BACKGROUND) \ E(kColorDownloadShelfButtonText, \ ThemeProperties::COLOR_DOWNLOAD_SHELF_BUTTON_TEXT) \ + /* Google branding colors. */ \ + E_CPONLY(kColorGooglePayLogo) \ /* Omnibox output colors. */ \ E(kColorOmniboxBackground, ThemeProperties::COLOR_OMNIBOX_BACKGROUND) \ E(kColorOmniboxBackgroundHovered, \
diff --git a/chrome/browser/ui/color/chrome_color_mixers.cc b/chrome/browser/ui/color/chrome_color_mixers.cc index f3549552..b4140c7b 100644 --- a/chrome/browser/ui/color/chrome_color_mixers.cc +++ b/chrome/browser/ui/color/chrome_color_mixers.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/color/chrome_color_mixers.h" +#include "chrome/browser/ui/color/autofill_color_mixer.h" #include "chrome/browser/ui/color/chrome_color_mixer.h" #include "chrome/browser/ui/color/native_chrome_color_mixer.h" #include "chrome/browser/ui/color/omnibox_color_mixer.h" @@ -12,6 +13,8 @@ const ui::ColorProviderManager::Key& key) { AddChromeColorMixer(provider, key); AddNativeChromeColorMixer(provider, key); + + AddAutofillColorMixer(provider, key); AddOmniboxColorMixer(provider, key); if (key.custom_theme) {
diff --git a/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller_chromeos_browsertest.cc b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller_chromeos_browsertest.cc new file mode 100644 index 0000000..391a0f9c --- /dev/null +++ b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller_chromeos_browsertest.cc
@@ -0,0 +1,50 @@ +// 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/sharesheet/sharesheet_service.h" +#include "chrome/browser/sharesheet/sharesheet_service_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/page_action/page_action_icon_type.h" +#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class SharingHubBubbleControllerChromeOsBrowserTest + : public InProcessBrowserTest { + public: + SharingHubBubbleControllerChromeOsBrowserTest() = default; + ~SharingHubBubbleControllerChromeOsBrowserTest() override = default; +}; + +IN_PROC_BROWSER_TEST_F(SharingHubBubbleControllerChromeOsBrowserTest, + OpenSharesheet) { + sharesheet::SharesheetService* sharesheet_service = + sharesheet::SharesheetServiceFactory::GetForProfile(browser()->profile()); + gfx::NativeWindow web_contents_containing_window_ = + browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetTopLevelNativeWindow(); + + // Open the sharesheet using the sharing hub controller. + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + sharing_hub::SharingHubBubbleController::CreateOrGetFromWebContents( + web_contents) + ->ShowBubble(); + + // Wait until the sharesheet is fully opened. + base::RunLoop().RunUntilIdle(); + + // Verify that the sharesheet is open. + sharesheet::SharesheetController* controller = + sharesheet_service->GetSharesheetController( + web_contents_containing_window_); + ASSERT_TRUE(controller->IsBubbleVisible()); +} + +} // namespace
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc index d522f31..86a1783 100644 --- a/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_bubble_views.cc
@@ -14,6 +14,7 @@ #include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/autofill/payments/dialog_view_ids.h" #include "chrome/browser/ui/views/autofill/payments/payments_view_util.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -103,17 +104,18 @@ views::BoxLayout::Orientation::kVertical, gfx::Insets(), ChromeLayoutProvider::Get()->GetDistanceMetric( DISTANCE_RELATED_CONTROL_VERTICAL_SMALL))); - const SkColor color = GetColorProvider()->GetColor(ui::kColorIcon); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) // kGooglePayLogoIcon is square, and CreateTiledImage() will clip it whereas // setting the icon size would rescale it incorrectly. gfx::ImageSkia image = gfx::ImageSkiaOperations::CreateTiledImage( - gfx::CreateVectorIcon(kGooglePayLogoIcon, color), + gfx::CreateVectorIcon(kGooglePayLogoIcon, + GetColorProvider()->GetColor(kColorGooglePayLogo)), /*x=*/0, /*y=*/0, kMigrationBubbleGooglePayLogoWidth, kMigrationBubbleGooglePayLogoHeight); #else gfx::ImageSkia image = gfx::CreateVectorIcon( - kCreditCardIcon, kMigrationBubbleGooglePayLogoHeight, color); + kCreditCardIcon, kMigrationBubbleGooglePayLogoHeight, + GetColorProvider()->GetColor(ui::kColorIcon)); #endif views::ImageView* icon_view = new views::ImageView(); icon_view->SetImage(image);
diff --git a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc index 9f9a0004..053de998 100644 --- a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc +++ b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
@@ -8,6 +8,7 @@ #include "base/ranges/algorithm.h" #include "build/branding_buildflags.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_typography.h" #include "components/strings/grit/components_strings.h" @@ -61,7 +62,6 @@ ImageView::OnThemeChanged(); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) gfx::ImageSkia image; - const SkColor color = GetColorProvider()->GetColor(ui::kColorIcon); switch (icon_to_show_) { case TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY: // kGooglePayLogoIcon is square overall, despite the drawn portion being @@ -69,11 +69,15 @@ // it whereas setting the icon size would rescale it incorrectly and // keep the bottom empty portion. image = gfx::ImageSkiaOperations::CreateTiledImage( - gfx::CreateVectorIcon(kGooglePayLogoIcon, color), + gfx::CreateVectorIcon( + kGooglePayLogoIcon, + GetColorProvider()->GetColor(kColorGooglePayLogo)), /*x=*/0, /*y=*/0, kGooglePayLogoWidth, kIconHeight); break; case TitleWithIconAndSeparatorView::Icon::GOOGLE_G: - image = gfx::CreateVectorIcon(kGoogleGLogoIcon, kIconHeight, color); + image = + gfx::CreateVectorIcon(kGoogleGLogoIcon, kIconHeight, + GetColorProvider()->GetColor(ui::kColorIcon)); break; }
diff --git a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc index 94af522..0e0b5e18 100644 --- a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc +++ b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
@@ -77,8 +77,7 @@ const gfx::VectorIcon* new_icon; SkColor icon_color; if (icon_state_ == download::DownloadIconState::kProgress) { - icon_color = GetThemeProvider()->GetColor( - ThemeProperties::COLOR_TAB_THROBBER_SPINNING); + icon_color = GetColorProvider()->GetColor(ui::kColorThrobber); new_icon = &kDownloadInProgressIcon; } else { icon_color = GetThemeProvider()->GetColor(
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc index cebecb12..09d3283 100644 --- a/chrome/browser/ui/views/download/download_item_view.cc +++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -1062,8 +1062,7 @@ const gfx::RectF& bounds, const base::TimeDelta& indeterminate_progress_time, int percent_done) const { - const SkColor color = GetThemeProvider()->GetColor( - ThemeProperties::COLOR_TAB_THROBBER_SPINNING); + const SkColor color = GetColorProvider()->GetColor(ui::kColorThrobber); // Draw background. cc::PaintFlags bg_flags;
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_loading_indicator_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_loading_indicator_view.cc index 5e76f52..75c22b6 100644 --- a/chrome/browser/ui/views/page_action/page_action_icon_loading_indicator_view.cc +++ b/chrome/browser/ui/views/page_action/page_action_icon_loading_indicator_view.cc
@@ -49,8 +49,7 @@ if (!throbber_start_time_) return; - const SkColor color = GetThemeProvider()->GetColor( - ThemeProperties::COLOR_TAB_THROBBER_SPINNING); + const SkColor color = GetColorProvider()->GetColor(ui::kColorThrobber); constexpr int kThrobberStrokeWidth = 2; gfx::PaintThrobberSpinning(canvas, GetLocalBounds(), color, base::TimeTicks::Now() - *throbber_start_time_,
diff --git a/chrome/browser/ui/views/payments/payment_request_retry_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_retry_browsertest.cc index d2cc36e..5711aae 100644 --- a/chrome/browser/ui/views/payments/payment_request_retry_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_retry_browsertest.cc
@@ -96,4 +96,64 @@ EXPECT_EQ(nullptr, add_card_button); } +// The tests in this class correspond to the tests of the same name in +// PaymentRequestRetryTest, with basic-card disabled. +// Parameterized tests are not used because the test setup for both tests are +// too different. +class PaymentRequestRetryBasicCardDisabledTest + : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestRetryBasicCardDisabledTest() { + feature_list_.InitAndDisableFeature(::features::kPaymentRequestBasicCard); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(PaymentRequestRetryBasicCardDisabledTest, + DoNotAllowPaymentInstrumentChange) { + // Installs two apps so that the Payment Request UI will be shown. + std::string a_method_name; + InstallPaymentApp("a.com", "payment_request_success_responder.js", + &a_method_name); + std::string b_method_name; + InstallPaymentApp("b.com", "payment_request_success_responder.js", + &b_method_name); + + NavigateTo("/payment_request_retry_with_payer_errors.html"); + autofill::AutofillProfile contact = autofill::test::GetFullProfile(); + AddAutofillProfile(contact); + + // Confirm that there are two payment apps available. + InvokePaymentRequestUIWithJs( + content::JsReplace("buyWithMethods([{supportedMethods:$1}" + ", {supportedMethods:$2}]);", + a_method_name, b_method_name)); + PaymentRequest* request = GetPaymentRequests().front(); + EXPECT_EQ(2U, request->state()->available_apps().size()); + + // Click on pay. + EXPECT_TRUE(IsPayButtonEnabled()); + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN}); + ClickOnDialogViewAndWait(DialogViewID::PAY_BUTTON, dialog_view()); + + // Confirm that only one payment app is available for retry(). + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::SPEC_DONE_UPDATING, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::BACK_TO_PAYMENT_SHEET_NAVIGATION, + DialogEvent::CONTACT_INFO_EDITOR_OPENED}); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), + "retry({" + " payer: {" + " email: 'EMAIL ERROR'," + " name: 'NAME ERROR'," + " phone: 'PHONE ERROR'" + " }" + "});")); + WaitForObservedEvent(); + EXPECT_EQ(1U, request->state()->available_apps().size()); +} + } // namespace payments
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_views_browsertest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_views_browsertest.cc index 2cdf2080..866022f 100644 --- a/chrome/browser/ui/views/user_education/help_bubble_factory_views_browsertest.cc +++ b/chrome/browser/ui/views/user_education/help_bubble_factory_views_browsertest.cc
@@ -86,44 +86,6 @@ EXPECT_EQ(context(), help_bubble_->GetContext()); } -// Note: if this test is flaky, it may need to be moved to an interactive UI -// test instead; please contact dfried@. -// TODO(crbug/1290983): Disabled because of failures on Mac. -#if BUILDFLAG(IS_MAC) -#define MAYBE_ToggleFocusForAccessibility DISABLED_ToggleFocusForAccessibility -#else -#define MAYBE_ToggleFocusForAccessibility ToggleFocusForAccessibility -#endif -IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryViewsBrowsertest, - MAYBE_ToggleFocusForAccessibility) { - HelpBubbleParams params; - params.body_text = u"Hello world!"; - HelpBubbleButtonParams button_params; - button_params.text = u"Button"; - button_params.is_default = true; - params.buttons.emplace_back(std::move(button_params)); - help_bubble_ = - registry()->CreateHelpBubble(GetAnchorElement(), std::move(params)); - HelpBubbleView* const bubble_view = - help_bubble_->AsA<HelpBubbleViews>()->bubble_view(); - - // Toggle focus to the help widget and then wait for it to be focused. - { - WidgetFocusWaiter waiter(bubble_view->GetWidget()); - waiter.WaitAfter(base::BindLambdaForTesting( - [&]() { help_bubble_->ToggleFocusForAccessibility(); })); - EXPECT_TRUE(bubble_view->GetButtonForTesting(0)->HasFocus()); - } - - // Toggle focus to the anchor view and wait for it to become focused. - { - WidgetFocusWaiter waiter(GetAnchorElement()->view()->GetWidget()); - waiter.WaitAfter(base::BindLambdaForTesting( - [&]() { help_bubble_->ToggleFocusForAccessibility(); })); - EXPECT_TRUE(GetAnchorElement()->view()->HasFocus()); - } -} - // Note: if this test is flaky (especially the final EXPECT_TRUE) it may be // that the browser window completely fills the test display and expanding it // does not work. Please look at the error message reported and make
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc new file mode 100644 index 0000000..2467ccb --- /dev/null +++ b/chrome/browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc
@@ -0,0 +1,84 @@ +// 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 "base/callback_forward.h" +#include "build/build_config.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/user_education/help_bubble_factory_registry.h" +#include "chrome/browser/ui/user_education/help_bubble_params.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h" +#include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/browser/ui/views/user_education/help_bubble_factory_views.h" +#include "chrome/browser/ui/views/user_education/help_bubble_view.h" +#include "chrome/browser/ui/views/user_education/user_education_test_util.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "ui/base/interaction/element_identifier.h" +#include "ui/base/interaction/element_tracker.h" +#include "ui/views/interaction/element_tracker_views.h" +#include "ui/views/test/widget_test.h" + +class HelpBubbleFactoryViewsUiTest : public InProcessBrowserTest { + public: + protected: + ui::ElementContext context() { + return browser()->window()->GetElementContext(); + } + + HelpBubbleFactoryRegistry* registry() { + return BrowserView::GetBrowserViewForBrowser(browser()) + ->GetFeaturePromoController() + ->bubble_factory_registry(); + } + + views::TrackedElementViews* GetAnchorElement() { + return views::ElementTrackerViews::GetInstance()->GetElementForView( + BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar() + ->app_menu_button()); + } +}; + +// Moved to interactive uitests due to crbug.com/1290983 (widget activation is +// not reliable when running alongside other tests). +IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryViewsUiTest, + ToggleFocusForAccessibility) { + HelpBubbleParams params; + params.body_text = u"Hello world!"; + HelpBubbleButtonParams button_params; + button_params.text = u"Button"; + button_params.is_default = true; + params.buttons.emplace_back(std::move(button_params)); + + std::unique_ptr<HelpBubble> help_bubble = + registry()->CreateHelpBubble(GetAnchorElement(), std::move(params)); + HelpBubbleView* const bubble_view = + help_bubble->AsA<HelpBubbleViews>()->bubble_view(); + + // Toggle focus to the help widget and then wait for it to be focused. + { + WidgetFocusWaiter waiter(bubble_view->GetWidget()); + waiter.WaitAfter(base::BindLambdaForTesting( + [&]() { help_bubble->ToggleFocusForAccessibility(); })); + EXPECT_TRUE(bubble_view->GetButtonForTesting(0)->HasFocus()); + } + + // Toggle focus to the anchor view and wait for it to become focused. +#if BUILDFLAG(IS_MAC) + // Widget activation is a little wonky on Mac, so we'll just ensure that the + // anchor element is correctly focused. + help_bubble->ToggleFocusForAccessibility(); +#else + // On non-Mac platforms, we can safely wait for widget focus to return to the + // browser window. + { + WidgetFocusWaiter waiter(GetAnchorElement()->view()->GetWidget()); + waiter.WaitAfter(base::BindLambdaForTesting( + [&]() { help_bubble->ToggleFocusForAccessibility(); })); + } +#endif + EXPECT_TRUE(GetAnchorElement()->view()->HasFocus()); +}
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 01187d1e..425869ec9 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -257,7 +257,6 @@ "chrome://print", "chrome://process-internals", "chrome://quota-internals", - "chrome://quota-internals-2", "chrome://reset-password", "chrome://safe-browsing", "chrome://serviceworker-internals",
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 6d07380..7450826 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -54,7 +54,6 @@ #include "chrome/browser/ui/webui/omnibox/omnibox_ui.h" #include "chrome/browser/ui/webui/policy/policy_ui.h" #include "chrome/browser/ui/webui/predictors/predictors_ui.h" -#include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h" #include "chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.h" #include "chrome/browser/ui/webui/signin_internals_ui.h" #include "chrome/browser/ui/webui/sync_internals/sync_internals_ui.h" @@ -211,6 +210,7 @@ #include "chrome/browser/ash/web_applications/chrome_file_manager_ui_delegate.h" #include "chrome/browser/ash/web_applications/help_app/help_app_ui_delegate.h" #include "chrome/browser/ash/web_applications/media_app/chrome_media_app_ui_delegate.h" +#include "chrome/browser/ash/web_applications/personalization_app/personalization_app_ambient_provider_impl.h" #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h" #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_user_provider_impl.h" #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h" @@ -589,15 +589,17 @@ template <> WebUIController* NewWebUI<ash::PersonalizationAppUI>(WebUI* web_ui, const GURL& url) { + auto ambient_provider = + std::make_unique<PersonalizationAppAmbientProviderImpl>(web_ui); auto theme_provider = std::make_unique<PersonalizationAppThemeProviderImpl>(web_ui); auto user_provider = std::make_unique<PersonalizationAppUserProviderImpl>(web_ui); auto wallpaper_provider = std::make_unique<PersonalizationAppWallpaperProviderImpl>(web_ui); - return new ash::PersonalizationAppUI(web_ui, std::move(theme_provider), - std::move(user_provider), - std::move(wallpaper_provider)); + return new ash::PersonalizationAppUI( + web_ui, std::move(ambient_provider), std::move(theme_provider), + std::move(user_provider), std::move(wallpaper_provider)); } #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -707,8 +709,6 @@ return &NewWebUI<PasswordManagerInternalsUI>; if (url.host_piece() == chrome::kChromeUIPredictorsHost) return &NewWebUI<PredictorsUI>; - if (url.host_piece() == chrome::kChromeUIQuotaInternalsHost) - return &NewWebUI<QuotaInternalsUI>; if (url.host_piece() == safe_browsing::kChromeUISafeBrowsingHost) return &NewWebUI<safe_browsing::SafeBrowsingUI>; if (url.host_piece() == chrome::kChromeUISegmentationInternalsHost)
diff --git a/chrome/browser/ui/webui/quota_internals/DIR_METADATA b/chrome/browser/ui/webui/quota_internals/DIR_METADATA deleted file mode 100644 index 4bba49e..0000000 --- a/chrome/browser/ui/webui/quota_internals/DIR_METADATA +++ /dev/null
@@ -1,4 +0,0 @@ -monorail { - component: "Blink>Storage>Quota" -} -team_email: "storage-dev@chromium.org"
diff --git a/chrome/browser/ui/webui/quota_internals/OWNERS b/chrome/browser/ui/webui/quota_internals/OWNERS deleted file mode 100644 index a61a714..0000000 --- a/chrome/browser/ui/webui/quota_internals/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://storage/browser/quota/OWNERS
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc deleted file mode 100644 index d0322042..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc +++ /dev/null
@@ -1,124 +0,0 @@ -// Copyright (c) 2011 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/webui/quota_internals/quota_internals_handler.h" - -#include <string> - -#include "base/bind.h" -#include "base/feature_list.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h" -#include "chrome/browser/ui/webui/quota_internals/quota_internals_types.h" -#include "content/public/browser/storage_partition.h" -#include "content/public/browser/web_ui.h" -#include "content/public/common/content_features.h" - -using content::BrowserContext; - -namespace { - -bool IsStoragePressureEnabled() { -#if BUILDFLAG(IS_ANDROID) - return false; -#else - return true; -#endif -} - -} // namespace - -namespace quota_internals { - -QuotaInternalsHandler::QuotaInternalsHandler() {} - -QuotaInternalsHandler::~QuotaInternalsHandler() { - if (proxy_.get()) - proxy_->handler_ = nullptr; -} - -void QuotaInternalsHandler::RegisterMessages() { - web_ui()->RegisterDeprecatedMessageCallback( - "requestInfo", base::BindRepeating(&QuotaInternalsHandler::OnRequestInfo, - base::Unretained(this))); - web_ui()->RegisterDeprecatedMessageCallback( - "triggerStoragePressure", - base::BindRepeating(&QuotaInternalsHandler::OnTriggerStoragePressure, - base::Unretained(this))); -} - -void QuotaInternalsHandler::ReportAvailableSpace(int64_t available_space) { - FireWebUIListener("AvailableSpaceUpdated", - base::Value(static_cast<double>(available_space))); -} - -void QuotaInternalsHandler::ReportGlobalInfo(const GlobalStorageInfo& data) { - base::Value value(data.NewValue()); - FireWebUIListener("GlobalInfoUpdated", value); -} - -void QuotaInternalsHandler::ReportPerHostInfo( - const std::vector<PerHostStorageInfo>& hosts) { - base::ListValue values; - for (auto itr(hosts.begin()); itr != hosts.end(); ++itr) { - values.Append(itr->NewValue()); - } - - FireWebUIListener("PerHostInfoUpdated", values); -} - -void QuotaInternalsHandler::ReportPerOriginInfo( - const std::vector<PerOriginStorageInfo>& origins) { - base::ListValue origins_value; - for (auto itr(origins.begin()); itr != origins.end(); ++itr) { - origins_value.Append(itr->NewValue()); - } - - FireWebUIListener("PerOriginInfoUpdated", origins_value); -} - -void QuotaInternalsHandler::ReportStatistics(const Statistics& stats) { - base::DictionaryValue dict; - for (auto itr(stats.begin()); itr != stats.end(); ++itr) { - dict.SetStringKey(itr->first, itr->second); - } - - FireWebUIListener("StatisticsUpdated", dict); -} - -void QuotaInternalsHandler::ReportStoragePressureFlag() { - base::DictionaryValue flag_enabled; - flag_enabled.SetBoolean("isStoragePressureEnabled", - IsStoragePressureEnabled()); - FireWebUIListener("StoragePressureFlagUpdated", flag_enabled); -} - -void QuotaInternalsHandler::OnRequestInfo(const base::ListValue*) { - AllowJavascript(); - if (!proxy_.get()) - proxy_ = new QuotaInternalsProxy(this); - ReportStoragePressureFlag(); - proxy_->RequestInfo(Profile::FromWebUI(web_ui()) - ->GetDefaultStoragePartition() - ->GetQuotaManager()); -} - -void QuotaInternalsHandler::OnTriggerStoragePressure( - const base::ListValue* args) { - AllowJavascript(); - CHECK_EQ(1U, args->GetList().size()); - const std::string& origin_string = args->GetList()[0].GetString(); - GURL url(origin_string); - - if (!proxy_.get()) - proxy_ = new QuotaInternalsProxy(this); - proxy_->TriggerStoragePressure(url::Origin::Create(url), - Profile::FromWebUI(web_ui()) - ->GetDefaultStoragePartition() - ->GetQuotaManager()); -} - -} // namespace quota_internals
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h b/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h deleted file mode 100644 index 925d8075..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright (c) 2011 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_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_HANDLER_H_ -#define CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_HANDLER_H_ - -#include <stdint.h> - -#include <map> -#include <string> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "content/public/browser/web_ui_message_handler.h" - -namespace base { -class ListValue; -} - -namespace quota_internals { - -class QuotaInternalsProxy; -class GlobalStorageInfo; -class PerHostStorageInfo; -class PerOriginStorageInfo; -typedef std::map<std::string, std::string> Statistics; - -// This class handles message from WebUI page of chrome://quota-internals/. -// All methods in this class should be called on UI thread. -class QuotaInternalsHandler : public content::WebUIMessageHandler { - public: - QuotaInternalsHandler(); - - QuotaInternalsHandler(const QuotaInternalsHandler&) = delete; - QuotaInternalsHandler& operator=(const QuotaInternalsHandler&) = delete; - - ~QuotaInternalsHandler() override; - void RegisterMessages() override; - - // Called by QuotaInternalsProxy to report information to WebUI page. - void ReportAvailableSpace(int64_t available_space); - void ReportGlobalInfo(const GlobalStorageInfo& data); - void ReportPerHostInfo(const std::vector<PerHostStorageInfo>& hosts); - void ReportPerOriginInfo(const std::vector<PerOriginStorageInfo>& origins); - void ReportStatistics(const Statistics& stats); - void ReportStoragePressureFlag(); - - private: - void OnRequestInfo(const base::ListValue*); - void OnTriggerStoragePressure(const base::ListValue*); - - scoped_refptr<QuotaInternalsProxy> proxy_; -}; -} // namespace quota_internals - -#endif // CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc deleted file mode 100644 index 7125d3d..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc +++ /dev/null
@@ -1,247 +0,0 @@ -// Copyright (c) 2012 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/webui/quota_internals/quota_internals_proxy.h" - -#include <set> -#include <string> - -#include "base/bind.h" -#include "chrome/browser/ui/webui/quota_internals/quota_internals_handler.h" -#include "chrome/browser/ui/webui/quota_internals/quota_internals_types.h" -#include "content/public/browser/browser_task_traits.h" -#include "third_party/blink/public/common/storage_key/storage_key.h" -#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h" -#include "url/origin.h" - -using blink::mojom::StorageType; -using content::BrowserThread; - -namespace quota_internals { - -QuotaInternalsProxy::QuotaInternalsProxy(QuotaInternalsHandler* handler) - : handler_(handler) {} - -void QuotaInternalsProxy::RequestInfo( - scoped_refptr<storage::QuotaManager> quota_manager) { - DCHECK(quota_manager.get()); - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&QuotaInternalsProxy::RequestInfo, this, quota_manager)); - return; - } - quota_manager_ = quota_manager; - - quota_manager_->GetQuotaSettings(base::BindOnce( - &QuotaInternalsProxy::DidGetSettings, weak_factory_.GetWeakPtr())); - - quota_manager_->GetStorageCapacity(base::BindOnce( - &QuotaInternalsProxy::DidGetCapacity, weak_factory_.GetWeakPtr())); - - quota_manager_->GetGlobalUsage( - StorageType::kTemporary, - base::BindOnce(&QuotaInternalsProxy::DidGetGlobalUsage, - weak_factory_.GetWeakPtr(), StorageType::kTemporary)); - - quota_manager_->GetGlobalUsage( - StorageType::kPersistent, - base::BindOnce(&QuotaInternalsProxy::DidGetGlobalUsage, - weak_factory_.GetWeakPtr(), StorageType::kPersistent)); - - quota_manager_->GetGlobalUsage( - StorageType::kSyncable, - base::BindOnce(&QuotaInternalsProxy::DidGetGlobalUsage, - weak_factory_.GetWeakPtr(), StorageType::kSyncable)); - - quota_manager_->GetStorageKeysForType( - StorageType::kTemporary, - base::BindOnce(&QuotaInternalsProxy::DidGetStorageKeys, - weak_factory_.GetWeakPtr(), StorageType::kTemporary)); - - quota_manager_->GetStorageKeysForType( - StorageType::kPersistent, - base::BindOnce(&QuotaInternalsProxy::DidGetStorageKeys, - weak_factory_.GetWeakPtr(), StorageType::kPersistent)); - - quota_manager_->GetStorageKeysForType( - StorageType::kSyncable, - base::BindOnce(&QuotaInternalsProxy::DidGetStorageKeys, - weak_factory_.GetWeakPtr(), StorageType::kSyncable)); - - quota_manager_->DumpQuotaTable(base::BindOnce( - &QuotaInternalsProxy::DidDumpQuotaTable, weak_factory_.GetWeakPtr())); - - quota_manager_->DumpBucketTable(base::BindOnce( - &QuotaInternalsProxy::DidDumpBucketTable, weak_factory_.GetWeakPtr())); - - quota_manager_->GetStatistics(base::BindOnce( - &QuotaInternalsProxy::DidGetStatistics, weak_factory_.GetWeakPtr())); -} - -void QuotaInternalsProxy::TriggerStoragePressure( - url::Origin origin, - scoped_refptr<storage::QuotaManager> quota_manager) { - DCHECK(quota_manager.get()); - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - content::GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, base::BindOnce(&QuotaInternalsProxy::TriggerStoragePressure, - this, origin, quota_manager)); - return; - } - quota_manager->SimulateStoragePressure(blink::StorageKey(origin)); -} - -QuotaInternalsProxy::~QuotaInternalsProxy() = default; - -#define RELAY_TO_HANDLER(func, arg_t) \ - void QuotaInternalsProxy::func(arg_t arg) { \ - if (!handler_) \ - return; \ - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { \ - content::GetUIThreadTaskRunner({})->PostTask( \ - FROM_HERE, base::BindOnce(&QuotaInternalsProxy::func, this, arg)); \ - return; \ - } \ - \ - handler_->func(arg); \ - } - -RELAY_TO_HANDLER(ReportAvailableSpace, int64_t) -RELAY_TO_HANDLER(ReportGlobalInfo, const GlobalStorageInfo&) -RELAY_TO_HANDLER(ReportPerHostInfo, const std::vector<PerHostStorageInfo>&) -RELAY_TO_HANDLER(ReportPerOriginInfo, const std::vector<PerOriginStorageInfo>&) -RELAY_TO_HANDLER(ReportStatistics, const Statistics&) - -#undef RELAY_TO_HANDLER - -void QuotaInternalsProxy::DidGetSettings( - const storage::QuotaSettings& settings) { - // TODO(michaeln): also report the other config fields - GlobalStorageInfo info(StorageType::kTemporary); - info.set_quota(settings.pool_size); - ReportGlobalInfo(info); -} - -void QuotaInternalsProxy::DidGetCapacity(int64_t total_space, - int64_t available_space) { - // TODO(michaeln): also report total_space - ReportAvailableSpace(available_space); -} - -void QuotaInternalsProxy::DidGetGlobalUsage(StorageType type, - int64_t usage, - int64_t unlimited_usage) { - GlobalStorageInfo info(type); - info.set_usage(usage); - info.set_unlimited_usage(unlimited_usage); - - ReportGlobalInfo(info); -} - -void QuotaInternalsProxy::DidGetStorageKeys( - StorageType type, - const std::set<blink::StorageKey>& storage_keys) { - std::vector<PerOriginStorageInfo> origin_infos; - origin_infos.reserve(storage_keys.size()); - - std::set<std::string> hosts; - std::vector<PerHostStorageInfo> host_infos; - - for (const blink::StorageKey& storage_key : storage_keys) { - PerOriginStorageInfo per_origin_info(storage_key.origin().GetURL(), type); - origin_infos.push_back(per_origin_info); - - const std::string& host = storage_key.origin().host(); - if (hosts.insert(host).second) { - PerHostStorageInfo per_host_info(host, type); - host_infos.push_back(per_host_info); - VisitHost(host, type); - } - } - ReportPerOriginInfo(origin_infos); - ReportPerHostInfo(host_infos); -} - -void QuotaInternalsProxy::DidDumpQuotaTable(const QuotaTableEntries& entries) { - std::vector<PerHostStorageInfo> host_info; - host_info.reserve(entries.size()); - - for (const auto& entry : entries) { - PerHostStorageInfo info(entry.host, entry.type); - info.set_quota(entry.quota); - host_info.push_back(info); - } - - ReportPerHostInfo(host_info); -} - -void QuotaInternalsProxy::DidDumpBucketTable( - const BucketTableEntries& entries) { - std::vector<PerOriginStorageInfo> origin_info; - origin_info.reserve(entries.size()); - - for (const auto& entry : entries) { - PerOriginStorageInfo info(entry.storage_key.origin().GetURL(), entry.type); - info.set_used_count(entry.use_count); - info.set_last_access_time(entry.last_accessed); - info.set_last_modified_time(entry.last_modified); - - origin_info.push_back(info); - } - - ReportPerOriginInfo(origin_info); -} - -void QuotaInternalsProxy::DidGetHostUsage( - const std::string& host, - StorageType type, - int64_t usage, - blink::mojom::UsageBreakdownPtr usage_breakdown) { - DCHECK(type == StorageType::kTemporary || type == StorageType::kPersistent || - type == StorageType::kSyncable); - - PerHostStorageInfo info(host, type); - info.set_usage(usage); - - report_pending_.push_back(info); - hosts_pending_.erase(make_pair(host, type)); - if (report_pending_.size() >= 10 || hosts_pending_.empty()) { - ReportPerHostInfo(report_pending_); - report_pending_.clear(); - } - - if (!hosts_pending_.empty()) - GetHostUsage(hosts_pending_.begin()->first, - hosts_pending_.begin()->second); -} - -void QuotaInternalsProxy::DidGetStatistics( - const base::flat_map<std::string, std::string>& stats) { - std::map<std::string, std::string> stats_map; - for (const auto& stat : stats) { - stats_map[stat.first] = stat.second; - } - ReportStatistics(stats_map); -} - -void QuotaInternalsProxy::VisitHost(const std::string& host, StorageType type) { - if (hosts_visited_.insert(std::make_pair(host, type)).second) { - hosts_pending_.insert(std::make_pair(host, type)); - if (hosts_pending_.size() == 1) { - GetHostUsage(host, type); - } - } -} - -void QuotaInternalsProxy::GetHostUsage(const std::string& host, - StorageType type) { - DCHECK(quota_manager_.get()); - quota_manager_->GetHostUsageWithBreakdown( - host, type, - base::BindOnce(&QuotaInternalsProxy::DidGetHostUsage, - weak_factory_.GetWeakPtr(), host, type)); -} - -} // namespace quota_internals
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h deleted file mode 100644 index 81cf880..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright (c) 2012 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_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_PROXY_H_ -#define CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_PROXY_H_ - -#include <stdint.h> - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "base/memory/raw_ptr.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/task/sequenced_task_runner_helpers.h" -#include "content/public/browser/browser_thread.h" -#include "storage/browser/quota/quota_manager.h" -#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h" - -namespace quota_internals { - -class QuotaInternalsHandler; -class GlobalStorageInfo; -class PerHostStorageInfo; -class PerOriginStorageInfo; -typedef std::map<std::string, std::string> Statistics; - -// This class is the bridge between QuotaInternalsHandler and QuotaManager. -// Each QuotaInternalsHandler instances creates and owns a instance of this -// class. -class QuotaInternalsProxy - : public base::RefCountedThreadSafe< - QuotaInternalsProxy, - content::BrowserThread::DeleteOnIOThread> { - public: - explicit QuotaInternalsProxy(QuotaInternalsHandler* handler); - - QuotaInternalsProxy(const QuotaInternalsProxy&) = delete; - QuotaInternalsProxy& operator=(const QuotaInternalsProxy&) = delete; - - void RequestInfo(scoped_refptr<storage::QuotaManager> quota_manager); - void TriggerStoragePressure( - url::Origin origin, - scoped_refptr<storage::QuotaManager> quota_manager); - - private: - friend class base::DeleteHelper<QuotaInternalsProxy>; - friend struct content::BrowserThread::DeleteOnThread< - content::BrowserThread::IO>; - friend class QuotaInternalsHandler; - - using QuotaTableEntries = storage::QuotaManager::QuotaTableEntries; - using BucketTableEntries = storage::QuotaManager::BucketTableEntries; - - virtual ~QuotaInternalsProxy(); - - void ReportAvailableSpace(int64_t available_space); - void ReportGlobalInfo(const GlobalStorageInfo& data); - void ReportPerHostInfo(const std::vector<PerHostStorageInfo>& hosts); - void ReportPerOriginInfo(const std::vector<PerOriginStorageInfo>& origins); - void ReportStatistics(const Statistics& stats); - - // Called on IO Thread by QuotaManager as callback. - void DidGetSettings(const storage::QuotaSettings& settings); - void DidGetCapacity(int64_t total_space, int64_t available_space); - void DidGetGlobalUsage(blink::mojom::StorageType type, - int64_t usage, - int64_t unlimited_usage); - void DidGetStorageKeys(blink::mojom::StorageType type, - const std::set<blink::StorageKey>& storage_keys); - void DidDumpQuotaTable(const QuotaTableEntries& entries); - void DidDumpBucketTable(const BucketTableEntries& entries); - void DidGetHostUsage(const std::string& host, - blink::mojom::StorageType type, - int64_t usage, - blink::mojom::UsageBreakdownPtr usage_breakdown); - void DidGetStatistics( - const base::flat_map<std::string, std::string>& statistics); - - // Helper. Called on IO Thread. - void VisitHost(const std::string& host, blink::mojom::StorageType type); - void GetHostUsage(const std::string& host, blink::mojom::StorageType type); - - // Used on UI Thread. - raw_ptr<QuotaInternalsHandler> handler_; - - // Used on IO Thread. - scoped_refptr<storage::QuotaManager> quota_manager_; - std::set<std::pair<std::string, blink::mojom::StorageType>> hosts_visited_, - hosts_pending_; - std::vector<PerHostStorageInfo> report_pending_; - base::WeakPtrFactory<QuotaInternalsProxy> weak_factory_{this}; -}; -} // namespace quota_internals - -#endif // CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_PROXY_H_
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_types.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_types.cc deleted file mode 100644 index 958719d4..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_types.cc +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright (c) 2011 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/webui/quota_internals/quota_internals_types.h" - -#include <utility> - -#include "base/check.h" -#include "base/values.h" -#include "net/base/url_util.h" - -namespace { - -std::string StorageTypeToString(blink::mojom::StorageType type) { - switch (type) { - case blink::mojom::StorageType::kTemporary: - return "temporary"; - case blink::mojom::StorageType::kPersistent: - return "persistent"; - case blink::mojom::StorageType::kSyncable: - return "syncable"; - case blink::mojom::StorageType::kQuotaNotManaged: - return "quota not managed"; - case blink::mojom::StorageType::kUnknown: - return "unknown"; - } - return "unknown"; -} - -} // anonymous namespace - -namespace quota_internals { - -GlobalStorageInfo::GlobalStorageInfo(blink::mojom::StorageType type) - : type_(type), usage_(-1), unlimited_usage_(-1), quota_(-1) {} - -GlobalStorageInfo::~GlobalStorageInfo() {} - -base::Value GlobalStorageInfo::NewValue() const { - // TODO(tzik): Add CreateLongIntegerValue to base/values.h and remove - // all static_cast<double> in this file. - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("type", StorageTypeToString(type_)); - if (usage_ >= 0) - dict.SetDoubleKey("usage", static_cast<double>(usage_)); - if (unlimited_usage_ >= 0) - dict.SetDoubleKey("unlimitedUsage", static_cast<double>(unlimited_usage_)); - if (quota_ >= 0) - dict.SetDoubleKey("quota", static_cast<double>(quota_)); - return dict; -} - -PerHostStorageInfo::PerHostStorageInfo(const std::string& host, - blink::mojom::StorageType type) - : host_(host), type_(type), usage_(-1), quota_(-1) {} - -PerHostStorageInfo::~PerHostStorageInfo() {} - -base::Value PerHostStorageInfo::NewValue() const { - base::Value dict(base::Value::Type::DICTIONARY); - DCHECK(!host_.empty()); - dict.SetStringKey("host", host_); - dict.SetStringKey("type", StorageTypeToString(type_)); - if (usage_ >= 0) - dict.SetDoubleKey("usage", static_cast<double>(usage_)); - if (quota_ >= 0) - dict.SetDoubleKey("quota", static_cast<double>(quota_)); - return dict; -} - -PerOriginStorageInfo::PerOriginStorageInfo(const GURL& origin, - blink::mojom::StorageType type) - : origin_(origin), - type_(type), - host_(origin.host()), - used_count_(-1) {} - -PerOriginStorageInfo::PerOriginStorageInfo(const PerOriginStorageInfo& other) = - default; - -PerOriginStorageInfo::~PerOriginStorageInfo() {} - -base::Value PerOriginStorageInfo::NewValue() const { - base::Value dict(base::Value::Type::DICTIONARY); - DCHECK(!origin_.is_empty()); - DCHECK(!host_.empty()); - dict.SetStringKey("origin", origin_.spec()); - dict.SetStringKey("type", StorageTypeToString(type_)); - dict.SetStringKey("host", host_); - if (used_count_ >= 0) - dict.SetIntKey("usedCount", used_count_); - if (!last_access_time_.is_null()) - dict.SetDoubleKey("lastAccessTime", last_access_time_.ToDoubleT() * 1000.0); - if (!last_modified_time_.is_null()) { - dict.SetDoubleKey("lastModifiedTime", - last_modified_time_.ToDoubleT() * 1000.0); - } - return dict; -} - -} // namespace quota_internals
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_types.h b/chrome/browser/ui/webui/quota_internals/quota_internals_types.h deleted file mode 100644 index 873bc86..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_types.h +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright (c) 2011 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_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_TYPES_H_ -#define CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_TYPES_H_ - -#include <stdint.h> - -#include <map> -#include <memory> -#include <string> - -#include "base/time/time.h" -#include "third_party/blink/public/mojom/quota/quota_types.mojom.h" -#include "url/gurl.h" - -namespace base { -class Value; -} - -namespace quota_internals { - -// Represents global usage and quota information for specific type of storage. -class GlobalStorageInfo { - public: - explicit GlobalStorageInfo(blink::mojom::StorageType type); - ~GlobalStorageInfo(); - - void set_usage(int64_t usage) { usage_ = usage; } - - void set_unlimited_usage(int64_t unlimited_usage) { - unlimited_usage_ = unlimited_usage; - } - - void set_quota(int64_t quota) { quota_ = quota; } - - // Create new Value for passing to WebUI page. - base::Value NewValue() const; - - private: - blink::mojom::StorageType type_; - - int64_t usage_; - int64_t unlimited_usage_; - int64_t quota_; -}; - -// Represents per host usage and quota information for the storage. -class PerHostStorageInfo { - public: - PerHostStorageInfo(const std::string& host, blink::mojom::StorageType type); - ~PerHostStorageInfo(); - - void set_usage(int64_t usage) { usage_ = usage; } - - void set_quota(int64_t quota) { quota_ = quota; } - - // Create new Value for passing to WebUI page. - base::Value NewValue() const; - - private: - std::string host_; - blink::mojom::StorageType type_; - - int64_t usage_; - int64_t quota_; -}; - -// Represents per origin usage and access time information. -class PerOriginStorageInfo { - public: - PerOriginStorageInfo(const GURL& origin, blink::mojom::StorageType type); - PerOriginStorageInfo(const PerOriginStorageInfo& other); - ~PerOriginStorageInfo(); - - void set_used_count(int used_count) { - used_count_ = used_count; - } - - void set_last_access_time(base::Time last_access_time) { - last_access_time_ = last_access_time; - } - - void set_last_modified_time(base::Time last_modified_time) { - last_modified_time_ = last_modified_time; - } - - // Create new Value for passing to WebUI page. - base::Value NewValue() const; - - private: - GURL origin_; - blink::mojom::StorageType type_; - std::string host_; - - int used_count_; - base::Time last_access_time_; - base::Time last_modified_time_; -}; -} // namespace quota_internals - -#endif // CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_TYPES_H_
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_ui.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_ui.cc deleted file mode 100644 index 15f04e9..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_ui.cc +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright (c) 2012 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/webui/quota_internals/quota_internals_ui.h" - -#include <memory> -#include <string> - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/quota_internals/quota_internals_handler.h" -#include "chrome/browser/ui/webui/webui_util.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/quota_internals_resources.h" -#include "chrome/grit/quota_internals_resources_map.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_data_source.h" -#include "services/network/public/mojom/content_security_policy.mojom.h" - -using content::WebContents; - -namespace { - -content::WebUIDataSource* CreateQuotaInternalsHTMLSource() { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIQuotaInternalsHost); - source->UseStringsJs(); - source->AddResourcePaths( - base::make_span(kQuotaInternalsResources, kQuotaInternalsResourcesSize)); - source->AddResourcePath("", IDR_QUOTA_INTERNALS_MAIN_HTML); - source->OverrideContentSecurityPolicy( - network::mojom::CSPDirectiveName::TrustedTypes, - "trusted-types static-types;"); - return source; -} - -} // namespace - -QuotaInternalsUI::QuotaInternalsUI(content::WebUI* web_ui) - : WebUIController(web_ui) { - web_ui->AddMessageHandler( - std::make_unique<quota_internals::QuotaInternalsHandler>()); - Profile* profile = Profile::FromWebUI(web_ui); - content::WebUIDataSource::Add(profile, CreateQuotaInternalsHTMLSource()); -}
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_ui.h b/chrome/browser/ui/webui/quota_internals/quota_internals_ui.h deleted file mode 100644 index 989e0f7..0000000 --- a/chrome/browser/ui/webui/quota_internals/quota_internals_ui.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright (c) 2011 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_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_UI_H_ - -#include "content/public/browser/web_ui_controller.h" - -class QuotaInternalsUI : public content::WebUIController { - public: - explicit QuotaInternalsUI(content::WebUI* web_ui); - - QuotaInternalsUI(const QuotaInternalsUI&) = delete; - QuotaInternalsUI& operator=(const QuotaInternalsUI&) = delete; - - ~QuotaInternalsUI() override {} -}; - -#endif // CHROME_BROWSER_UI_WEBUI_QUOTA_INTERNALS_QUOTA_INTERNALS_UI_H_
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc index 4d02856..8b07d26 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc +++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
@@ -121,6 +121,17 @@ return dict; } +::account_manager::Account ValueToGaiaAccount(const base::Value& value) { + DCHECK(value.is_dict()); + const std::string* id = value.FindStringKey(kAccountKeyId); + DCHECK(id); + const std::string* email = value.FindStringKey(kAccountKeyEmail); + DCHECK(email); + return ::account_manager::Account{ + ::account_manager::AccountKey{*id, account_manager::AccountType::kGaia}, + *email}; +} + class EduCoexistenceChildSigninHelper : public SigninHelper { public: EduCoexistenceChildSigninHelper( @@ -233,6 +244,11 @@ base::BindRepeating( &InlineLoginHandlerChromeOS::GetAccountsNotAvailableInArc, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "makeAvailableInArc", + base::BindRepeating( + &InlineLoginHandlerChromeOS::MakeAvailableInArcAndCloseDialog, + base::Unretained(this))); web_ui()->RegisterDeprecatedMessageCallback( "skipWelcomePage", base::BindRepeating(&InlineLoginHandlerChromeOS::HandleSkipWelcomePage, @@ -424,6 +440,18 @@ ResolveJavascriptCallback(base::Value(callback_id), std::move(result)); } +void InlineLoginHandlerChromeOS::MakeAvailableInArcAndCloseDialog( + base::Value::ConstListView args) { + CHECK_EQ(1u, args.size()); + const base::Value& dictionary = args[0]; + CHECK(dictionary.is_dict()); + ash::AccountAppsAvailabilityFactory::GetForProfile( + Profile::FromWebUI(web_ui())) + ->SetIsAccountAvailableInArc(ValueToGaiaAccount(dictionary), + /*is_available=*/true); + close_dialog_closure_.Run(); +} + void InlineLoginHandlerChromeOS::HandleSkipWelcomePage( const base::ListValue* args) { const auto& list = args->GetList();
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h index 8a7794659..6f16f43 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h +++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h
@@ -58,6 +58,7 @@ const std::string& callback_id, const std::vector<::account_manager::Account>& accounts, const base::flat_set<account_manager::Account>& arc_accounts); + void MakeAvailableInArcAndCloseDialog(base::Value::ConstListView args); void HandleSkipWelcomePage(const base::ListValue* args); base::RepeatingClosure close_dialog_closure_;
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos_browsertest.cc b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos_browsertest.cc index 47467e4a..c686cca 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos_browsertest.cc +++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos_browsertest.cc
@@ -63,6 +63,7 @@ constexpr char kSecondaryAccountOAuthCode[] = "fake_oauth_code"; constexpr char kSecondaryAccountRefreshToken[] = "fake_refresh_token"; constexpr char kCompleteLoginMessage[] = "completeLogin"; +constexpr char kMakeAvailableInArcMessage[] = "makeAvailableInArc"; constexpr char kGetAccountsNotAvailableInArcMessage[] = "getAccountsNotAvailableInArc"; constexpr char kHandleFunctionName[] = "handleFunctionName"; @@ -413,13 +414,37 @@ bool ValuesListContainAccount(const base::span<const base::Value> values, const std::string& email) { + return ValuesListGetAccount(values, email).has_value(); + } + + absl::optional<base::Value> ValuesListGetAccount( + const base::span<const base::Value> values, + const std::string& email) { for (const base::Value& value : values) { const std::string* email_val = value.FindStringKey("email"); EXPECT_TRUE(email_val != nullptr); if (*email_val == email) - return true; + return value.Clone(); } - return false; + return absl::nullopt; + } + + const base::span<const base::Value> CallGetAccountsNotAvailableInArc() { + // Call "getAccountsNotAvailableInArc". + base::Value args(base::Value::Type::LIST); + args.Append(kHandleFunctionName); + web_ui()->HandleReceivedMessage(kGetAccountsNotAvailableInArcMessage, + &base::Value::AsListValue(args)); + base::RunLoop().RunUntilIdle(); + + const content::TestWebUI::CallData& call_data = + *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIResponse", call_data.function_name()); + EXPECT_EQ(kHandleFunctionName, call_data.arg1()->GetString()); + EXPECT_TRUE(call_data.arg2()->GetBool()); + + // Get results from JS callback. + return call_data.arg3()->GetList(); } private: @@ -506,19 +531,8 @@ AddAccount(kSecondaryAccount3Email, /*is_available_in_arc=*/false); // Call "getAccountsNotAvailableInArc". - base::Value args(base::Value::Type::LIST); - args.Append(kHandleFunctionName); - web_ui()->HandleReceivedMessage(kGetAccountsNotAvailableInArcMessage, - &base::Value::AsListValue(args)); - base::RunLoop().RunUntilIdle(); - - const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back(); - EXPECT_EQ("cr.webUIResponse", call_data.function_name()); - EXPECT_EQ(kHandleFunctionName, call_data.arg1()->GetString()); - ASSERT_TRUE(call_data.arg2()->GetBool()); - - // Get results from JS callback. - const base::span<const base::Value> result = call_data.arg3()->GetList(); + const base::span<const base::Value> result = + CallGetAccountsNotAvailableInArc(); // Two accounts are not available in ARC. EXPECT_EQ(2, result.size()); EXPECT_FALSE(ValuesListContainAccount(result, kSecondaryAccount1Email)); @@ -526,6 +540,32 @@ EXPECT_TRUE(ValuesListContainAccount(result, kSecondaryAccount3Email)); } +IN_PROC_BROWSER_TEST_P(InlineLoginHandlerChromeOSTestWithArcRestrictions, + MakeAvailableInArc) { + AddAccount(kSecondaryAccount1Email, /*is_available_in_arc=*/true); + AddAccount(kSecondaryAccount2Email, /*is_available_in_arc=*/false); + + // Call "getAccountsNotAvailableInArc". + const base::span<const base::Value> result = + CallGetAccountsNotAvailableInArc(); + // One account is not available in ARC. + EXPECT_EQ(1, result.size()); + EXPECT_FALSE(ValuesListContainAccount(result, kSecondaryAccount1Email)); + EXPECT_TRUE(ValuesListContainAccount(result, kSecondaryAccount2Email)); + + // Call "makeAvailableInArc". + base::Value args_1(base::Value::Type::LIST); + args_1.Append(ValuesListGetAccount(result, kSecondaryAccount2Email).value()); + web_ui()->HandleReceivedMessage(kMakeAvailableInArcMessage, + &base::Value::AsListValue(args_1)); + + // Call "getAccountsNotAvailableInArc". + const base::span<const base::Value> result_1 = + CallGetAccountsNotAvailableInArc(); + // Zero accounts are not available in ARC. + EXPECT_EQ(0, result_1.size()); +} + INSTANTIATE_TEST_SUITE_P(InlineLoginHandlerChromeOSTestWithArcRestrictionsSuite, InlineLoginHandlerChromeOSTestWithArcRestrictions, ::testing::Values(GetGaiaDeviceAccountInfo(),
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc index f8f6a349..a672e327 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc
@@ -598,11 +598,11 @@ /* 16% opacity */ 0.16 * 255)); std::string throbber_color = color_utils::SkColorToRgbaString( - embedder_->GetColor(ThemeProperties::COLOR_TAB_THROBBER_SPINNING)); + embedder_->GetColorProviderColor(ui::kColorThrobber)); colors["--tabstrip-tab-loading-spinning-color"] = throbber_color; colors["--tabstrip-tab-waiting-spinning-color"] = color_utils::SkColorToRgbaString( - embedder_->GetColor(ThemeProperties::COLOR_TAB_THROBBER_WAITING)); + embedder_->GetColorProviderColor(ui::kColorThrobberPreconnect)); colors["--tabstrip-indicator-recording-color"] = color_utils::SkColorToRgbaString( embedder_->GetColorProviderColor(ui::kColorAlertHighSeverity));
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index e8ce158..44e469c19 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1643284754-95e64ca29eb53e4d882fc2eecd37abeaef1d7e33.profdata +chrome-mac-arm-main-1643306390-7032204a04a8b859e8609b7773ac3e7e043aeac7.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index f4a4bee..4951b7b 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1643284754-e6072bf75b1d01e02013b9c0a038e83f0e166a59.profdata +chrome-mac-main-1643306390-b51115e6a28640651dc4c4d7bafac76a4a6bac80.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 134a42b..7afc549 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1643295498-1e46a15413da3e019634ff4ee57ba12b04a94734.profdata +chrome-win32-main-1643306390-4fff76475fcca879feb7aeb7adcea44a12b5a086.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index a672d13..d38597b 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1643295498-2123a7627edf68fdccd462dd15b336c8ca0c40fd.profdata +chrome-win64-main-1643306390-cae13a233894eb61c2f7c603004b4a48a0699857.profdata
diff --git a/chrome/common/extensions/api/accessibility_private.json b/chrome/common/extensions/api/accessibility_private.json index be0dfbe..41bf82a3 100644 --- a/chrome/common/extensions/api/accessibility_private.json +++ b/chrome/common/extensions/api/accessibility_private.json
@@ -271,6 +271,12 @@ "type": "string", "description": "The text to be displayed in the bubble UI. If `text` is undefined, the bubble will clear its current text.", "optional": true + }, + "hints": { + "type": "array", + "items": { "type": "string" }, + "description": "Array of hints to show in the UI.", + "optional": true } } }
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 926ea21..92e80ad 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -157,9 +157,7 @@ "chrome://privacy-sandbox-dialog"; const char kChromeUIQuitHost[] = "quit"; const char kChromeUIQuitURL[] = "chrome://quit/"; -// TODO(crbug.com/1202165): Remove when new quota-internals page is done. const char kChromeUIQuotaInternalsHost[] = "quota-internals"; -const char kChromeUIQuotaInternals2Host[] = "quota-internals-2"; const char kChromeUIResetPasswordHost[] = "reset-password"; const char kChromeUIResetPasswordURL[] = "chrome://reset-password/"; const char kChromeUIRestartHost[] = "restart"; @@ -607,9 +605,7 @@ kChromeUIPolicyHost, kChromeUIPredictorsHost, kChromeUIPrefsInternalsHost, - // TODO(crbug.com/1202165): Remove when new quota-internals page is done. kChromeUIQuotaInternalsHost, - kChromeUIQuotaInternals2Host, kChromeUISignInInternalsHost, kChromeUISiteEngagementHost, kChromeUINTPTilesInternalsHost,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 7e6a109..e928ce3 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -156,9 +156,6 @@ extern const char kChromeUIPrivacySandboxDialogURL[]; extern const char kChromeUIQuitHost[]; extern const char kChromeUIQuitURL[]; -// TODO(crbug.com/1202165): Remove when new quota-internals page is done. -extern const char kChromeUIQuotaInternalsHost[]; -extern const char kChromeUIQuotaInternals2Host[]; extern const char kChromeUIResetPasswordHost[]; extern const char kChromeUIResetPasswordURL[]; extern const char kChromeUIRestartHost[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 50914408..5ecbe6d 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3545,6 +3545,7 @@ "../browser/ui/browser_navigator_browsertest_chromeos.cc", "../browser/ui/extensions/application_launch_browsertest.cc", "../browser/ui/settings_window_manager_browsertest_chromeos.cc", + "../browser/ui/sharing_hub/sharing_hub_bubble_controller_chromeos_browsertest.cc", "../browser/ui/views/apps/app_dialog/app_dialog_view_browsertest.cc", "../browser/ui/views/apps/app_dialog/app_uninstall_dialog_view_browsertest.cc", "../browser/ui/views/apps/chrome_native_app_window_views_aura_ash_browsertest.cc", @@ -4085,6 +4086,9 @@ ] sources = [ + "../browser/chromeos/policy/dlp/dlp_content_manager_lacros_browsertest.cc", + "../browser/chromeos/policy/dlp/dlp_content_manager_test_helper.cc", + "../browser/chromeos/policy/dlp/dlp_content_manager_test_helper.h", "../browser/lacros/browser_service_lacros_browsertest.cc", "../browser/lacros/browser_test_util.cc", "../browser/lacros/browser_test_util.h", @@ -8622,6 +8626,7 @@ "../browser/ui/views/user_education/browser_feature_promo_controller_interactive_uitest.cc", "../browser/ui/views/user_education/feature_promo_dialog_interactive_uitest.cc", "../browser/ui/views/user_education/feature_promo_snooze_interactive_uitest.cc", + "../browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc", "../browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc", "../browser/ui/views/user_education/interaction_sequence_interactive_uitest.cc", ] @@ -8802,12 +8807,10 @@ } if (enable_extensions) { - # TODO(rockot) bug 505926: The chrome_extensions_interactive_uitests - # target should be deleted and this line removed. See the - # chrome_extensions_interactive_uitests target for more. - deps += [ "//extensions:chrome_extensions_interactive_uitests" ] - - sources += [ "../browser/extensions/api/extension_action/extension_action_api_interactive_uitest.cc" ] + sources += [ + "../browser/extensions/api/extension_action/extension_action_api_interactive_uitest.cc", + "../browser/guest_view/mime_handler_view/chrome_mime_handler_view_interactive_uitest.cc", + ] if (include_js_tests) { sources += [
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java index 805f2c9..c4b825c 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/OmniboxTestUtils.java
@@ -32,6 +32,7 @@ import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionsDropdown; import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderView; import org.chromium.chrome.browser.searchwidget.SearchActivity; +import org.chromium.chrome.browser.toolbar.top.ToolbarLayout; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.content_public.browser.test.util.KeyUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -56,6 +57,7 @@ private final @NonNull AutocompleteCoordinator mAutocomplete; private final @NonNull UrlBar mUrlBar; private final @NonNull Instrumentation mInstrumentation; + private final @Nullable ToolbarLayout mToolbar; /** * Class describing individual suggestion, delivering access to broad range of information. @@ -91,8 +93,10 @@ mActivity = activity; if (activity instanceof SearchActivity) { mLocationBar = mActivity.findViewById(R.id.search_location_bar); + mToolbar = null; } else { mLocationBar = mActivity.findViewById(R.id.location_bar); + mToolbar = mActivity.findViewById(R.id.toolbar); } mAutocomplete = mLocationBar.getAutocompleteCoordinator(); mUrlBar = mActivity.findViewById(R.id.url_bar); @@ -107,12 +111,24 @@ } /** + * Waits for all the animations to complete. + * Allows any preceding operation to kick off an animation. + */ + public void waitAnimationsComplete() { + // Note: SearchActivity has no toolbar and no animations, but we still need to + // give keyboard a bit of time to pop up (requested with delay). + do { + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } while (mToolbar != null && mToolbar.isAnimationRunningForTesting()); + } + + /** * Check that the Omnibox reaches the expected focus state. * * @param active Whether the Omnibox is expected to have focus or not. */ public void checkFocus(boolean active) { - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + waitAnimationsComplete(); CriteriaHelper.pollUiThread(() -> { Criteria.checkThat( "unexpected Omnibox focus state", mUrlBar.hasFocus(), Matchers.is(active)); @@ -135,6 +151,7 @@ * Request the Omnibox focus and wait for soft keyboard to show. */ public void requestFocus() { + waitAnimationsComplete(); // During early startup (before completion of its first onDraw), the UrlBar // is not focusable. Tests have to wait for that to happen before trying to focus it. CriteriaHelper.pollUiThread(() -> { @@ -151,6 +168,7 @@ * Expects the Omnibox to be focused before the call. */ public void clearFocus() { + waitAnimationsComplete(); sendKey(KeyEvent.KEYCODE_BACK); checkFocus(false); }
diff --git a/chrome/test/base/devtools_listener.cc b/chrome/test/base/devtools_listener.cc index 1692612..b5c5c44 100644 --- a/chrome/test/base/devtools_listener.cc +++ b/chrome/test/base/devtools_listener.cc
@@ -153,17 +153,17 @@ auto entries = std::make_unique<base::ListValue>(); for (size_t i = 0; i != coverage_entries->GetList().size(); ++i) { - base::DictionaryValue* entry = nullptr; - CHECK(coverage_entries->GetDictionary(i, &entry)); + base::Value& entry = coverage_entries->GetList()[i]; + CHECK(entry.is_dict()); - std::string* script_id = entry->FindStringKey("scriptId"); + std::string* script_id = entry.FindStringKey("scriptId"); CHECK(script_id); const auto it = script_id_map_.find(*script_id); if (it == script_id_map_.end()) continue; - CHECK(entry->SetString("hash", it->second)); - entries->Append(entry->CreateDeepCopy()); + CHECK(entry.SetStringKey("hash", it->second)); + entries->Append(entry.CreateDeepCopy()); } std::string url = host->GetURL().spec();
diff --git a/chrome/test/data/extensions/api_test/accessibility_private/background.js b/chrome/test/data/extensions/api_test/accessibility_private/background.js index 1c412f48..08ae1b0 100644 --- a/chrome/test/data/extensions/api_test/accessibility_private/background.js +++ b/chrome/test/data/extensions/api_test/accessibility_private/background.js
@@ -135,6 +135,22 @@ chrome.test.notifyPass(); }, + function testUpdateDictationBubbleWithHints() { + const update = chrome.accessibilityPrivate.updateDictationBubble; + const IconType = chrome.accessibilityPrivate.DictationBubbleIconType; + update({ + visible: true, + icon: IconType.STANDBY, + hints: ['One', 'Two', 'Three'] + }); + chrome.test.sendMessage('Some hints', (proceed) => { + update({visible: true, icon: IconType.STANDBY}); + chrome.test.sendMessage('No hints'); + chrome.test.succeed(); + }); + + chrome.test.notifyPass(); + }, ]; chrome.test.getConfig(function(config) {
diff --git a/chrome/test/data/webui/inline_login/arc_account_picker_page_test.js b/chrome/test/data/webui/inline_login/arc_account_picker_page_test.js index 09b3a40..21476b8 100644 --- a/chrome/test/data/webui/inline_login/arc_account_picker_page_test.js +++ b/chrome/test/data/webui/inline_login/arc_account_picker_page_test.js
@@ -9,7 +9,7 @@ import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {assertEquals} from '../chai_assert.js'; +import {assertDeepEquals, assertEquals} from '../chai_assert.js'; import {fakeAuthExtensionData, fakeAuthExtensionDataWithEmail, TestAuthenticator, TestInlineLoginBrowserProxy} from './inline_login_test_util.js'; @@ -23,6 +23,7 @@ ArcPickerHiddenForReauth: 'ArcPickerHiddenForReauth', ArcPickerHiddenNoAccounts: 'ArcPickerHiddenNoAccounts', AddAccount: 'AddAccount', + MakeAvailableInArc: 'MakeAvailableInArc', }; /** @return {!Array<Account>} */ @@ -149,4 +150,30 @@ inlineLoginComponent.View.welcome, getActiveViewId(), 'Welcome screen should be active after Add account button click'); }); + + test( + assert(arc_account_picker_page_test.TestNames.MakeAvailableInArc), + async () => { + testSetup( + {isAvailableInArc: true, showArcAvailabilityPicker: true}, + getFakeAccountsNotAvailableInArcList()); + // Send auth extension data without email -> it's account addition flow. + webUIListenerCallback('load-auth-extension', fakeAuthExtensionData); + // Wait for getAccountsNotAvailableInArc call which will return > 0 + // accounts. + await testBrowserProxy.whenCalled('getAccountsNotAvailableInArc'); + flush(); + assertEquals( + inlineLoginComponent.View.arcAccountPicker, getActiveViewId(), + 'ARC account picker screen should be active'); + + const expectedAccount = getFakeAccountsNotAvailableInArcList()[0]; + arcAccountPickerComponent.shadowRoot + .querySelectorAll('.account-item')[0] + .click(); + return testBrowserProxy.whenCalled('makeAvailableInArc') + .then(function(account) { + assertDeepEquals(expectedAccount, account); + }); + }); });
diff --git a/chrome/test/data/webui/inline_login/inline_login_browsertest.js b/chrome/test/data/webui/inline_login/inline_login_browsertest.js index d5eb9f5..b69129f 100644 --- a/chrome/test/data/webui/inline_login/inline_login_browsertest.js +++ b/chrome/test/data/webui/inline_login/inline_login_browsertest.js
@@ -229,4 +229,10 @@ TEST_F('InlineLoginArcAccountPickerBrowserTest', 'AddAccount', function() { this.runMochaTest(arc_account_picker_page_test.TestNames.AddAccount); }); + +TEST_F( + 'InlineLoginArcAccountPickerBrowserTest', 'MakeAvailableInArc', function() { + this.runMochaTest( + arc_account_picker_page_test.TestNames.MakeAvailableInArc); + }); GEN('#endif');
diff --git a/chrome/test/data/webui/inline_login/inline_login_test_util.js b/chrome/test/data/webui/inline_login/inline_login_test_util.js index ccb5e22..6a666bfa 100644 --- a/chrome/test/data/webui/inline_login/inline_login_test_util.js +++ b/chrome/test/data/webui/inline_login/inline_login_test_util.js
@@ -89,6 +89,7 @@ // <if expr="chromeos"> 'skipWelcomePage', 'getAccountsNotAvailableInArc', + 'makeAvailableInArc', 'getDialogArguments', // </if> ]); @@ -178,6 +179,11 @@ } /** @override */ + makeAvailableInArc(account) { + this.methodCalled('makeAvailableInArc', account); + } + + /** @override */ getDialogArguments() { return JSON.stringify(this.dialogArguments_); }
diff --git a/chrome/updater/mac/privileged_helper/server.h b/chrome/updater/mac/privileged_helper/server.h index 2d3d4fc3..9cf232cf 100644 --- a/chrome/updater/mac/privileged_helper/server.h +++ b/chrome/updater/mac/privileged_helper/server.h
@@ -8,6 +8,7 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_refptr.h" #include "base/sequence_checker.h" +#include "base/time/time.h" #include "chrome/updater/app/app.h" #include "chrome/updater/mac/privileged_helper/service.h" @@ -16,6 +17,8 @@ class PrivilegedHelperServer : public App { public: PrivilegedHelperServer(); + void TaskStarted(); + void TaskCompleted(); protected: ~PrivilegedHelperServer() override; @@ -28,9 +31,15 @@ void FirstTaskRun() override; void Uninitialize() override; + void MarkTaskStarted(); + void AcknowledgeTaskCompletion(); + base::TimeDelta ServerKeepAlive(); + + scoped_refptr<base::SequencedTaskRunner> main_task_runner_; scoped_refptr<PrivilegedHelperService> service_; base::scoped_nsobject<NSXPCListener> service_listener_; base::scoped_nsobject<PrivilegedHelperServiceXPCDelegate> service_delegate_; + int tasks_running_ = 0; }; scoped_refptr<App> PrivilegedHelperServerInstance();
diff --git a/chrome/updater/mac/privileged_helper/server.mm b/chrome/updater/mac/privileged_helper/server.mm index d0dbd7c..61b52214 100644 --- a/chrome/updater/mac/privileged_helper/server.mm +++ b/chrome/updater/mac/privileged_helper/server.mm
@@ -4,16 +4,25 @@ #include "chrome/updater/mac/privileged_helper/server.h" +#include "base/bind.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" +#include "base/sequence_checker.h" #include "base/strings/sys_string_conversions.h" +#include "base/task/post_task.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/time.h" #include "chrome/updater/updater_branding.h" namespace updater { +namespace { +int kServerKeepAliveSeconds = 10; +} + PrivilegedHelperServer::PrivilegedHelperServer() - : service_(base::MakeRefCounted<PrivilegedHelperService>()) {} + : main_task_runner_(base::SequencedTaskRunnerHandle::Get()), + service_(base::MakeRefCounted<PrivilegedHelperService>()) {} PrivilegedHelperServer::~PrivilegedHelperServer() = default; void PrivilegedHelperServer::Initialize() { @@ -38,6 +47,36 @@ service_listener_.reset(); } +void PrivilegedHelperServer::TaskStarted() { + main_task_runner_->PostTask( + FROM_HERE, BindOnce(&PrivilegedHelperServer::MarkTaskStarted, this)); +} + +void PrivilegedHelperServer::MarkTaskStarted() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + ++tasks_running_; +} + +base::TimeDelta PrivilegedHelperServer::ServerKeepAlive() { + int seconds = kServerKeepAliveSeconds; + return base::Seconds(seconds); +} + +void PrivilegedHelperServer::TaskCompleted() { + main_task_runner_->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PrivilegedHelperServer::AcknowledgeTaskCompletion, this), + ServerKeepAlive()); +} + +void PrivilegedHelperServer::AcknowledgeTaskCompletion() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (--tasks_running_ < 1) { + main_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&PrivilegedHelperServer::Shutdown, this, 0)); + } +} + scoped_refptr<App> PrivilegedHelperServerInstance() { return base::MakeRefCounted<PrivilegedHelperServer>(); }
diff --git a/chrome/updater/mac/privileged_helper/service.mm b/chrome/updater/mac/privileged_helper/service.mm index 08319f6..030995e 100644 --- a/chrome/updater/mac/privileged_helper/service.mm +++ b/chrome/updater/mac/privileged_helper/service.mm
@@ -60,8 +60,10 @@ VLOG(0) << "SetupSystemUpdaterWithUpdaterPath complete. Result: " << rc; if (reply) reply(rc); + _server->TaskCompleted(); })); + _server->TaskStarted(); _callbackRunner->PostTask( FROM_HERE, base::BindOnce(&updater::PrivilegedHelperService::SetupSystemUpdater,
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastAudioManager.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastAudioManager.java index 3deb001..ffccf93b 100644 --- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastAudioManager.java +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastAudioManager.java
@@ -99,6 +99,10 @@ mInternal.unregisterAudioPolicyAsync(audioPolicy); } + public void unregisterAudioPolicy(AudioPolicy audioPolicy) { + mInternal.unregisterAudioPolicy(audioPolicy); + } + @TargetApi(VERSION_CODES.M) public AudioDeviceInfo[] getDevices(int flags) { return mInternal.getDevices(flags);
diff --git a/chromecast/browser/cast_extension_message_filter.cc b/chromecast/browser/cast_extension_message_filter.cc index 52002b94..e2388b75 100644 --- a/chromecast/browser/cast_extension_message_filter.cc +++ b/chromecast/browser/cast_extension_message_filter.cc
@@ -21,9 +21,9 @@ #include "content/public/browser/render_process_host.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/info_map.h" +#include "extensions/browser/l10n_file_util.h" #include "extensions/common/extension_messages.h" #include "extensions/common/extension_set.h" -#include "extensions/common/file_util.h" #include "extensions/common/manifest_handlers/default_locale_handler.h" #include "extensions/common/manifest_handlers/shared_module_info.h" #include "extensions/common/message_bundle.h" @@ -95,8 +95,8 @@ if (default_locale.empty()) { // A little optimization: send the answer here to avoid an extra thread hop. std::unique_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map( - extensions::file_util::LoadNonLocalizedMessageBundleSubstitutionMap( - extension_id)); + extensions::l10n_file_util:: + LoadNonLocalizedMessageBundleSubstitutionMap(extension_id)); ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg, *dictionary_map); Send(reply_msg); @@ -138,7 +138,7 @@ extension_l10n_util::GzippedMessagesPermission gzip_permission, IPC::Message* reply_msg) { std::unique_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map( - extensions::file_util::LoadMessageBundleSubstitutionMapFromPaths( + extensions::l10n_file_util::LoadMessageBundleSubstitutionMapFromPaths( extension_paths, main_extension_id, default_locale, gzip_permission)); ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg,
diff --git a/chromecast/media/audio/cma_audio_output.cc b/chromecast/media/audio/cma_audio_output.cc index 76d42b0..e9941af 100644 --- a/chromecast/media/audio/cma_audio_output.cc +++ b/chromecast/media/audio/cma_audio_output.cc
@@ -57,16 +57,20 @@ SampleFormat sample_format, const std::string& device_id, const std::string& application_session_id, + bool use_hw_av_sync, + int audio_track_session_id, chromecast::mojom::MultiroomInfoPtr multiroom_info, CmaBackendFactory* cma_backend_factory, CmaBackend::Decoder::Delegate* delegate) : audio_params_(audio_params), sample_size_(GetSampleSize(sample_format)), + use_hw_av_sync_(use_hw_av_sync), delegate_(delegate), timestamp_helper_(audio_params_.sample_rate()) { DCHECK(delegate_); Initialize(sample_format, device_id, application_session_id, - std::move(multiroom_info), cma_backend_factory); + audio_track_session_id, std::move(multiroom_info), + cma_backend_factory); } CmaAudioOutput::~CmaAudioOutput() = default; @@ -75,6 +79,7 @@ SampleFormat sample_format, const std::string& device_id, const std::string& application_session_id, + int audio_track_session_id, chromecast::mojom::MultiroomInfoPtr multiroom_info, CmaBackendFactory* cma_backend_factory) { DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_); @@ -114,6 +119,8 @@ audio_config.bytes_per_channel = sample_size_; audio_config.channel_number = audio_params_.channels(); audio_config.samples_per_second = audio_params_.sample_rate(); + audio_config.use_hw_av_sync = use_hw_av_sync_; + audio_config.audio_track_session_id = audio_track_session_id; DCHECK(IsValidConfig(audio_config)); // Need to first set the config of the audio decoder then initialize the cma // backend if succeed. @@ -184,7 +191,11 @@ 0u); DCHECK(audio_decoder_); - decoder_buffer->set_timestamp(timestamp_helper_.GetTimestamp()); + if (!use_hw_av_sync_) { + // Keep the timestamp of the buffer if the stream is on hardware av sync + // mode. + decoder_buffer->set_timestamp(timestamp_helper_.GetTimestamp()); + } int frame_count = decoder_buffer->data_size() / (sample_size_ * audio_params_.channels()); timestamp_helper_.AddFrames(frame_count);
diff --git a/chromecast/media/audio/cma_audio_output.h b/chromecast/media/audio/cma_audio_output.h index 53a0328..037bc0e 100644 --- a/chromecast/media/audio/cma_audio_output.h +++ b/chromecast/media/audio/cma_audio_output.h
@@ -33,6 +33,8 @@ SampleFormat sample_format, const std::string& device_id, const std::string& application_session_id, + bool use_hw_av_sync, + int audio_track_session_id, chromecast::mojom::MultiroomInfoPtr multiroom_info, CmaBackendFactory* cma_backend_factory, CmaBackend::Decoder::Delegate* delegate); @@ -57,11 +59,13 @@ void Initialize(SampleFormat sample_format, const std::string& device_id, const std::string& application_session_id, + int audio_track_session_id, chromecast::mojom::MultiroomInfoPtr multiroom_info, CmaBackendFactory* cma_backend_factory); const ::media::AudioParameters audio_params_; const int sample_size_; + const bool use_hw_av_sync_; CmaBackend::Decoder::Delegate* const delegate_; ::media::AudioTimestampHelper timestamp_helper_;
diff --git a/chromecast/media/audio/cma_audio_output_stream.cc b/chromecast/media/audio/cma_audio_output_stream.cc index de2ce5c..bad298e 100644 --- a/chromecast/media/audio/cma_audio_output_stream.cc +++ b/chromecast/media/audio/cma_audio_output_stream.cc
@@ -63,6 +63,7 @@ DCHECK_EQ(cma_backend_state_, CmaBackendState::kUninitialized); output_ = std::make_unique<CmaAudioOutput>( audio_params_, kSampleFormatS16, device_id_, application_session_id, + false /*use_hw_av_sync*/, 0 /*audio_track_session_id*/, std::move(multiroom_info), cma_backend_factory_, this); cma_backend_state_ = CmaBackendState::kStopped;
diff --git a/chromecast/media/cma/backend/android/audio_decoder_android.cc b/chromecast/media/cma/backend/android/audio_decoder_android.cc index 6c23782..87fc4d1 100644 --- a/chromecast/media/cma/backend/android/audio_decoder_android.cc +++ b/chromecast/media/cma/backend/android/audio_decoder_android.cc
@@ -127,7 +127,8 @@ DCHECK(IsValidConfig(config_)); DCHECK(IsValidChannelNumber(config_.channel_number)); sink_.Reset(this, config_.channel_number, config_.samples_per_second, - backend_->Primary(), backend_->DeviceId(), + config_.audio_track_session_id, backend_->Primary(), + config_.use_hw_av_sync, backend_->DeviceId(), backend_->ContentType()); sink_->SetStreamVolumeMultiplier(volume_multiplier_); // Create decoder_ if necessary. This can happen if Stop() was called, and @@ -291,7 +292,8 @@ void AudioDecoderAndroid::ResetSinkForNewConfig(const AudioConfig& config) { sink_.Reset(this, config.channel_number, config.samples_per_second, - backend_->Primary(), backend_->DeviceId(), + config.audio_track_session_id, backend_->Primary(), + config.use_hw_av_sync, backend_->DeviceId(), backend_->ContentType()); sink_->SetStreamVolumeMultiplier(volume_multiplier_); pending_output_frames_ = kNoPendingOutput;
diff --git a/chromecast/media/cma/backend/android/audio_sink_android.cc b/chromecast/media/cma/backend/android/audio_sink_android.cc index 54ccaf6..ad6d40b 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android.cc +++ b/chromecast/media/cma/backend/android/audio_sink_android.cc
@@ -12,22 +12,6 @@ namespace media { // static -bool AudioSinkAndroid::GetSessionIds(SinkType sink_type, - int* media_id, - int* communication_id) { - switch (sink_type) { - case AudioSinkAndroid::kSinkTypeNativeBased: - // TODO(ckuiper): implement a sink using native code. - NOTREACHED() << "Native-based audio sink is not implemented yet!"; - break; - case AudioSinkAndroid::kSinkTypeJavaBased: - return AudioSinkAndroidAudioTrackImpl::GetSessionIds(media_id, - communication_id); - } - return false; -} - -// static int64_t AudioSinkAndroid::GetMinimumBufferedTime(SinkType sink_type, const AudioConfig& config) { const int64_t kDefaultMinBufferTimeUs = 50000; @@ -57,7 +41,9 @@ void ManagedAudioSink::Reset(Delegate* delegate, int num_channels, int samples_per_second, + int audio_track_session_id, bool primary, + bool use_hw_av_sync, const std::string& device_id, AudioContentType content_type) { Remove(); @@ -69,9 +55,9 @@ NOTREACHED() << "Native-based audio sink is not implemented yet!"; break; case AudioSinkAndroid::kSinkTypeJavaBased: - sink_ = new AudioSinkAndroidAudioTrackImpl(delegate, num_channels, - samples_per_second, primary, - device_id, content_type); + sink_ = new AudioSinkAndroidAudioTrackImpl( + delegate, num_channels, samples_per_second, audio_track_session_id, + primary, use_hw_av_sync, device_id, content_type); } AudioSinkManager::Get()->Add(sink_); }
diff --git a/chromecast/media/cma/backend/android/audio_sink_android.h b/chromecast/media/cma/backend/android/audio_sink_android.h index 9519f6b..2a625617 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android.h +++ b/chromecast/media/cma/backend/android/audio_sink_android.h
@@ -54,14 +54,6 @@ virtual ~Delegate() {} }; - // Gets the Android audio session ids used for media and communication (TTS) - // tracks. - // Set a return value pointer to null if that id is not needed. - // Returns true if the ids populated are valid. - static bool GetSessionIds(SinkType sink_type, - int* media_id, - int* communication_id); - static int64_t GetMinimumBufferedTime(SinkType sink_type, const AudioConfig& config); @@ -124,7 +116,9 @@ void Reset(Delegate* delegate, int num_channels, int samples_per_second, + int audio_track_session_id, bool primary, + bool use_hw_av_sync, const std::string& device_id, AudioContentType content_type);
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc index 47c8f6c..f4a9b0f 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc +++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
@@ -47,25 +47,6 @@ namespace media { // static -bool AudioSinkAndroidAudioTrackImpl::GetSessionIds(int* media_id, - int* communication_id) { - bool is_valid = true; - if (media_id) { - *media_id = Java_AudioSinkAudioTrackImpl_getSessionIdMedia( - base::android::AttachCurrentThread()); - if (*media_id == -1) - is_valid = false; - } - if (communication_id) { - *communication_id = Java_AudioSinkAudioTrackImpl_getSessionIdCommunication( - base::android::AttachCurrentThread()); - if (*communication_id == -1) - is_valid = false; - } - return is_valid; -} - -// static int64_t AudioSinkAndroidAudioTrackImpl::GetMinimumBufferedTime( int num_channels, int samples_per_second) { @@ -77,13 +58,16 @@ AudioSinkAndroid::Delegate* delegate, int num_channels, int input_samples_per_second, + int audio_track_session_id, bool primary, + bool use_hw_av_sync, const std::string& device_id, AudioContentType content_type) : delegate_(delegate), num_channels_(num_channels), input_samples_per_second_(input_samples_per_second), primary_(primary), + use_hw_av_sync_(use_hw_av_sync), device_id_(device_id), content_type_(content_type), stream_volume_multiplier_(1.0f), @@ -98,7 +82,10 @@ LOG(INFO) << __func__ << "(" << this << "):" << " num_channels_=" << num_channels_ << " input_samples_per_second_=" << input_samples_per_second_ - << " primary_=" << primary_ << " device_id_=" << device_id_ + << " audio_track_session_id=" << audio_track_session_id + << " primary_=" << primary_ + << " use_hw_av_sync_=" << use_hw_av_sync_ + << " device_id_=" << device_id_ << " content_type_=" << content_type_; DCHECK(delegate_); DCHECK_GT(num_channels_, 0); @@ -112,7 +99,7 @@ Java_AudioSinkAudioTrackImpl_init( base::android::AttachCurrentThread(), j_audio_sink_audiotrack_impl_, static_cast<int>(content_type_), num_channels_, input_samples_per_second_, - kDirectBufferSize); + kDirectBufferSize, audio_track_session_id, use_hw_av_sync_); // Should be set now. DCHECK(direct_pcm_buffer_address_); DCHECK(direct_rendering_delay_address_); @@ -197,21 +184,21 @@ return; } - DVLOG(3) << __func__ << "(" << this << "):" - << " [" << pending_data_->data_size() << "]" - << " @ts=" << pending_data_->timestamp(); - if (pending_data_->data_size() == 0) { LOG(INFO) << __func__ << "(" << this << "): empty data buffer!"; PostPcmCallback(sink_rendering_delay_); return; } - ReformatData(); + pending_data_bytes_after_reformat_ = ReformatData(); + DVLOG(3) << __func__ << "(" << this << "):" + << " [" << pending_data_bytes_after_reformat_ << "]" + << " @ts=" << pending_data_->timestamp(); int written = Java_AudioSinkAudioTrackImpl_writePcm( base::android::AttachCurrentThread(), j_audio_sink_audiotrack_impl_, - pending_data_->data_size()); + pending_data_bytes_after_reformat_, + pending_data_->timestamp() * base::Time::kNanosecondsPerMicrosecond); if (written < 0) { LOG(ERROR) << __func__ << "(" << this << "): Cannot write PCM via JNI!"; @@ -219,17 +206,16 @@ return; } - if (state_ == kStatePaused && - written < static_cast<int>(pending_data_->data_size())) { + if (state_ == kStatePaused && written < pending_data_bytes_after_reformat_) { LOG(INFO) << "Audio Server is full while in PAUSED, " << "will continue when entering PLAY mode."; pending_data_bytes_already_fed_ = written; return; } - if (written != static_cast<int>(pending_data_->data_size())) { + if (written != pending_data_bytes_after_reformat_) { LOG(ERROR) << __func__ << "(" << this << "): Wrote " << written - << " instead of " << pending_data_->data_size(); + << " instead of " << pending_data_bytes_after_reformat_; // continue anyway, better to do a best-effort than fail completely } @@ -265,7 +251,7 @@ PostPcmCallback(sink_rendering_delay_); } -void AudioSinkAndroidAudioTrackImpl::ReformatData() { +int AudioSinkAndroidAudioTrackImpl::ReformatData() { // Data is in planar float format, i.e., planar audio data for stereo is all // left samples first, then all right -> "LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR"). // AudioTrack needs interleaved format -> "LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR"). @@ -279,11 +265,25 @@ src[c] = reinterpret_cast<const float*>(pending_data_->data()) + c * num_of_frames; } - float* dst = reinterpret_cast<float*>(direct_pcm_buffer_address_); - for (int f = 0; f < num_of_frames; f++) { - for (int c = 0; c < num_channels_; c++) { - *dst++ = *src[c]++; + if (use_hw_av_sync_) { + // Convert audio data from float to int16_t since hardware av sync audio + // track requires ENCODING_PCM_16BIT audio format. + int16_t* dst = reinterpret_cast<int16_t*>(direct_pcm_buffer_address_); + for (int f = 0; f < num_of_frames; f++) { + for (int c = 0; c < num_channels_; c++) { + *dst++ = *src[c]++; + } } + return static_cast<int>(pending_data_->data_size()) / + (sizeof(float) / sizeof(int16_t)); + } else { + float* dst = reinterpret_cast<float*>(direct_pcm_buffer_address_); + for (int f = 0; f < num_of_frames; f++) { + for (int c = 0; c < num_channels_; c++) { + *dst++ = *src[c]++; + } + } + return static_cast<int>(pending_data_->data_size()); } } @@ -308,17 +308,23 @@ DCHECK(pending_data_bytes_already_fed_); int left_to_send = - pending_data_->data_size() - pending_data_bytes_already_fed_; + pending_data_bytes_after_reformat_ - pending_data_bytes_already_fed_; LOG(INFO) << __func__ << "(" << this << "): send remaining " << left_to_send - << "/" << pending_data_->data_size(); + << "/" << pending_data_bytes_after_reformat_; memmove(direct_pcm_buffer_address_, direct_pcm_buffer_address_ + pending_data_bytes_already_fed_, left_to_send); + int bytes_per_frame = + num_channels_ * (use_hw_av_sync_ ? sizeof(int16_t) : sizeof(float)); + int64_t fed_frames = pending_data_bytes_already_fed_ / bytes_per_frame; + int64_t timestamp_ns_new = pending_data_->timestamp() + + fed_frames * base::Time::kNanosecondsPerSecond / + input_samples_per_second_; int written = Java_AudioSinkAudioTrackImpl_writePcm( base::android::AttachCurrentThread(), j_audio_sink_audiotrack_impl_, - left_to_send); + left_to_send, timestamp_ns_new); DCHECK(written == left_to_send);
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h index bd7b2a0..3c1c70ed 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h +++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h
@@ -45,12 +45,6 @@ AudioSinkAndroidAudioTrackImpl& operator=( const AudioSinkAndroidAudioTrackImpl&) = delete; - // Gets the Android audio session ids used for media and communication (TTS) - // tracks. - // Set a return value pointer to null if that id is not needed. - // Returns true if the ids populated are valid. - static bool GetSessionIds(int* media_id, int* communication_id); - static int64_t GetMinimumBufferedTime(int num_channels, int samples_per_second); @@ -87,7 +81,9 @@ AudioSinkAndroidAudioTrackImpl(AudioSinkAndroid::Delegate* delegate, int num_channels, int input_samples_per_second, + int audio_track_session_id, bool primary, + bool use_hw_av_sync, const std::string& device_id, AudioContentType content_type); @@ -101,10 +97,11 @@ void ScheduleWaitForEosTask(); void OnPlayoutDone(); - // Reformats audio data from planar float into interleaved float for - // AudioTrack. I.e.: + // Reformats audio data from planar into interleaved for AudioTrack. I.e.: // "LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR" -> "LRLRLRLRLRLRLRLRLRLRLRLRLRLRLRLR". - void ReformatData(); + // If using hardware av sync, also convert audio data from float to int16_t. + // Returns the data size after reformatting. + int ReformatData(); void TrackRawMonotonicClockDeviation(); @@ -121,6 +118,7 @@ const int num_channels_; const int input_samples_per_second_; const bool primary_; + const bool use_hw_av_sync_; const std::string device_id_; const AudioContentType content_type_; @@ -155,6 +153,7 @@ State state_; scoped_refptr<DecoderBufferBase> pending_data_; + int pending_data_bytes_after_reformat_; int pending_data_bytes_already_fed_; MediaPipelineBackendAndroid::RenderingDelay sink_rendering_delay_;
diff --git a/chromecast/media/cma/backend/android/audio_sink_manager.cc b/chromecast/media/cma/backend/android/audio_sink_manager.cc index 4b86c343..434681a 100644 --- a/chromecast/media/cma/backend/android/audio_sink_manager.cc +++ b/chromecast/media/cma/backend/android/audio_sink_manager.cc
@@ -38,12 +38,6 @@ return AudioSinkAndroid::kSinkTypeJavaBased; } -// static -bool AudioSinkManager::GetSessionIds(int* media_id, int* communication_id) { - return AudioSinkAndroid::GetSessionIds(GetDefaultSinkType(), media_id, - communication_id); -} - AudioSinkManager::AudioSinkManager() {} AudioSinkManager::~AudioSinkManager() {}
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java index 2452d50..93934e1 100644 --- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java +++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
@@ -90,8 +90,8 @@ // Hardcoded AudioTrack config parameters. private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_FLOAT; + private static final int AUDIO_FORMAT_HW_AV_SYNC = AudioFormat.ENCODING_PCM_16BIT; private static final int AUDIO_MODE = AudioTrack.MODE_STREAM; - private static final int BYTES_PER_SAMPLE = 4; // float (4-bytes) // Parameter to determine the proper internal buffer size of the AudioTrack instance. In order // to minimize latency we want a buffer as small as possible. However, to avoid underruns we @@ -144,9 +144,6 @@ private static AudioManager sAudioManager; - private static int sSessionIdMedia = AudioManager.ERROR; - private static int sSessionIdCommunication = AudioManager.ERROR; - private final long mNativeAudioSinkAudioTrackImpl; private String mTag = TAG; @@ -178,8 +175,10 @@ private boolean mIsInitialized; // Dynamic AudioTrack config parameter. + private boolean mUseHwAvSync; private int mSampleRateInHz; private int mChannelCount; + private int mSampleSize; private AudioTrack mAudioTrack; @@ -256,41 +255,30 @@ } } + private static int getSampleSize(int sampleFormat) { + switch (sampleFormat) { + case AudioFormat.ENCODING_PCM_8BIT: + return 1; + case AudioFormat.ENCODING_PCM_16BIT: + return 2; + case AudioFormat.ENCODING_PCM_24BIT_PACKED: + return 3; + case AudioFormat.ENCODING_PCM_32BIT: + case AudioFormat.ENCODING_PCM_FLOAT: + default: + return 4; + } + } + @CalledByNative public static long getMinimumBufferedTime(int channelCount, int sampleRateInHz) { int sizeBytes = AudioTrack.getMinBufferSize( sampleRateInHz, getChannelConfig(channelCount), AUDIO_FORMAT); long sizeUs = SEC_IN_USEC * (long) sizeBytes - / (BYTES_PER_SAMPLE * channelCount * (long) sampleRateInHz); + / (getSampleSize(AUDIO_FORMAT) * channelCount * (long) sampleRateInHz); return sizeUs + MIN_BUFFERED_TIME_PADDING_US; } - @CalledByNative - public static int getSessionIdMedia() { - if (sSessionIdMedia == AudioManager.ERROR) { - sSessionIdMedia = getAudioManager().generateAudioSessionId(); - if (sSessionIdMedia == AudioManager.ERROR) { - Log.e(TAG, "Cannot generate session-id for media tracks!"); - } else { - Log.i(TAG, "Session-id for media tracks is " + sSessionIdMedia); - } - } - return sSessionIdMedia; - } - - @CalledByNative - public static int getSessionIdCommunication() { - if (sSessionIdCommunication == AudioManager.ERROR) { - sSessionIdCommunication = getAudioManager().generateAudioSessionId(); - if (sSessionIdCommunication == AudioManager.ERROR) { - Log.e(TAG, "Cannot generate session-id for communication tracks!"); - } else { - Log.i(TAG, "Session-id for communication tracks is " + sSessionIdCommunication); - } - } - return sSessionIdCommunication; - } - /** Construction */ @CalledByNative private static AudioSinkAudioTrackImpl createAudioSinkAudioTrackImpl( @@ -325,13 +313,17 @@ return (SEC_IN_NSEC * numOfFrames + mSampleRateInHz / 2) / mSampleRateInHz; } + private boolean isValidSessionId(int sessionId) { + return sessionId > 0; + } + /** * Initializes the instance by creating the AudioTrack object and allocating * the shared memory buffers. */ @CalledByNative private void init(@AudioContentType int castContentType, int channelCount, int sampleRateInHz, - int bytesPerBuffer) { + int bytesPerBuffer, int sessionId, boolean useHwAvSync) { mTag = TAG + "(" + castContentType + ":" + (sInstanceCounter++) + ")"; // Setup throttled logs: pass the first 5, then every 1sec, reset after 5. @@ -353,25 +345,21 @@ Log.e(mTag, "Invalid sampleRateInHz=" + sampleRateInHz + " given!"); return; } + mUseHwAvSync = useHwAvSync; + int audioEncodingFormat = mUseHwAvSync ? AUDIO_FORMAT_HW_AV_SYNC : AUDIO_FORMAT; mSampleRateInHz = sampleRateInHz; mChannelCount = channelCount; + mSampleSize = getSampleSize(audioEncodingFormat); int usageType = CAST_TYPE_TO_ANDROID_USAGE_TYPE_MAP.get(castContentType); - int contentType = CAST_TYPE_TO_ANDROID_CONTENT_TYPE_MAP.get(castContentType); - - int sessionId = AudioManager.ERROR; - if (castContentType == AudioContentType.MEDIA) { - sessionId = getSessionIdMedia(); - } else if (castContentType == AudioContentType.COMMUNICATION) { - sessionId = getSessionIdCommunication(); - } - // AudioContentType.ALARM doesn't get a sessionId. + int contentType = mUseHwAvSync ? AudioAttributes.CONTENT_TYPE_MOVIE + : CAST_TYPE_TO_ANDROID_CONTENT_TYPE_MAP.get(castContentType); int channelConfig = getChannelConfig(mChannelCount); int bufferSizeInBytes = MIN_BUFFER_SIZE_MULTIPLIER - * AudioTrack.getMinBufferSize(mSampleRateInHz, channelConfig, AUDIO_FORMAT); + * AudioTrack.getMinBufferSize(mSampleRateInHz, channelConfig, audioEncodingFormat); int bufferSizeInMs = - 1000 * bufferSizeInBytes / (BYTES_PER_SAMPLE * mChannelCount * mSampleRateInHz); + 1000 * bufferSizeInBytes / (mSampleSize * mChannelCount * mSampleRateInHz); Log.i(mTag, "Init: create an AudioTrack of size=" + bufferSizeInBytes + " (" + bufferSizeInMs + "ms) usageType=" + usageType + " contentType=" + contentType @@ -381,31 +369,33 @@ // Retry if AudioTrack creation fails. int retries = 0; do { + AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder(); + attributesBuilder.setContentType(contentType).setUsage(usageType); + if (mUseHwAvSync) { + attributesBuilder.setFlags(AudioAttributes.FLAG_HW_AV_SYNC); + } AudioTrack.Builder builder = new AudioTrack.Builder(); builder.setBufferSizeInBytes(bufferSizeInBytes) .setTransferMode(AUDIO_MODE) - .setAudioAttributes(new AudioAttributes.Builder() - .setUsage(usageType) - .setContentType(contentType) - .build()) + .setAudioAttributes(attributesBuilder.build()) .setAudioFormat(new AudioFormat.Builder() - .setEncoding(AUDIO_FORMAT) + .setEncoding(audioEncodingFormat) .setSampleRate(mSampleRateInHz) .setChannelMask(channelConfig) .build()); - if (sessionId != AudioManager.ERROR) builder.setSessionId(sessionId); + if (isValidSessionId(sessionId)) builder.setSessionId(sessionId); mAudioTrack = builder.build(); } while (mAudioTrack == null && retries++ < MAX_RETRIES_FOR_AUDIO_TRACKS); } else { // Using pre-M API. - if (sessionId == AudioManager.ERROR) { + if (isValidSessionId(sessionId)) { mAudioTrack = new AudioTrack(CAST_TYPE_TO_ANDROID_STREAM_TYPE.get(castContentType), - mSampleRateInHz, channelConfig, AUDIO_FORMAT, bufferSizeInBytes, - AudioTrack.MODE_STREAM); + mSampleRateInHz, channelConfig, audioEncodingFormat, bufferSizeInBytes, + AUDIO_MODE, sessionId); } else { mAudioTrack = new AudioTrack(CAST_TYPE_TO_ANDROID_STREAM_TYPE.get(castContentType), - mSampleRateInHz, channelConfig, AUDIO_FORMAT, bufferSizeInBytes, - AudioTrack.MODE_STREAM, sessionId); + mSampleRateInHz, channelConfig, audioEncodingFormat, bufferSizeInBytes, + AUDIO_MODE); } } @@ -530,7 +520,7 @@ * error. */ @CalledByNative - private int writePcm(int sizeInBytes) { + private int writePcm(int sizeInBytes, long timestampNs) { if (DEBUG_LEVEL >= 3) { Log.i(mTag, "Writing new PCM data:" @@ -552,7 +542,13 @@ // Feed into AudioTrack - blocking call. long beforeMsecs = SystemClock.elapsedRealtime(); - int bytesWritten = mAudioTrack.write(mPcmBuffer, sizeInBytes, AudioTrack.WRITE_BLOCKING); + int bytesWritten; + if (mUseHwAvSync) { + bytesWritten = mAudioTrack.write( + mPcmBuffer, sizeInBytes, AudioTrack.WRITE_BLOCKING, timestampNs); + } else { + bytesWritten = mAudioTrack.write(mPcmBuffer, sizeInBytes, AudioTrack.WRITE_BLOCKING); + } if (bytesWritten < 0) { int error = bytesWritten; @@ -569,8 +565,14 @@ int bytesLeft = sizeInBytes - bytesWritten; if (bytesLeft > 0) { mPcmBuffer.position(bytesWritten); - int moreBytesWritten = - mAudioTrack.write(mPcmBuffer, bytesLeft, AudioTrack.WRITE_BLOCKING); + int moreBytesWritten; + if (mUseHwAvSync) { + moreBytesWritten = mAudioTrack.write( + mPcmBuffer, bytesLeft, AudioTrack.WRITE_BLOCKING, timestampNs); + } else { + moreBytesWritten = + mAudioTrack.write(mPcmBuffer, bytesLeft, AudioTrack.WRITE_BLOCKING); + } if (moreBytesWritten < 0) { int error = moreBytesWritten; Log.e(mTag, "Couldn't write into AudioTrack (" + error + ")"); @@ -580,13 +582,13 @@ } } - int framesWritten = bytesWritten / (BYTES_PER_SAMPLE * mChannelCount); + int framesWritten = bytesWritten / (mSampleSize * mChannelCount); mTotalFramesWritten += framesWritten; if (DEBUG_LEVEL >= 3) { Log.i(mTag, " wrote " + bytesWritten + "/" + sizeInBytes + " total_bytes_written=" - + (mTotalFramesWritten * BYTES_PER_SAMPLE * mChannelCount) + + (mTotalFramesWritten * mSampleSize * mChannelCount) + " took:" + (SystemClock.elapsedRealtime() - beforeMsecs) + "ms"); }
diff --git a/chromecast/public/media/decoder_config.h b/chromecast/public/media/decoder_config.h index 67e572d..a2a14af5 100644 --- a/chromecast/public/media/decoder_config.h +++ b/chromecast/public/media/decoder_config.h
@@ -302,6 +302,13 @@ std::vector<uint8_t> extra_data; // Encryption scheme (if any) used for the content. EncryptionScheme encryption_scheme; + // Hardware AV sync flag. + bool use_hw_av_sync; + // The session id which the Android AudioTrack will be attached to. If not + // valid, a new one will be atomically generated by the Android system. + // For Cast Connect Multizone use case, if the app uses hardware av sync, + // mediashell will get the id of the media session opened by the app. + int audio_track_session_id; }; inline AudioConfig::AudioConfig() @@ -312,7 +319,9 @@ bytes_per_channel(0), channel_number(0), samples_per_second(0), - encryption_scheme(EncryptionScheme::kUnencrypted) {} + encryption_scheme(EncryptionScheme::kUnencrypted), + use_hw_av_sync(false), + audio_track_session_id(0) {} inline AudioConfig::AudioConfig(const AudioConfig& other) = default; inline AudioConfig::~AudioConfig() { }
diff --git a/chromeos/crosapi/mojom/dlp.mojom b/chromeos/crosapi/mojom/dlp.mojom index df23dee7..4b0f3cd 100644 --- a/chromeos/crosapi/mojom/dlp.mojom +++ b/chromeos/crosapi/mojom/dlp.mojom
@@ -4,6 +4,7 @@ module crosapi.mojom; +import "mojo/public/mojom/base/string16.mojom"; import "url/mojom/url.mojom"; // Corresponds to DlpRulesManager::Level enum. @@ -13,6 +14,7 @@ kReport = 1, kWarn = 2, kBlock = 3, + [MinVersion=2] kNotSet = 4, }; // Corresponds to RestrictionLevelAndUrl struct. @@ -31,10 +33,44 @@ DlpRestrictionLevelAndUrl screen_share@3; }; +// Captured area. +[Stable, Extensible] +struct ScreenShareArea { + // All root windows if |window_id| is null. + string? window_id; +}; + +// Callback to control the state (pause/resume) of a remote screen share. +[Stable] +interface StateChangeDelegate { + // Request to pause the screen share. + OnPause@0(); + // Request to resume the screen share. + OnResume@1(); + // Request to stop the screen share. Should be called only once. + OnStop@2(); +}; + // Interface to communicate from Lacros DLP layer to Ash. Used to notify Ash // about changes in restrictions applied to web content in Lacros. +// +// Next MinVersion: 3 +// Next ID: 4 [Stable, Uuid="793ee9c6-3873-4ea8-a541-894412ddfc0b"] interface Dlp { // Called when |restrictions| are changed for window with |window_id|. DlpRestrictionsUpdated@0(string window_id, DlpRestrictionSet restrictions); + + // Called to evaluate screenshare restriction for a window or full screen. + [MinVersion=1] CheckScreenShareRestriction@1( + ScreenShareArea area, mojo_base.mojom.String16 application_title) => + (bool proceed); + + // Called when screen share in Lacros is started. + [MinVersion=2] OnScreenShareStarted@2(string label, ScreenShareArea area, + mojo_base.mojom.String16 application_title, + pending_remote<StateChangeDelegate> delegate); + + // Called when screen share in Lacros is stopped. + [MinVersion=2] OnScreenShareStopped@3(string label, ScreenShareArea area); };
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt index 6812d3e..9c023e4 100644 --- a/chromeos/profiles/orderfile.newest.txt +++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@ -chromeos-chrome-orderfile-field-99-4815.0-1642417637-benchmark-99.0.4837.0-r1.orderfile.xz +chromeos-chrome-orderfile-field-99-4815.0-1642417637-benchmark-99.0.4840.0-r1.orderfile.xz
diff --git a/chromeos/services/bluetooth_config/discovery_session_manager_impl.cc b/chromeos/services/bluetooth_config/discovery_session_manager_impl.cc index 34233e3..3248b3c 100644 --- a/chromeos/services/bluetooth_config/discovery_session_manager_impl.cc +++ b/chromeos/services/bluetooth_config/discovery_session_manager_impl.cc
@@ -5,6 +5,7 @@ #include "chromeos/services/bluetooth_config/discovery_session_manager_impl.h" #include "chromeos/services/bluetooth_config/device_pairing_handler_impl.h" +#include "components/device_event_log/device_event_log.h" #include "device/bluetooth/bluetooth_discovery_session.h" namespace chromeos { @@ -74,6 +75,8 @@ if (is_discovery_attempt_in_progress_) return; + BLUETOOTH_LOG(DEBUG) << "Starting discovery session"; + is_discovery_attempt_in_progress_ = true; bluetooth_adapter_->StartDiscoverySession( kDiscoveryClientName, @@ -108,6 +111,8 @@ } void DiscoverySessionManagerImpl::DestroyDiscoverySession() { + BLUETOOTH_LOG(DEBUG) << "Destroying discovery session"; + discovery_session_.reset(); NotifyDiscoveryStoppedAndClearActiveClients(); }
diff --git a/components/autofill_assistant/browser/batch_element_checker.cc b/components/autofill_assistant/browser/batch_element_checker.cc index 527ab78..b4df6c83 100644 --- a/components/autofill_assistant/browser/batch_element_checker.cc +++ b/components/autofill_assistant/browser/batch_element_checker.cc
@@ -4,15 +4,19 @@ #include "components/autofill_assistant/browser/batch_element_checker.h" +#include <cstddef> #include <utility> #include "base/bind.h" #include "base/callback_forward.h" +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" #include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "components/autofill_assistant/browser/web/element_action_util.h" #include "components/autofill_assistant/browser/web/element_finder.h" +#include "components/autofill_assistant/browser/web/selector_observer.h" #include "components/autofill_assistant/browser/web/web_controller.h" namespace autofill_assistant { @@ -46,10 +50,9 @@ check.proto = condition; check.callback = std::move(callback); element_condition_checks_.emplace_back(std::move(check)); - size_t index = element_condition_checks_.size() - 1; - AddElementConditionResults(element_condition_checks_[index].proto, index); } +// TODO(b/215335501): Refactor out of BatchElementChecker. void BatchElementChecker::AddFieldValueCheck(const Selector& selector, GetFieldValueCallback callback) { DCHECK(!started_); @@ -72,12 +75,30 @@ all_done_.emplace_back(std::move(all_done)); } +void BatchElementChecker::EnableObserver( + base::TimeDelta max_wait_time, + base::TimeDelta periodic_check_interval) { + DCHECK(!use_observers_); + DCHECK(!started_); + DCHECK(get_field_value_callbacks_.empty()) + << "Observer-based BatchElementChecker doesn't work with " + "AddFieldValueCheck"; + + use_observers_ = true; + observer_max_wait_time_ = max_wait_time; + observer_periodic_check_interval_ = periodic_check_interval; +} + void BatchElementChecker::Run(WebController* web_controller) { DCHECK(web_controller); DCHECK(!started_); for (size_t i = 0; i < element_condition_checks_.size(); ++i) { AddElementConditionResults(element_condition_checks_[i].proto, i); } + if (use_observers_) { + RunWithObserver(web_controller); + return; + } started_ = true; pending_checks_count_ = @@ -122,6 +143,135 @@ CheckDone(); } +void BatchElementChecker::RunWithObserver(WebController* web_controller) { + DCHECK(get_field_value_callbacks_.empty()) + << "Observer-based BatchElementChecker doesn't work with " + "AddFieldValueCheck"; + DCHECK(!started_); + std::vector<SelectorObserver::ObservableSelector> selectors; + + size_t index = 0; + for (auto& entry : unique_selectors_) { + selectors.emplace_back(SelectorObserver::SelectorId(index++), + /* proto = */ entry.first.first.proto, + /* strict = */ entry.first.second); + } + if (selectors.size() == 0) { + FinishedCallbacks(); + return; + } + started_ = true; + auto result = web_controller->ObserveSelectors( + selectors, observer_max_wait_time_, observer_periodic_check_interval_, + base::BindRepeating(&BatchElementChecker::OnResultsUpdated, + weak_ptr_factory_.GetWeakPtr()) + + ); + if (!result.ok()) { + CallAllCallbacksWithError(result); + } +} + +void BatchElementChecker::OnResultsUpdated( + const ClientStatus& status, + const std::vector<SelectorObserver::Update>& updates, + SelectorObserver* selector_observer) { + if (!status.ok()) { + CallAllCallbacksWithError(status); + return; + } + std::vector<size_t> updated_conditions_vector; + // Apply updates + for (auto& update : updates) { + size_t selector_id = update.selector_id.value(); + DCHECK_LT(selector_id, unique_selectors_.size()); + auto& affected_results = + std::next(unique_selectors_.begin(), selector_id)->second; + for (auto& pair : affected_results) { + size_t condition_index = pair.first; + size_t result_index = pair.second; + auto& condition = element_condition_checks_[condition_index]; + auto& result = condition.results[result_index]; + result.match = {/* has_value= */ true, /* value= */ update.match}; + result.element_id = update.match ? update.element_id : -1; + updated_conditions_vector.emplace_back(condition_index); + } + } + auto updated_conditions = + base::flat_set<size_t>(std::move(updated_conditions_vector)); + + bool any_match = false; + for (size_t condition_index : updated_conditions) { + auto& condition = element_condition_checks_[condition_index]; + size_t index = 0; + if (EvaluateElementPrecondition(condition.proto, condition.results, &index, + nullptr) + .matches()) { + any_match = true; + break; + } + } + if (!any_match) { + selector_observer->Continue(); + return; + } + std::vector<SelectorObserver::RequestedElement> wanted_elements; + size_t index = 0; + for (auto& entry : unique_selectors_) { + for (auto& pair : entry.second) { + size_t condition_index = pair.first; + size_t result_index = pair.second; + auto& condition = element_condition_checks_[condition_index]; + auto& result = condition.results[result_index]; + if (result.match.matches() && result.client_id) { + wanted_elements.emplace_back(SelectorObserver::SelectorId(index), + result.element_id); + } + } + ++index; + } + selector_observer->GetElementsAndStop( + wanted_elements, base::BindOnce(&BatchElementChecker::OnGetElementsDone, + weak_ptr_factory_.GetWeakPtr())); +} + +void BatchElementChecker::OnGetElementsDone( + const ClientStatus& status, + const base::flat_map<SelectorObserver::SelectorId, DomObjectFrameStack>& + elements) { + if (!status.ok()) { + CallAllCallbacksWithError(status); + return; + } + for (auto& element : elements) { + size_t results_index = element.first.value(); + DCHECK_LT(results_index, unique_selectors_.size()); + auto& affected_results = + std::next(unique_selectors_.begin(), results_index)->second; + for (auto& pair : affected_results) { + size_t condition_index = pair.first; + size_t result_index = pair.second; + DCHECK(condition_index < element_condition_checks_.size()); + auto& condition = element_condition_checks_[condition_index]; + DCHECK(result_index < condition.results.size()); + auto& result = condition.results[result_index]; + DCHECK(result.client_id.has_value()); + condition.elements[result.client_id.value()] = element.second; + } + } + CheckElementConditions(); + FinishedCallbacks(); +} + +void BatchElementChecker::CallAllCallbacksWithError( + const ClientStatus& status) { + DCHECK(!status.ok()); + for (auto& entry : element_condition_checks_) { + std::move(entry.callback).Run(status, {}, {}); + } + FinishedCallbacks(); +} + void BatchElementChecker::OnSelectorChecked( std::vector<std::pair</* element_condition_index */ size_t, /* result_index */ size_t>>* results, @@ -134,7 +284,7 @@ auto& condition = element_condition_checks_[condition_index]; DCHECK(result_index < condition.results.size()); Result& result = condition.results[result_index]; - result.match = element_status.ok(); + result.match = {/* has_value= */ true, /* value= */ element_status.ok()}; // TODO(szermatt): Consider reporting element_status as an unexpected error // right away if it is neither success nor ELEMENT_RESOLUTION_FAILED. if (element_status.ok() && result.client_id.has_value()) { @@ -160,12 +310,16 @@ DCHECK_GE(pending_checks_count_, 0); if (pending_checks_count_ <= 0) { CheckElementConditions(); - std::vector<base::OnceCallback<void()>> all_done = std::move(all_done_); - // Callbacks in all_done_ can delete the current instance. Nothing can - // safely access |this| after this point. - for (auto& callback : all_done) { - std::move(callback).Run(); - } + FinishedCallbacks(); + } +} + +void BatchElementChecker::FinishedCallbacks() { + std::vector<base::OnceCallback<void()>> all_done = std::move(all_done_); + // Callbacks in all_done_ can delete the current instance. Nothing can + // safely access |this| after this point. + for (auto& callback : all_done) { + std::move(callback).Run(); } } @@ -173,8 +327,9 @@ for (auto& check : element_condition_checks_) { std::vector<std::string> payloads; size_t index = 0; - const auto match = EvaluateElementPrecondition(check.proto, check.results, - &index, &payloads); + bool match = EvaluateElementPrecondition(check.proto, check.results, &index, + &payloads) + .matches(); std::move(check.callback) .Run(match ? ClientStatus(ACTION_APPLIED) : ClientStatus(ELEMENT_RESOLUTION_FAILED), @@ -182,20 +337,24 @@ } } -bool BatchElementChecker::EvaluateElementPrecondition( +BatchElementChecker::MatchResult +BatchElementChecker::EvaluateElementPrecondition( const ElementConditionProto& proto, const std::vector<Result>& results, size_t* next_result_index, std::vector<std::string>* payloads) { - bool match = false; + MatchResult match{/* checked = */ true, /* match_result= */ false}; switch (proto.type_case()) { case ElementConditionProto::kAllOf: { - match = true; + match.match_result = true; for (const ElementConditionProto& condition : proto.all_of().conditions()) { - if (!EvaluateElementPrecondition(condition, results, next_result_index, - payloads)) { - match = false; + MatchResult result = EvaluateElementPrecondition( + condition, results, next_result_index, payloads); + if (match.checked && result.checked) { + match.match_result = match.match_result && result.match_result; + } else { + match.checked = false; } } break; @@ -204,20 +363,24 @@ for (const ElementConditionProto& condition : proto.any_of().conditions()) { if (EvaluateElementPrecondition(condition, results, next_result_index, - payloads)) { - match = true; + payloads) + .matches()) { + match.match_result = true; } } break; } case ElementConditionProto::kNoneOf: { - match = true; + match.match_result = true; for (const ElementConditionProto& condition : proto.none_of().conditions()) { - if (EvaluateElementPrecondition(condition, results, next_result_index, - payloads)) { - match = false; + MatchResult result = EvaluateElementPrecondition( + condition, results, next_result_index, payloads); + if (match.checked && result.checked) { + match.match_result = match.match_result && !result.match_result; + } else { + match.checked = false; } } break; @@ -236,10 +399,10 @@ } case ElementConditionProto::TYPE_NOT_SET: - match = true; // An empty condition is true + match.match_result = true; // An empty condition is true break; } - if (match && !proto.payload().empty()) { + if (payloads && match.matches() && !proto.payload().empty()) { payloads->emplace_back(proto.payload()); } return match; @@ -281,7 +444,7 @@ result.strict = proto.require_unique_element(); if (result.selector.empty()) { // Empty selectors never match. - result.match = false; + result.match = {/* has_value= */ true, /* value= */ false}; } else { unique_selectors_[std::make_pair(result.selector, result.strict)] .emplace_back(element_condition_index, results.size() - 1);
diff --git a/components/autofill_assistant/browser/batch_element_checker.h b/components/autofill_assistant/browser/batch_element_checker.h index d129af1..c015a62 100644 --- a/components/autofill_assistant/browser/batch_element_checker.h +++ b/components/autofill_assistant/browser/batch_element_checker.h
@@ -20,6 +20,7 @@ #include "components/autofill_assistant/browser/service.pb.h" #include "components/autofill_assistant/browser/web/element.h" #include "components/autofill_assistant/browser/web/element_finder.h" +#include "components/autofill_assistant/browser/web/selector_observer.h" namespace autofill_assistant { class WebController; @@ -79,25 +80,33 @@ // Returns true if all there are no checks to run. bool empty() const; + // Turns on observer mode. When BatchElementChecker runs in observer mode, it + // waits until any element condition checks or element checks become true. + void EnableObserver(base::TimeDelta max_wait_time, + base::TimeDelta periodic_check_interval); + // Runs the checks. Once all checks are done, calls the callbacks registered // to AddAllDoneCallback(). void Run(WebController* web_controller); - // Awaits for element conditions - void AwaitConditions(WebController* web_controller); - private: - // For ElementPreconditionChecks, results of one independent selector within - // one element precondition + // Not using absl::optional because it's hard to see what "if (var)" means. + struct MatchResult { + bool checked = false; + bool match_result = false; + bool matches() { return checked && match_result; } + }; + + // Results of one independent |Selector| within one |ElementCondition|. struct Result { Result(); ~Result(); Result(const Result&); - // Selector checked + // Selector checked. Selector selector; - // Result of checking that selector - bool match = false; + // Result of checking that selector. + MatchResult match{/* checked= */ false, /* match_result= */ false}; // The identifier given to this result through the script. This identifier // can be used to later find the element in the |ElementStore|. @@ -105,30 +114,36 @@ // Whether the matching should be done strict or not. bool strict = false; + + // Used in SelectorObserver runs, element_id to retrieve result from + // SelectorObserver. + int element_id = -1; }; - // For ElementConditionChecks struct ElementConditionCheck { ElementConditionCheck(); ~ElementConditionCheck(); ElementConditionCheck(ElementConditionCheck&&); - // Result of individual Selector within the ElementCondition. + // Result of individual |Selector|s within the |ElementCondition|. std::vector<Result> results; - // Callback called with the result after the check is done (if using Run()) - // or after one condition matches (if using AwaitAny()). + // Callback called with the result after the check is done (if observer + // mode is enabled) or after one condition matches (if observer mode + // is disabled). ElementConditionCheckCallback callback; - // ElementConditionProto to check. + // |ElementConditionProto| to check. ElementConditionProto proto; - // Resulting found elements. Key is the client_id in the Match - // ElementConditions (used to refer to this element in the scripts), value + // Resulting found elements. Key is the |client_id| in the |Match| + // |ElementCondition|s (used to refer to this element in the scripts), value // is the found element. base::flat_map<std::string, DomObjectFrameStack> elements; }; + void RunWithObserver(WebController* web_controller); + // Gets called for each Selector checked. void OnSelectorChecked( std::vector<std::pair</* element_condition_index */ size_t, @@ -146,26 +161,37 @@ const std::string& value); void CheckDone(); + void FinishedCallbacks(); + void CallAllCallbacksWithError(const ClientStatus& status); // Add selectors from |proto| to |results_|, doing a depth-first search. void AddElementConditionResults(const ElementConditionProto& proto, size_t element_condition_index); - bool EvaluateElementPrecondition(const ElementConditionProto& proto_, - const std::vector<Result>& results, - size_t* results_iter, - std::vector<std::string>* payloads); + MatchResult EvaluateElementPrecondition(const ElementConditionProto& proto, + const std::vector<Result>& results, + size_t* results_iter, + std::vector<std::string>* payloads); void CheckElementConditions(); + void OnResultsUpdated(const ClientStatus& status, + const std::vector<SelectorObserver::Update>& updates, + SelectorObserver* selector_observer); + + void OnGetElementsDone(const ClientStatus& status, + const base::flat_map<SelectorObserver::SelectorId, + DomObjectFrameStack>& elements); // A way to find unique selectors and what |Result|'s are affected by them. // - // Must not be modified after Run() is called because it's referenced by + // Must not be modified after |Run()| is called because it's referenced by // index. base::flat_map<std::pair<Selector, /* strict */ bool>, std::vector<std::pair</* element_condition_index */ size_t, /* result_index */ size_t>>> unique_selectors_; + // Must not be modified after |Run()| is called because it's referenced by + // index. std::vector<ElementConditionCheck> element_condition_checks_; // A map of GetFieldValue arguments (selector) to callbacks that take the @@ -177,6 +203,11 @@ // Run() was called. Checking elements might or might not have finished yet. bool started_ = false; + // Whether to wait until one of the conditions becomes true. + bool use_observers_ = false; + base::TimeDelta observer_max_wait_time_; + base::TimeDelta observer_periodic_check_interval_; + std::vector<base::OnceCallback<void()>> all_done_; base::WeakPtrFactory<BatchElementChecker> weak_ptr_factory_{this};
diff --git a/components/autofill_assistant/browser/client_context.h b/components/autofill_assistant/browser/client_context.h index fa3a1728..d798fdb 100644 --- a/components/autofill_assistant/browser/client_context.h +++ b/components/autofill_assistant/browser/client_context.h
@@ -19,7 +19,7 @@ // Updates the client context based on the current state of the client. virtual void Update(const TriggerContext& trigger_context) = 0; // Updates the payments client token. This is not part of the normal update. - virtual void SetPaymentsClientToken(const std::string& client_token); + virtual void SetPaymentsClientToken(const std::string& client_token) = 0; // Returns the proto representation of this client context. virtual ClientContextProto AsProto() const = 0; };
diff --git a/components/autofill_assistant/browser/web/web_controller_browsertest.cc b/components/autofill_assistant/browser/web/web_controller_browsertest.cc index 9e08279..698e3999 100644 --- a/components/autofill_assistant/browser/web/web_controller_browsertest.cc +++ b/components/autofill_assistant/browser/web/web_controller_browsertest.cc
@@ -862,6 +862,86 @@ /* node_frame_id= */ std::string()); } + static ElementConditionProto AllOfConditions( + std::vector<ElementConditionProto> conditions) { + ElementConditionProto proto; + for (auto& condition : conditions) { + proto.mutable_any_of()->mutable_conditions()->Add(std::move(condition)); + } + return proto; + } + + static ElementConditionProto AnyOfConditions( + std::vector<ElementConditionProto> conditions) { + ElementConditionProto proto; + for (auto& condition : conditions) { + proto.mutable_any_of()->mutable_conditions()->Add(std::move(condition)); + } + return proto; + } + + static ElementConditionProto NoneOfConditions( + std::vector<ElementConditionProto> conditions) { + ElementConditionProto proto; + for (auto& condition : conditions) { + proto.mutable_none_of()->mutable_conditions()->Add(std::move(condition)); + } + return proto; + } + + static ElementConditionProto Match(Selector selector, bool strict = false) { + ElementConditionProto proto; + *proto.mutable_match() = selector.proto; + proto.set_require_unique_element(strict); + return proto; + } + + // Run Observer BatchElementChecker on the provided conditions. The second + // value in the pairs (bool) is the match expectation. + void RunObserverBatchElementChecker( + const std::vector<std::pair<ElementConditionProto, bool>>& conditions) { + base::RunLoop run_loop; + BatchElementChecker checker; + std::vector<bool> actual_results(conditions.size(), false); + std::vector<bool> expected_results(conditions.size(), false); + + for (size_t i = 0; i < conditions.size(); ++i) { + expected_results[i] = conditions[i].second; + checker.AddElementConditionCheck( + conditions[i].first, + base::BindOnce(&WebControllerBrowserTest:: + ObserverBatchElementCheckerElementCallback, + &actual_results, i)); + } + checker.AddAllDoneCallback(base::BindOnce( + &WebControllerBrowserTest::ObserverBatchElementCheckerAllDoneCallback, + run_loop.QuitClosure(), &expected_results, &actual_results)); + + checker.EnableObserver(base::Milliseconds(30000), base::Milliseconds(1000)); + checker.Run(web_controller_.get()); + run_loop.Run(); + EXPECT_EQ(web_controller_->pending_workers_.size(), 0u); + } + + static void ObserverBatchElementCheckerElementCallback( + std::vector<bool>* res, + size_t i, + const ClientStatus& status, + const std::vector<std::string>& payloads, + const base::flat_map<std::string, DomObjectFrameStack>& elms) { + (*res)[i] = status.ok(); + } + + static void ObserverBatchElementCheckerAllDoneCallback( + base::OnceClosure on_done, + const std::vector<bool>* expected, + const std::vector<bool>* actual) { + for (size_t i = 0; i < expected->size(); ++i) { + EXPECT_EQ(actual->at(i), expected->at(i)) << "condition number " << i; + } + std::move(on_done).Run(); + } + protected: std::unique_ptr<WebController> web_controller_; UserData user_data_; @@ -3048,6 +3128,110 @@ WaitForElementRemove(Selector({"#iframeExternal", "#div"})); } +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, + ObserverBatchElementCheckerStaticConditions) { + RunObserverBatchElementChecker({ + {Match(Selector({"#button"})), true}, // A visible element. + {Match(Selector({"#hidden"})), true}, // A hidden element. + {Match(Selector({"#doesnotexist"})), false} // A nonexistent element. + }); + + RunObserverBatchElementChecker({{ + AllOfConditions({ + Match(Selector({"#button"})), // A visible element. + Match(Selector({"#hidden"})), // A hidden element. + }), + true // Expected to match. + }}); + + RunObserverBatchElementChecker({{ + AnyOfConditions({ + Match(Selector({"#button"})), // A visible element. + Match(Selector({"#doesnotexist"})) // A nonexistent element. + }), + true // Expected to match. + }}); + + RunObserverBatchElementChecker({{ + NoneOfConditions({// A nonexistent element. + Match(Selector({"#doesnotexist"})), + // A non-existent element inside an iFrame. + Match(Selector({"#iframe", "#doesnotexists"}))}), + true // Expected to match. + }}); + + RunObserverBatchElementChecker({{ + AllOfConditions( + {Match(Selector({"#iframe"})), // An iFrame. + Match(Selector({"#iframeExternal"})), // An OOPIF. + Match(Selector( + {"#iframe", "#button"})), // An element in a same-origin iFrame. + Match(Selector( + {"#iframeExternal", "#button"})), // An element in an OOPIF. + NoneOfConditions( + {// A non-existent element in an OOPIF. + Match(Selector({"#iframeExternal", "#doesnotexist"})), + // A non-existent element in a same-origin iFrame. + Match(Selector({"#iframe", "#doesnotexist"}))})}), + true // Expected to match. + }}); +} + +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, + ObserverBatchElementCheckerDynamicElements) { + RunObserverBatchElementChecker({{ + // A selector that only matches for ~200ms. + Match(Selector({".dynamic.about-2-seconds"})), + true // Expected to match. + }}); + + RunObserverBatchElementChecker({{ + // A selector that only matches for ~200ms inside of an iFrame. + Match(Selector({"#iframe", ".dynamic.about-2-seconds"})), + true // Expected to match. + }}); + + RunObserverBatchElementChecker({{ + // A selector that only matches for ~200ms inside of an external iFrame. + Match(Selector({"#iframeExternal", ".dynamic.about-2-seconds"})), + true // Expected to match. + }}); +} + +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, + ObserverBatchElementCheckerDifferentFilters) { + Selector non_empty_bounding_box = Selector({"#button"}); + non_empty_bounding_box.proto.add_filters() + ->mutable_bounding_box() + ->set_require_nonempty(true); + + // Matches exactly one visible element. + auto with_inner_text = + Selector({"#with_inner_text span"}).MatchingInnerText("hello, world"); + + Selector match_css_selector({"label"}); + match_css_selector.MatchingInnerText("terms and conditions"); + match_css_selector.proto.add_filters()->mutable_labelled(); + match_css_selector.proto.add_filters()->set_match_css_selector( + "input[type='checkbox']"); + + RunObserverBatchElementChecker({{ + AllOfConditions( + {// A visible element. + Match(Selector({"#button"}).MustBeVisible()), + // An element in a same-origin iFrame. + Match(Selector({"#iframe", "#button"}).MustBeVisible()), + Match(non_empty_bounding_box), Match(with_inner_text), + Match(with_inner_text.MustBeVisible()), Match(match_css_selector), + NoneOfConditions( + {// A hidden element. + Match(Selector({"#hidden"}).MustBeVisible()), + // A non-existent element. + Match(Selector({"#doesnotexist"}).MustBeVisible())})}), + true // Expected to match. + }}); +} + IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectorObserver) { base::RunLoop run_loop; // Selector ids can be any number as long as unique. @@ -3101,7 +3285,7 @@ expected_updates.erase(expected_updates.begin()); } if (expected_updates.empty()) { - // Done receiving updates + // Done receiving updates. observer->GetElementsAndStop( {{SelectorObserver::SelectorId(iframe_button_id), /* element_id */ button_element_id}},
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index 3f1dd19..5f41cf15 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -660,9 +660,8 @@ std::unique_ptr<icu::Collator> collator(icu::Collator::createInstance(error)); if (U_FAILURE(error)) collator.reset(nullptr); - BookmarkNode* mutable_parent = AsMutable(parent); - std::sort(mutable_parent->children_.begin(), mutable_parent->children_.end(), - SortComparator(collator.get())); + + AsMutable(parent)->SortChildren(SortComparator(collator.get())); if (store_) store_->ScheduleSave(); @@ -690,14 +689,15 @@ for (size_t i = 0; i < ordered_nodes.size(); ++i) order[ordered_nodes[i]] = i; - std::vector<std::unique_ptr<BookmarkNode>> new_children( - ordered_nodes.size()); - BookmarkNode* mutable_parent = AsMutable(parent); - for (auto& child : mutable_parent->children_) { - size_t new_location = order[child.get()]; - new_children[new_location] = std::move(child); + std::vector<size_t> new_order(ordered_nodes.size()); + for (size_t old_index = 0; old_index < parent->children().size(); + ++old_index) { + const BookmarkNode* node = parent->children()[old_index].get(); + size_t new_index = order[node]; + new_order[old_index] = new_index; } - mutable_parent->children_.swap(new_children); + + AsMutable(parent)->ReorderChildren(new_order); if (store_) store_->ScheduleSave(); @@ -811,8 +811,7 @@ std::make_unique<TypedCountSorter>(client_.get())); // Sorting the permanent nodes has to happen on the main thread, so we do it // here, after loading completes. - std::stable_sort(root_->children_.begin(), root_->children_.end(), - VisibilityComparator(client_.get())); + root_->SortChildren(VisibilityComparator(client_.get())); root_->SetMetaInfoMap(details->model_meta_info_map());
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn index 6e88c2e..6bc7406 100644 --- a/components/browser_ui/styles/android/BUILD.gn +++ b/components/browser_ui/styles/android/BUILD.gn
@@ -23,6 +23,8 @@ android_resources("java_resources") { sources = [ + "java/res/color-night/switch_thumb_tint.xml", + "java/res/color-night/switch_track_tint.xml", "java/res/color/chip_text_color_secondary.xml", "java/res/color/default_icon_color_accent1_tint_list.xml", "java/res/color/default_icon_color_dark_tint_list.xml", @@ -42,7 +44,9 @@ "java/res/color/progress_bar_bg_color.xml", "java/res/color/selection_control_button_tint.xml", "java/res/color/switch_thumb_tint.xml", + "java/res/color/switch_thumb_tint_incognito.xml", "java/res/color/switch_track_tint.xml", + "java/res/color/switch_track_tint_incognito.xml", "java/res/color/text_highlight_color.xml", "java/res/drawable-hdpi/btn_star_filled.png", "java/res/drawable-hdpi/ic_chrome.png",
diff --git a/components/browser_ui/styles/android/java/res/color-night/switch_thumb_tint.xml b/components/browser_ui/styles/android/java/res/color-night/switch_thumb_tint.xml new file mode 100644 index 0000000..7fec1bf --- /dev/null +++ b/components/browser_ui/styles/android/java/res/color-night/switch_thumb_tint.xml
@@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2022 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="@macro/switch_thumb_disabled_color" android:state_enabled="false"/> + <item android:color="@macro/default_control_color_active" android:state_checked="true"/> + <item android:color="@macro/switch_enabled_unchecked_color_light"/> +</selector>
diff --git a/components/browser_ui/styles/android/java/res/color-night/switch_track_tint.xml b/components/browser_ui/styles/android/java/res/color-night/switch_track_tint.xml new file mode 100644 index 0000000..be32c52 --- /dev/null +++ b/components/browser_ui/styles/android/java/res/color-night/switch_track_tint.xml
@@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2022 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:alpha="@dimen/switch_track_disabled_alpha" + android:color="@macro/switch_track_disabled_color" android:state_enabled="false"/> + <item android:alpha="@dimen/switch_track_enabled_alpha" + android:color="@macro/default_control_color_active" android:state_checked="true"/> + <item android:alpha="@dimen/switch_track_enabled_alpha" + android:color="@macro/switch_enabled_unchecked_color_light"/> +</selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_thumb_tint.xml b/components/browser_ui/styles/android/java/res/color/switch_thumb_tint.xml index b36fefe..4b7f25e 100644 --- a/components/browser_ui/styles/android/java/res/color/switch_thumb_tint.xml +++ b/components/browser_ui/styles/android/java/res/color/switch_thumb_tint.xml
@@ -4,10 +4,7 @@ found in the LICENSE file. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- This would ideally be colorSwitchThumbNormal at 38% alpha. However, making the thumb - translucent causes the track to be visible behind the thumb. This color is not compatible - with dynamic colors. --> - <item android:color="?attr/colorSwitchThumbDisabledNonDynamic" android:state_enabled="false"/> - <item android:color="?attr/colorPrimaryNonDynamic" android:state_checked="true"/> - <item android:color="?attr/colorSwitchThumbNormalNonDynamic"/> + <item android:color="@macro/switch_thumb_disabled_color" android:state_enabled="false"/> + <item android:color="@macro/default_control_color_active" android:state_checked="true"/> + <item android:color="@macro/switch_enabled_unchecked_color_dark"/> </selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_incognito.xml b/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_incognito.xml new file mode 100644 index 0000000..bcfef2d --- /dev/null +++ b/components/browser_ui/styles/android/java/res/color/switch_thumb_tint_incognito.xml
@@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="@color/switch_thumb_disabled_color_baseline_dark" android:state_enabled="false"/> + <item android:color="@color/default_control_color_active_dark" android:state_checked="true"/> + <item android:color="@color/switch_enabled_unchecked_color_baseline_light"/> +</selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_track_tint.xml b/components/browser_ui/styles/android/java/res/color/switch_track_tint.xml index ad2e6c1..faeaa808 100644 --- a/components/browser_ui/styles/android/java/res/color/switch_track_tint.xml +++ b/components/browser_ui/styles/android/java/res/color/switch_track_tint.xml
@@ -4,8 +4,10 @@ found in the LICENSE file. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:alpha="@dimen/default_disabled_alpha" - android:color="?attr/colorSwitchTrackNormalNonDynamic" android:state_enabled="false"/> - <item android:color="?attr/colorPrimaryContainerNonDynamic" android:state_checked="true"/> - <item android:color="?attr/colorSwitchTrackNormalNonDynamic"/> + <item android:alpha="@dimen/switch_track_disabled_alpha" + android:color="@macro/switch_track_disabled_color" android:state_enabled="false"/> + <item android:alpha="@dimen/switch_track_enabled_alpha" + android:color="@macro/default_control_color_active" android:state_checked="true"/> + <item android:alpha="@dimen/switch_track_enabled_alpha" + android:color="@macro/switch_enabled_unchecked_color_dark"/> </selector>
diff --git a/components/browser_ui/styles/android/java/res/color/switch_track_tint_incognito.xml b/components/browser_ui/styles/android/java/res/color/switch_track_tint_incognito.xml new file mode 100644 index 0000000..86b4d4d3 --- /dev/null +++ b/components/browser_ui/styles/android/java/res/color/switch_track_tint_incognito.xml
@@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:alpha="@dimen/switch_track_disabled_alpha" + android:color="@color/switch_track_disabled_color_baseline_light" android:state_enabled="false"/> + <item android:alpha="@dimen/switch_track_enabled_alpha" + android:color="@color/default_control_color_active_dark" android:state_checked="true"/> + <item android:alpha="@dimen/switch_track_enabled_alpha" + android:color="@color/switch_enabled_unchecked_color_baseline_light"/> +</selector>
diff --git a/components/browser_ui/styles/android/java/res/values-night/colors.xml b/components/browser_ui/styles/android/java/res/values-night/colors.xml index 5c5c4bbd2..d212f1a 100644 --- a/components/browser_ui/styles/android/java/res/values-night/colors.xml +++ b/components/browser_ui/styles/android/java/res/values-night/colors.xml
@@ -7,4 +7,6 @@ <!-- Control colors for toggles, checkboxes, radio buttons, list item highlight, and accent. Note that these should NOT be used for icon tint. --> <color name="control_highlight_color">@color/default_control_color_highlight_dark</color> + <color name="switch_track_disabled_color_baseline">@color/switch_track_disabled_color_baseline_light</color> + <color name="switch_thumb_disabled_color_baseline">@color/switch_thumb_disabled_color_baseline_dark</color> </resources>
diff --git a/components/browser_ui/styles/android/java/res/values-night/styles.xml b/components/browser_ui/styles/android/java/res/values-night/styles.xml index 14aadea..608357d 100644 --- a/components/browser_ui/styles/android/java/res/values-night/styles.xml +++ b/components/browser_ui/styles/android/java/res/values-night/styles.xml
@@ -21,17 +21,5 @@ <item name="elevationOverlayAccentColor">?attr/colorPrimary</item> <item name="elevationOverlayColor">@color/baseline_neutral_200</item> <item name="elevationOverlayEnabled">true</item> - - <item name="colorSwitchThumbNormal">?attr/colorOnSurface</item> - <item name="colorSwitchThumbDisabled">?attr/colorFixedOnSurfaceAlpha38OverSurface</item> - <item name="colorSwitchTrackNormal">?attr/colorOutline</item> - <item name="colorFixedOnSurfaceAlpha38OverSurface">@color/baseline_neutral_900_with_neutral_100_alpha_38</item> - - <!-- Splintered SwitchMaterial roles to roll back dynamic colors. --> - <item name="colorPrimaryNonDynamic">@color/baseline_primary_200</item> - <item name="colorPrimaryContainerNonDynamic">@color/baseline_primary_100</item> - <item name="colorSwitchThumbNormalNonDynamic">@color/baseline_neutral_100</item> - <item name="colorSwitchThumbDisabledNonDynamic">@color/baseline_neutral_900_with_neutral_100_alpha_38</item> - <item name="colorSwitchTrackNormalNonDynamic">@color/baseline_neutral_variant_400</item> </style> </resources>
diff --git a/components/browser_ui/styles/android/java/res/values-night/themes.xml b/components/browser_ui/styles/android/java/res/values-night/themes.xml index 30657b4..c171db4 100644 --- a/components/browser_ui/styles/android/java/res/values-night/themes.xml +++ b/components/browser_ui/styles/android/java/res/values-night/themes.xml
@@ -22,19 +22,5 @@ <!-- Elevation overlays --> <item name="elevationOverlayColor">@color/baseline_neutral_200</item> - - <!-- Custom roles --> - <!-- Dynamic roles --> - <item name="colorSwitchThumbNormal">?attr/colorOnSurface</item> - <item name="colorSwitchThumbDisabled">?attr/colorFixedOnSurfaceAlpha38OverSurface</item> - <item name="colorSwitchTrackNormal">?attr/colorOutline</item> - <!-- Non-dynamic roles for switches --> - <item name="colorFixedOnSurfaceAlpha38OverSurface">@color/baseline_neutral_900_with_neutral_100_alpha_38</item> - <!-- Splintered SwitchMaterial roles to roll back dynamic colors. --> - <item name="colorPrimaryNonDynamic">@color/baseline_primary_200</item> - <item name="colorPrimaryContainerNonDynamic">@color/baseline_primary_100</item> - <item name="colorSwitchThumbNormalNonDynamic">@color/baseline_neutral_100</item> - <item name="colorSwitchThumbDisabledNonDynamic">@color/baseline_neutral_900_with_neutral_100_alpha_38</item> - <item name="colorSwitchTrackNormalNonDynamic">@color/baseline_neutral_variant_400</item> </style> </resources>
diff --git a/components/browser_ui/styles/android/java/res/values/colors.xml b/components/browser_ui/styles/android/java/res/values/colors.xml index 4b412273..2cd5ba0 100644 --- a/components/browser_ui/styles/android/java/res/values/colors.xml +++ b/components/browser_ui/styles/android/java/res/values/colors.xml
@@ -22,6 +22,12 @@ <color name="control_highlight_color" tools:ignore="UnusedResources"> @color/default_control_color_highlight_light </color> + <color name="switch_enabled_unchecked_color_baseline_dark" tools:ignore="UnusedResources">@color/baseline_neutral_variant_500</color> + <color name="switch_enabled_unchecked_color_baseline_light">@color/baseline_neutral_100</color> + <color name="switch_track_disabled_color_baseline" tools:ignore="UnusedResources">@color/baseline_neutral_900</color> + <color name="switch_track_disabled_color_baseline_light">@color/baseline_neutral_100</color> + <color name="switch_thumb_disabled_color_baseline" tools:ignore="UnusedResources">@color/baseline_neutral_50</color> + <color name="switch_thumb_disabled_color_baseline_dark">@color/baseline_neutral_800</color> <!-- Favicons --> <color name="default_favicon_background_color">@color/default_control_color_normal_light</color>
diff --git a/components/browser_ui/styles/android/java/res/values/dimens.xml b/components/browser_ui/styles/android/java/res/values/dimens.xml index c55ea4d..0fc5ebd 100644 --- a/components/browser_ui/styles/android/java/res/values/dimens.xml +++ b/components/browser_ui/styles/android/java/res/values/dimens.xml
@@ -18,8 +18,11 @@ <dimen name="toolbar_shadow_height">8dp</dimen> <dimen name="toolbar_hairline_height">1dp</dimen> + <!-- Alpha values for various things --> <item name="text_highlight_alpha" format="float" type="dimen">0.2</item> <item name="progress_bar_bg_alpha" format="float" type="dimen">0.2</item> + <item name="switch_track_disabled_alpha" format="float" type="dimen">0.12</item> + <item name="switch_track_enabled_alpha" format="float" type="dimen">0.3</item> <!-- Surface color elevations --> <dimen name="dialog_bg_color_elev">@dimen/default_elevation_0</dimen>
diff --git a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml index e7457af9..2ef5e261 100644 --- a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml +++ b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml
@@ -7,16 +7,25 @@ <!-- <macro name="default_bg_color">?attr/colorSurface</macro> <macro name="default_bg_color_elev_0">?attr/colorSurface</macro> + <macro name="default_control_color_active">?attr/colorPrimary</macro> <macro name="default_control_color_normal">?attr/colorOnSurfaceVariant</macro> + <macro name="default_icon_color">?attr/colorOnSurface</macro> <macro name="default_icon_color_accent1">?attr/colorPrimary</macro> <macro name="default_icon_color_inverse">?attr/colorOnSurfaceInverse</macro> <macro name="default_icon_color_on_accent1">?attr/colorOnPrimary</macro> <macro name="default_icon_color_secondary">?attr/colorOnSurfaceVariant</macro> + <macro name="default_text_color">?attr/colorOnSurface</macro> <macro name="default_text_color_accent1">?attr/colorPrimary</macro> <macro name="default_text_color_on_accent1">?attr/colorOnPrimary</macro> + + <macro name="switch_enabled_unchecked_color_dark">?attr/colorOutline</macro> + <macro name="switch_enabled_unchecked_color_light">?attr/colorOnSurface</macro> + <macro name="switch_track_disabled_color">?attr/colorOnSurface</macro> + <macro name="switch_thumb_disabled_color">?attr/colorOnSurfaceInverse</macro> + <macro name="hairline_stroke_color">?attr/colorOutline</macro> <macro name="divider_line_bg_color">?attr/colorSurfaceVariant</macro> --> @@ -24,16 +33,25 @@ <!-- Temporarily holdback @color version. Use for checkin. --> <macro name="default_bg_color">@color/default_bg_color_baseline</macro> <macro name="default_bg_color_elev_0">@color/default_bg_color_elev_0_baseline</macro> + <macro name="default_control_color_active">@color/default_control_color_active_baseline</macro> <macro name="default_control_color_normal">@color/default_control_color_normal_baseline</macro> + <macro name="default_icon_color">@color/default_icon_color_baseline</macro> <macro name="default_icon_color_accent1">@color/default_icon_color_accent1_baseline</macro> <macro name="default_icon_color_inverse">@color/default_icon_color_inverse_baseline</macro> <macro name="default_icon_color_on_accent1">@color/default_icon_color_on_accent1_baseline</macro> <macro name="default_icon_color_secondary">@color/default_icon_color_secondary_baseline</macro> + <macro name="default_text_color">@color/default_text_color_baseline</macro> <macro name="default_text_color_accent1">@color/default_text_color_blue_baseline</macro> <macro name="default_text_color_on_accent1">@color/default_text_color_on_accent1_baseline</macro> + + <macro name="switch_enabled_unchecked_color_dark">@color/switch_enabled_unchecked_color_baseline_dark</macro> + <macro name="switch_enabled_unchecked_color_light">@color/switch_enabled_unchecked_color_baseline_light</macro> + <macro name="switch_track_disabled_color">@color/switch_track_disabled_color_baseline</macro> + <macro name="switch_thumb_disabled_color">@color/switch_thumb_disabled_color_baseline</macro> + <macro name="hairline_stroke_color">@color/hairline_stroke_color_baseline</macro> <macro name="divider_line_bg_color">@color/divider_line_bg_color_baseline</macro>
diff --git a/components/browser_ui/styles/android/java/res/values/styles.xml b/components/browser_ui/styles/android/java/res/values/styles.xml index b6fd206..231af0d 100644 --- a/components/browser_ui/styles/android/java/res/values/styles.xml +++ b/components/browser_ui/styles/android/java/res/values/styles.xml
@@ -85,6 +85,10 @@ <item name="trackTint">@color/switch_track_tint</item> <item name="trackTintMode">src_in</item> </style> + <style name="Widget.BrowserUI.Switch.Incognito" parent="Widget.MaterialComponents.CompoundButton.Switch"> + <item name="thumbTint">@color/switch_thumb_tint_incognito</item> + <item name="trackTint">@color/switch_track_tint_incognito</item> + </style> <!-- TextInputLayout style --> <style name="Widget.BrowserUI.TextInputLayout" parent="Widget.Design.TextInputLayout"> <item name="errorTextAppearance">@style/TextAppearance.ErrorCaption</item> @@ -181,12 +185,12 @@ <!-- TODO(sinansahin): See if we can pass the baseline dark theme to the incognito NTP instead. --> <style name="SwitchMaterialDark"> - <item name="colorPrimaryNonDynamic">@color/baseline_primary_200</item> - <item name="colorPrimaryContainerNonDynamic">@color/baseline_primary_100</item> - <item name="colorSwitchThumbNormalNonDynamic">@color/baseline_neutral_100</item> - <item name="colorSwitchTrackNormalNonDynamic">@color/baseline_neutral_variant_400</item> + <!-- TODO(sinansahin): When we migrate the switch style to Material3, we should override + colorOnSurface and colorPrimary instead of these attributes because they are what + m3_selection_control_ripple_color_selector uses. --> + <item name="colorControlActivated">@color/default_control_color_active_dark</item> <item name="colorControlHighlight">@color/default_control_color_highlight_dark</item> - <item name="switchStyle">@style/Widget.BrowserUI.Switch</item> + <item name="switchStyle">@style/Widget.BrowserUI.Switch.Incognito</item> </style> <!-- Styling for an app menu item row. -->
diff --git a/components/browser_ui/styles/android/java/res/values/themes.xml b/components/browser_ui/styles/android/java/res/values/themes.xml index 06f7517..672eb34e 100644 --- a/components/browser_ui/styles/android/java/res/values/themes.xml +++ b/components/browser_ui/styles/android/java/res/values/themes.xml
@@ -42,18 +42,6 @@ <item name="elevationOverlayColor">@color/baseline_neutral_600</item> <item name="elevationOverlayAccentColor">?attr/colorPrimary</item> - <!-- Custom roles --> - <!-- Dynamic roles --> - <item name="colorSwitchThumbNormal">?attr/colorSurface</item> - <item name="colorSwitchThumbDisabled">?attr/colorSurface</item> - <item name="colorSwitchTrackNormal">?attr/colorSurfaceVariant</item> - <!-- Non-dynamic roles for switches --> - <item name="colorPrimaryNonDynamic">@color/baseline_primary_600</item> - <item name="colorPrimaryContainerNonDynamic">@color/baseline_primary_100</item> - <item name="colorSwitchThumbDisabledNonDynamic">@color/baseline_neutral_0</item> - <item name="colorSwitchThumbNormalNonDynamic">@color/baseline_neutral_0</item> - <item name="colorSwitchTrackNormalNonDynamic">@color/baseline_neutral_variant_100</item> - <!-- Custom semantic names --> <!-- Supports dynamic colors now. --> <item name="default_bg_color_dynamic">?attr/colorSurface</item> @@ -100,18 +88,6 @@ <item name="elevationOverlayColor">@color/baseline_neutral_600</item> <item name="elevationOverlayAccentColor">?attr/colorPrimary</item> - <!-- Custom roles --> - <!-- Dynamic roles --> - <item name="colorSwitchThumbNormal">?attr/colorSurface</item> - <item name="colorSwitchThumbDisabled">?attr/colorSurface</item> - <item name="colorSwitchTrackNormal">?attr/colorSurfaceVariant</item> - <!-- Non-dynamic roles for switches --> - <item name="colorPrimaryNonDynamic">@color/baseline_primary_600</item> - <item name="colorPrimaryContainerNonDynamic">@color/baseline_primary_100</item> - <item name="colorSwitchThumbDisabledNonDynamic">@color/baseline_neutral_0</item> - <item name="colorSwitchThumbNormalNonDynamic">@color/baseline_neutral_0</item> - <item name="colorSwitchTrackNormalNonDynamic">@color/baseline_neutral_variant_100</item> - <!-- Custom semantic names --> <!-- Supports dynamic colors now. --> <item name="default_bg_color_dynamic">?attr/colorSurface</item> @@ -183,17 +159,6 @@ <item name="elevationOverlayAccentColor">?attr/colorPrimary</item> <item name="elevationOverlayColor">@color/baseline_neutral_600</item> <item name="elevationOverlayEnabled">true</item> - - <item name="colorSwitchThumbNormal">?attr/colorSurface</item> - <item name="colorSwitchThumbDisabled">?attr/colorSurface</item> - <item name="colorSwitchTrackNormal">?attr/colorSurfaceVariant</item> - - <!-- Non-dynamic roles for switches. --> - <item name="colorPrimaryNonDynamic">@color/baseline_primary_600</item> - <item name="colorPrimaryContainerNonDynamic">@color/baseline_primary_100</item> - <item name="colorSwitchThumbDisabledNonDynamic">@color/baseline_neutral_0</item> - <item name="colorSwitchThumbNormalNonDynamic">@color/baseline_neutral_0</item> - <item name="colorSwitchTrackNormalNonDynamic">@color/baseline_neutral_variant_100</item> </style> <style name="ColorOverlay.BrowserUi.DayNight" parent="ColorOverlay.Ui"> <item name="android:textColorPrimary">@color/default_text_color_list</item>
diff --git a/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java b/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java index a5f3dfd..a8a710f 100644 --- a/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java +++ b/components/feature_engagement/internal/android/java/src/org/chromium/components/feature_engagement/internal/TrackerImpl.java
@@ -136,6 +136,30 @@ } @Override + public void setPriorityNotification(String feature) { + TrackerImplJni.get().setPriorityNotification(mNativePtr, TrackerImpl.this, feature); + } + + @Override + @Nullable + public String getPendingPriorityNotification() { + return TrackerImplJni.get().getPendingPriorityNotification(mNativePtr, TrackerImpl.this); + } + + @Override + public void registerPriorityNotificationHandler( + String feature, Runnable priorityNotificationHandler) { + TrackerImplJni.get().registerPriorityNotificationHandler( + mNativePtr, TrackerImpl.this, feature, priorityNotificationHandler); + } + + @Override + public void unregisterPriorityNotificationHandler(String feature) { + TrackerImplJni.get().unregisterPriorityNotificationHandler( + mNativePtr, TrackerImpl.this, feature); + } + + @Override public boolean isInitialized() { assert mNativePtr != 0; return TrackerImplJni.get().isInitialized(mNativePtr, TrackerImpl.this); @@ -181,6 +205,13 @@ int snoozeAction); DisplayLockHandleAndroid acquireDisplayLock( long nativeTrackerImplAndroid, TrackerImpl caller); + void setPriorityNotification( + long nativeTrackerImplAndroid, TrackerImpl caller, String feature); + String getPendingPriorityNotification(long nativeTrackerImplAndroid, TrackerImpl caller); + void registerPriorityNotificationHandler(long nativeTrackerImplAndroid, TrackerImpl caller, + String feature, Runnable priorityNotificationHandler); + void unregisterPriorityNotificationHandler( + long nativeTrackerImplAndroid, TrackerImpl caller, String feature); boolean isInitialized(long nativeTrackerImplAndroid, TrackerImpl caller); void addOnInitializedCallback( long nativeTrackerImplAndroid, TrackerImpl caller, Callback<Boolean> callback);
diff --git a/components/feature_engagement/internal/android/tracker_impl_android.cc b/components/feature_engagement/internal/android/tracker_impl_android.cc index 175cff0..4a591df 100644 --- a/components/feature_engagement/internal/android/tracker_impl_android.cc +++ b/components/feature_engagement/internal/android/tracker_impl_android.cc
@@ -18,6 +18,7 @@ #include "components/feature_engagement/internal/jni_headers/TrackerImpl_jni.h" #include "components/feature_engagement/public/feature_list.h" #include "components/feature_engagement/public/tracker.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { @@ -185,6 +186,51 @@ return lock_handle_android.release()->GetJavaObject(); } +void TrackerImplAndroid::SetPriorityNotification( + JNIEnv* env, + const base::android::JavaRef<jobject>& jobj, + const base::android::JavaParamRef<jstring>& jfeature) { + std::string feature = ConvertJavaStringToUTF8(env, jfeature); + DCHECK(features_.find(feature) != features_.end()); + + return tracker_->SetPriorityNotification(*features_[feature]); +} + +base::android::ScopedJavaLocalRef<jstring> +TrackerImplAndroid::GetPendingPriorityNotification( + JNIEnv* env, + const base::android::JavaRef<jobject>& jobj) { + auto notification = tracker_->GetPendingPriorityNotification(); + std::string pending_notification_string = + notification.value_or(std::string()); + return base::android::ConvertUTF8ToJavaString(env, + pending_notification_string); +} + +void TrackerImplAndroid::RegisterPriorityNotificationHandler( + JNIEnv* env, + const base::android::JavaRef<jobject>& jobj, + const base::android::JavaParamRef<jstring>& jfeature, + const base::android::JavaRef<jobject>& jrunnable) { + std::string feature = ConvertJavaStringToUTF8(env, jfeature); + DCHECK(features_.find(feature) != features_.end()); + + return tracker_->RegisterPriorityNotificationHandler( + *features_[feature], + base::BindOnce(&base::android::RunRunnableAndroid, + base::android::ScopedJavaGlobalRef<jobject>(jrunnable))); +} + +void TrackerImplAndroid::UnregisterPriorityNotificationHandler( + JNIEnv* env, + const base::android::JavaRef<jobject>& jobj, + const base::android::JavaParamRef<jstring>& jfeature) { + std::string feature = ConvertJavaStringToUTF8(env, jfeature); + DCHECK(features_.find(feature) != features_.end()); + + return tracker_->UnregisterPriorityNotificationHandler(*features_[feature]); +} + bool TrackerImplAndroid::IsInitialized( JNIEnv* env, const base::android::JavaRef<jobject>& jobj) {
diff --git a/components/feature_engagement/internal/android/tracker_impl_android.h b/components/feature_engagement/internal/android/tracker_impl_android.h index e877697..9a686747 100644 --- a/components/feature_engagement/internal/android/tracker_impl_android.h +++ b/components/feature_engagement/internal/android/tracker_impl_android.h
@@ -111,6 +111,22 @@ virtual base::android::ScopedJavaLocalRef<jobject> AcquireDisplayLock( JNIEnv* env, const base::android::JavaRef<jobject>& jobj); + virtual void SetPriorityNotification( + JNIEnv* env, + const base::android::JavaRef<jobject>& jobj, + const base::android::JavaParamRef<jstring>& jfeature); + virtual base::android::ScopedJavaLocalRef<jstring> + GetPendingPriorityNotification(JNIEnv* env, + const base::android::JavaRef<jobject>& jobj); + virtual void RegisterPriorityNotificationHandler( + JNIEnv* env, + const base::android::JavaRef<jobject>& jobj, + const base::android::JavaParamRef<jstring>& jfeature, + const base::android::JavaRef<jobject>& jcallback); + virtual void UnregisterPriorityNotificationHandler( + JNIEnv* env, + const base::android::JavaRef<jobject>& jobj, + const base::android::JavaParamRef<jstring>& jfeature); virtual bool IsInitialized(JNIEnv* env, const base::android::JavaRef<jobject>& jobj); virtual void AddOnInitializedCallback(
diff --git a/components/feature_engagement/internal/condition_validator.cc b/components/feature_engagement/internal/condition_validator.cc index 155cbdf..2bada26 100644 --- a/components/feature_engagement/internal/condition_validator.cc +++ b/components/feature_engagement/internal/condition_validator.cc
@@ -21,6 +21,7 @@ availability_ok(initial_values), display_lock_ok(initial_values), snooze_expiration_ok(initial_values), + priority_notification_ok(initial_values), should_show_snooze(initial_values) {} ConditionValidator::Result::Result(const Result& other) = default; @@ -32,7 +33,7 @@ return event_model_ready_ok && currently_showing_ok && feature_enabled_ok && config_ok && used_ok && trigger_ok && preconditions_ok && session_rate_ok && availability_model_ready_ok && availability_ok && - display_lock_ok && snooze_expiration_ok; + display_lock_ok && snooze_expiration_ok && priority_notification_ok; } std::ostream& operator<<(std::ostream& os, @@ -50,6 +51,7 @@ << ", availability_ok=" << result.availability_ok << ", display_lock_ok=" << result.display_lock_ok << ", snooze_expiration_ok=" << result.snooze_expiration_ok + << ", priority_notification_ok=" << result.priority_notification_ok << ", should_show_snooze=" << result.should_show_snooze << " }"; }
diff --git a/components/feature_engagement/internal/condition_validator.h b/components/feature_engagement/internal/condition_validator.h index edd4700..facd64d 100644 --- a/components/feature_engagement/internal/condition_validator.h +++ b/components/feature_engagement/internal/condition_validator.h
@@ -13,6 +13,7 @@ #include "components/feature_engagement/public/configuration.h" #include "components/feature_engagement/public/feature_list.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { struct Feature; @@ -73,6 +74,10 @@ // Whether the current snooze timer has expired. bool snooze_expiration_ok; + // Whether the given feature is a priority notification, or there are no + // other priority notifications. + bool priority_notification_ok; + // Whether the snooze option should be shown. // This value is excluded from the NoErrors() check. bool should_show_snooze; @@ -106,6 +111,14 @@ // Must be called to notify that the |feature| is no longer showing. virtual void NotifyDismissed(const base::Feature& feature) = 0; + // Called to notify that we have a priority notification to be shown next. All + // other IPHs will be blocked until then. + virtual void SetPriorityNotification( + const absl::optional<std::string>& feature) = 0; + + // Called to get if there is a pending priority notification to be shown next. + virtual absl::optional<std::string> GetPendingPriorityNotification() = 0; + protected: ConditionValidator() = default; };
diff --git a/components/feature_engagement/internal/condition_validator_unittest.cc b/components/feature_engagement/internal/condition_validator_unittest.cc index 860d396..70c734aea 100644 --- a/components/feature_engagement/internal/condition_validator_unittest.cc +++ b/components/feature_engagement/internal/condition_validator_unittest.cc
@@ -82,6 +82,12 @@ EXPECT_FALSE(result.NoErrors()); } +TEST(ConditionValidatorResultTest, TestPriorityNotificationFailed) { + ConditionValidator::Result result(true); + result.priority_notification_ok = false; + EXPECT_FALSE(result.NoErrors()); +} + TEST(ConditionValidatorResultTest, TestMultipleErrors) { ConditionValidator::Result result(true); result.preconditions_ok = false;
diff --git a/components/feature_engagement/internal/feature_config_condition_validator.cc b/components/feature_engagement/internal/feature_config_condition_validator.cc index 1144945..7c5ae7f 100644 --- a/components/feature_engagement/internal/feature_config_condition_validator.cc +++ b/components/feature_engagement/internal/feature_config_condition_validator.cc
@@ -18,6 +18,7 @@ #include "components/feature_engagement/internal/proto/feature_event.pb.h" #include "components/feature_engagement/public/configuration.h" #include "components/feature_engagement/public/feature_list.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { @@ -63,6 +64,10 @@ (event_model.GetLastSnoozeTimestamp(config.trigger.name) < base::Time::Now() - base::Days(config.snooze_params.snooze_interval)); + result.priority_notification_ok = + !pending_priority_notification_.has_value() || + pending_priority_notification_.value() == feature.name; + result.should_show_snooze = result.snooze_expiration_ok && event_model.GetSnoozeCount(config.trigger.name, config.trigger.window, @@ -115,6 +120,17 @@ return event_config.comparator.MeetsCriteria(event_count); } +void FeatureConfigConditionValidator::SetPriorityNotification( + const absl::optional<std::string>& feature) { + DCHECK(!pending_priority_notification_.has_value() || !feature.has_value()); + pending_priority_notification_ = feature; +} + +absl::optional<std::string> +FeatureConfigConditionValidator::GetPendingPriorityNotification() { + return pending_priority_notification_; +} + bool FeatureConfigConditionValidator::AvailabilityMeetsConditions( const base::Feature& feature, Comparator comparator,
diff --git a/components/feature_engagement/internal/feature_config_condition_validator.h b/components/feature_engagement/internal/feature_config_condition_validator.h index 4e1583c..37bf99d 100644 --- a/components/feature_engagement/internal/feature_config_condition_validator.h +++ b/components/feature_engagement/internal/feature_config_condition_validator.h
@@ -10,6 +10,7 @@ #include <set> #include "components/feature_engagement/internal/condition_validator.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { class AvailabilityModel; @@ -43,6 +44,9 @@ const FeatureConfig& config, const std::vector<std::string>& all_feature_names) override; void NotifyDismissed(const base::Feature& feature) override; + void SetPriorityNotification( + const absl::optional<std::string>& feature) override; + absl::optional<std::string> GetPendingPriorityNotification() override; private: bool EventConfigMeetsConditions(const EventConfig& event_config, @@ -69,6 +73,9 @@ // By default, all features impact each other, but some features override this // through the use of |session_rate_impact|. std::map<std::string, uint32_t> times_shown_for_feature_; + + // Pending priority notification to be shown if any. + absl::optional<std::string> pending_priority_notification_; }; } // namespace feature_engagement
diff --git a/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc b/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc index ca69e34..bb10b17 100644 --- a/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc +++ b/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc
@@ -440,6 +440,50 @@ EXPECT_FALSE(result.preconditions_ok); } +TEST_F(FeatureConfigConditionValidatorTest, PriorityNotification) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {kFeatureConfigTestFeatureFoo, kFeatureConfigTestFeatureBar}, {}); + std::vector<std::string> all_feature_names = { + kFeatureConfigTestFeatureFoo.name, kFeatureConfigTestFeatureBar.name}; + + FeatureConfig foo_config = GetAcceptingFeatureConfig(); + FeatureConfig bar_config = GetAcceptingFeatureConfig(); + + EXPECT_TRUE( + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureFoo, foo_config) + .NoErrors()); + EXPECT_TRUE( + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureBar, bar_config) + .NoErrors()); + + validator_.SetPriorityNotification(kFeatureConfigTestFeatureFoo.name); + EXPECT_TRUE( + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureFoo, foo_config) + .NoErrors()); + ConditionValidator::Result result = + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureBar, bar_config); + EXPECT_FALSE(result.NoErrors()); + EXPECT_FALSE(result.priority_notification_ok); + + validator_.SetPriorityNotification(absl::nullopt); + validator_.SetPriorityNotification(kFeatureConfigTestFeatureBar.name); + EXPECT_FALSE( + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureFoo, foo_config) + .NoErrors()); + EXPECT_TRUE( + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureBar, bar_config) + .NoErrors()); + + validator_.SetPriorityNotification(absl::nullopt); + EXPECT_TRUE( + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureFoo, foo_config) + .NoErrors()); + EXPECT_TRUE( + GetResultForDayZeroForFeature(kFeatureConfigTestFeatureBar, bar_config) + .NoErrors()); +} + TEST_F(FeatureConfigConditionValidatorTest, SessionRate) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitWithFeatures(
diff --git a/components/feature_engagement/internal/never_condition_validator.cc b/components/feature_engagement/internal/never_condition_validator.cc index 5108c06a..7fbfa601 100644 --- a/components/feature_engagement/internal/never_condition_validator.cc +++ b/components/feature_engagement/internal/never_condition_validator.cc
@@ -4,6 +4,8 @@ #include "components/feature_engagement/internal/never_condition_validator.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + namespace feature_engagement { NeverConditionValidator::NeverConditionValidator() = default; @@ -28,4 +30,12 @@ void NeverConditionValidator::NotifyDismissed(const base::Feature& feature) {} +void NeverConditionValidator::SetPriorityNotification( + const absl::optional<std::string>& feature) {} + +absl::optional<std::string> +NeverConditionValidator::GetPendingPriorityNotification() { + return absl::nullopt; +} + } // namespace feature_engagement
diff --git a/components/feature_engagement/internal/never_condition_validator.h b/components/feature_engagement/internal/never_condition_validator.h index b7ecdba0..b5f6c15 100644 --- a/components/feature_engagement/internal/never_condition_validator.h +++ b/components/feature_engagement/internal/never_condition_validator.h
@@ -7,6 +7,7 @@ #include "components/feature_engagement/internal/condition_validator.h" #include "components/feature_engagement/public/feature_list.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { struct Feature; @@ -42,6 +43,9 @@ const FeatureConfig& config, const std::vector<std::string>& all_feature_names) override; void NotifyDismissed(const base::Feature& feature) override; + void SetPriorityNotification( + const absl::optional<std::string>& feature) override; + absl::optional<std::string> GetPendingPriorityNotification() override; }; } // namespace feature_engagement
diff --git a/components/feature_engagement/internal/never_condition_validator_unittest.cc b/components/feature_engagement/internal/never_condition_validator_unittest.cc index fcaea750..e3da1cb 100644 --- a/components/feature_engagement/internal/never_condition_validator_unittest.cc +++ b/components/feature_engagement/internal/never_condition_validator_unittest.cc
@@ -98,6 +98,7 @@ event_model_, availability_model_, display_lock_controller_, nullptr, 0u) .NoErrors()); + EXPECT_FALSE(validator_.GetPendingPriorityNotification().has_value()); } } // namespace feature_engagement
diff --git a/components/feature_engagement/internal/once_condition_validator.cc b/components/feature_engagement/internal/once_condition_validator.cc index 975d859..629329d 100644 --- a/components/feature_engagement/internal/once_condition_validator.cc +++ b/components/feature_engagement/internal/once_condition_validator.cc
@@ -6,6 +6,7 @@ #include "components/feature_engagement/internal/event_model.h" #include "components/feature_engagement/public/configuration.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { @@ -38,6 +39,10 @@ (event_model.GetLastSnoozeTimestamp(config.trigger.name) < base::Time::Now() - base::Days(config.snooze_params.snooze_interval)); + result.priority_notification_ok = + !pending_priority_notification_.has_value() || + pending_priority_notification_.value() == feature.name; + result.should_show_snooze = result.snooze_expiration_ok && event_model.GetSnoozeCount(config.trigger.name, config.trigger.window, @@ -61,4 +66,14 @@ currently_showing_feature_.clear(); } +void OnceConditionValidator::SetPriorityNotification( + const absl::optional<std::string>& feature) { + pending_priority_notification_ = feature; +} + +absl::optional<std::string> +OnceConditionValidator::GetPendingPriorityNotification() { + return pending_priority_notification_; +} + } // namespace feature_engagement
diff --git a/components/feature_engagement/internal/once_condition_validator.h b/components/feature_engagement/internal/once_condition_validator.h index 726493e4..aa8791f 100644 --- a/components/feature_engagement/internal/once_condition_validator.h +++ b/components/feature_engagement/internal/once_condition_validator.h
@@ -9,6 +9,7 @@ #include "components/feature_engagement/internal/condition_validator.h" #include "components/feature_engagement/public/feature_list.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { struct Feature; @@ -55,6 +56,9 @@ const FeatureConfig& config, const std::vector<std::string>& all_feature_names) override; void NotifyDismissed(const base::Feature& feature) override; + void SetPriorityNotification( + const absl::optional<std::string>& feature) override; + absl::optional<std::string> GetPendingPriorityNotification() override; private: // Contains all features that have met conditions within the current session. @@ -63,6 +67,9 @@ // Which feature that is currently being shown, or nullptr if nothing is // currently showing. std::string currently_showing_feature_; + + // Pending priority notification to be shown if any. + absl::optional<std::string> pending_priority_notification_; }; } // namespace feature_engagement
diff --git a/components/feature_engagement/internal/once_condition_validator_unittest.cc b/components/feature_engagement/internal/once_condition_validator_unittest.cc index c7e8a65..64305c3 100644 --- a/components/feature_engagement/internal/once_condition_validator_unittest.cc +++ b/components/feature_engagement/internal/once_condition_validator_unittest.cc
@@ -176,6 +176,22 @@ .NoErrors()); } +TEST_F(OnceConditionValidatorTest, PriorityNotificationBlocksOtherIPHs) { + validator_.SetPriorityNotification("test_bar"); + ConditionValidator::Result result = validator_.MeetsConditions( + kOnceTestFeatureFoo, kValidFeatureConfig, event_model_, + availability_model_, display_lock_controller_, nullptr, 0u); + EXPECT_FALSE(result.NoErrors()); + EXPECT_FALSE(result.priority_notification_ok); + + validator_.SetPriorityNotification(absl::nullopt); + EXPECT_TRUE(validator_ + .MeetsConditions(kOnceTestFeatureFoo, kValidFeatureConfig, + event_model_, availability_model_, + display_lock_controller_, nullptr, 0u) + .NoErrors()); +} + TEST_F(OnceConditionValidatorTest, DoNotTriggerForInvalidConfig) { ConditionValidator::Result result = validator_.MeetsConditions( kOnceTestFeatureFoo, kInvalidFeatureConfig, event_model_,
diff --git a/components/feature_engagement/internal/tracker_impl.cc b/components/feature_engagement/internal/tracker_impl.cc index 885df49..66842b9c 100644 --- a/components/feature_engagement/internal/tracker_impl.cc +++ b/components/feature_engagement/internal/tracker_impl.cc
@@ -36,6 +36,7 @@ #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/feature_list.h" #include "components/leveldb_proto/public/proto_database_provider.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { @@ -296,6 +297,46 @@ return display_lock_controller_->AcquireDisplayLock(); } +void TrackerImpl::SetPriorityNotification(const base::Feature& feature) { + // If the handler hasn't been registered. + auto iter = priority_notification_handlers_.find(feature.name); + if (iter == priority_notification_handlers_.end()) { + condition_validator_->SetPriorityNotification(feature.name); + return; + } + + // We already have a handler. Serve the request and remove the handler. + condition_validator_->SetPriorityNotification(absl::nullopt); + std::move(iter->second).Run(); + priority_notification_handlers_.erase(feature.name); +} + +absl::optional<std::string> TrackerImpl::GetPendingPriorityNotification() { + return condition_validator_->GetPendingPriorityNotification(); +} + +void TrackerImpl::RegisterPriorityNotificationHandler( + const base::Feature& feature, + base::OnceClosure callback) { + // If we already have a pending notification, handle it right away. + auto pending_priority_notification = + condition_validator_->GetPendingPriorityNotification(); + if (pending_priority_notification.has_value() && + pending_priority_notification.value() == feature.name) { + std::move(callback).Run(); + condition_validator_->SetPriorityNotification(absl::nullopt); + return; + } + + // We don't have the notification yet. Cache the handler. + priority_notification_handlers_.emplace(feature.name, std::move(callback)); +} + +void TrackerImpl::UnregisterPriorityNotificationHandler( + const base::Feature& feature) { + priority_notification_handlers_.erase(feature.name); +} + bool TrackerImpl::IsInitialized() const { return event_model_->IsReady() && availability_model_->IsReady(); }
diff --git a/components/feature_engagement/internal/tracker_impl.h b/components/feature_engagement/internal/tracker_impl.h index 0c1621bd..21580b3 100644 --- a/components/feature_engagement/internal/tracker_impl.h +++ b/components/feature_engagement/internal/tracker_impl.h
@@ -12,6 +12,7 @@ #include "base/feature_list.h" #include "base/memory/weak_ptr.h" #include "components/feature_engagement/public/tracker.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { class AvailabilityModel; @@ -53,6 +54,12 @@ std::unique_ptr<DisplayLockHandle> AcquireDisplayLock() override; bool IsInitialized() const override; void AddOnInitializedCallback(OnInitializedCallback callback) override; + void SetPriorityNotification(const base::Feature& feature) override; + absl::optional<std::string> GetPendingPriorityNotification() override; + void RegisterPriorityNotificationHandler(const base::Feature& feature, + base::OnceClosure callback) override; + void UnregisterPriorityNotificationHandler( + const base::Feature& feature) override; private: // Invoked by the EventModel when it has been initialized. @@ -102,6 +109,9 @@ // is cleared after the initialization has happened. std::vector<OnInitializedCallback> on_initialized_callbacks_; + // Registered priority notification handlers for various features. + std::map<std::string, base::OnceClosure> priority_notification_handlers_; + base::WeakPtrFactory<TrackerImpl> weak_ptr_factory_{this}; };
diff --git a/components/feature_engagement/internal/tracker_impl_unittest.cc b/components/feature_engagement/internal/tracker_impl_unittest.cc index ad76fee..0b407e6 100644 --- a/components/feature_engagement/internal/tracker_impl_unittest.cc +++ b/components/feature_engagement/internal/tracker_impl_unittest.cc
@@ -9,12 +9,14 @@ #include <utility> #include "base/bind.h" +#include "base/callback_forward.h" #include "base/callback_helpers.h" #include "base/feature_list.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" +#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/task_environment.h" @@ -646,6 +648,85 @@ EXPECT_FALSE(callback.success()); } +TEST_F(TrackerImplTest, TestSetPriorityNotificationBeforeRegistration) { + // Ensure all initialization is finished. + StoringInitializedCallback callback; + tracker_->AddOnInitializedCallback(base::BindOnce( + &StoringInitializedCallback::OnInitialized, base::Unretained(&callback))); + base::RunLoop().RunUntilIdle(); + + bool invoked = false; + + // Set priority notification, and then register handler. IPH will show up + // immediately after registration. + tracker_->SetPriorityNotification(kTrackerTestFeatureFoo); + tracker_->RegisterPriorityNotificationHandler( + kTrackerTestFeatureFoo, + base::BindLambdaForTesting([&]() { invoked = true; })); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(invoked); + + // Try registering handler once again. The IPH won't show up again since the + // notification has been consumed. + invoked = false; + tracker_->RegisterPriorityNotificationHandler( + kTrackerTestFeatureFoo, + base::BindLambdaForTesting([&]() { invoked = true; })); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(invoked); + + // Set priority notification one more time. Now the IPH will show up. + tracker_->SetPriorityNotification(kTrackerTestFeatureFoo); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(invoked); +} + +TEST_F(TrackerImplTest, TestSetPriorityNotificationAfterRegistration) { + // Ensure all initialization is finished. + StoringInitializedCallback callback; + tracker_->AddOnInitializedCallback(base::BindOnce( + &StoringInitializedCallback::OnInitialized, base::Unretained(&callback))); + base::RunLoop().RunUntilIdle(); + + bool invoked = false; + + // Register the handler first, and then set priority notification. + tracker_->RegisterPriorityNotificationHandler( + kTrackerTestFeatureFoo, + base::BindLambdaForTesting([&]() { invoked = true; })); + tracker_->SetPriorityNotification(kTrackerTestFeatureFoo); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(invoked); + + // Set priority notification again. The IPH won't show up again, since the + // handler is good for only one use. + invoked = false; + tracker_->SetPriorityNotification(kTrackerTestFeatureFoo); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(invoked); +} + +TEST_F(TrackerImplTest, TestUnregisterPriorityNotification) { + // Ensure all initialization is finished. + StoringInitializedCallback callback; + tracker_->AddOnInitializedCallback(base::BindOnce( + &StoringInitializedCallback::OnInitialized, base::Unretained(&callback))); + base::RunLoop().RunUntilIdle(); + + bool invoked = false; + + // Register the handler, and unregister before setting the notification. The + // IPH won't show up. + invoked = false; + tracker_->RegisterPriorityNotificationHandler( + kTrackerTestFeatureFoo, + base::BindLambdaForTesting([&]() { invoked = true; })); + tracker_->UnregisterPriorityNotificationHandler(kTrackerTestFeatureFoo); + tracker_->SetPriorityNotification(kTrackerTestFeatureFoo); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(invoked); +} + TEST_F(TrackerImplTest, TestTriggering) { // Ensure all initialization is finished. StoringInitializedCallback callback;
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/CppWrappedTestTracker.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/CppWrappedTestTracker.java index 55a1e51..781c303 100644 --- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/CppWrappedTestTracker.java +++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/CppWrappedTestTracker.java
@@ -116,6 +116,22 @@ return () -> {}; } + @Override + public void setPriorityNotification(String feature) {} + + @Override + @Nullable + public String getPendingPriorityNotification() { + return null; + } + + @Override + public void registerPriorityNotificationHandler( + String feature, Runnable priorityNotificationHandler) {} + + @Override + public void unregisterPriorityNotificationHandler(String feature) {} + @CalledByNative @Override public boolean isInitialized() {
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/Tracker.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/Tracker.java index c54f368..868eeea 100644 --- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/Tracker.java +++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/Tracker.java
@@ -128,6 +128,31 @@ DisplayLockHandle acquireDisplayLock(); /** + * Called by the client to notify the tracker that a priority notification should be shown. If a + * handler has already been registered, the IPH will be shown right away. Otherwise, the tracker + * will cache the priority feature and will show the IPH whenever a handler is registered in + * future. All other IPHs will be blocked until then. + */ + void setPriorityNotification(String feature); + + /** + * Called to check if there is a priority notification scheduled to be shown next. Returns null + * if there is none scheduled to be shown or the notification has already been shown. + */ + @Nullable + String getPendingPriorityNotification(); + + /** + * Called by the client to register a handler for priority notifications. This + * will essentially contain the code to spin up an IPH. The handler runs only once and + * unregisters itself. + */ + void registerPriorityNotificationHandler(String feature, Runnable priorityNotificationHandler); + + /** Unregister the handler. Must be called during client destruction. */ + void unregisterPriorityNotificationHandler(String feature); + + /** * Returns whether the tracker has been successfully initialized. During startup, this will be * false until the internal models have been loaded at which point it is set to true if the * initialization was successful. The state will never change from initialized to uninitialized.
diff --git a/components/feature_engagement/public/android/wrapping_test_tracker.cc b/components/feature_engagement/public/android/wrapping_test_tracker.cc index 951bbb75..71c1dd1f 100644 --- a/components/feature_engagement/public/android/wrapping_test_tracker.cc +++ b/components/feature_engagement/public/android/wrapping_test_tracker.cc
@@ -10,6 +10,7 @@ #include "base/android/jni_string.h" #include "base/threading/thread_task_runner_handle.h" #include "components/feature_engagement/public/jni_headers/CppWrappedTestTracker_jni.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { @@ -91,6 +92,21 @@ return nullptr; } +void WrappingTestTracker::SetPriorityNotification( + const base::Feature& feature) {} + +absl::optional<std::string> +WrappingTestTracker::GetPendingPriorityNotification() { + return absl::nullopt; +} + +void WrappingTestTracker::RegisterPriorityNotificationHandler( + const base::Feature& feature, + base::OnceClosure callback) {} + +void WrappingTestTracker::UnregisterPriorityNotificationHandler( + const base::Feature& feature) {} + bool WrappingTestTracker::IsInitialized() const { return Java_CppWrappedTestTracker_isInitialized( base::android::AttachCurrentThread(), java_tracker_);
diff --git a/components/feature_engagement/public/android/wrapping_test_tracker.h b/components/feature_engagement/public/android/wrapping_test_tracker.h index 5fb0f68..ee39acd 100644 --- a/components/feature_engagement/public/android/wrapping_test_tracker.h +++ b/components/feature_engagement/public/android/wrapping_test_tracker.h
@@ -11,6 +11,7 @@ #include "base/android/jni_android.h" #include "base/callback.h" #include "components/feature_engagement/public/tracker.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { // This class wraps a Tracker from Java and forwards to it all calls received. @@ -37,6 +38,12 @@ void DismissedWithSnooze(const base::Feature& feature, absl::optional<SnoozeAction> snooze_action) override; std::unique_ptr<DisplayLockHandle> AcquireDisplayLock() override; + absl::optional<std::string> GetPendingPriorityNotification() override; + void SetPriorityNotification(const base::Feature& feature) override; + void RegisterPriorityNotificationHandler(const base::Feature& feature, + base::OnceClosure callback) override; + void UnregisterPriorityNotificationHandler( + const base::Feature& feature) override; bool IsInitialized() const override; void AddOnInitializedCallback(OnInitializedCallback callback) override;
diff --git a/components/feature_engagement/public/tracker.h b/components/feature_engagement/public/tracker.h index 17e6ed9b..899eef8 100644 --- a/components/feature_engagement/public/tracker.h +++ b/components/feature_engagement/public/tracker.h
@@ -16,6 +16,7 @@ #include "base/task/sequenced_task_runner.h" #include "build/build_config.h" #include "components/keyed_service/core/keyed_service.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #if BUILDFLAG(IS_ANDROID) #include "base/android/jni_android.h" @@ -191,6 +192,27 @@ // This method returns nullptr if no handle could be retrieved. virtual std::unique_ptr<DisplayLockHandle> AcquireDisplayLock() = 0; + // Called by the client to notify the tracker that a priority notification + // should be shown. If a handler has already been registered, the IPH will be + // shown right away. Otherwise, the tracker will cache the priority feature + // and will show the IPH whenever a handler is registered in future. All other + // IPHs will be blocked until then. It isn't allowed to invoke this method + // again with another notification before the existing one is processed. + virtual void SetPriorityNotification(const base::Feature& feature) = 0; + + // Called to get if there is a pending priority notification to be shown next. + virtual absl::optional<std::string> GetPendingPriorityNotification() = 0; + + // Called by the client to register a handler for priority notifications. This + // will essentially contain the code to spin up an IPH. + virtual void RegisterPriorityNotificationHandler( + const base::Feature& feature, + base::OnceClosure callback) = 0; + + // Unregister the handler. Must be called during client destruction. + virtual void UnregisterPriorityNotificationHandler( + const base::Feature& feature) = 0; + // Returns whether the tracker has been successfully initialized. During // startup, this will be false until the internal models have been loaded at // which point it is set to true if the initialization was successful. The
diff --git a/components/feature_engagement/test/mock_tracker.h b/components/feature_engagement/test/mock_tracker.h index a4ba043..25aefb2 100644 --- a/components/feature_engagement/test/mock_tracker.h +++ b/components/feature_engagement/test/mock_tracker.h
@@ -10,6 +10,7 @@ #include "components/feature_engagement/public/tracker.h" #include "testing/gmock/include/gmock/gmock.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace feature_engagement { namespace test { @@ -39,6 +40,12 @@ void(const base::Feature& feature, absl::optional<SnoozeAction> snooze_action)); MOCK_METHOD0(AcquireDisplayLock, std::unique_ptr<DisplayLockHandle>()); + MOCK_METHOD1(SetPriorityNotification, void(const base::Feature&)); + MOCK_METHOD0(GetPendingPriorityNotification, absl::optional<std::string>()); + MOCK_METHOD2(RegisterPriorityNotificationHandler, + void(const base::Feature&, base::OnceClosure)); + MOCK_METHOD1(UnregisterPriorityNotificationHandler, + void(const base::Feature&)); MOCK_METHOD1(AddOnInitializedCallback, void(OnInitializedCallback callback)); };
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory.cc b/components/invalidation/impl/invalidator_registrar_with_memory.cc index bead8450..1f35ce4 100644 --- a/components/invalidation/impl/invalidator_registrar_with_memory.cc +++ b/components/invalidation/impl/invalidator_registrar_with_memory.cc
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/feature_list.h" #include "base/logging.h" #include "base/stl_util.h" #include "base/values.h" @@ -55,6 +56,9 @@ } // namespace +const base::Feature kRestoreInterestingTopicsFeature{ + "InvalidatorRestoreInterestingTopics", base::FEATURE_ENABLED_BY_DEFAULT}; + // static void InvalidatorRegistrarWithMemory::RegisterProfilePrefs( PrefRegistrySimple* registry) { @@ -87,16 +91,18 @@ return; } // Restore |handler_name_to_subscribed_topics_map_| from prefs. + if (!base::FeatureList::IsEnabled(kRestoreInterestingTopicsFeature)) + return; for (auto it : pref_data->DictItems()) { const std::string& topic_name = it.first; if (it.second.is_dict()) { - const base::Value* handler = it.second.FindDictKey(kHandler); - const base::Value* is_public = it.second.FindDictKey(kIsPublic); + const std::string* handler = it.second.FindStringKey(kHandler); + const absl::optional<bool> is_public = it.second.FindBoolKey(kIsPublic); if (!handler || !is_public) { continue; } - handler_name_to_subscribed_topics_map_[handler->GetString()].insert( - TopicData(topic_name, is_public->GetBool())); + handler_name_to_subscribed_topics_map_[*handler].insert( + TopicData(topic_name, *is_public)); } else if (it.second.is_string()) { handler_name_to_subscribed_topics_map_[it.second.GetString()].insert( TopicData(topic_name, false));
diff --git a/components/invalidation/impl/invalidator_registrar_with_memory_unittest.cc b/components/invalidation/impl/invalidator_registrar_with_memory_unittest.cc index c92918a7..68352df 100644 --- a/components/invalidation/impl/invalidator_registrar_with_memory_unittest.cc +++ b/components/invalidation/impl/invalidator_registrar_with_memory_unittest.cc
@@ -6,6 +6,9 @@ #include <memory> +#include "base/feature_list.h" +#include "base/json/json_reader.h" +#include "base/test/scoped_feature_list.h" #include "components/invalidation/impl/fake_invalidation_handler.h" #include "components/invalidation/public/invalidation.h" #include "components/invalidation/public/invalidation_util.h" @@ -243,6 +246,48 @@ invalidator->UnregisterHandler(&handler1); } +TEST(InvalidatorRegistrarWithMemoryTest, RestoresInterestingTopics) { + constexpr char kTopicsToHandler[] = + "invalidation.per_sender_topics_to_handler"; + + const base::Feature restore_interesting_topics_feature{ + "InvalidatorRestoreInterestingTopics", base::FEATURE_ENABLED_BY_DEFAULT}; + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(restore_interesting_topics_feature); + + TestingPrefServiceSimple pref_service; + InvalidatorRegistrarWithMemory::RegisterProfilePrefs(pref_service.registry()); + + // Set up some previously-registered topics in the pref. + constexpr char kStoredTopicsJson[] = + R"({"sender_id": { + "topic_1": {"handler": "handler_1", "is_public": true}, + "topic_2": {"handler": "handler_2", "is_public": true}, + "topic_3": "handler_3", + "topic_4_1": {"handler": "handler_4", "is_public": false}, + "topic_4_2": {"handler": "handler_4", "is_public": false}, + "topic_4_3": {"handler": "handler_4", "is_public": false} + }})"; + + absl::optional<base::Value> stored_topics = + base::JSONReader::Read(kStoredTopicsJson); + ASSERT_TRUE(stored_topics); + pref_service.Set(kTopicsToHandler, std::move(*stored_topics)); + + // Create an invalidator and make sure it correctly restored state from the + // pref. + auto invalidator = std::make_unique<InvalidatorRegistrarWithMemory>( + &pref_service, "sender_id", /*migrate_old_prefs=*/false); + + std::map<std::string, TopicMetadata> expected_subscribed_topics{ + {"topic_1", TopicMetadata{true}}, {"topic_2", TopicMetadata{true}}, + {"topic_3", TopicMetadata{false}}, {"topic_4_1", TopicMetadata{false}}, + {"topic_4_2", TopicMetadata{false}}, {"topic_4_3", TopicMetadata{false}}, + }; + + EXPECT_EQ(expected_subscribed_topics, invalidator->GetAllSubscribedTopics()); +} + } // namespace } // namespace invalidation
diff --git a/components/optimization_guide/content/browser/page_content_annotations_service.cc b/components/optimization_guide/content/browser/page_content_annotations_service.cc index 48e2b09..d3ba5ba6 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_service.cc +++ b/components/optimization_guide/content/browser/page_content_annotations_service.cc
@@ -98,7 +98,8 @@ const base::FilePath& database_dir, scoped_refptr<base::SequencedTaskRunner> background_task_runner) : last_annotated_history_visits_( - features::MaxContentAnnotationRequestsCached()) { + features::MaxContentAnnotationRequestsCached()), + annotated_text_cache_(features::MaxVisitAnnotationCacheSize()) { DCHECK(optimization_guide_model_provider); DCHECK(history_service); history_service_ = history_service; @@ -143,7 +144,25 @@ // Used for testing. LOCAL_HISTOGRAM_BOOLEAN( "PageContentAnnotations.AnnotateVisit.AnnotationRequested", true); + + if (annotated_text_cache_.Peek(*visit.text_to_annotate) != + annotated_text_cache_.end()) { + // We have annotations the text for this visit, so return that immediately + // rather than re-executing the model. + // + // TODO(crbug.com/1291275): If the model was updated, the cached value could + // be stale so we should invalidate the cache on model updates. + OnPageContentAnnotated( + visit, annotated_text_cache_.Get(*visit.text_to_annotate)->second); + base::UmaHistogramBoolean( + "OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached", + true); + return; + } visits_to_annotate_.emplace_back(visit); + base::UmaHistogramBoolean( + "OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached", + false); if (visits_to_annotate_.size() >= features::AnnotateVisitBatchSize()) { if (current_visit_annotation_batch_.empty()) { // Used for testing. @@ -260,6 +279,10 @@ if (!content_annotations) return; + if (annotated_text_cache_.Peek(*visit.text_to_annotate) == + annotated_text_cache_.end()) { + annotated_text_cache_.Put(*visit.text_to_annotate, *content_annotations); + } MaybeRecordVisibilityUKM(visit, content_annotations); if (!features::ShouldWriteContentAnnotationsToHistoryService())
diff --git a/components/optimization_guide/content/browser/page_content_annotations_service.h b/components/optimization_guide/content/browser/page_content_annotations_service.h index 0d490fa..278a005 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_service.h +++ b/components/optimization_guide/content/browser/page_content_annotations_service.h
@@ -225,6 +225,11 @@ base::LRUCache<HistoryVisit, bool, HistoryVisit::Comp> last_annotated_history_visits_; + // A LRU cache of the annotation results for visits. If the text of the visit + // is in the cache, the cached model annotations will be used. + base::HashingLRUCache<std::string, history::VisitContentModelAnnotations> + annotated_text_cache_; + // The set of visits to be annotated, this is added to by Annotate requests // from the web content observer. These will be annotated when the set is full // and annotations can be scheduled with minimal impact to browsing.
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index 13b1cb6b..1abf629 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -550,5 +550,11 @@ return std::max(1, batch_size); } +size_t MaxVisitAnnotationCacheSize() { + int batch_size = GetFieldTrialParamByFeatureAsInt( + kPageContentAnnotations, "max_visit_annotation_cache_size", 50); + return std::max(1, batch_size); +} + } // namespace features } // namespace optimization_guide
diff --git a/components/optimization_guide/core/optimization_guide_features.h b/components/optimization_guide/core/optimization_guide_features.h index d12ff9a..8eb0a55 100644 --- a/components/optimization_guide/core/optimization_guide_features.h +++ b/components/optimization_guide/core/optimization_guide_features.h
@@ -269,6 +269,9 @@ // The size of batches to run for validation. size_t BatchAnnotationsValidationBatchSize(); +// The maximum size of the visit annotation cache. +size_t MaxVisitAnnotationCacheSize(); + } // namespace features } // namespace optimization_guide
diff --git a/components/reporting/storage/BUILD.gn b/components/reporting/storage/BUILD.gn index 0f201eda..bf3ea44 100644 --- a/components/reporting/storage/BUILD.gn +++ b/components/reporting/storage/BUILD.gn
@@ -44,6 +44,7 @@ "//components/reporting/proto:record_constants", "//components/reporting/proto:record_proto", "//components/reporting/resources:resource_interface", + "//components/reporting/util:file", "//components/reporting/util:status", "//components/reporting/util:status_macros", "//components/reporting/util:task_runner_context", @@ -71,6 +72,7 @@ "//components/reporting/encryption:verification", "//components/reporting/proto:record_constants", "//components/reporting/proto:record_proto", + "//components/reporting/util:file", "//components/reporting/util:status", "//components/reporting/util:status_macros", "//components/reporting/util:task_runner_context",
diff --git a/components/reporting/storage/storage.cc b/components/reporting/storage/storage.cc index ee92940..40257243 100644 --- a/components/reporting/storage/storage.cc +++ b/components/reporting/storage/storage.cc
@@ -33,6 +33,7 @@ #include "components/reporting/storage/storage_configuration.h" #include "components/reporting/storage/storage_queue.h" #include "components/reporting/storage/storage_uploader_interface.h" +#include "components/reporting/util/file.h" #include "components/reporting/util/status.h" #include "components/reporting/util/status_macros.h" #include "components/reporting/util/statusor.h" @@ -345,7 +346,7 @@ if (full_name == signed_encryption_key_result.value().first) { continue; // This file is used. } - base::DeleteFile(full_name); // Ignore errors, if any. + DeleteFileWarnIfFailed(full_name); // Ignore errors, if any. } // Return the key. @@ -445,7 +446,7 @@ } // Delete all files assigned for deletion. for (const auto& file_to_remove : key_files_to_remove) { - base::DeleteFile(file_to_remove); // Ignore errors, if any. + DeleteFileWarnIfFailed(file_to_remove); // Ignore errors, if any. } }
diff --git a/components/reporting/storage/storage_queue.cc b/components/reporting/storage/storage_queue.cc index b48f061aa..f786258f 100644 --- a/components/reporting/storage/storage_queue.cc +++ b/components/reporting/storage/storage_queue.cc
@@ -42,6 +42,7 @@ #include "components/reporting/resources/resource_interface.h" #include "components/reporting/storage/storage_configuration.h" #include "components/reporting/storage/storage_uploader_interface.h" +#include "components/reporting/util/file.h" #include "components/reporting/util/status.h" #include "components/reporting/util/status_macros.h" #include "components/reporting/util/statusor.h" @@ -758,8 +759,8 @@ } } for (const auto& file_to_delete : files_to_delete) { - // Ignore result. If it fails, the file will be naturally handled next time. - base::DeleteFile(file_to_delete); + // If it fails, the file will be naturally handled next time. + DeleteFileWarnIfFailed(file_to_delete); } } @@ -790,8 +791,8 @@ for (const auto& file_to_delete : files_to_delete) { // Delete file on disk. Note: disk space has already been released when the // metafile was destructed, and so we don't need to do that here. - // Ignore result. If it fails, the file will be naturally handled next time. - base::DeleteFile(file_to_delete); + // If it fails, the file will be naturally handled next time. + DeleteFileWarnIfFailed(file_to_delete); } } @@ -1635,7 +1636,7 @@ // Current file holds only ids <= sequencing_id. // Delete it. files_.begin()->second->Close(); - files_.begin()->second->Delete(); // ignore results + files_.begin()->second->DeleteWarnIfFailed(); files_.erase(files_.begin()); } // Even if there were errors, ignore them. @@ -1747,15 +1748,11 @@ } } -Status StorageQueue::SingleFile::Delete() { +void StorageQueue::SingleFile::DeleteWarnIfFailed() { DCHECK(!handle_); GetDiskResource()->Discard(size_); size_ = 0; - if (!base::DeleteFile(filename_)) { - return Status(error::DATA_LOSS, - base::StrCat({"Cannot delete file=", name()})); - } - return Status::StatusOK(); + DeleteFileWarnIfFailed(filename_); } StatusOr<base::StringPiece> StorageQueue::SingleFile::Read(
diff --git a/components/reporting/storage/storage_queue.h b/components/reporting/storage/storage_queue.h index 4f367ed9..88619b3 100644 --- a/components/reporting/storage/storage_queue.h +++ b/components/reporting/storage/storage_queue.h
@@ -151,7 +151,7 @@ Status Open(bool read_only); // No-op if already opened. void Close(); // No-op if not opened. - Status Delete(); + void DeleteWarnIfFailed(); // Attempts to read |size| bytes from position |pos| and returns // reference to the data that were actually read (no more than |size|).
diff --git a/components/reporting/util/BUILD.gn b/components/reporting/util/BUILD.gn index a5cacd7..5b45f1d 100644 --- a/components/reporting/util/BUILD.gn +++ b/components/reporting/util/BUILD.gn
@@ -15,6 +15,14 @@ deps = [ "//net" ] } +static_library("file") { + sources = [ + "file.cc", + "file.h", + ] + deps = [ "//base" ] +} + source_set("shared_vector") { sources = [ "shared_vector.h" ] deps = [ @@ -73,6 +81,7 @@ source_set("unit_tests") { testonly = true sources = [ + "file_unittest.cc", "shared_queue_unittest.cc", "shared_vector_unittest.cc", "status_macros_unittest.cc", @@ -80,6 +89,7 @@ "statusor_unittest.cc", ] deps = [ + ":file", ":shared_queue", ":shared_vector", ":status",
diff --git a/components/reporting/util/file.cc b/components/reporting/util/file.cc new file mode 100644 index 0000000..02411606 --- /dev/null +++ b/components/reporting/util/file.cc
@@ -0,0 +1,20 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/reporting/util/file.h" + +#include "base/files/file_util.h" +#include "base/logging.h" + +namespace reporting { + +bool DeleteFileWarnIfFailed(const base::FilePath& path) { + const auto delete_result = base::DeleteFile(path); + if (!delete_result) { + LOG(WARNING) << "Failed to delete " << path.MaybeAsASCII(); + } + return delete_result; +} + +} // namespace reporting
diff --git a/components/reporting/util/file.h b/components/reporting/util/file.h new file mode 100644 index 0000000..9825441f --- /dev/null +++ b/components/reporting/util/file.h
@@ -0,0 +1,22 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Utilities for file operations. + +#ifndef COMPONENTS_REPORTING_UTIL_FILE_H_ +#define COMPONENTS_REPORTING_UTIL_FILE_H_ + +#include "base/files/file_util.h" + +namespace reporting { + +// Deletes the given path, whether it's a file or a directory. +// This function is identical to base::DeleteFile() except that it issues a +// warning if the deletion fails. Useful when we do not care about whether the +// deletion succeeds or not. +bool DeleteFileWarnIfFailed(const base::FilePath& path); + +} // namespace reporting + +#endif // COMPONENTS_REPORTING_UTIL_FILE_H_
diff --git a/components/reporting/util/file_unittest.cc b/components/reporting/util/file_unittest.cc new file mode 100644 index 0000000..2f47eb4 --- /dev/null +++ b/components/reporting/util/file_unittest.cc
@@ -0,0 +1,68 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/reporting/util/file.h" + +#include "base/files/file.h" +#include "base/files/scoped_temp_dir.h" +#include "base/test/test_file_util.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace reporting { +namespace { + +TEST(FileTest, DeleteFileWarnIfFailed) { + // This test briefly tests DeleteFileWarnIfFailed, as it mostly calls + // DeleteFile(), which should be more extensively tested in base. + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + const auto dir_path = temp_dir.GetPath(); + ASSERT_TRUE(base::DirectoryExists(dir_path)); + + base::FilePath file_path; + ASSERT_TRUE(base::CreateTemporaryFileInDir(dir_path, &file_path)); + + // Delete an existing file with no permission. + // Don't test on Fuchsia: No file permission support. See + // base/files/file_util_unittest.cc for some similar tests being skipped. +#if !BUILDFLAG(IS_FUCHSIA) + { + // On Windows, we open the file to prevent it from being deleted. Otherwise, + // we modify the directory permission to prevent it from being deleted. +#if BUILDFLAG(IS_WIN) + base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + ASSERT_TRUE(file.IsValid()); +#else // BUILDFLAG(IS_WIN) + base::FilePermissionRestorer restore_permissions_for(dir_path); + // Get rid of the write permission from temp_dir + ASSERT_TRUE(base::MakeFileUnwritable(dir_path)); + // Ensure no deletion permission + ASSERT_FALSE(base::PathIsWritable(dir_path)); +#endif // BUILDFLAG(IS_WIN) + ASSERT_TRUE(base::PathExists(file_path)); + ASSERT_FALSE(DeleteFileWarnIfFailed(file_path)) + << "Deletion of an existing file without permission should fail"; + } +#endif // !BUILDFLAG(IS_FUCHSIA) + + { + // Delete with permission + ASSERT_TRUE(base::PathIsWritable(dir_path)); // Ensure deletion permission + ASSERT_TRUE(base::PathExists(file_path)); + ASSERT_TRUE(DeleteFileWarnIfFailed(file_path)) + << "Deletion of an existing file should succeed"; + ASSERT_FALSE(base::PathExists(file_path)) << "File failed to be deleted"; + } + + // Delete a non-existing file + { + ASSERT_FALSE(base::PathExists(file_path)); + ASSERT_TRUE(DeleteFileWarnIfFailed(file_path)) + << "Deletion of a nonexisting file should succeed"; + } +} + +} // namespace +} // namespace reporting
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc index 387c93ca..e6a6f68 100644 --- a/components/url_pattern_index/url_pattern_index.cc +++ b/components/url_pattern_index/url_pattern_index.cc
@@ -792,6 +792,11 @@ const flat::UrlPatternIndex* flat_index) : flat_index_(flat_index) { DCHECK(!flat_index || flat_index->n() == kNGramSize); + // Speculative investigation for crash (see crbug.com/1286207): check that we + // can access the ngram_index on each UrlPatternIndexMatcher without failure. + if (flat_index) { + CHECK_GT(flat_index->ngram_index()->size(), 0u); + } } UrlPatternIndexMatcher::~UrlPatternIndexMatcher() = default;
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc index 176f1bde..39e9b18c 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -123,9 +123,10 @@ const int kCompatibleVersionNumber = 15; // Latest version of the database that cannot be upgraded to -// |kCurrentVersionNumber| without razing the database. No versions are -// currently deprecated. -const int kDeprecatedVersionNumber = 0; +// |kCurrentVersionNumber| without razing the database. +// +// Versions 1-14 were deprecated by https://crrev.com/c/3421175. +const int kDeprecatedVersionNumber = 14; void RecordInitializationStatus( const AttributionStorageSql::InitStatus status) { @@ -1475,8 +1476,7 @@ return CreateSchema(); } - return UpgradeAttributionStorageSqlSchema(db_.get(), &meta_table_, - delegate_.get()); + return UpgradeAttributionStorageSqlSchema(db_.get(), &meta_table_); } bool AttributionStorageSql::CreateSchema() {
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_migrations.cc b/content/browser/attribution_reporting/attribution_storage_sql_migrations.cc index 9bb8f608..996713f 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_migrations.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql_migrations.cc
@@ -4,1292 +4,19 @@ #include "content/browser/attribution_reporting/attribution_storage_sql_migrations.h" -#include <vector> - -#include "base/guid.h" +#include "base/check.h" #include "base/metrics/histogram_functions.h" -#include "content/browser/attribution_reporting/attribution_report.h" -#include "content/browser/attribution_reporting/attribution_storage.h" -#include "content/browser/attribution_reporting/common_source_info.h" -#include "content/browser/attribution_reporting/sql_utils.h" -#include "content/browser/attribution_reporting/stored_source.h" -#include "net/base/schemeful_site.h" -#include "sql/database.h" -#include "sql/meta_table.h" -#include "sql/statement.h" -#include "sql/transaction.h" -#include "url/origin.h" +#include "base/time/time.h" namespace content { -namespace { - -StoredSource::Id NextImpressionId(StoredSource::Id id) { - return StoredSource::Id(*id + 1); -} - -AttributionReport::EventLevelData::Id NextConversionId( - AttributionReport::EventLevelData::Id id) { - return AttributionReport::EventLevelData::Id(*id + 1); -} - -struct ImpressionIdAndConversionOrigin { - StoredSource::Id source_id; - url::Origin conversion_origin; -}; - -std::vector<ImpressionIdAndConversionOrigin> -GetImpressionIdAndConversionOrigins(sql::Database* db, - StoredSource::Id start_source_id) { - static constexpr char kGetImpressionsSql[] = - "SELECT impression_id,conversion_origin " - "FROM impressions " - "WHERE impression_id >= ? " - "ORDER BY impression_id " - "LIMIT ?"; - - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kGetImpressionsSql)); - statement.BindInt64(0, *start_source_id); - - const int kNumImpressions = 100; - statement.BindInt(1, kNumImpressions); - - std::vector<ImpressionIdAndConversionOrigin> impressions; - while (statement.Step()) { - StoredSource::Id source_id(statement.ColumnInt64(0)); - url::Origin conversion_origin = - DeserializeOrigin(statement.ColumnString(1)); - - impressions.push_back({source_id, std::move(conversion_origin)}); - } - if (!statement.Succeeded()) - return {}; - return impressions; -} - -struct ImpressionIdAndImpressionOrigin { - StoredSource::Id source_id; - url::Origin impression_origin; -}; - -std::vector<ImpressionIdAndImpressionOrigin> -GetImpressionIdAndImpressionOrigins(sql::Database* db, - StoredSource::Id start_source_id) { - static constexpr char kGetImpressionsSql[] = - "SELECT impression_id,impression_origin " - "FROM impressions " - "WHERE impression_id >= ? " - "ORDER BY impression_id " - "LIMIT ?"; - - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kGetImpressionsSql)); - statement.BindInt64(0, *start_source_id); - - const int kNumImpressions = 100; - statement.BindInt(1, kNumImpressions); - - std::vector<ImpressionIdAndImpressionOrigin> impressions; - while (statement.Step()) { - StoredSource::Id source_id(statement.ColumnInt64(0)); - url::Origin impression_origin = - DeserializeOrigin(statement.ColumnString(1)); - - impressions.push_back({source_id, std::move(impression_origin)}); - } - if (!statement.Succeeded()) - return {}; - return impressions; -} - -std::vector<AttributionReport::EventLevelData::Id> GetConversionIds( - sql::Database* db, - AttributionReport::EventLevelData::Id start_conversion_id) { - static constexpr char kGetConversionsSql[] = - "SELECT conversion_id FROM conversions " - "WHERE conversion_id >= ? " - "ORDER BY conversion_id " - "LIMIT ?"; - - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kGetConversionsSql)); - statement.BindInt64(0, *start_conversion_id); - - const int kNumConversions = 100; - statement.BindInt(1, kNumConversions); - - std::vector<AttributionReport::EventLevelData::Id> conversion_ids; - while (statement.Step()) { - conversion_ids.emplace_back(statement.ColumnInt64(0)); - } - if (!statement.Succeeded()) - return {}; - return conversion_ids; -} - -bool MigrateToVersion2(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. This results in smaller - // transactions, so it's less likely that a transaction's buffer will need to - // spill to disk. Also, if the database grows a lot and Chrome stops (user - // quit, process kill, etc.) during the migration process, per-migration - // transactions make it more likely that we'll make forward progress each time - // Chrome stops. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Add a new conversion_destination column to the impressions table. This - // follows the steps documented at - // https://sqlite.org/lang_altertable.html#otheralter. Other approaches, like - // using "ALTER ... ADD COLUMN" require setting a DEFAULT value for the column - // which is undesirable. - static constexpr char kNewImpressionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_impressions" - "(impression_id INTEGER PRIMARY KEY," - "impression_data TEXT NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "reporting_origin TEXT NOT NULL," - "impression_time INTEGER NOT NULL," - "expiry_time INTEGER NOT NULL," - "num_conversions INTEGER DEFAULT 0," - "active INTEGER DEFAULT 1," - "conversion_destination TEXT NOT NULL)"; - if (!db->Execute(kNewImpressionTableSql)) - return false; - - // Transfer the existing rows to the new table, inserting a placeholder for - // the conversion_destination column. - static constexpr char kPopulateNewImpressionTableSql[] = - "INSERT INTO new_impressions SELECT " - "impression_id,impression_data,impression_origin," - "conversion_origin,reporting_origin,impression_time," - "expiry_time,num_conversions,active,'' " - "FROM impressions"; - if (!db->Execute(kPopulateNewImpressionTableSql)) - return false; - - static constexpr char kDropOldImpressionTableSql[] = "DROP TABLE impressions"; - if (!db->Execute(kDropOldImpressionTableSql)) - return false; - - static constexpr char kRenameImpressionTableSql[] = - "ALTER TABLE new_impressions RENAME TO impressions"; - if (!db->Execute(kRenameImpressionTableSql)) - return false; - - // Update each of the impression rows to have the correct associated - // conversion_destination. This is only relevant for active impressions, as - // the column is only used for matching impressions to conversions, but we - // update all impressions regardless. - // - // We update a subset of rows at a time to avoid pulling the entire - // impressions table into memory. - std::vector<ImpressionIdAndConversionOrigin> impressions = - GetImpressionIdAndConversionOrigins(db, StoredSource::Id(0)); - - static constexpr char kUpdateDestinationSql[] = - "UPDATE impressions SET conversion_destination = ? WHERE impression_id = " - "?"; - sql::Statement update_destination_statement( - db->GetCachedStatement(SQL_FROM_HERE, kUpdateDestinationSql)); - - while (!impressions.empty()) { - // Perform the column updates for each row we pulled into memory. - for (const auto& impression : impressions) { - update_destination_statement.Reset(/*clear_bound_vars=*/true); - - // The conversion destination is derived from the conversion origin - // dynamically. - update_destination_statement.BindString( - 0, net::SchemefulSite(impression.conversion_origin).Serialize()); - update_destination_statement.BindInt64(1, *impression.source_id); - update_destination_statement.Run(); - } - - // Fetch the next batch of rows from the database. - impressions = GetImpressionIdAndConversionOrigins( - db, NextImpressionId(impressions.back().source_id)); - } - - // Create the pre-existing impression table indices on the new table. - static constexpr char kImpressionExpiryIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_expiry_idx " - "ON impressions(expiry_time)"; - if (!db->Execute(kImpressionExpiryIndexSql)) - return false; - - static constexpr char kImpressionOriginIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_origin_idx " - "ON impressions(impression_origin)"; - if (!db->Execute(kImpressionOriginIndexSql)) - return false; - - // Replace the pre-existing conversion_origin_idx with an index that uses the - // conversion destination, as attribution logic now depends on the - // conversion_destination. - static constexpr char kConversionDestinationIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_destination_idx " - "ON impressions(active,conversion_destination,reporting_origin)"; - if (!db->Execute(kConversionDestinationIndexSql)) - return false; - - meta_table->SetVersionNumber(2); - return transaction.Commit(); -} - -bool MigrateToVersion3(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Add new source_type and attributed_truthfully columns to the impressions - // table. This follows the steps documented at - // https://sqlite.org/lang_altertable.html#otheralter. Other approaches, like - // using "ALTER ... ADD COLUMN" require setting a DEFAULT value for the column - // which is undesirable. - static constexpr char kNewImpressionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_impressions" - "(impression_id INTEGER PRIMARY KEY," - "impression_data TEXT NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "reporting_origin TEXT NOT NULL," - "impression_time INTEGER NOT NULL," - "expiry_time INTEGER NOT NULL," - "num_conversions INTEGER DEFAULT 0," - "active INTEGER DEFAULT 1," - "conversion_destination TEXT NOT NULL," - "source_type INTEGER NOT NULL," - "attributed_truthfully INTEGER NOT NULL)"; - if (!db->Execute(kNewImpressionTableSql)) - return false; - - // Transfer the existing rows to the new table, inserting default values for - // the source_type and attributed_truthfully columns. - static constexpr char kPopulateNewImpressionTableSql[] = - "INSERT INTO new_impressions SELECT " - "impression_id,impression_data,impression_origin," - "conversion_origin,reporting_origin,impression_time," - "expiry_time,num_conversions,active,conversion_destination,?,? " - "FROM impressions"; - sql::Statement populate_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateNewImpressionTableSql)); - // Only navigation type was supported prior to this column being added. - populate_statement.BindInt( - 0, static_cast<int>(CommonSourceInfo::SourceType::kNavigation)); - populate_statement.BindBool(1, true); - if (!populate_statement.Run()) - return false; - - static constexpr char kDropOldImpressionTableSql[] = "DROP TABLE impressions"; - if (!db->Execute(kDropOldImpressionTableSql)) - return false; - - static constexpr char kRenameImpressionTableSql[] = - "ALTER TABLE new_impressions RENAME TO impressions"; - if (!db->Execute(kRenameImpressionTableSql)) - return false; - - // Create the pre-existing impression table indices on the new table. - static constexpr char kImpressionExpiryIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_expiry_idx " - "ON impressions(expiry_time)"; - if (!db->Execute(kImpressionExpiryIndexSql)) - return false; - - static constexpr char kImpressionOriginIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_origin_idx " - "ON impressions(impression_origin)"; - if (!db->Execute(kImpressionOriginIndexSql)) - return false; - - static constexpr char kConversionDestinationIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_destination_idx " - "ON impressions(active,conversion_destination,reporting_origin)"; - if (!db->Execute(kConversionDestinationIndexSql)) - return false; - - meta_table->SetVersionNumber(3); - return transaction.Commit(); -} - -bool MigrateToVersion4(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - static constexpr char kRateLimitTableSql[] = - "CREATE TABLE IF NOT EXISTS rate_limits" - "(rate_limit_id INTEGER PRIMARY KEY," - "attribution_type INTEGER NOT NULL," - "impression_id INTEGER NOT NULL," - "impression_site TEXT NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_destination TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "conversion_time INTEGER NOT NULL)"; - if (!db->Execute(kRateLimitTableSql)) - return false; - - static constexpr char kRateLimitImpressionSiteTypeIndexSql[] = - "CREATE INDEX IF NOT EXISTS rate_limit_impression_site_type_idx " - "ON rate_limits(attribution_type,conversion_destination," - "impression_site,conversion_time)"; - if (!db->Execute(kRateLimitImpressionSiteTypeIndexSql)) - return false; - - static constexpr char kRateLimitConversionTimeIndexSql[] = - "CREATE INDEX IF NOT EXISTS rate_limit_conversion_time_idx " - "ON rate_limits(conversion_time)"; - if (!db->Execute(kRateLimitConversionTimeIndexSql)) - return false; - - static constexpr char kRateLimitImpressionIndexSql[] = - "CREATE INDEX IF NOT EXISTS rate_limit_impression_id_idx " - "ON rate_limits(impression_id)"; - if (!db->Execute(kRateLimitImpressionIndexSql)) - return false; - - meta_table->SetVersionNumber(4); - return transaction.Commit(); -} - -bool MigrateToVersion5(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Any corresponding impressions will naturally be cleaned up by the expiry - // logic. - static constexpr char kDropZeroCreditConversionsSql[] = - "DELETE FROM conversions WHERE attribution_credit = 0"; - if (!db->Execute(kDropZeroCreditConversionsSql)) - return false; - - static constexpr char kDropAttributionCreditColumnSql[] = - "ALTER TABLE conversions DROP COLUMN attribution_credit"; - if (!db->Execute(kDropAttributionCreditColumnSql)) - return false; - - meta_table->SetVersionNumber(5); - return transaction.Commit(); -} - -bool MigrateToVersion6(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Add new priority column to the impressions table. This follows the steps - // documented at https://sqlite.org/lang_altertable.html#otheralter. Other - // approaches, like using "ALTER ... ADD COLUMN" require setting a DEFAULT - // value for the column which is undesirable. - static constexpr char kNewImpressionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_impressions" - "(impression_id INTEGER PRIMARY KEY," - "impression_data TEXT NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "reporting_origin TEXT NOT NULL," - "impression_time INTEGER NOT NULL," - "expiry_time INTEGER NOT NULL," - "num_conversions INTEGER DEFAULT 0," - "active INTEGER DEFAULT 1," - "conversion_destination TEXT NOT NULL," - "source_type INTEGER NOT NULL," - "attributed_truthfully INTEGER NOT NULL," - "priority INTEGER NOT NULL)"; - if (!db->Execute(kNewImpressionTableSql)) - return false; - - // Transfer the existing rows to the new table, inserting default values for - // the priority column. - static constexpr char kPopulateNewImpressionTableSql[] = - "INSERT INTO new_impressions SELECT " - "impression_id,impression_data,impression_origin," - "conversion_origin,reporting_origin,impression_time," - "expiry_time,num_conversions,active,conversion_destination,source_type," - "attributed_truthfully,0 " - "FROM impressions"; - sql::Statement populate_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateNewImpressionTableSql)); - if (!populate_statement.Run()) - return false; - - static constexpr char kDropOldImpressionTableSql[] = "DROP TABLE impressions"; - if (!db->Execute(kDropOldImpressionTableSql)) - return false; - - static constexpr char kRenameImpressionTableSql[] = - "ALTER TABLE new_impressions RENAME TO impressions"; - if (!db->Execute(kRenameImpressionTableSql)) - return false; - - // Create the pre-existing impression table indices on the new table. - static constexpr char kImpressionExpiryIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_expiry_idx " - "ON impressions(expiry_time)"; - if (!db->Execute(kImpressionExpiryIndexSql)) - return false; - - static constexpr char kImpressionOriginIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_origin_idx " - "ON impressions(impression_origin)"; - if (!db->Execute(kImpressionOriginIndexSql)) - return false; - - static constexpr char kConversionDestinationIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_destination_idx " - "ON impressions(active,conversion_destination,reporting_origin)"; - if (!db->Execute(kConversionDestinationIndexSql)) - return false; - - meta_table->SetVersionNumber(6); - return transaction.Commit(); -} - -bool MigrateToVersion7(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Add new impression_site column to the impressions table. This follows the - // steps documented at https://sqlite.org/lang_altertable.html#otheralter. - // Other approaches, like using "ALTER ... ADD COLUMN" require setting a - // DEFAULT value for the column which is undesirable. - static constexpr char kNewImpressionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_impressions" - "(impression_id INTEGER PRIMARY KEY," - "impression_data TEXT NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "reporting_origin TEXT NOT NULL," - "impression_time INTEGER NOT NULL," - "expiry_time INTEGER NOT NULL," - "num_conversions INTEGER DEFAULT 0," - "active INTEGER DEFAULT 1," - "conversion_destination TEXT NOT NULL," - "source_type INTEGER NOT NULL," - "attributed_truthfully INTEGER NOT NULL," - "priority INTEGER NOT NULL," - "impression_site TEXT NOT NULL)"; - if (!db->Execute(kNewImpressionTableSql)) - return false; - - // Transfer the existing rows to the new table, inserting placeholder values - // for the impression_site column. - static constexpr char kPopulateNewImpressionTableSql[] = - "INSERT INTO new_impressions SELECT " - "impression_id,impression_data,impression_origin," - "conversion_origin,reporting_origin,impression_time," - "expiry_time,num_conversions,active,conversion_destination,source_type," - "attributed_truthfully,priority,'' " - "FROM impressions"; - sql::Statement populate_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateNewImpressionTableSql)); - if (!populate_statement.Run()) - return false; - - static constexpr char kDropOldImpressionTableSql[] = "DROP TABLE impressions"; - if (!db->Execute(kDropOldImpressionTableSql)) - return false; - - static constexpr char kRenameImpressionTableSql[] = - "ALTER TABLE new_impressions RENAME TO impressions"; - if (!db->Execute(kRenameImpressionTableSql)) - return false; - - // Update each of the impression rows to have the correct associated - // impression_site. - // - // We update a subset of rows at a time to avoid pulling the entire - // impressions table into memory. - std::vector<ImpressionIdAndImpressionOrigin> impressions = - GetImpressionIdAndImpressionOrigins(db, StoredSource::Id(0)); - - static constexpr char kUpdateImpressionSiteSql[] = - "UPDATE impressions SET impression_site = ? WHERE impression_id = ?"; - sql::Statement update_impression_site_statement( - db->GetCachedStatement(SQL_FROM_HERE, kUpdateImpressionSiteSql)); - - while (!impressions.empty()) { - // Perform the column updates for each row we pulled into memory. - for (const auto& impression : impressions) { - update_impression_site_statement.Reset(/*clear_bound_vars=*/true); - - // The impression site is derived from the impression origin dynamically. - update_impression_site_statement.BindString( - 0, net::SchemefulSite(impression.impression_origin).Serialize()); - update_impression_site_statement.BindInt64(1, *impression.source_id); - if (!update_impression_site_statement.Run()) - return false; - } - - // Fetch the next batch of rows from the database. - impressions = GetImpressionIdAndImpressionOrigins( - db, NextImpressionId(impressions.back().source_id)); - } - - // Create the pre-existing impression table indices on the new table. - static constexpr char kImpressionExpiryIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_expiry_idx " - "ON impressions(expiry_time)"; - if (!db->Execute(kImpressionExpiryIndexSql)) - return false; - - static constexpr char kImpressionOriginIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_origin_idx " - "ON impressions(impression_origin)"; - if (!db->Execute(kImpressionOriginIndexSql)) - return false; - - static constexpr char kConversionDestinationIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_destination_idx " - "ON impressions(active,conversion_destination,reporting_origin)"; - if (!db->Execute(kConversionDestinationIndexSql)) - return false; - - // Create the new impression table index. - static constexpr char kImpressionSiteIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_site_idx " - "ON impressions(active,impression_site,source_type)"; - if (!db->Execute(kImpressionSiteIndexSql)) - return false; - - meta_table->SetVersionNumber(7); - return transaction.Commit(); -} - -struct ImpressionIdAndImpressionData { - StoredSource::Id source_id; - std::string impression_data; -}; - -std::vector<ImpressionIdAndImpressionData> GetImpressionIdAndImpressionData( - sql::Database* db, - StoredSource::Id start_source_id) { - static constexpr char kGetImpressionsSql[] = - "SELECT impression_id,impression_data " - "FROM impressions " - "WHERE impression_id >= ? " - "ORDER BY impression_id " - "LIMIT ?"; - - sql::Statement statement( - db->GetCachedStatement(SQL_FROM_HERE, kGetImpressionsSql)); - statement.BindInt64(0, *start_source_id); - - const int kNumImpressions = 100; - statement.BindInt(1, kNumImpressions); - - std::vector<ImpressionIdAndImpressionData> impressions; - while (statement.Step()) { - StoredSource::Id source_id(statement.ColumnInt64(0)); - std::string impression_data = statement.ColumnString(1); - - impressions.push_back({source_id, std::move(impression_data)}); - } - if (!statement.Succeeded()) - return {}; - return impressions; -} - -bool MigrateToVersion8(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Change the impression_data column from TEXT to INTEGER. This follows the - // steps documented at https://sqlite.org/lang_altertable.html#otheralter. - // Other approaches, like using "ALTER ... ADD COLUMN" require setting a - // DEFAULT value for the column which is undesirable. - static constexpr char kNewImpressionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_impressions" - "(impression_id INTEGER PRIMARY KEY," - "impression_data INTEGER NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "reporting_origin TEXT NOT NULL," - "impression_time INTEGER NOT NULL," - "expiry_time INTEGER NOT NULL," - "num_conversions INTEGER DEFAULT 0," - "active INTEGER DEFAULT 1," - "conversion_destination TEXT NOT NULL," - "source_type INTEGER NOT NULL," - "attributed_truthfully INTEGER NOT NULL," - "priority INTEGER NOT NULL," - "impression_site TEXT NOT NULL)"; - if (!db->Execute(kNewImpressionTableSql)) - return false; - - // Transfer the existing impressions rows to the new table with a placeholder - // for the impression_data column. - static constexpr char kPopulateNewImpressionsSql[] = - "INSERT INTO new_impressions SELECT " - "impression_id,0,impression_origin,conversion_origin,reporting_origin," - "impression_time,expiry_time,num_conversions,active," - "conversion_destination,source_type,attributed_truthfully,priority," - "impression_site FROM impressions"; - sql::Statement populate_new_impressions_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateNewImpressionsSql)); - if (!populate_new_impressions_statement.Run()) - return false; - - // Update each of the impression rows to have the correct associated - // impression_data. We can't use the CAST SQL function here because it - // doesn't support the full range of `uint64_t`. - // - // We update a subset of rows at a time to avoid pulling the entire - // impressions table into memory. - std::vector<ImpressionIdAndImpressionData> impressions = - GetImpressionIdAndImpressionData(db, StoredSource::Id(0)); - - static constexpr char kUpdateImpressionDataSql[] = - "UPDATE new_impressions SET impression_data = ? WHERE impression_id = ?"; - sql::Statement update_impression_data_statement( - db->GetCachedStatement(SQL_FROM_HERE, kUpdateImpressionDataSql)); - - while (!impressions.empty()) { - // Perform the column updates for each row we pulled into memory. - for (const auto& impression : impressions) { - // If we can't parse the data, skip the update to leave the column as 0. - uint64_t impression_data = 0u; - if (!base::StringToUint64(impression.impression_data, &impression_data)) - continue; - - update_impression_data_statement.Reset(/*clear_bound_vars=*/true); - update_impression_data_statement.BindInt64( - 0, SerializeUint64(impression_data)); - update_impression_data_statement.BindInt64(1, *impression.source_id); - update_impression_data_statement.Run(); - } - - // Fetch the next batch of rows from the database. - impressions = GetImpressionIdAndImpressionData( - db, NextImpressionId(impressions.back().source_id)); - } - - static constexpr char kDropOldImpressionTableSql[] = "DROP TABLE impressions"; - if (!db->Execute(kDropOldImpressionTableSql)) - return false; - - static constexpr char kRenameImpressionTableSql[] = - "ALTER TABLE new_impressions RENAME TO impressions"; - if (!db->Execute(kRenameImpressionTableSql)) - return false; - - // Create the pre-existing impression table indices on the new table. - static constexpr char kImpressionExpiryIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_expiry_idx " - "ON impressions(expiry_time)"; - if (!db->Execute(kImpressionExpiryIndexSql)) - return false; - - static constexpr char kImpressionOriginIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_origin_idx " - "ON impressions(impression_origin)"; - if (!db->Execute(kImpressionOriginIndexSql)) - return false; - - static constexpr char kConversionDestinationIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_destination_idx " - "ON impressions(active,conversion_destination,reporting_origin)"; - if (!db->Execute(kConversionDestinationIndexSql)) - return false; - - static constexpr char kImpressionSiteIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_site_idx " - "ON impressions(active,impression_site,source_type)"; - if (!db->Execute(kImpressionSiteIndexSql)) - return false; - - // Change the conversion_data column from TEXT to INTEGER and make - // impression_id NOT NULL. This follows the steps documented at - // https://sqlite.org/lang_altertable.html#otheralter./ Other approaches, like - // using "ALTER ... ADD COLUMN" require setting a DEFAULT value for the column - // which is undesirable. - static constexpr char kNewConversionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_conversions" - "(conversion_id INTEGER PRIMARY KEY," - "impression_id INTEGER NOT NULL," - "conversion_data INTEGER NOT NULL," - "conversion_time INTEGER NOT NULL," - "report_time INTEGER NOT NULL)"; - if (!db->Execute(kNewConversionTableSql)) - return false; - - // Transfer the existing conversions rows to the new table. See - // https://www.sqlite.org/lang_expr.html#castexpr for details on CAST, which - // we can use here because valid conversion_data is in the range [0, 8]. - // Existing impression_id values should never be NULL, but if they are, we - // insert 0 instead of failing. - static constexpr char kPopulateNewConversionsSql[] = - "INSERT INTO new_conversions SELECT " - "conversion_id,IFNULL(impression_id,0)," - "CAST(conversion_data AS INTEGER),conversion_time,report_time " - "FROM conversions"; - sql::Statement populate_new_conversions_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateNewConversionsSql)); - if (!populate_new_conversions_statement.Run()) - return false; - - static constexpr char kDropOldConversionTableSql[] = "DROP TABLE conversions"; - if (!db->Execute(kDropOldConversionTableSql)) - return false; - - static constexpr char kRenameConversionTableSql[] = - "ALTER TABLE new_conversions RENAME TO conversions"; - if (!db->Execute(kRenameConversionTableSql)) - return false; - - // Create the pre-existing conversion table indices on the new table. - static constexpr char kConversionReportTimeIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_report_idx " - "ON conversions(report_time)"; - if (!db->Execute(kConversionReportTimeIndexSql)) - return false; - - static constexpr char kConversionClickIdIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_impression_id_idx " - "ON conversions(impression_id)"; - if (!db->Execute(kConversionClickIdIndexSql)) - return false; - - meta_table->SetVersionNumber(8); - return transaction.Commit(); -} - -bool MigrateToVersion9(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Add new priority column to the conversions table. This follows the - // steps documented at https://sqlite.org/lang_altertable.html#otheralter. - // Other approaches, like using "ALTER ... ADD COLUMN" require setting a - // DEFAULT value for the column which is undesirable. - static constexpr char kNewTableSql[] = - "CREATE TABLE IF NOT EXISTS new_conversions" - "(conversion_id INTEGER PRIMARY KEY," - "impression_id INTEGER NOT NULL," - "conversion_data INTEGER NOT NULL," - "conversion_time INTEGER NOT NULL," - "report_time INTEGER NOT NULL," - "priority INTEGER NOT NULL)"; - if (!db->Execute(kNewTableSql)) - return false; - - // Transfer the existing rows to the new table, inserting 0 for the priority - // column. - static constexpr char kPopulateSql[] = - "INSERT INTO new_conversions SELECT " - "conversion_id,impression_id,conversion_data,conversion_time," - "report_time,0 " - "FROM conversions"; - sql::Statement populate_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateSql)); - if (!populate_statement.Run()) - return false; - - static constexpr char kDropOldTableSql[] = "DROP TABLE conversions"; - if (!db->Execute(kDropOldTableSql)) - return false; - - static constexpr char kRenameTableSql[] = - "ALTER TABLE new_conversions RENAME TO conversions"; - if (!db->Execute(kRenameTableSql)) - return false; - - // Create the pre-existing conversion table indices on the new table. - static constexpr char kConversionReportTimeIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_report_idx " - "ON conversions(report_time)"; - if (!db->Execute(kConversionReportTimeIndexSql)) - return false; - - static constexpr char kConversionClickIdIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_impression_id_idx " - "ON conversions(impression_id)"; - if (!db->Execute(kConversionClickIdIndexSql)) - return false; - - meta_table->SetVersionNumber(9); - return transaction.Commit(); -} - -bool MigrateToVersion10(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - static constexpr char kDedupKeyTableSql[] = - "CREATE TABLE IF NOT EXISTS dedup_keys" - "(impression_id INTEGER NOT NULL," - "dedup_key INTEGER NOT NULL," - "PRIMARY KEY(impression_id,dedup_key))WITHOUT ROWID"; - if (!db->Execute(kDedupKeyTableSql)) - return false; - - meta_table->SetVersionNumber(10); - return transaction.Commit(); -} - -bool MigrateToVersion11(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - static constexpr char kDropOldImpressionSiteIdxSql[] = - "DROP INDEX impression_site_idx"; - if (!db->Execute(kDropOldImpressionSiteIdxSql)) - return false; - - static constexpr char kEventSourceImpressionSiteIndexSql[] = - "CREATE INDEX IF NOT EXISTS event_source_impression_site_idx " - "ON impressions(impression_site)" - "WHERE active = 1 AND num_conversions = 0 AND source_type = 1"; - if (!db->Execute(kEventSourceImpressionSiteIndexSql)) - return false; - - meta_table->SetVersionNumber(11); - return transaction.Commit(); -} - -bool MigrateToVersion12(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - static constexpr char kNewRateLimitTableSql[] = - "CREATE TABLE IF NOT EXISTS new_rate_limits" - "(rate_limit_id INTEGER PRIMARY KEY NOT NULL," - "attribution_type INTEGER NOT NULL," - "impression_id INTEGER NOT NULL," - "impression_site TEXT NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_destination TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "conversion_time INTEGER NOT NULL," - "bucket TEXT NOT NULL," - "value INTEGER NOT NULL)"; - if (!db->Execute(kNewRateLimitTableSql)) - return false; - - // Transfer the existing rows to the new table, inserting 0 for `bucket` and - // 1 for `value`, since all existing rows are non-aggregate. - static constexpr char kPopulateNewRateLimitTableSql[] = - "INSERT INTO new_rate_limits SELECT " - "rate_limit_id,attribution_type,impression_id,impression_site," - "impression_origin,conversion_destination,conversion_origin," - "conversion_time,0,1 " - "FROM rate_limits"; - if (!db->Execute(kPopulateNewRateLimitTableSql)) - return false; - - static constexpr char kDropOldRateLimitTableSql[] = "DROP TABLE rate_limits"; - if (!db->Execute(kDropOldRateLimitTableSql)) - return false; - - static constexpr char kRenameRateLimitTableSql[] = - "ALTER TABLE new_rate_limits RENAME TO rate_limits"; - if (!db->Execute(kRenameRateLimitTableSql)) - return false; - - // Create the pre-existing indices on the new table. - - static constexpr char kRateLimitImpressionSiteTypeIndexSql[] = - "CREATE INDEX IF NOT EXISTS rate_limit_impression_site_type_idx " - "ON rate_limits(attribution_type,conversion_destination," - "impression_site,conversion_time)"; - if (!db->Execute(kRateLimitImpressionSiteTypeIndexSql)) - return false; - - // Add the attribution_type as a prefix of the index. - static constexpr char kRateLimitAttributionTypeConversionTimeIndexSql[] = - "CREATE INDEX IF NOT EXISTS " - "rate_limit_attribution_type_conversion_time_idx " - "ON rate_limits(attribution_type,conversion_time)"; - if (!db->Execute(kRateLimitAttributionTypeConversionTimeIndexSql)) - return false; - - static constexpr char kRateLimitImpressionIndexSql[] = - "CREATE INDEX IF NOT EXISTS rate_limit_impression_id_idx " - "ON rate_limits(impression_id)"; - if (!db->Execute(kRateLimitImpressionIndexSql)) - return false; - - meta_table->SetVersionNumber(12); - return transaction.Commit(); -} - -bool MigrateToVersion13(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Create the new impressions table with impression_id `NOT NULL` and - // `AUTOINCREMENT`. - static constexpr char kNewImpressionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_impressions" - "(impression_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," - "impression_data INTEGER NOT NULL," - "impression_origin TEXT NOT NULL," - "conversion_origin TEXT NOT NULL," - "reporting_origin TEXT NOT NULL," - "impression_time INTEGER NOT NULL," - "expiry_time INTEGER NOT NULL," - "num_conversions INTEGER DEFAULT 0," - "active INTEGER DEFAULT 1," - "conversion_destination TEXT NOT NULL," - "source_type INTEGER NOT NULL," - "attributed_truthfully INTEGER NOT NULL," - "priority INTEGER NOT NULL," - "impression_site TEXT NOT NULL)"; - if (!db->Execute(kNewImpressionTableSql)) - return false; - - // Transfer the existing rows to the new table. - static constexpr char kPopulateNewImpressionTableSql[] = - "INSERT INTO new_impressions SELECT " - "impression_id,impression_data,impression_origin," - "conversion_origin,reporting_origin,impression_time," - "expiry_time,num_conversions,active,conversion_destination," - "source_type,attributed_truthfully,priority,impression_site " - "FROM impressions"; - if (!db->Execute(kPopulateNewImpressionTableSql)) - return false; - - static constexpr char kDropOldImpressionTableSql[] = "DROP TABLE impressions"; - if (!db->Execute(kDropOldImpressionTableSql)) - return false; - - static constexpr char kRenameImpressionTableSql[] = - "ALTER TABLE new_impressions RENAME TO impressions"; - if (!db->Execute(kRenameImpressionTableSql)) - return false; - - // Create the pre-existing impression table indices on the new table. - - static constexpr char kConversionDestinationIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_destination_idx " - "ON impressions(active,conversion_destination,reporting_origin)"; - if (!db->Execute(kConversionDestinationIndexSql)) - return false; - - static constexpr char kImpressionExpiryIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_expiry_idx " - "ON impressions(expiry_time)"; - if (!db->Execute(kImpressionExpiryIndexSql)) - return false; - - static constexpr char kImpressionOriginIndexSql[] = - "CREATE INDEX IF NOT EXISTS impression_origin_idx " - "ON impressions(impression_origin)"; - if (!db->Execute(kImpressionOriginIndexSql)) - return false; - - static constexpr char kEventSourceImpressionSiteIndexSql[] = - "CREATE INDEX IF NOT EXISTS event_source_impression_site_idx " - "ON impressions(impression_site)" - "WHERE active = 1 AND num_conversions = 0 AND source_type = 1"; - if (!db->Execute(kEventSourceImpressionSiteIndexSql)) - return false; - - // Create the new conversions table with conversion_id `NOT NULL` and - // `AUTOINCREMENT`. - static constexpr char kNewConversionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_conversions" - "(conversion_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," - "impression_id INTEGER NOT NULL," - "conversion_data INTEGER NOT NULL," - "conversion_time INTEGER NOT NULL," - "report_time INTEGER NOT NULL," - "priority INTEGER NOT NULL)"; - if (!db->Execute(kNewConversionTableSql)) - return false; - - // Transfer the existing rows to the new table. - static constexpr char kPopulateNewConversionTableSql[] = - "INSERT INTO new_conversions SELECT " - "conversion_id,impression_id,conversion_data,conversion_time," - "report_time,priority " - "FROM conversions"; - if (!db->Execute(kPopulateNewConversionTableSql)) - return false; - - static constexpr char kDropOldConversionTableSql[] = "DROP TABLE conversions"; - if (!db->Execute(kDropOldConversionTableSql)) - return false; - - static constexpr char kRenameConversionTableSql[] = - "ALTER TABLE new_conversions RENAME TO conversions"; - if (!db->Execute(kRenameConversionTableSql)) - return false; - - // Create the pre-existing conversion table indices on the new table. - - static constexpr char kConversionReportTimeIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_report_idx " - "ON conversions(report_time)"; - if (!db->Execute(kConversionReportTimeIndexSql)) - return false; - - static constexpr char kConversionImpressionIdIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_impression_id_idx " - "ON conversions(impression_id)"; - if (!db->Execute(kConversionImpressionIdIndexSql)) - return false; - - meta_table->SetVersionNumber(13); - return transaction.Commit(); -} - -bool MigrateToVersion14(sql::Database* db, sql::MetaTable* meta_table) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Create the new conversions table with failed_send_attempts. - static constexpr char kNewConversionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_conversions" - "(conversion_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," - "impression_id INTEGER NOT NULL," - "conversion_data INTEGER NOT NULL," - "conversion_time INTEGER NOT NULL," - "report_time INTEGER NOT NULL," - "priority INTEGER NOT NULL," - "failed_send_attempts INTEGER NOT NULL)"; - if (!db->Execute(kNewConversionTableSql)) - return false; - - // Transfer the existing conversions rows to the new table, using 0 for - // failed_send_attempts since we have no basis to say otherwise. - static constexpr char kPopulateNewConversionsSql[] = - "INSERT INTO new_conversions SELECT " - "conversion_id,impression_id,conversion_data,conversion_time,report_time," - "priority,0 FROM conversions"; - sql::Statement populate_new_conversions_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateNewConversionsSql)); - if (!populate_new_conversions_statement.Run()) - return false; - - static constexpr char kDropOldConversionTableSql[] = "DROP TABLE conversions"; - if (!db->Execute(kDropOldConversionTableSql)) - return false; - - static constexpr char kRenameConversionTableSql[] = - "ALTER TABLE new_conversions RENAME TO conversions"; - if (!db->Execute(kRenameConversionTableSql)) - return false; - - // Create the pre-existing conversion table indices on the new table. - - static constexpr char kConversionReportTimeIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_report_idx " - "ON conversions(report_time)"; - if (!db->Execute(kConversionReportTimeIndexSql)) - return false; - - static constexpr char kConversionImpressionIdIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_impression_id_idx " - "ON conversions(impression_id)"; - if (!db->Execute(kConversionImpressionIdIndexSql)) - return false; - - meta_table->SetVersionNumber(14); - return transaction.Commit(); -} - -bool MigrateToVersion15(sql::Database* db, - sql::MetaTable* meta_table, - AttributionStorage::Delegate* delegate) { - // Wrap each migration in its own transaction. See comment in - // |MigrateToVersion2|. - sql::Transaction transaction(db); - if (!transaction.Begin()) - return false; - - // Create the new conversions table with external_report_id. - static constexpr char kNewConversionTableSql[] = - "CREATE TABLE IF NOT EXISTS new_conversions" - "(conversion_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," - "impression_id INTEGER NOT NULL," - "conversion_data INTEGER NOT NULL," - "conversion_time INTEGER NOT NULL," - "report_time INTEGER NOT NULL," - "priority INTEGER NOT NULL," - "failed_send_attempts INTEGER NOT NULL," - "external_report_id TEXT NOT NULL)"; - if (!db->Execute(kNewConversionTableSql)) - return false; - - // Transfer the existing conversions rows to the new table, using the empty - // string for external_report_id, which we will update afterward. - static constexpr char kPopulateNewConversionsSql[] = - "INSERT INTO new_conversions SELECT " - "conversion_id,impression_id,conversion_data,conversion_time,report_time," - "priority,failed_send_attempts,'' FROM conversions"; - sql::Statement populate_new_conversions_statement( - db->GetCachedStatement(SQL_FROM_HERE, kPopulateNewConversionsSql)); - if (!populate_new_conversions_statement.Run()) - return false; - - // Update each of the conversion rows to have a random external_report_id. - // - // We update a subset of rows at a time to avoid pulling the entire - // conversions table into memory. - std::vector<AttributionReport::EventLevelData::Id> conversion_ids = - GetConversionIds(db, AttributionReport::EventLevelData::Id(0)); - - static constexpr char kUpdateExternalReportIdSql[] = - "UPDATE new_conversions SET external_report_id = ? " - "WHERE conversion_id = ?"; - sql::Statement update_statement( - db->GetCachedStatement(SQL_FROM_HERE, kUpdateExternalReportIdSql)); - - while (!conversion_ids.empty()) { - // Perform the column updates for each row we pulled into memory. - for (AttributionReport::EventLevelData::Id conversion_id : conversion_ids) { - update_statement.Reset(/*clear_bound_vars=*/true); - - base::GUID external_report_id = delegate->NewReportID(); - DCHECK(external_report_id.is_valid()); - update_statement.BindString(0, external_report_id.AsLowercaseString()); - - update_statement.BindInt64(1, *conversion_id); - - if (!update_statement.Run()) - return false; - } - - // Fetch the next batch of rows from the database. - conversion_ids = - GetConversionIds(db, NextConversionId(conversion_ids.back())); - } - - static constexpr char kDropOldConversionTableSql[] = "DROP TABLE conversions"; - if (!db->Execute(kDropOldConversionTableSql)) - return false; - - static constexpr char kRenameConversionTableSql[] = - "ALTER TABLE new_conversions RENAME TO conversions"; - if (!db->Execute(kRenameConversionTableSql)) - return false; - - // Create the pre-existing conversion table indices on the new table. - - static constexpr char kConversionReportTimeIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_report_idx " - "ON conversions(report_time)"; - if (!db->Execute(kConversionReportTimeIndexSql)) - return false; - - static constexpr char kConversionImpressionIdIndexSql[] = - "CREATE INDEX IF NOT EXISTS conversion_impression_id_idx " - "ON conversions(impression_id)"; - if (!db->Execute(kConversionImpressionIdIndexSql)) - return false; - - meta_table->SetVersionNumber(15); - return transaction.Commit(); -} - -} // namespace - -bool UpgradeAttributionStorageSqlSchema( - sql::Database* db, - sql::MetaTable* meta_table, - AttributionStorage::Delegate* delegate) { +bool UpgradeAttributionStorageSqlSchema(sql::Database* db, + sql::MetaTable* meta_table) { DCHECK(db); DCHECK(meta_table); - DCHECK(delegate); base::ThreadTicks start_timestamp = base::ThreadTicks::Now(); - if (meta_table->GetVersionNumber() == 1) { - if (!MigrateToVersion2(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 2) { - if (!MigrateToVersion3(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 3) { - if (!MigrateToVersion4(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 4) { - if (!MigrateToVersion5(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 5) { - if (!MigrateToVersion6(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 6) { - if (!MigrateToVersion7(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 7) { - if (!MigrateToVersion8(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 8) { - if (!MigrateToVersion9(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 9) { - if (!MigrateToVersion10(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 10) { - if (!MigrateToVersion11(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 11) { - if (!MigrateToVersion12(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 12) { - if (!MigrateToVersion13(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 13) { - if (!MigrateToVersion14(db, meta_table)) - return false; - } - if (meta_table->GetVersionNumber() == 14) { - if (!MigrateToVersion15(db, meta_table, delegate)) - return false; - } - // Add similar if () blocks for new versions here. - base::UmaHistogramMediumTimes("Conversions.Storage.MigrationTime", base::ThreadTicks::Now() - start_timestamp); return true;
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_migrations.h b/content/browser/attribution_reporting/attribution_storage_sql_migrations.h index eff1a4f..bbb5622a 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_migrations.h +++ b/content/browser/attribution_reporting/attribution_storage_sql_migrations.h
@@ -5,8 +5,6 @@ #ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_SQL_MIGRATIONS_H_ #define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_STORAGE_SQL_MIGRATIONS_H_ -#include "content/browser/attribution_reporting/attribution_storage.h" - namespace sql { class Database; class MetaTable; @@ -47,8 +45,7 @@ // failure. [[nodiscard]] bool UpgradeAttributionStorageSqlSchema( sql::Database* db, - sql::MetaTable* meta_table, - AttributionStorage::Delegate* delegate); + sql::MetaTable* meta_table); } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc b/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc index 2b13614..c32b1fa 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql_migrations_unittest.cc
@@ -134,698 +134,7 @@ histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 0); } -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion1ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_1.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_FALSE(db.DoesTableExist("meta")); - ASSERT_FALSE(db.DoesColumnExist("impressions", "conversion_destination")); - - sql::Statement s( - db.GetUniqueStatement("SELECT conversion_origin FROM impressions")); - - ASSERT_TRUE(s.Step()); - ASSERT_EQ("https://sub.conversion.test", s.ColumnString(0)); - ASSERT_FALSE(s.Step()); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Check that expected tables are present. - EXPECT_TRUE(db.DoesTableExist("conversions")); - EXPECT_TRUE(db.DoesTableExist("impressions")); - EXPECT_TRUE(db.DoesTableExist("meta")); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - EXPECT_TRUE(db.DoesColumnExist("impressions", "conversion_destination")); - - // Verify that data is preserved across the migration. - size_t rows = 0; - sql::test::CountTableRows(&db, "impressions", &rows); - EXPECT_EQ(1u, rows); - - sql::Statement s(db.GetUniqueStatement( - "SELECT conversion_origin, conversion_destination FROM impressions")); - - ASSERT_TRUE(s.Step()); - ASSERT_EQ("https://sub.conversion.test", s.ColumnString(0)); - ASSERT_EQ("https://conversion.test", s.ColumnString(1)); - ASSERT_FALSE(s.Step()); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion2ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_2.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_FALSE(db.DoesColumnExist("impressions", "source_type")); - ASSERT_FALSE(db.DoesColumnExist("impressions", "attributed_truthfully")); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Check that expected tables are present. - EXPECT_TRUE(db.DoesTableExist("conversions")); - EXPECT_TRUE(db.DoesTableExist("impressions")); - EXPECT_TRUE(db.DoesTableExist("meta")); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - EXPECT_TRUE(db.DoesColumnExist("impressions", "source_type")); - EXPECT_TRUE(db.DoesColumnExist("impressions", "attributed_truthfully")); - - // Verify that data is preserved across the migration. - size_t rows = 0; - sql::test::CountTableRows(&db, "impressions", &rows); - EXPECT_EQ(1u, rows); - - sql::Statement s(db.GetUniqueStatement( - "SELECT source_type, attributed_truthfully FROM impressions")); - - ASSERT_TRUE(s.Step()); - ASSERT_EQ(0, s.ColumnInt(0)); - ASSERT_EQ(true, s.ColumnBool(1)); - ASSERT_FALSE(s.Step()); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion3ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_3.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_FALSE(db.DoesTableExist("rate_limits")); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Check that expected tables are present. - EXPECT_TRUE(db.DoesTableExist("conversions")); - EXPECT_TRUE(db.DoesTableExist("impressions")); - EXPECT_TRUE(db.DoesTableExist("meta")); - EXPECT_TRUE(db.DoesTableExist("rate_limits")); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion4ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_4.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_TRUE(db.DoesColumnExist("conversions", "attribution_credit")); - - sql::Statement s(db.GetUniqueStatement( - "SELECT conversion_id FROM conversions ORDER BY conversion_id")); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(2, s.ColumnInt(0)); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(3, s.ColumnInt(0)); - ASSERT_FALSE(s.Step()); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Check that expected tables are present. - EXPECT_TRUE(db.DoesTableExist("conversions")); - EXPECT_TRUE(db.DoesTableExist("impressions")); - EXPECT_TRUE(db.DoesTableExist("meta")); - EXPECT_TRUE(db.DoesTableExist("rate_limits")); - - // Check that the expected column is dropped. - EXPECT_FALSE(db.DoesColumnExist("conversions", "attribution_credit")); - - // Check that only the 0-credit conversions are deleted. - sql::Statement s(db.GetUniqueStatement( - "SELECT conversion_id FROM conversions ORDER BY conversion_id")); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(3, s.ColumnInt(0)); - ASSERT_FALSE(s.Step()); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion5ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_5.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_FALSE(db.DoesColumnExist("impressions", "priority")); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Check that expected tables are present. - EXPECT_TRUE(db.DoesTableExist("conversions")); - EXPECT_TRUE(db.DoesTableExist("impressions")); - EXPECT_TRUE(db.DoesTableExist("meta")); - EXPECT_TRUE(db.DoesTableExist("rate_limits")); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - EXPECT_TRUE(db.DoesColumnExist("impressions", "priority")); - - // Verify that data is preserved across the migration. - size_t rows = 0; - sql::test::CountTableRows(&db, "impressions", &rows); - EXPECT_EQ(1u, rows); - - sql::Statement s(db.GetUniqueStatement( - "SELECT conversion_origin, priority FROM impressions")); - - ASSERT_TRUE(s.Step()); - ASSERT_EQ("https://conversion.test", s.ColumnString(0)); - ASSERT_EQ(0, s.ColumnInt64(1)); - ASSERT_FALSE(s.Step()); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion6ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_6.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_FALSE(db.DoesColumnExist("impressions", "impression_site")); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - EXPECT_TRUE(db.DoesColumnExist("impressions", "impression_site")); - - // Verify that data is preserved across the migration. - size_t rows = 0; - sql::test::CountTableRows(&db, "impressions", &rows); - EXPECT_EQ(2u, rows); - - sql::Statement s(db.GetUniqueStatement( - "SELECT impression_origin, impression_site FROM impressions")); - - ASSERT_TRUE(s.Step()); - ASSERT_EQ("https://a.impression.test", s.ColumnString(0)); - ASSERT_EQ("https://impression.test", s.ColumnString(1)); - ASSERT_TRUE(s.Step()); - ASSERT_EQ("https://b.impression.test", s.ColumnString(0)); - ASSERT_EQ("https://impression.test", s.ColumnString(1)); - ASSERT_FALSE(s.Step()); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion7ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_7.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - sql::Statement impression_statement(db.GetUniqueStatement( - "SELECT impression_data FROM impressions ORDER BY impression_id")); - ASSERT_TRUE(impression_statement.Step()); - ASSERT_EQ("18446744073709551615", impression_statement.ColumnString(0)); - ASSERT_TRUE(impression_statement.Step()); - ASSERT_EQ("invalid", impression_statement.ColumnString(0)); - ASSERT_FALSE(impression_statement.Step()); - - sql::Statement conversion_statement( - db.GetUniqueStatement("SELECT conversion_data, impression_id FROM " - "conversions ORDER BY conversion_id")); - ASSERT_TRUE(conversion_statement.Step()); - ASSERT_EQ("234", conversion_statement.ColumnString(0)); - ASSERT_EQ(29L, conversion_statement.ColumnInt64(1)); - ASSERT_TRUE(conversion_statement.Step()); - ASSERT_EQ("invalid", conversion_statement.ColumnString(0)); - ASSERT_EQ(sql::ColumnType::kNull, conversion_statement.GetColumnType(1)); - ASSERT_FALSE(conversion_statement.Step()); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Check that expected tables are present. - EXPECT_TRUE(db.DoesTableExist("conversions")); - EXPECT_TRUE(db.DoesTableExist("impressions")); - EXPECT_TRUE(db.DoesTableExist("meta")); - EXPECT_TRUE(db.DoesTableExist("rate_limits")); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - sql::Statement impression_statement(db.GetUniqueStatement( - "SELECT impression_data FROM impressions ORDER BY impression_id")); - ASSERT_TRUE(impression_statement.Step()); - ASSERT_EQ(18446744073709551615UL, - static_cast<uint64_t>(impression_statement.ColumnInt64(0))); - ASSERT_TRUE(impression_statement.Step()); - ASSERT_EQ(0L, impression_statement.ColumnInt64(0)); - ASSERT_FALSE(impression_statement.Step()); - - sql::Statement conversion_statement( - db.GetUniqueStatement("SELECT conversion_data, impression_id FROM " - "conversions ORDER BY conversion_id")); - ASSERT_TRUE(conversion_statement.Step()); - ASSERT_EQ(234L, conversion_statement.ColumnInt64(0)); - ASSERT_EQ(29L, conversion_statement.ColumnInt64(1)); - ASSERT_TRUE(conversion_statement.Step()); - ASSERT_EQ(0L, conversion_statement.ColumnInt64(0)); - ASSERT_EQ(0L, conversion_statement.ColumnInt64(1)); - ASSERT_FALSE(conversion_statement.Step()); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion8ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_8.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_FALSE(db.DoesColumnExist("conversions", "priority")); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - EXPECT_TRUE(db.DoesColumnExist("conversions", "priority")); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion9ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_9.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_FALSE(db.DoesTableExist("dedup_keys")); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - EXPECT_TRUE(db.DoesTableExist("dedup_keys")); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion10ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_10.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - ASSERT_TRUE(db.DoesIndexExist("impression_site_idx")); - ASSERT_FALSE(db.DoesIndexExist("event_source_impression_site_idx")); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - ASSERT_FALSE(db.DoesIndexExist("impression_site_idx")); - ASSERT_TRUE(db.DoesIndexExist("event_source_impression_site_idx")); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion11ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_11.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - ASSERT_FALSE(db.DoesColumnExist("rate_limits", "bucket")); - ASSERT_FALSE(db.DoesColumnExist("rate_limits", "value")); - ASSERT_FALSE( - db.DoesIndexExist("rate_limit_attribution_type_conversion_time_idx")); - ASSERT_TRUE(db.DoesIndexExist("rate_limit_conversion_time_idx")); - - sql::Statement s(db.GetUniqueStatement("SELECT * FROM rate_limits")); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_EQ(0, s.ColumnInt(1)); - ASSERT_EQ(11, s.ColumnInt64(2)); - ASSERT_EQ("https://a.example", s.ColumnString(3)); - ASSERT_EQ("https://a.a.example", s.ColumnString(4)); - ASSERT_EQ("https://b.example", s.ColumnString(5)); - ASSERT_EQ("https://b.b.example", s.ColumnString(6)); - ASSERT_EQ(7, s.ColumnInt64(7)); - ASSERT_FALSE(s.Step()); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - ASSERT_TRUE(db.DoesColumnExist("rate_limits", "bucket")); - ASSERT_TRUE(db.DoesColumnExist("rate_limits", "value")); - ASSERT_TRUE( - db.DoesIndexExist("rate_limit_attribution_type_conversion_time_idx")); - ASSERT_FALSE(db.DoesIndexExist("rate_limit_conversion_time_idx")); - - // Verify that data is preserved across the migration. - sql::Statement s(db.GetUniqueStatement("SELECT * FROM rate_limits")); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_EQ(0, s.ColumnInt(1)); - ASSERT_EQ(11, s.ColumnInt64(2)); - ASSERT_EQ("https://a.example", s.ColumnString(3)); - ASSERT_EQ("https://a.a.example", s.ColumnString(4)); - ASSERT_EQ("https://b.example", s.ColumnString(5)); - ASSERT_EQ("https://b.b.example", s.ColumnString(6)); - ASSERT_EQ(7, s.ColumnInt64(7)); - ASSERT_EQ(0, s.ColumnInt64(8)); - ASSERT_EQ(1, s.ColumnInt64(9)); - ASSERT_FALSE(s.Step()); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion12ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_12.sql"), DbPath()); - - auto check_data = [](sql::Database& db) { - sql::Statement s(db.GetUniqueStatement("SELECT * FROM impressions")); - ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_EQ(2, s.ColumnInt(1)); - ASSERT_EQ("a", s.ColumnString(2)); - ASSERT_EQ("b", s.ColumnString(3)); - ASSERT_EQ("c", s.ColumnString(4)); - ASSERT_EQ(3, s.ColumnInt(5)); - ASSERT_EQ(4, s.ColumnInt(6)); - ASSERT_EQ(5, s.ColumnInt(7)); - ASSERT_EQ(6, s.ColumnInt(8)); - ASSERT_EQ("d", s.ColumnString(9)); - ASSERT_EQ(7, s.ColumnInt(10)); - ASSERT_EQ(8, s.ColumnInt(11)); - ASSERT_EQ(9, s.ColumnInt(12)); - ASSERT_EQ("e", s.ColumnString(13)); - ASSERT_FALSE(s.Step()); - - sql::Statement t(db.GetUniqueStatement("SELECT * FROM conversions")); - ASSERT_TRUE(t.Step()); - ASSERT_EQ(10, t.ColumnInt(0)); - ASSERT_EQ(11, t.ColumnInt(1)); - ASSERT_EQ(12, t.ColumnInt(2)); - ASSERT_EQ(13, t.ColumnInt(3)); - ASSERT_EQ(14, t.ColumnInt(4)); - ASSERT_EQ(15, t.ColumnInt(5)); - ASSERT_FALSE(t.Step()); - }; - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - check_data(db); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - check_data(db); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion13ToCurrent) { - base::HistogramTester histograms; - LoadDatabase(FILE_PATH_LITERAL("version_13.sql"), DbPath()); - - // Verify pre-conditions. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - ASSERT_FALSE(db.DoesColumnExist("conversions", "failed_send_attempts")); - - sql::Statement s(db.GetUniqueStatement("SELECT * FROM conversions")); - - ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_EQ(2, s.ColumnInt(1)); - ASSERT_EQ(3, s.ColumnInt(2)); - ASSERT_EQ(4, s.ColumnInt(3)); - ASSERT_EQ(5, s.ColumnInt(4)); - ASSERT_EQ(6, s.ColumnInt(5)); - ASSERT_FALSE(s.Step()); - } - - MigrateDatabase(); - - // Verify schema is current. - { - sql::Database db; - ASSERT_TRUE(db.Open(DbPath())); - - // Check version. - EXPECT_EQ(kCurrentVersionNumber, VersionFromDatabase(&db)); - - // Compare without quotes as sometimes migrations cause table names to be - // string literals. - EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - - // Check that the relevant schema changes are made. - ASSERT_TRUE(db.DoesColumnExist("conversions", "failed_send_attempts")); - - // Verify that data is preserved across the migration. - sql::Statement s(db.GetUniqueStatement("SELECT * FROM conversions")); - - ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_EQ(2, s.ColumnInt(1)); - ASSERT_EQ(3, s.ColumnInt(2)); - ASSERT_EQ(4, s.ColumnInt(3)); - ASSERT_EQ(5, s.ColumnInt(4)); - ASSERT_EQ(6, s.ColumnInt(5)); - ASSERT_EQ(0, s.ColumnInt(6)); - ASSERT_FALSE(s.Step()); - } - - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); -} - -TEST_F(AttributionStorageSqlMigrationsTest, MigrateVersion14ToCurrent) { +TEST_F(AttributionStorageSqlMigrationsTest, MigrateLatestDeprecatedToCurrent) { base::HistogramTester histograms; LoadDatabase(FILE_PATH_LITERAL("version_14.sql"), DbPath()); @@ -833,19 +142,11 @@ { sql::Database db; ASSERT_TRUE(db.Open(DbPath())); - ASSERT_FALSE(db.DoesColumnExist("conversions", "external_report_id")); - sql::Statement s(db.GetUniqueStatement("SELECT * FROM conversions")); + sql::Statement s(db.GetUniqueStatement("SELECT COUNT(*) FROM conversions")); ASSERT_TRUE(s.Step()); ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_EQ(2, s.ColumnInt(1)); - ASSERT_EQ(3, s.ColumnInt(2)); - ASSERT_EQ(4, s.ColumnInt(3)); - ASSERT_EQ(5, s.ColumnInt(4)); - ASSERT_EQ(6, s.ColumnInt(5)); - ASSERT_EQ(7, s.ColumnInt(6)); - ASSERT_FALSE(s.Step()); } MigrateDatabase(); @@ -862,27 +163,16 @@ // string literals. EXPECT_EQ(RemoveQuotes(GetCurrentSchema()), RemoveQuotes(db.GetSchema())); - // Check that the relevant schema changes are made. - ASSERT_TRUE(db.DoesColumnExist("conversions", "external_report_id")); - - // Verify that data is preserved across the migration. - sql::Statement s(db.GetUniqueStatement("SELECT * FROM conversions")); + // Verify that data is not preserved across the migration. + sql::Statement s(db.GetUniqueStatement("SELECT COUNT(*) FROM conversions")); ASSERT_TRUE(s.Step()); - ASSERT_EQ(1, s.ColumnInt(0)); - ASSERT_EQ(2, s.ColumnInt(1)); - ASSERT_EQ(3, s.ColumnInt(2)); - ASSERT_EQ(4, s.ColumnInt(3)); - ASSERT_EQ(5, s.ColumnInt(4)); - ASSERT_EQ(6, s.ColumnInt(5)); - ASSERT_EQ(7, s.ColumnInt(6)); - ASSERT_TRUE(base::GUID::ParseLowercase(s.ColumnString(7)).is_valid()); - ASSERT_FALSE(s.Step()); + ASSERT_EQ(0, s.ColumnInt(0)); } - // DB migration histograms should be recorded. - histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 0); - histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 1); + // DB creation histograms should be recorded. + histograms.ExpectTotalCount("Conversions.Storage.CreationTime", 1); + histograms.ExpectTotalCount("Conversions.Storage.MigrationTime", 0); } } // namespace content
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 9c238de..ededacc 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -298,10 +298,10 @@ mojo::PendingReceiver<storage::mojom::QuotaInternalsHandler> receiver) { WebUI* web_ui = host->GetWebUI(); - // Performs a safe downcast to the concrete QuotaInternals2UI + // Performs a safe downcast to the concrete QuotaInternalsUI // subclass. - QuotaInternals2UI* quota_internals_ui = - web_ui ? web_ui->GetController()->GetAs<QuotaInternals2UI>() : nullptr; + QuotaInternalsUI* quota_internals_ui = + web_ui ? web_ui->GetController()->GetAs<QuotaInternalsUI>() : nullptr; // This is expected to be called only for main frames and for the right WebUI // pages matching the same WebUI associated to the RenderFrameHost. @@ -313,7 +313,7 @@ } DCHECK_EQ(host->GetLastCommittedURL().host_piece(), - kChromeUIQuotaInternals2Host); + kChromeUIQuotaInternalsHost); DCHECK(host->GetLastCommittedURL().SchemeIs(kChromeUIScheme)); static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index 49c3c4c..08c99ac 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -161,6 +161,102 @@ return issue; } +std::string RequestIdTokenStatusToProtocol( + blink::mojom::RequestIdTokenStatus status) { + using blink::mojom::RequestIdTokenStatus; + namespace FederatedAuthRequestIssueReasonEnum = + protocol::Audits::FederatedAuthRequestIssueReasonEnum; + switch (status) { + case RequestIdTokenStatus::kApprovalDeclined: { + return FederatedAuthRequestIssueReasonEnum::ApprovalDeclined; + } + case RequestIdTokenStatus::kErrorTooManyRequests: { + return FederatedAuthRequestIssueReasonEnum::TooManyRequests; + } + case RequestIdTokenStatus::kErrorFetchingWellKnownHttpNotFound: { + return FederatedAuthRequestIssueReasonEnum::WellKnownHttpNotFound; + } + case RequestIdTokenStatus::kErrorFetchingWellKnownNoResponse: { + return FederatedAuthRequestIssueReasonEnum::WellKnownNoResponse; + } + case RequestIdTokenStatus::kErrorFetchingWellKnownInvalidResponse: { + return FederatedAuthRequestIssueReasonEnum::WellKnownInvalidResponse; + } + case RequestIdTokenStatus::kErrorFetchingClientIdMetadataHttpNotFound: { + return FederatedAuthRequestIssueReasonEnum::ClientIdMetadataHttpNotFound; + } + case RequestIdTokenStatus::kErrorFetchingClientIdMetadataNoResponse: { + return FederatedAuthRequestIssueReasonEnum::ClientIdMetadataNoResponse; + } + case RequestIdTokenStatus::kErrorFetchingClientIdMetadataInvalidResponse: { + return FederatedAuthRequestIssueReasonEnum:: + ClientIdMetadataInvalidResponse; + } + case RequestIdTokenStatus::kErrorFetchingSignin: { + return FederatedAuthRequestIssueReasonEnum::ErrorFetchingSignin; + } + case RequestIdTokenStatus::kErrorInvalidSigninResponse: { + return FederatedAuthRequestIssueReasonEnum::InvalidSigninResponse; + } + case RequestIdTokenStatus::kErrorFetchingAccountsHttpNotFound: { + return FederatedAuthRequestIssueReasonEnum::AccountsHttpNotFound; + } + case RequestIdTokenStatus::kErrorFetchingAccountsNoResponse: { + return FederatedAuthRequestIssueReasonEnum::AccountsNoResponse; + } + case RequestIdTokenStatus::kErrorFetchingAccountsInvalidResponse: { + return FederatedAuthRequestIssueReasonEnum::AccountsInvalidResponse; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenHttpNotFound: { + return FederatedAuthRequestIssueReasonEnum::IdTokenHttpNotFound; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenNoResponse: { + return FederatedAuthRequestIssueReasonEnum::IdTokenNoResponse; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenInvalidResponse: { + return FederatedAuthRequestIssueReasonEnum::IdTokenInvalidResponse; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenInvalidRequest: { + return FederatedAuthRequestIssueReasonEnum::IdTokenInvalidRequest; + } + case RequestIdTokenStatus::kErrorCanceled: { + return FederatedAuthRequestIssueReasonEnum::Canceled; + } + case RequestIdTokenStatus::kError: { + return FederatedAuthRequestIssueReasonEnum::ErrorIdToken; + } + case RequestIdTokenStatus::kSuccess: { + DCHECK(false); + return ""; + } + } +} + +std::unique_ptr<protocol::Audits::InspectorIssue> +BuildFederatedAuthRequestIssue( + const blink::mojom::FederatedAuthRequestIssueDetailsPtr& issue_details) { + protocol::String type_string = + RequestIdTokenStatusToProtocol(issue_details->status); + + auto federated_auth_request_details = + protocol::Audits::FederatedAuthRequestIssueDetails::Create() + .SetFederatedAuthRequestIssueReason(type_string) + .Build(); + + auto protocol_issue_details = + protocol::Audits::InspectorIssueDetails::Create() + .SetFederatedAuthRequestIssueDetails( + std::move(federated_auth_request_details)) + .Build(); + + auto issue = protocol::Audits::InspectorIssue::Create() + .SetCode(protocol::Audits::InspectorIssueCodeEnum:: + FederatedAuthRequestIssue) + .SetDetails(std::move(protocol_issue_details)) + .Build(); + return issue; +} + } // namespace void OnResetNavigationRequest(NavigationRequest* navigation_request) { @@ -1177,20 +1273,18 @@ void BuildAndReportBrowserInitiatedIssue( RenderFrameHostImpl* frame, blink::mojom::InspectorIssueInfoPtr info) { - // This method does not support other types for now. - CHECK(info && info->details && - (info->code == blink::mojom::InspectorIssueCode::kHeavyAdIssue && - info->details->heavy_ad_issue_details || - info->code == - blink::mojom::InspectorIssueCode::kTrustedWebActivityIssue && - info->details->twa_issue_details)); - std::unique_ptr<protocol::Audits::InspectorIssue> issue; if (info->code == blink::mojom::InspectorIssueCode::kTrustedWebActivityIssue) { issue = BuildTWAQualityIssue(info->details->twa_issue_details); - } else { + } else if (info->code == blink::mojom::InspectorIssueCode::kHeavyAdIssue) { issue = BuildHeavyAdIssue(info->details->heavy_ad_issue_details); + } else if (info->code == + blink::mojom::InspectorIssueCode::kFederatedAuthRequestIssue) { + issue = BuildFederatedAuthRequestIssue( + info->details->federated_auth_request_details); + } else { + NOTREACHED() << "Unsupported type of browser-initiated issue"; } ReportBrowserInitiatedIssue(frame, issue.get()); }
diff --git a/content/browser/quota/quota_internals_browsertest.cc b/content/browser/quota/quota_internals_browsertest.cc index bcf56f70..20270f6 100644 --- a/content/browser/quota/quota_internals_browsertest.cc +++ b/content/browser/quota/quota_internals_browsertest.cc
@@ -18,7 +18,7 @@ namespace { -const char kQuotaInternalsUrl[] = "chrome://quota-internals-2/"; +const char kQuotaInternalsUrl[] = "chrome://quota-internals/"; } // namespace
diff --git a/content/browser/quota/quota_internals_ui.cc b/content/browser/quota/quota_internals_ui.cc index bb34781..23b9447 100644 --- a/content/browser/quota/quota_internals_ui.cc +++ b/content/browser/quota/quota_internals_ui.cc
@@ -15,14 +15,14 @@ namespace content { -QuotaInternals2UI::QuotaInternals2UI(WebUI* web_ui) : WebUIController(web_ui) { +QuotaInternalsUI::QuotaInternalsUI(WebUI* web_ui) : WebUIController(web_ui) { WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIQuotaInternals2Host); + WebUIDataSource::Create(kChromeUIQuotaInternalsHost); source->AddResourcePath("quota_internals.mojom-webui.js", IDR_QUOTA_INTERNALS_MOJOM_JS); source->AddResourcePath("quota_internals.js", IDR_QUOTA_INTERNALS_JS); - source->AddResourcePath("quota-internals-2", IDR_QUOTA_INTERNALS_HTML); + source->AddResourcePath("quota-internals", IDR_QUOTA_INTERNALS_HTML); source->SetDefaultResource(IDR_QUOTA_INTERNALS_HTML); source->OverrideContentSecurityPolicy( @@ -33,11 +33,11 @@ WebUIDataSource::Add(web_contents->GetBrowserContext(), source); } -WEB_UI_CONTROLLER_TYPE_IMPL(QuotaInternals2UI) +WEB_UI_CONTROLLER_TYPE_IMPL(QuotaInternalsUI) -QuotaInternals2UI::~QuotaInternals2UI() = default; +QuotaInternalsUI::~QuotaInternalsUI() = default; -void QuotaInternals2UI::WebUIRenderFrameCreated( +void QuotaInternalsUI::WebUIRenderFrameCreated( RenderFrameHost* render_frame_host) { // Enable the JavaScript Mojo bindings in the renderer process, so the JS // code can call the Mojo APIs exposed by this WebUI.
diff --git a/content/browser/quota/quota_internals_ui.h b/content/browser/quota/quota_internals_ui.h index 10644b18..8f9773f 100644 --- a/content/browser/quota/quota_internals_ui.h +++ b/content/browser/quota/quota_internals_ui.h
@@ -14,13 +14,13 @@ class RenderFrameHost; class WebUI; -// WebUIController for the chrome://quota-internals-2 page. -class CONTENT_EXPORT QuotaInternals2UI : public WebUIController { +// WebUIController for the chrome://quota-internals page. +class CONTENT_EXPORT QuotaInternalsUI : public WebUIController { public: - explicit QuotaInternals2UI(WebUI* web_ui); - QuotaInternals2UI(const QuotaInternals2UI& other) = delete; - QuotaInternals2UI& operator=(const QuotaInternals2UI& other) = delete; - ~QuotaInternals2UI() override; + explicit QuotaInternalsUI(WebUI* web_ui); + QuotaInternalsUI(const QuotaInternalsUI& other) = delete; + QuotaInternalsUI& operator=(const QuotaInternalsUI& other) = delete; + ~QuotaInternalsUI() override; // WebUIController overrides: void WebUIRenderFrameCreated(RenderFrameHost* render_frame_host) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 20d613c4..99f3ba03 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -531,7 +531,7 @@ // which updates `visibility_`, unless the host is hidden. Make sure no update // is needed. DCHECK(host_->is_hidden() || visibility_ == Visibility::VISIBLE); - OnShowWithPageVisibility(PageVisibilityState::kVisible); + OnShowWithPageVisibility(page_visibility); } void RenderWidgetHostViewAura::NotifyHostAndDelegateOnWasShown(
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc index cebb22b..687ebf7 100644 --- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/feature_list.h" #include "base/location.h" #include "base/memory/raw_ptr.h" #include "base/path_service.h" @@ -13,7 +14,10 @@ #include "base/strings/stringprintf.h" #include "base/task/current_thread.h" #include "base/task/single_thread_task_runner.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/test_timeouts.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "cc/layers/surface_layer.h" @@ -21,6 +25,7 @@ #include "content/browser/renderer_host/dip_util.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" +#include "content/browser/renderer_host/visible_time_request_trigger.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/browser/render_frame_host.h" @@ -39,6 +44,8 @@ #include "net/base/filename_util.h" #include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-shared.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/layout.h" #include "ui/display/display_switches.h" @@ -1030,6 +1037,179 @@ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI, kTestCompositingModes); +class RenderWidgetHostViewPresentationFeedbackBrowserTest + : public NoCompositingRenderWidgetHostViewBrowserTest { + public: + RenderWidgetHostViewPresentationFeedbackBrowserTest( + const RenderWidgetHostViewPresentationFeedbackBrowserTest&) = delete; + RenderWidgetHostViewPresentationFeedbackBrowserTest& operator=( + const RenderWidgetHostViewPresentationFeedbackBrowserTest&) = delete; + + protected: + RenderWidgetHostViewPresentationFeedbackBrowserTest() = default; + ~RenderWidgetHostViewPresentationFeedbackBrowserTest() override = default; + + void SetUpOnMainThread() override { + NoCompositingRenderWidgetHostViewBrowserTest::SetUpOnMainThread(); + + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("/page_with_animation.html"))); + + RenderWidgetHostViewBase* rwhvb = GetRenderWidgetHostView(); + ASSERT_TRUE(rwhvb); + + // Start with the widget hidden. + rwhvb->Hide(); + + // Set a VisibleTimeRequest that will be sent the first time the widget + // becomes visible. + VisibleTimeRequestTrigger* request_trigger = + rwhvb->host()->GetVisibleTimeRequestTrigger(); + ASSERT_TRUE(request_trigger); + request_trigger->UpdateRequest(base::TimeTicks::Now(), + /*destination_is_loaded=*/true, + /*show_reason_tab_switching=*/true, + /*show_reason_unoccluded=*/false, + /*show_reason_bfcache_restore=*/false); + } + + enum class HistogramToExpect { + kTotalSwitchDuration, + kTotalIncompleteSwitchDuration, + }; + + ::testing::AssertionResult WaitForPresentationFeedback( + HistogramToExpect histogram_to_expect) { + // If TabSwitchMetrics2 is enabled, both Browser.Tabs.TotalSwitchDuration.* + // and Browser.Tabs.TotalSwitchDuration2.* will be logged. + const size_t expected_histogram_count = + base::FeatureList::IsEnabled(blink::features::kTabSwitchMetrics2) ? 2 + : 1; + + // Expect one of Browser.Tabs.TotalSwitchDuration.* or + // Browser.Tabs.TotalIncompleteSwitchDuration.*. + // + // Browser.Tabs.TabSwitchResult.* is also logged with a result code, but the + // HistogramTest API makes it easier to count the number of samples for any + // suffix of TotalSwitchDuration than to check the exact histogram values + // for each possible suffix of TabSwitchResult. + const char* expected_prefix; + const char* unexpected_prefix; + switch (histogram_to_expect) { + case HistogramToExpect::kTotalSwitchDuration: + expected_prefix = "Browser.Tabs.TotalSwitchDuration"; + unexpected_prefix = "Browser.Tabs.TotalIncompleteSwitchDuration"; + break; + case HistogramToExpect::kTotalIncompleteSwitchDuration: + expected_prefix = "Browser.Tabs.TotalIncompleteSwitchDuration"; + unexpected_prefix = "Browser.Tabs.TotalSwitchDuration"; + break; + } + + // Wait for the expected histograms (only) to be logged. + const base::TimeTicks start_time = base::TimeTicks::Now(); + while (base::TimeTicks::Now() - start_time < + TestTimeouts::action_timeout()) { + GiveItSomeTime(); + + if (!histogram_tester_.GetTotalCountsForPrefix(unexpected_prefix) + .empty()) { + return ::testing::AssertionFailure() + << "Unexpected histogram " << unexpected_prefix + << ". All histograms: " + << ::testing::PrintToString( + histogram_tester_.GetTotalCountsForPrefix( + "Browser.Tabs.")); + } + if (histogram_tester_.GetTotalCountsForPrefix(expected_prefix).size() == + expected_histogram_count) { + return ::testing::AssertionSuccess(); + } + } + + return ::testing::AssertionFailure() + << "Timed out waiting for " << expected_prefix + << ". All histograms: " + << ::testing::PrintToString( + histogram_tester_.GetTotalCountsForPrefix("Browser.Tabs.")); + } + + base::HistogramTester histogram_tester_; +}; + +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewPresentationFeedbackBrowserTest, + Show) { + GetRenderWidgetHostView()->ShowWithVisibility(PageVisibilityState::kVisible); + EXPECT_TRUE( + WaitForPresentationFeedback(HistogramToExpect::kTotalSwitchDuration)); +} + +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewPresentationFeedbackBrowserTest, + ShowThenHide) { + // Browser.Tabs.TotalIncompleteSwitchDuration.* is logged when the widget + // is hidden before presenting a frame. + GetRenderWidgetHostView()->ShowWithVisibility(PageVisibilityState::kVisible); + GetRenderWidgetHostView()->Hide(); + EXPECT_TRUE(WaitForPresentationFeedback( + HistogramToExpect::kTotalIncompleteSwitchDuration)); +} + +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewPresentationFeedbackBrowserTest, + HiddenButPainting) { + if (!base::FeatureList::IsEnabled(blink::features::kTabSwitchMetrics2)) { + GTEST_SKIP() << "Visibility changes with a hidden capturer are only " + "handled when TabSwitchMetrics2 is enabled"; + } + + // Browser.Tabs.* is not logged if the page becomes "visible" due to a hidden + // capturer. + GetRenderWidgetHostView()->ShowWithVisibility( + PageVisibilityState::kHiddenButPainting); + + // The full action_timeout is excessively long for the expected path. + const base::TimeTicks start_time = base::TimeTicks::Now(); + while (base::TimeTicks::Now() - start_time < base::Seconds(1)) { + GiveItSomeTime(); + ASSERT_TRUE( + histogram_tester_.GetTotalCountsForPrefix("Browser.Tabs.").empty()) + << "Unexpected histogram Browser.Tabs. All histograms: " + << ::testing::PrintToString( + histogram_tester_.GetTotalCountsForPrefix("Browser.Tabs.")); + } +} + +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewPresentationFeedbackBrowserTest, + ShowWhileCapturing) { + if (!base::FeatureList::IsEnabled(blink::features::kTabSwitchMetrics2)) { + GTEST_SKIP() << "Visibility changes with a hidden capturer are only " + "handled when TabSwitchMetrics2 is enabled"; + } + + // Frame is captured and then becomes visible. + GetRenderWidgetHostView()->ShowWithVisibility( + PageVisibilityState::kHiddenButPainting); + GetRenderWidgetHostView()->ShowWithVisibility(PageVisibilityState::kVisible); + EXPECT_TRUE( + WaitForPresentationFeedback(HistogramToExpect::kTotalSwitchDuration)); +} + +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewPresentationFeedbackBrowserTest, + HideWhileCapturing) { + if (!base::FeatureList::IsEnabled(blink::features::kTabSwitchMetrics2)) { + GTEST_SKIP() << "Visibility changes with a hidden capturer are only " + "handled when TabSwitchMetrics2 is enabled"; + } + + // Capture starts and frame becomes "hidden" before a render frame is + // presented. + GetRenderWidgetHostView()->ShowWithVisibility(PageVisibilityState::kVisible); + GetRenderWidgetHostView()->ShowWithVisibility( + PageVisibilityState::kHiddenButPainting); + EXPECT_TRUE(WaitForPresentationFeedback( + HistogramToExpect::kTotalIncompleteSwitchDuration)); +} + #endif // !BUILDFLAG(IS_ANDROID) } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc index bfcb10a..f112293 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -413,6 +413,11 @@ }; ASSERT_TRUE(trigger_subframe_tab_switch()); + // If TabSwitchMetrics2 is enabled, both Browser.Tabs.TotalSwitchDuration.* + // and Browser.Tabs.TotalSwitchDuration2.* will be logged. + const size_t expected_histogram_count = + base::FeatureList::IsEnabled(blink::features::kTabSwitchMetrics2) ? 2 : 1; + bool got_incomplete_tab_switch = false; const base::TimeTicks start_time = base::TimeTicks::Now(); do { @@ -454,7 +459,7 @@ histogram_tester .GetTotalCountsForPrefix( "Browser.Tabs.TotalIncompleteSwitchDuration") - .size() == 1) { + .size() == expected_histogram_count) { LOG(ERROR) << "Incomplete tab switch - try again."; got_incomplete_tab_switch = true; ASSERT_TRUE(trigger_subframe_tab_switch()); @@ -464,7 +469,7 @@ // single TotalSwitchDuration histogram to be logged. } while (histogram_tester .GetTotalCountsForPrefix("Browser.Tabs.TotalSwitchDuration") - .size() != 1); + .size() != expected_histogram_count); } // Auto-resize is only implemented for Ash and GuestViews. So we need to inject
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index a9401841..1161566a 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -4894,6 +4894,7 @@ EXPECT_TRUE(browser_td >= renderer_td); } +#if !BUILDFLAG(IS_ANDROID) class WebContentsImplBrowserTestWindowControlsOverlay : public WebContentsImplBrowserTest { public: @@ -5059,7 +5060,6 @@ EXPECT_EQ(bounding_client_rect.height(), EvalJs(web_contents, "rect.height")); } -#if !BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTestWindowControlsOverlay, ValidatePageScaleChangesInfoAndFiresEvent) { auto* web_contents = shell()->web_contents(); @@ -5104,7 +5104,6 @@ EXPECT_EQ(scaled_rect.height(), EvalJs(web_contents, "rect.height")); ValidateWindowsControlOverlayState(web_contents, scaled_rect, 60); } -#endif class WebContentsImplBrowserTestWindowControlsOverlayNonOneDeviceScaleFactor : public WebContentsImplBrowserTestWindowControlsOverlay { @@ -5146,6 +5145,7 @@ WaitForWindowControlsOverlayUpdate(web_contents, bounding_client_rect); ValidateWindowsControlOverlayState(web_contents, bounding_client_rect, 70); } +#endif class RenderFrameCreatedObserver : public WebContentsObserver { public:
diff --git a/content/browser/webid/fedcm_metrics.cc b/content/browser/webid/fedcm_metrics.cc index c587c450..8daa1c2 100644 --- a/content/browser/webid/fedcm_metrics.cc +++ b/content/browser/webid/fedcm_metrics.cc
@@ -10,32 +10,68 @@ namespace content { -void RecordShowAccountsDialogTime(base::TimeDelta duration) { +void RecordShowAccountsDialogTime(base::TimeDelta duration, + ukm::SourceId source_id) { + ukm::builders::Blink_FedCm builder(source_id); + builder.SetTiming_ShowAccountsDialog( + ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds())); + builder.Record(ukm::UkmRecorder::Get()); + UMA_HISTOGRAM_MEDIUM_TIMES("Blink.FedCm.Timing.ShowAccountsDialog", duration); } -void RecordContinueOnDialogTime(base::TimeDelta duration) { +void RecordContinueOnDialogTime(base::TimeDelta duration, + ukm::SourceId source_id) { + ukm::builders::Blink_FedCm builder(source_id); + builder.SetTiming_ContinueOnDialog( + ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds())); + builder.Record(ukm::UkmRecorder::Get()); + UMA_HISTOGRAM_MEDIUM_TIMES("Blink.FedCm.Timing.ContinueOnDialog", duration); } -void RecordCancelOnDialogTime(base::TimeDelta duration) { +void RecordCancelOnDialogTime(base::TimeDelta duration, + ukm::SourceId source_id) { + ukm::builders::Blink_FedCm builder(source_id); + builder.SetTiming_CancelOnDialog( + ukm::GetExponentialBucketMinForUserTiming(duration.InMilliseconds())); + builder.Record(ukm::UkmRecorder::Get()); + UMA_HISTOGRAM_MEDIUM_TIMES("Blink.FedCm.Timing.CancelOnDialog", duration); } void RecordIdTokenResponseAndTurnaroundTime( base::TimeDelta id_token_response_time, - base::TimeDelta turnaround_time) { + base::TimeDelta turnaround_time, + ukm::SourceId source_id) { + ukm::builders::Blink_FedCm builder(source_id); + builder + .SetTiming_IdTokenResponse(ukm::GetExponentialBucketMinForUserTiming( + id_token_response_time.InMilliseconds())) + .SetTiming_TurnaroundTime(ukm::GetExponentialBucketMinForUserTiming( + turnaround_time.InMilliseconds())); + builder.Record(ukm::UkmRecorder::Get()); + UMA_HISTOGRAM_MEDIUM_TIMES("Blink.FedCm.Timing.IdTokenResponse", id_token_response_time); UMA_HISTOGRAM_MEDIUM_TIMES("Blink.FedCm.Timing.TurnaroundTime", turnaround_time); } -void RecordRequestIdTokenStatus(FedCmRequestIdTokenStatus status) { +void RecordRequestIdTokenStatus(FedCmRequestIdTokenStatus status, + ukm::SourceId source_id) { + ukm::builders::Blink_FedCm builder(source_id); + builder.SetStatus_RequestIdToken(static_cast<int>(status)); + builder.Record(ukm::UkmRecorder::Get()); + UMA_HISTOGRAM_ENUMERATION("Blink.FedCm.Status.RequestIdToken", status); } -void RecordRevokeStatus(FedCmRevokeStatus status) { +void RecordRevokeStatus(FedCmRevokeStatus status, ukm::SourceId source_id) { + ukm::builders::Blink_FedCm builder(source_id); + builder.SetStatus_Revoke(static_cast<int>(status)); + builder.Record(ukm::UkmRecorder::Get()); + UMA_HISTOGRAM_ENUMERATION("Blink.FedCm.Status.Revoke", status); }
diff --git a/content/browser/webid/fedcm_metrics.h b/content/browser/webid/fedcm_metrics.h index a36cf58..cb31426b 100644 --- a/content/browser/webid/fedcm_metrics.h +++ b/content/browser/webid/fedcm_metrics.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_WEBID_FEDCM_METRICS_H_ #define CONTENT_BROWSER_WEBID_FEDCM_METRICS_H_ +#include "services/metrics/public/cpp/ukm_builders.h" + namespace base { class TimeDelta; } @@ -58,32 +60,37 @@ // Records the time from when a call to the API was made to when the accounts // dialog is shown. -void RecordShowAccountsDialogTime(base::TimeDelta duration); +void RecordShowAccountsDialogTime(base::TimeDelta duration, + ukm::SourceId source_id); // Records the time from when the accounts dialog is shown to when the user // presses the Continue button. -void RecordContinueOnDialogTime(base::TimeDelta duration); +void RecordContinueOnDialogTime(base::TimeDelta duration, + ukm::SourceId source_id); // Records the time from when the accounts dialog is shown to when the user // closes the dialog without selecting any account. -void RecordCancelOnDialogTime(base::TimeDelta duration); +void RecordCancelOnDialogTime(base::TimeDelta duration, + ukm::SourceId source_id); // Records the time from when the user presses the Continue button to when the // idtoken response is received. Also records the overall time from when the API // is called to when the idtoken response is received. void RecordIdTokenResponseAndTurnaroundTime( base::TimeDelta id_token_response_time, - base::TimeDelta turnaround_time); + base::TimeDelta turnaround_time, + ukm::SourceId source_id); // Records the status of the |RequestIdToken| call. // TODO(yigu): Call this function from |CompleteRequest| once the mojom side // |RequestIdTokenStatus| is cleaned up. -void RecordRequestIdTokenStatus(FedCmRequestIdTokenStatus status); +void RecordRequestIdTokenStatus(FedCmRequestIdTokenStatus status, + ukm::SourceId source_id); // Records the status of the |Revoke| call. // TODO(yigu): Call this function from |CompleteRevokeRequest| once the mojom // side |RevokeStatus| is cleaned up. -void RecordRevokeStatus(FedCmRevokeStatus status); +void RecordRevokeStatus(FedCmRevokeStatus status, ukm::SourceId source_id); } // namespace content #endif // CONTENT_BROWSER_WEBID_FEDCM_METRICS_H_
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index 4035f9d..984effc 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -22,6 +22,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" +#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h" #include "ui/accessibility/ax_mode.h" #include "url/url_constants.h" @@ -96,12 +97,14 @@ if (auth_request_callback_) { DCHECK(!revoke_callback_); DCHECK(!logout_callback_); - RecordRequestIdTokenStatus(IdTokenStatus::kUnhandledRequest); + RecordRequestIdTokenStatus(IdTokenStatus::kUnhandledRequest, + render_frame_host_->GetPageUkmSourceId()); } if (revoke_callback_) { DCHECK(!auth_request_callback_); DCHECK(!logout_callback_); - RecordRevokeStatus(RevokeStatusForMetrics::kUnhandledRequest); + RecordRevokeStatus(RevokeStatusForMetrics::kUnhandledRequest, + render_frame_host_->GetPageUkmSourceId()); } CompleteRequest(RequestIdTokenStatus::kError, ""); } @@ -114,7 +117,8 @@ bool prefer_auto_sign_in, blink::mojom::FederatedAuthRequest::RequestIdTokenCallback callback) { if (HasPendingRequest()) { - RecordRequestIdTokenStatus(IdTokenStatus::kTooManyRequests); + RecordRequestIdTokenStatus(IdTokenStatus::kTooManyRequests, + render_frame_host_->GetPageUkmSourceId()); std::move(callback).Run(RequestIdTokenStatus::kErrorTooManyRequests, ""); return; } @@ -129,7 +133,8 @@ network_manager_ = CreateNetworkManager(provider); if (!network_manager_) { - RecordRequestIdTokenStatus(IdTokenStatus::kNoNetworkManager); + RecordRequestIdTokenStatus(IdTokenStatus::kNoNetworkManager, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kError, ""); return; } @@ -168,7 +173,8 @@ // Dialog will be hidden by the destructor for request_dialog_controller_, // triggered by CompleteRequest. - RecordRequestIdTokenStatus(IdTokenStatus::kAborted); + RecordRequestIdTokenStatus(IdTokenStatus::kAborted, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorCanceled, ""); } @@ -178,7 +184,8 @@ const std::string& account_id, blink::mojom::FederatedAuthRequest::RevokeCallback callback) { if (HasPendingRequest()) { - RecordRevokeStatus(RevokeStatusForMetrics::kTooManyRequests); + RecordRevokeStatus(RevokeStatusForMetrics::kTooManyRequests, + render_frame_host_->GetPageUkmSourceId()); std::move(callback).Run(RevokeStatus::kError); return; } @@ -190,7 +197,8 @@ network_manager_ = CreateNetworkManager(provider); if (!network_manager_) { - RecordRevokeStatus(RevokeStatusForMetrics::kNoNetworkManager); + RecordRevokeStatus(RevokeStatusForMetrics::kNoNetworkManager, + render_frame_host_->GetPageUkmSourceId()); CompleteRevokeRequest(RevokeStatus::kError); return; } @@ -198,7 +206,8 @@ if (!GetRequestPermissionContext() || !GetRequestPermissionContext()->HasRequestPermission( origin_, url::Origin::Create(provider_))) { - RecordRevokeStatus(RevokeStatusForMetrics::kNoAccountToRevoke); + RecordRevokeStatus(RevokeStatusForMetrics::kNoAccountToRevoke, + render_frame_host_->GetPageUkmSourceId()); CompleteRevokeRequest(RevokeStatus::kError); return; } @@ -274,19 +283,22 @@ IdpNetworkRequestManager::Endpoints endpoints) { switch (status) { case IdpNetworkRequestManager::FetchStatus::kHttpNotFoundError: { - RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownHttpNotFound); + RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownHttpNotFound, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorFetchingWellKnownHttpNotFound, ""); return; } case IdpNetworkRequestManager::FetchStatus::kNoResponseError: { - RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownNoResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownNoResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorFetchingWellKnownNoResponse, ""); return; } case IdpNetworkRequestManager::FetchStatus::kInvalidResponseError: { - RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownInvalidResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownInvalidResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest( RequestIdTokenStatus::kErrorFetchingWellKnownInvalidResponse, ""); return; @@ -311,7 +323,8 @@ // For Mediated mode we require accounts, token and client ID endpoints. if (endpoints_.token.is_empty() || endpoints_.accounts.is_empty() || endpoints_.client_id_metadata.is_empty()) { - RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownInvalidResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownInvalidResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest( RequestIdTokenStatus::kErrorFetchingWellKnownInvalidResponse, ""); return; @@ -321,7 +334,8 @@ if (!IdpUrlIsValid(endpoints_.token) || !IdpUrlIsValid(endpoints_.accounts) || !IdpUrlIsValid(endpoints_.client_id_metadata)) { - RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownInvalidResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kWellKnownInvalidResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest( RequestIdTokenStatus::kErrorFetchingWellKnownInvalidResponse, ""); return; @@ -362,17 +376,20 @@ IdpNetworkRequestManager::Endpoints endpoints) { switch (status) { case IdpNetworkRequestManager::FetchStatus::kHttpNotFoundError: { - RecordRevokeStatus(RevokeStatusForMetrics::kWellKnownHttpNotFound); + RecordRevokeStatus(RevokeStatusForMetrics::kWellKnownHttpNotFound, + render_frame_host_->GetPageUkmSourceId()); CompleteRevokeRequest(RevokeStatus::kError); return; } case IdpNetworkRequestManager::FetchStatus::kNoResponseError: { - RecordRevokeStatus(RevokeStatusForMetrics::kWellKnownNoResponse); + RecordRevokeStatus(RevokeStatusForMetrics::kWellKnownNoResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRevokeRequest(RevokeStatus::kError); return; } case IdpNetworkRequestManager::FetchStatus::kInvalidResponseError: { - RecordRevokeStatus(RevokeStatusForMetrics::kWellKnownInvalidResponse); + RecordRevokeStatus(RevokeStatusForMetrics::kWellKnownInvalidResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRevokeRequest(RevokeStatus::kError); return; } @@ -389,7 +406,8 @@ // TODO(kenrb): This has to be same-origin with the provider. // https://crbug.com/1141125 if (!IdpUrlIsValid(revoke_url)) { - RecordRevokeStatus(RevokeStatusForMetrics::kRevokeUrlIsCrossOrigin); + RecordRevokeStatus(RevokeStatusForMetrics::kRevokeUrlIsCrossOrigin, + render_frame_host_->GetPageUkmSourceId()); CompleteRevokeRequest(RevokeStatus::kError); return; } @@ -420,9 +438,11 @@ GetActiveSessionPermissionContext()->RevokeActiveSession( origin_, idp_origin, account_id_); } - RecordRevokeStatus(RevokeStatusForMetrics::kSuccess); + RecordRevokeStatus(RevokeStatusForMetrics::kSuccess, + render_frame_host_->GetPageUkmSourceId()); } else { - RecordRevokeStatus(RevokeStatusForMetrics::kRevocationFailedOnServer); + RecordRevokeStatus(RevokeStatusForMetrics::kRevocationFailedOnServer, + render_frame_host_->GetPageUkmSourceId()); } CompleteRevokeRequest(status); } @@ -605,19 +625,22 @@ IdentityProviderMetadata idp_metadata) { switch (status) { case IdpNetworkRequestManager::FetchStatus::kHttpNotFoundError: { - RecordRequestIdTokenStatus(IdTokenStatus::kAccountsHttpNotFound); + RecordRequestIdTokenStatus(IdTokenStatus::kAccountsHttpNotFound, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorFetchingAccountsHttpNotFound, ""); return; } case IdpNetworkRequestManager::FetchStatus::kNoResponseError: { - RecordRequestIdTokenStatus(IdTokenStatus::kAccountsNoResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kAccountsNoResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorFetchingAccountsNoResponse, ""); return; } case IdpNetworkRequestManager::FetchStatus::kInvalidResponseError: { - RecordRequestIdTokenStatus(IdTokenStatus::kAccountsInvalidResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kAccountsInvalidResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest( RequestIdTokenStatus::kErrorFetchingAccountsInvalidResponse, ""); return; @@ -655,7 +678,8 @@ ClientIdData data{GURL(client_id_metadata_.terms_of_service_url), GURL(client_id_metadata_.privacy_policy_url)}; show_accounts_dialog_time_ = base::TimeTicks::Now(); - RecordShowAccountsDialogTime(show_accounts_dialog_time_ - start_time_); + RecordShowAccountsDialogTime(show_accounts_dialog_time_ - start_time_, + render_frame_host_->GetPageUkmSourceId()); request_dialog_controller_->ShowAccountsDialog( rp_web_contents, idp_web_contents_.get(), provider_, accounts, @@ -676,8 +700,10 @@ // This could happen if user didn't select any accounts. if (account_id.empty()) { base::TimeTicks dismiss_dialog_time = base::TimeTicks::Now(); - RecordCancelOnDialogTime(dismiss_dialog_time - show_accounts_dialog_time_); - RecordRequestIdTokenStatus(IdTokenStatus::kNotSelectAccount); + RecordCancelOnDialogTime(dismiss_dialog_time - show_accounts_dialog_time_, + render_frame_host_->GetPageUkmSourceId()); + RecordRequestIdTokenStatus(IdTokenStatus::kNotSelectAccount, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kError, ""); return; } @@ -691,7 +717,8 @@ account_id_ = account_id; select_account_time_ = base::TimeTicks::Now(); - RecordContinueOnDialogTime(select_account_time_ - show_accounts_dialog_time_); + RecordContinueOnDialogTime(select_account_time_ - show_accounts_dialog_time_, + render_frame_host_->GetPageUkmSourceId()); network_manager_->SendTokenRequest( endpoints_.token, account_id_, @@ -708,7 +735,7 @@ // takes a long time due to latency etc.. In case that the fetching process is // fast, we still want to show the "Verify" sheet for at least // |kIdTokenRequestDelay| seconds for better UX. - base::TimeTicks id_token_response_time_ = base::TimeTicks::Now(); + id_token_response_time_ = base::TimeTicks::Now(); base::TimeDelta fetch_time = id_token_response_time_ - select_account_time_; if (fetch_time >= kIdTokenRequestDelay) { CompleteIdTokenRequest(status, id_token); @@ -728,25 +755,29 @@ DCHECK(!start_time_.is_null()); switch (status) { case IdpNetworkRequestManager::FetchStatus::kHttpNotFoundError: { - RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenHttpNotFound); + RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenHttpNotFound, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorFetchingIdTokenHttpNotFound, ""); return; } case IdpNetworkRequestManager::FetchStatus::kNoResponseError: { - RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenNoResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenNoResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorFetchingIdTokenNoResponse, ""); return; } case IdpNetworkRequestManager::FetchStatus::kInvalidRequestError: { - RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenInvalidRequest); + RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenInvalidRequest, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kErrorFetchingIdTokenInvalidRequest, ""); return; } case IdpNetworkRequestManager::FetchStatus::kInvalidResponseError: { - RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenInvalidResponse); + RecordRequestIdTokenStatus(IdTokenStatus::kIdTokenInvalidResponse, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest( RequestIdTokenStatus::kErrorFetchingIdTokenInvalidResponse, ""); return; @@ -778,9 +809,11 @@ RecordIdTokenResponseAndTurnaroundTime( id_token_response_time_ - select_account_time_, - id_token_response_time_ - start_time_); + id_token_response_time_ - start_time_, + render_frame_host_->GetPageUkmSourceId()); id_token_ = id_token; - RecordRequestIdTokenStatus(IdTokenStatus::kSuccess); + RecordRequestIdTokenStatus(IdTokenStatus::kSuccess, + render_frame_host_->GetPageUkmSourceId()); CompleteRequest(RequestIdTokenStatus::kSuccess, id_token_); return; } @@ -844,6 +877,17 @@ const std::string& id_token) { DCHECK(status == RequestIdTokenStatus::kSuccess || id_token.empty()); + if (status != RequestIdTokenStatus::kSuccess) { + // It would be possible to add this inspector issue on the renderer, which + // will receive the callback. However, it is preferable to do so on the + // browser because this is closer to the source, which means adding + // additional metadata is easier. In addition, in the future we may only + // need to pass a small amount of information to the renderer in the case of + // an error, so it would be cleaner to do this by reporting the inspector + // issue from the browser. + AddInspectorIssue(status); + } + CleanUp(); if (auth_request_callback_) @@ -863,6 +907,20 @@ id_token_response_time_ = base::TimeTicks(); } +void FederatedAuthRequestImpl::AddInspectorIssue( + blink::mojom::RequestIdTokenStatus status) { + DCHECK_NE(status, blink::mojom::RequestIdTokenStatus::kSuccess); + auto details = blink::mojom::InspectorIssueDetails::New(); + auto federated_auth_request_details = + blink::mojom::FederatedAuthRequestIssueDetails::New(status); + details->federated_auth_request_details = + std::move(federated_auth_request_details); + render_frame_host_->ReportInspectorIssue( + blink::mojom::InspectorIssueInfo::New( + blink::mojom::InspectorIssueCode::kFederatedAuthRequestIssue, + std::move(details))); +} + void FederatedAuthRequestImpl::CompleteLogoutRequest( blink::mojom::LogoutStatus status) { network_manager_.reset();
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h index 41c2831..7ebd1f81c 100644 --- a/content/browser/webid/federated_auth_request_impl.h +++ b/content/browser/webid/federated_auth_request_impl.h
@@ -119,6 +119,10 @@ FederatedIdentitySharingPermissionContextDelegate* GetSharingPermissionContext(); + // Creates an inspector issue related to a federated authentication request to + // the Issues panel in DevTools. + void AddInspectorIssue(blink::mojom::RequestIdTokenStatus status); + const raw_ptr<RenderFrameHost> render_frame_host_ = nullptr; const url::Origin origin_;
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index df3e5bf..4531a2aa8 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_util.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" +#include "components/ukm/test_ukm_recorder.h" #include "content/browser/webid/fedcm_metrics.h" #include "content/browser/webid/federated_auth_request_service.h" #include "content/browser/webid/id_token_request_callback_data.h" @@ -25,8 +26,10 @@ #include "content/public/browser/browser_accessibility_state.h" #include "content/public/browser/identity_request_dialog_controller.h" #include "content/public/common/content_features.h" -#include "content/public/test/test_renderer_host.h" +#include "content/test/test_render_frame_host.h" +#include "content/test/test_render_view_host.h" #include "mojo/public/cpp/bindings/remote.h" +#include "services/metrics/public/cpp/ukm_builders.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -40,6 +43,7 @@ using blink::mojom::RequestIdTokenStatus; using blink::mojom::RequestMode; using blink::mojom::RevokeStatus; +using Entry = ukm::builders::Blink_FedCm; using FetchStatus = content::IdpNetworkRequestManager::FetchStatus; using LogoutResponse = content::IdpNetworkRequestManager::LogoutResponse; using SigninResponse = content::IdpNetworkRequestManager::SigninResponse; @@ -459,11 +463,11 @@ } // namespace -class FederatedAuthRequestImplTest : public RenderViewHostTestHarness { +class FederatedAuthRequestImplTest : public RenderViewHostImplTestHarness { protected: - FederatedAuthRequestImplTest() - : RenderViewHostTestHarness( - base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + FederatedAuthRequestImplTest() { + ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); + } ~FederatedAuthRequestImplTest() override = default; FederatedAuthRequestImpl& CreateAuthRequest(const GURL& provider) { @@ -712,6 +716,70 @@ return mock_dialog_controller_; } + ukm::TestAutoSetUkmRecorder* ukm_recorder() { return ukm_recorder_.get(); } + + void ExpectRequestIdTokenStatusUKM(IdTokenStatus status) { + auto entries = ukm_recorder()->GetEntriesByName(Entry::kEntryName); + + if (entries.empty()) + FAIL() << "No RequestIdTokenStatus was recorded"; + + // There are multiple types of metrics under the same FedCM UKM. We need to + // make sure that the metric only includes the expected one. + for (const auto* const entry : entries) { + const int64_t* metric = + ukm_recorder()->GetEntryMetric(entry, "Status_RequestIdToken"); + if (metric && *metric != static_cast<int>(status)) + FAIL() << "Unexpected status was recorded"; + } + + SUCCEED(); + } + + void ExpectRevokeStatusUKM(RevokeStatusForMetrics status) { + auto entries = ukm_recorder()->GetEntriesByName(Entry::kEntryName); + + if (entries.empty()) + FAIL() << "No RevokeStatus was recorded"; + + // There are multiple types of metrics under the same FedCM UKM. We need to + // make sure that the metric only includes the expected one. + for (const auto* const entry : entries) { + const int64_t* metric = + ukm_recorder()->GetEntryMetric(entry, "Status_Revoke"); + if (metric && *metric != static_cast<int>(status)) + FAIL() << "Unexpected status was recorded"; + } + + SUCCEED(); + } + + void ExpectTimingUKM(const std::string& metric_name) { + auto entries = ukm_recorder()->GetEntriesByName(Entry::kEntryName); + + ASSERT_FALSE(entries.empty()); + + for (const auto* const entry : entries) { + if (ukm_recorder()->GetEntryMetric(entry, metric_name)) { + SUCCEED(); + return; + } + } + FAIL() << "Expected UKM was not recorded"; + } + + void ExpectNoTimingUKM(const std::string& metric_name) { + auto entries = ukm_recorder()->GetEntriesByName(Entry::kEntryName); + + ASSERT_FALSE(entries.empty()); + + for (const auto* const entry : entries) { + if (ukm_recorder()->GetEntryMetric(entry, metric_name)) + FAIL() << "Unexpected UKM was recorded"; + } + SUCCEED(); + } + protected: mojo::Remote<blink::mojom::FederatedAuthRequest> request_remote_; // Note: `auth_request_service_` owns itself, and will generally be deleted @@ -739,6 +807,9 @@ AccountList displayed_accounts_; GURL provider_; + + private: + std::unique_ptr<ukm::TestAutoSetUkmRecorder> ukm_recorder_; }; class BasicFederatedAuthRequestImplTest @@ -767,6 +838,18 @@ EXPECT_EQ(auth_response.second, test_case.expected.token); } +TEST_P(BasicFederatedAuthRequestImplTest, FederatedAuthRequestIssue) { + AuthRequestTestCase test_case = GetParam(); + CreateAuthRequest(GURL(test_case.inputs.provider)); + SetMockExpectations(test_case); + auto auth_response = PerformAuthRequest( + test_case.inputs.client_id, test_case.inputs.nonce, test_case.inputs.mode, + test_case.inputs.prefer_auto_sign_in); + EXPECT_EQ( + main_test_rfh()->GetFederatedAuthRequestIssueCount(auth_response.first), + auth_response.first == RequestIdTokenStatus::kSuccess ? 0 : 1); +} + // Test Logout method success with multiple relying parties. TEST_F(BasicFederatedAuthRequestImplTest, LogoutSuccessMultiple) { CreateAuthRequest(GURL(kIdpTestOrigin)); @@ -1124,11 +1207,21 @@ EXPECT_EQ(kAccountId, account_id); std::move(callback).Run(RevokeResponse::kSuccess); })); + + base::RunLoop ukm_loop; + ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName, + ukm_loop.QuitClosure()); + auto status = PerformRevokeRequest(kAccountId); EXPECT_EQ(RevokeStatus::kSuccess, status); + + ukm_loop.Run(); + histogram_tester.ExpectTotalCount("Blink.FedCm.Status.Revoke", 1); histogram_tester.ExpectBucketCount("Blink.FedCm.Status.Revoke", RevokeStatusForMetrics::kSuccess, 1); + + ExpectRevokeStatusUKM(RevokeStatusForMetrics::kSuccess); } TEST_F(FederatedAuthRequestImplTest, RevokeNoPermission) { @@ -1146,12 +1239,20 @@ HasRequestPermission(_, url::Origin::Create(GURL(kIdpTestOrigin)))) .WillOnce(Return(false)); + base::RunLoop ukm_loop; + ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName, + ukm_loop.QuitClosure()); + auto status = PerformRevokeRequest(kAccountId); EXPECT_EQ(RevokeStatus::kError, status); + + ukm_loop.Run(); histogram_tester.ExpectTotalCount("Blink.FedCm.Status.Revoke", 1); histogram_tester.ExpectBucketCount("Blink.FedCm.Status.Revoke", RevokeStatusForMetrics::kNoAccountToRevoke, 1); + + ExpectRevokeStatusUKM(RevokeStatusForMetrics::kNoAccountToRevoke); } TEST_F(BasicFederatedAuthRequestImplTest, MetricsForSuccessfulSignUpCase) { @@ -1166,11 +1267,18 @@ &mock_sharing_permission_delegate); EXPECT_EQ(test_case.config.Mediated_conf.accounts.size(), 1u); + + base::RunLoop ukm_loop; + ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName, + ukm_loop.QuitClosure()); + auto auth_response = PerformAuthRequest( test_case.inputs.client_id, test_case.inputs.nonce, test_case.inputs.mode, test_case.inputs.prefer_auto_sign_in); EXPECT_EQ(auth_response.second.value(), kToken); + ukm_loop.Run(); + histogram_tester.ExpectTotalCount("Blink.FedCm.Timing.ShowAccountsDialog", 1); histogram_tester.ExpectTotalCount("Blink.FedCm.Timing.ContinueOnDialog", 1); histogram_tester.ExpectTotalCount("Blink.FedCm.Timing.CancelOnDialog", 0); @@ -1180,6 +1288,14 @@ histogram_tester.ExpectTotalCount("Blink.FedCm.Status.RequestIdToken", 1); histogram_tester.ExpectBucketCount("Blink.FedCm.Status.RequestIdToken", IdTokenStatus::kSuccess, 1); + + ExpectTimingUKM("Timing.ShowAccountsDialog"); + ExpectTimingUKM("Timing.ContinueOnDialog"); + ExpectTimingUKM("Timing.IdTokenResponse"); + ExpectTimingUKM("Timing.TurnaroundTime"); + ExpectNoTimingUKM("Timing.CancelOnDialog"); + + ExpectRequestIdTokenStatusUKM(IdTokenStatus::kSuccess); } TEST_F(BasicFederatedAuthRequestImplTest, MetricsForSuccessfulSignInCase) { @@ -1199,11 +1315,17 @@ url::Origin::Create(GURL(kIdpTestOrigin)), _, "1234")) .WillOnce(Return(true)); + base::RunLoop ukm_loop; + ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName, + ukm_loop.QuitClosure()); + auto auth_response = PerformAuthRequest( test_case.inputs.client_id, test_case.inputs.nonce, test_case.inputs.mode, test_case.inputs.prefer_auto_sign_in); EXPECT_EQ(LoginState::kSignIn, displayed_accounts()[0].login_state); + ukm_loop.Run(); + histogram_tester.ExpectTotalCount("Blink.FedCm.Timing.ShowAccountsDialog", 1); histogram_tester.ExpectTotalCount("Blink.FedCm.Timing.ContinueOnDialog", 1); histogram_tester.ExpectTotalCount("Blink.FedCm.Timing.CancelOnDialog", 0); @@ -1213,6 +1335,14 @@ histogram_tester.ExpectTotalCount("Blink.FedCm.Status.RequestIdToken", 1); histogram_tester.ExpectBucketCount("Blink.FedCm.Status.RequestIdToken", IdTokenStatus::kSuccess, 1); + + ExpectTimingUKM("Timing.ShowAccountsDialog"); + ExpectTimingUKM("Timing.ContinueOnDialog"); + ExpectTimingUKM("Timing.IdTokenResponse"); + ExpectTimingUKM("Timing.TurnaroundTime"); + ExpectNoTimingUKM("Timing.CancelOnDialog"); + + ExpectRequestIdTokenStatusUKM(IdTokenStatus::kSuccess); } TEST_F(BasicFederatedAuthRequestImplTest, MetricsForNotSelectingAccount) { @@ -1259,10 +1389,17 @@ })); EXPECT_EQ(test_case.config.Mediated_conf.accounts.size(), 1u); + + base::RunLoop ukm_loop; + ukm_recorder()->SetOnAddEntryCallback(Entry::kEntryName, + ukm_loop.QuitClosure()); + auto auth_response = PerformAuthRequest( test_case.inputs.client_id, test_case.inputs.nonce, test_case.inputs.mode, test_case.inputs.prefer_auto_sign_in); + ukm_loop.Run(); + ASSERT_FALSE(displayed_accounts.empty()); EXPECT_EQ(displayed_accounts[0].login_state, LoginState::kSignUp); @@ -1275,6 +1412,14 @@ histogram_tester.ExpectTotalCount("Blink.FedCm.Status.RequestIdToken", 1); histogram_tester.ExpectBucketCount("Blink.FedCm.Status.RequestIdToken", IdTokenStatus::kNotSelectAccount, 1); + + ExpectTimingUKM("Timing.ShowAccountsDialog"); + ExpectTimingUKM("Timing.CancelOnDialog"); + ExpectNoTimingUKM("Timing.ContinueOnDialog"); + ExpectNoTimingUKM("Timing.IdTokenResponse"); + ExpectNoTimingUKM("Timing.TurnaroundTime"); + + ExpectRequestIdTokenStatusUKM(IdTokenStatus::kNotSelectAccount); } } // namespace content
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc index 37efb34..354da6e2d 100644 --- a/content/browser/webid/idp_network_request_manager.cc +++ b/content/browser/webid/idp_network_request_manager.cc
@@ -114,6 +114,7 @@ std::unique_ptr<network::ResourceRequest> CreateCredentialedResourceRequest( GURL target_url, + bool send_referrer, url::Origin initiator) { auto resource_request = std::make_unique<network::ResourceRequest>(); auto target_origin = url::Origin::Create(target_url); @@ -122,6 +123,11 @@ resource_request->request_initiator = initiator; resource_request->url = target_url; resource_request->site_for_cookies = site_for_cookies; + if (send_referrer) { + resource_request->referrer = initiator.GetURL(); + resource_request->referrer_policy = + net::ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE; + } resource_request->headers.SetHeader(net::HttpRequestHeaders::kAccept, kRequestBodyContentType); @@ -329,7 +335,8 @@ GURL target_url = provider_.Resolve(IdpNetworkRequestManager::kWellKnownFilePath); - url_loader_ = CreateUncredentialedUrlLoader(target_url); + url_loader_ = + CreateUncredentialedUrlLoader(target_url, /* send_referrer= */ false); url_loader_->DownloadToString( loader_factory_.get(), @@ -350,7 +357,8 @@ std::string escaped_request = net::EscapeUrlEncodedData(request, true); GURL target_url = GURL(signin_url.spec() + "?" + escaped_request); - url_loader_ = CreateCredentialedUrlLoader(target_url); + url_loader_ = + CreateCredentialedUrlLoader(target_url, /* send_referrer= */ true); url_loader_->DownloadToString( loader_factory_.get(), base::BindOnce(&IdpNetworkRequestManager::OnSigninRequestResponse, @@ -366,13 +374,8 @@ AccountsRequestCallback callback) { DCHECK(!url_loader_); - // Use ReferrerPolicy::NO_REFERRER for this request so that relying party - // identity is not exposed to the Identity provider via referrer. - // TODO(cbiesinger): I don't think this does the right thing; per comments - // in referrer_policy.h this only applies to redirects. - net::ReferrerPolicy policy = net::ReferrerPolicy::NO_REFERRER; url_loader_ = - CreateCredentialedUrlLoader(accounts_url, absl::nullopt, policy); + CreateCredentialedUrlLoader(accounts_url, /* send_referrer= */ false); url_loader_->DownloadToString( loader_factory_.get(), @@ -422,7 +425,8 @@ return; } - url_loader_ = CreateCredentialedUrlLoader(token_url, request); + url_loader_ = CreateCredentialedUrlLoader(token_url, + /* send_referrer= */ true, request); url_loader_->DownloadToString( loader_factory_.get(), @@ -480,7 +484,8 @@ return; } - url_loader_ = CreateCredentialedUrlLoader(revoke_url, revoke_request_body); + url_loader_ = CreateCredentialedUrlLoader( + revoke_url, /* send_referrer= */ true, revoke_request_body); url_loader_->DownloadToString( loader_factory_.get(), @@ -498,8 +503,8 @@ logout_callback_ = std::move(callback); - auto resource_request = - CreateCredentialedResourceRequest(logout_url, relying_party_origin_); + auto resource_request = CreateCredentialedResourceRequest( + logout_url, /* send_referrer= */ false, relying_party_origin_); resource_request->headers.SetHeader(net::HttpRequestHeaders::kAccept, "*/*"); auto traffic_annotation = CreateTrafficAnnotation(); @@ -769,7 +774,8 @@ GURL target_url = endpoint.Resolve( "?client_id=" + net::EscapeQueryParamValue(client_id, true)); - url_loader_ = CreateUncredentialedUrlLoader(target_url); + url_loader_ = + CreateUncredentialedUrlLoader(target_url, /* send_referrer= */ true); url_loader_->DownloadToString( loader_factory_.get(), @@ -822,7 +828,8 @@ std::unique_ptr<network::SimpleURLLoader> IdpNetworkRequestManager::CreateUncredentialedUrlLoader( - const GURL& target_url) const { + const GURL& target_url, + bool send_referrer) const { net::NetworkTrafficAnnotationTag traffic_annotation = CreateTrafficAnnotation(); @@ -840,6 +847,11 @@ resource_request->headers.SetHeader(net::HttpRequestHeaders::kAccept, kRequestBodyContentType); AddCsrfHeader(resource_request.get()); + if (send_referrer) { + resource_request->referrer = relying_party_origin_.GetURL(); + // Since referrer_policy only affects redirects and we disable redirects + // below, we don't need to set referrer_policy here. + } // TODO(kenrb): Not following redirects is important for security because // this bypasses CORB. Ensure there is a test added. // https://crbug.com/1155312. @@ -857,12 +869,10 @@ std::unique_ptr<network::SimpleURLLoader> IdpNetworkRequestManager::CreateCredentialedUrlLoader( const GURL& target_url, - absl::optional<std::string> request_body, - absl::optional<net::ReferrerPolicy> policy) const { - auto resource_request = - CreateCredentialedResourceRequest(target_url, relying_party_origin_); - if (policy) - resource_request->referrer_policy = *policy; + bool send_referrer, + absl::optional<std::string> request_body) const { + auto resource_request = CreateCredentialedResourceRequest( + target_url, send_referrer, relying_party_origin_); if (request_body) { resource_request->method = net::HttpRequestHeaders::kPostMethod; resource_request->headers.SetHeader(net::HttpRequestHeaders::kContentType,
diff --git a/content/browser/webid/idp_network_request_manager.h b/content/browser/webid/idp_network_request_manager.h index 82c6e3d..0fe1850 100644 --- a/content/browser/webid/idp_network_request_manager.h +++ b/content/browser/webid/idp_network_request_manager.h
@@ -211,11 +211,12 @@ void OnLogoutCompleted(std::unique_ptr<std::string> response_body); std::unique_ptr<network::SimpleURLLoader> CreateUncredentialedUrlLoader( - const GURL& url) const; + const GURL& url, + bool send_referrer) const; std::unique_ptr<network::SimpleURLLoader> CreateCredentialedUrlLoader( const GURL& url, - absl::optional<std::string> request_body = absl::nullopt, - absl::optional<net::ReferrerPolicy> policy = absl::nullopt) const; + bool send_referrer, + absl::optional<std::string> request_body = absl::nullopt) const; // URL of the Identity Provider. GURL provider_;
diff --git a/content/browser/webid/idp_network_request_manager_unittest.cc b/content/browser/webid/idp_network_request_manager_unittest.cc index 75c77bf..5f1cc74 100644 --- a/content/browser/webid/idp_network_request_manager_unittest.cc +++ b/content/browser/webid/idp_network_request_manager_unittest.cc
@@ -23,6 +23,7 @@ #include "url/gurl.h" using AccountList = content::IdpNetworkRequestManager::AccountList; +using ClientIdMetadata = content::IdpNetworkRequestManager::ClientIdMetadata; using FetchStatus = content::IdpNetworkRequestManager::FetchStatus; using AccountsRequestCallback = content::IdpNetworkRequestManager::AccountsRequestCallback; @@ -39,6 +40,9 @@ const char kTestIdpUrl[] = "https://idp.test"; const char kTestRpUrl[] = "https://rp.test"; const char kTestAccountsEndpoint[] = "https://idp.test/accounts_endpoint"; +const char kTestTokenEndpoint[] = "https://idp.test/token_endpoint"; +const char kTestClientIdMetadataEndpoint[] = + "https://idp.test/client_id_metadata_endpoint"; const char kTestRevokeEndpoint[] = "https://idp.test/revoke_endpoint"; class IdpNetworkRequestManagerTest : public ::testing::Test { @@ -86,6 +90,50 @@ std::move(parsed_idp_metadata)}; } + std::string SendTokenRequestAndWaitForResponse( + const char* account, + const char* request, + net::HttpStatusCode http_status = net::HTTP_OK) { + const char response[] = R"({"id_token": "token"})"; + GURL token_endpoint(kTestTokenEndpoint); + test_url_loader_factory().AddResponse(token_endpoint.spec(), response, + http_status); + + std::string token; + base::RunLoop run_loop; + auto callback = base::BindLambdaForTesting( + [&](FetchStatus status, const std::string& token_response) { + token = token_response; + run_loop.Quit(); + }); + manager().SendTokenRequest(token_endpoint, account, request, + std::move(callback)); + run_loop.Run(); + return token; + } + + ClientIdMetadata SendClientIdMetadataRequestAndWaitForResponse( + const char* client_id, + net::HttpStatusCode http_status = net::HTTP_OK) { + const char response[] = R"({})"; + GURL client_id_endpoint(kTestClientIdMetadataEndpoint); + test_url_loader_factory().AddResponse( + client_id_endpoint.spec() + "?client_id=" + client_id, response, + http_status); + + ClientIdMetadata data; + base::RunLoop run_loop; + auto callback = base::BindLambdaForTesting( + [&](FetchStatus status, ClientIdMetadata metadata) { + data = metadata; + run_loop.Quit(); + }); + manager().FetchClientIdMetadata(client_id_endpoint, client_id, + std::move(callback)); + run_loop.Run(); + return data; + } + RevokeResponse SendRevokeRequestAndWaitForResponse( const char* client_id, const char* account_id, @@ -585,12 +633,90 @@ EXPECT_EQ(FetchStatus::kSuccess, accounts_response); } +// Tests that we send the correct referrer for account requests. +TEST_F(IdpNetworkRequestManagerTest, AccountRequestReferrer) { + bool called = false; + auto interceptor = + base::BindLambdaForTesting([&](const network::ResourceRequest& request) { + called = true; + EXPECT_EQ(GURL(kTestAccountsEndpoint), request.url); + EXPECT_EQ(request.request_body, nullptr); + EXPECT_EQ(false, request.referrer.is_valid()); + }); + test_url_loader_factory().SetInterceptor(interceptor); + + const char test_accounts_json[] = R"({ + "accounts" : [ + { + "sub" : "1234", + "email": "ken@idp.test", + "name": "Ken R. Example" + } + ] + })"; + + FetchStatus accounts_response; + AccountList accounts; + IdentityProviderMetadata idp_metadata; + std::tie(accounts_response, accounts, idp_metadata) = + SendAccountsRequestAndWaitForResponse(test_accounts_json); + + ASSERT_TRUE(called); + EXPECT_EQ(FetchStatus::kSuccess, accounts_response); +} + +// Tests the token request implementation. +TEST_F(IdpNetworkRequestManagerTest, TokenRequest) { + bool called = false; + auto interceptor = + base::BindLambdaForTesting([&](const network::ResourceRequest& request) { + called = true; + EXPECT_EQ(GURL(kTestTokenEndpoint), request.url); + EXPECT_EQ(GURL(kTestRpUrl), request.referrer); + + // Check that the request body is correct (should be "request") + ASSERT_NE(request.request_body, nullptr); + ASSERT_EQ(1ul, request.request_body->elements()->size()); + const network::DataElement& elem = + request.request_body->elements()->at(0); + ASSERT_EQ(network::DataElement::Tag::kBytes, elem.type()); + const network::DataElementBytes& byte_elem = + elem.As<network::DataElementBytes>(); + EXPECT_EQ("request", byte_elem.AsStringPiece()); + }); + test_url_loader_factory().SetInterceptor(interceptor); + std::string token = SendTokenRequestAndWaitForResponse("account", "request"); + ASSERT_TRUE(called); + ASSERT_EQ("token", token); +} + +// Tests the client id metadata implementation. +TEST_F(IdpNetworkRequestManagerTest, ClientIdMetadata) { + bool called = false; + auto interceptor = + base::BindLambdaForTesting([&](const network::ResourceRequest& request) { + called = true; + std::string url_string = + std::string(kTestClientIdMetadataEndpoint) + "?client_id=xxx"; + EXPECT_EQ(GURL(url_string), request.url); + EXPECT_EQ(request.request_body, nullptr); + EXPECT_EQ(GURL(kTestRpUrl), request.referrer); + }); + test_url_loader_factory().SetInterceptor(interceptor); + ClientIdMetadata data = SendClientIdMetadataRequestAndWaitForResponse("xxx"); + ASSERT_TRUE(called); + ASSERT_EQ("", data.privacy_policy_url); + ASSERT_EQ("", data.terms_of_service_url); +} + // Tests the revoke implementation. TEST_F(IdpNetworkRequestManagerTest, Revoke) { bool called = false; auto interceptor = base::BindLambdaForTesting([&](const network::ResourceRequest& request) { called = true; + EXPECT_EQ(GURL(kTestRpUrl), request.referrer); + // Check that the request body is correct ASSERT_NE(request.request_body, nullptr); ASSERT_EQ(1ul, request.request_body->elements()->size()); const network::DataElement& elem =
diff --git a/content/browser/webui/content_web_ui_controller_factory.cc b/content/browser/webui/content_web_ui_controller_factory.cc index 3d7511e..1324e1c9 100644 --- a/content/browser/webui/content_web_ui_controller_factory.cc +++ b/content/browser/webui/content_web_ui_controller_factory.cc
@@ -46,7 +46,7 @@ url.host_piece() == kChromeUIPrerenderInternalsHost || url.host_piece() == kChromeUIProcessInternalsHost || url.host_piece() == kChromeUIAttributionInternalsHost || - url.host_piece() == kChromeUIQuotaInternals2Host || + url.host_piece() == kChromeUIQuotaInternalsHost || url.host_piece() == kChromeUIUkmHost) { return const_cast<ContentWebUIControllerFactory*>(this); } @@ -86,8 +86,8 @@ return std::make_unique<ProcessInternalsUI>(web_ui); if (url.host_piece() == kChromeUIAttributionInternalsHost) return std::make_unique<AttributionInternalsUI>(web_ui); - if (url.host_piece() == kChromeUIQuotaInternals2Host) - return std::make_unique<QuotaInternals2UI>(web_ui); + if (url.host_piece() == kChromeUIQuotaInternalsHost) + return std::make_unique<QuotaInternalsUI>(web_ui); if (url.host_piece() == kChromeUIUkmHost) return std::make_unique<UkmInternalsUI>(web_ui); if (url.host_piece() == kChromeUIMediaInternalsHost) {
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc index 6122c0be..2e72ca2 100644 --- a/content/public/common/url_constants.cc +++ b/content/public/common/url_constants.cc
@@ -38,7 +38,7 @@ const char kChromeUINetworkErrorsListingHost[] = "network-errors"; const char kChromeUIPrerenderInternalsHost[] = "prerender-internals"; const char kChromeUIProcessInternalsHost[] = "process-internals"; -const char kChromeUIQuotaInternals2Host[] = "quota-internals-2"; +const char kChromeUIQuotaInternalsHost[] = "quota-internals"; const char kChromeUIResourcesHost[] = "resources"; const char kChromeUIServiceWorkerInternalsHost[] = "serviceworker-internals"; const char kChromeUITracingHost[] = "tracing";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h index 587304b..ebbb5796 100644 --- a/content/public/common/url_constants.h +++ b/content/public/common/url_constants.h
@@ -48,7 +48,7 @@ CONTENT_EXPORT extern const char kChromeUINetworkErrorsListingHost[]; CONTENT_EXPORT extern const char kChromeUIPrerenderInternalsHost[]; CONTENT_EXPORT extern const char kChromeUIProcessInternalsHost[]; -CONTENT_EXPORT extern const char kChromeUIQuotaInternals2Host[]; +CONTENT_EXPORT extern const char kChromeUIQuotaInternalsHost[]; CONTENT_EXPORT extern const char kChromeUIResourcesHost[]; CONTENT_EXPORT extern const char kChromeUIServiceWorkerInternalsHost[]; CONTENT_EXPORT extern const char kChromeUITracingHost[];
diff --git a/content/test/data/attribution_reporting/databases/version_1.sql b/content/test/data/attribution_reporting/databases/version_1.sql deleted file mode 100644 index 9188982..0000000 --- a/content/test/data/attribution_reporting/databases/version_1.sql +++ /dev/null
@@ -1,30 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1); - -INSERT INTO impressions -VALUES(1, - '9357e17751666f64', - 'https://impression.test', - 'https://sub.conversion.test', - 'https://report.test', - 13245278349693988, - 13247870349693988, - 0, - 1); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER,conversion_data TEXT NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,attribution_credit INTEGER NOT NULL); - -CREATE INDEX conversion_origin_idx ON impressions(active,conversion_origin,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_10.sql b/content/test/data/attribution_reporting/databases/version_10.sql deleted file mode 100644 index be8e732..0000000 --- a/content/test/data/attribution_reporting/databases/version_10.sql +++ /dev/null
@@ -1,37 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data INTEGER NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL,impression_site TEXT NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER NOT NULL,conversion_data INTEGER NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,priority INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE dedup_keys(impression_id INTEGER NOT NULL,dedup_key INTEGER NOT NULL,PRIMARY KEY(impression_id,dedup_key))WITHOUT ROWID; - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','10'); -INSERT INTO meta VALUES('last_compatible_version','10'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX impression_site_idx ON impressions(active,impression_site,source_type); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_11.sql b/content/test/data/attribution_reporting/databases/version_11.sql deleted file mode 100644 index 617cdbe..0000000 --- a/content/test/data/attribution_reporting/databases/version_11.sql +++ /dev/null
@@ -1,40 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data INTEGER NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL,impression_site TEXT NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER NOT NULL,conversion_data INTEGER NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,priority INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE dedup_keys(impression_id INTEGER NOT NULL,dedup_key INTEGER NOT NULL,PRIMARY KEY(impression_id,dedup_key))WITHOUT ROWID; - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','11'); -INSERT INTO meta VALUES('last_compatible_version','11'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX event_source_impression_site_idx ON impressions(impression_site)WHERE active = 1 AND num_conversions = 0 AND source_type = 1; - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -INSERT INTO rate_limits VALUES - (1, 0, 11, 'https://a.example', 'https://a.a.example', 'https://b.example', 'https://b.b.example', 7); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_12.sql b/content/test/data/attribution_reporting/databases/version_12.sql deleted file mode 100644 index 6db38be..0000000 --- a/content/test/data/attribution_reporting/databases/version_12.sql +++ /dev/null
@@ -1,40 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data INTEGER NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL,impression_site TEXT NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER NOT NULL,conversion_data INTEGER NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,priority INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY NOT NULL,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL,bucket TEXT NOT NULL,value INTEGER NOT NULL); - -CREATE TABLE dedup_keys(impression_id INTEGER NOT NULL,dedup_key INTEGER NOT NULL,PRIMARY KEY(impression_id,dedup_key))WITHOUT ROWID; - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','12'); -INSERT INTO meta VALUES('last_compatible_version','12'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX event_source_impression_site_idx ON impressions(impression_site)WHERE active = 1 AND num_conversions = 0 AND source_type = 1; - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_attribution_type_conversion_time_idx ON rate_limits(attribution_type,conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -INSERT INTO impressions VALUES (1,2,'a','b','c',3,4,5,6,'d',7,8,9,'e'); -INSERT INTO conversions VALUES (10,11,12,13,14,15); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_13.sql b/content/test/data/attribution_reporting/databases/version_13.sql deleted file mode 100644 index 3b8fb02..0000000 --- a/content/test/data/attribution_reporting/databases/version_13.sql +++ /dev/null
@@ -1,39 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,impression_data INTEGER NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL,impression_site TEXT NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,impression_id INTEGER NOT NULL,conversion_data INTEGER NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,priority INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY NOT NULL,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL,bucket TEXT NOT NULL,value INTEGER NOT NULL); - -CREATE TABLE dedup_keys(impression_id INTEGER NOT NULL,dedup_key INTEGER NOT NULL,PRIMARY KEY(impression_id,dedup_key))WITHOUT ROWID; - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','13'); -INSERT INTO meta VALUES('last_compatible_version','13'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX event_source_impression_site_idx ON impressions(impression_site)WHERE active = 1 AND num_conversions = 0 AND source_type = 1; - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_attribution_type_conversion_time_idx ON rate_limits(attribution_type,conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -INSERT INTO conversions VALUES (1,2,3,4,5,6); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_2.sql b/content/test/data/attribution_reporting/databases/version_2.sql deleted file mode 100644 index bf3037a..0000000 --- a/content/test/data/attribution_reporting/databases/version_2.sql +++ /dev/null
@@ -1,37 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL); - -INSERT INTO impressions -VALUES(1, - '9357e17751666f64', - 'https://impression.test', - 'https://sub.conversion.test', - 'https://report.test', - 13245278349693988, - 13247870349693988, - 0, - 1, - 'https://conversion.test/'); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER,conversion_data TEXT NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,attribution_credit INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status', '-1'); -INSERT INTO meta VALUES('last_compatible_version', '2'); -INSERT INTO meta VALUES('version', '2'); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_3.sql b/content/test/data/attribution_reporting/databases/version_3.sql deleted file mode 100644 index 24a7f9f..0000000 --- a/content/test/data/attribution_reporting/databases/version_3.sql +++ /dev/null
@@ -1,25 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER,conversion_data TEXT NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,attribution_credit INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','3'); -INSERT INTO meta VALUES('last_compatible_version','3'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_4.sql b/content/test/data/attribution_reporting/databases/version_4.sql deleted file mode 100644 index 87c43673..0000000 --- a/content/test/data/attribution_reporting/databases/version_4.sql +++ /dev/null
@@ -1,39 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER,conversion_data TEXT NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,attribution_credit INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','4'); -INSERT INTO meta VALUES('last_compatible_version','3'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - --- Add some conversions to test 0-credit deletion in version 5. -INSERT INTO conversions (conversion_id, conversion_data, conversion_time, report_time, attribution_credit) VALUES - (1, 'a', 2, 3, 5), - (2, 'b', 7, 11, 0), - (3, 'c', 13, 17, 19); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_5.sql b/content/test/data/attribution_reporting/databases/version_5.sql deleted file mode 100644 index 14f755b..0000000 --- a/content/test/data/attribution_reporting/databases/version_5.sql +++ /dev/null
@@ -1,47 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER,conversion_data TEXT NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','5'); -INSERT INTO meta VALUES('last_compatible_version','5'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -INSERT INTO impressions -VALUES(1, - '9357e17751666f64', - 'https://impression.test', - 'https://conversion.test', - 'https://report.test', - 13245278349693988, - 13247870349693988, - 0, - 1, - 'https://conversion.test/', - 0, - 1); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_6.sql b/content/test/data/attribution_reporting/databases/version_6.sql deleted file mode 100644 index 67365cc..0000000 --- a/content/test/data/attribution_reporting/databases/version_6.sql +++ /dev/null
@@ -1,61 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER,conversion_data TEXT NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','6'); -INSERT INTO meta VALUES('last_compatible_version','6'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -INSERT INTO impressions -VALUES (1, - '9357e17751666f64', - 'https://a.impression.test', - 'https://conversion.test', - 'https://report.test', - 13245278349693988, - 13247870349693988, - 0, - 1, - 'https://conversion.test/', - 0, - 1, - 3), - (2, - '9357e17751666f64', - 'https://b.impression.test', - 'https://conversion.test', - 'https://report.test', - 13245278349693988, - 13247870349693988, - 0, - 1, - 'https://conversion.test/', - 0, - 1, - 4); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_7.sql b/content/test/data/attribution_reporting/databases/version_7.sql deleted file mode 100644 index 543d96f7..0000000 --- a/content/test/data/attribution_reporting/databases/version_7.sql +++ /dev/null
@@ -1,69 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL,impression_site TEXT NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER,conversion_data TEXT NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','7'); -INSERT INTO meta VALUES('last_compatible_version','7'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX impression_site_idx ON impressions(active,impression_site,source_type); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -INSERT INTO impressions -VALUES (1, - '18446744073709551615', - 'https://impression.test', - 'https://conversion.test', - 'https://report.test', - 13245278349693988, - 13247870349693988, - 0, - 1, - 'https://conversion.test/', - 0, - 1, - 3, - 'https://impression.test'), - (2, - 'invalid', - 'https://impression2.test', - 'https://conversion2.test', - 'https://report2.test', - 13245278349693988, - 13247870349693988, - 0, - 1, - 'https://conversion2.test/', - 0, - 1, - 5, - 'https://impression2.test'); - -INSERT INTO conversions -VALUES (0, 29, '234', 5, 6), - (7, NULL, 'invalid', 8, 9); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_8.sql b/content/test/data/attribution_reporting/databases/version_8.sql deleted file mode 100644 index a9ec23e..0000000 --- a/content/test/data/attribution_reporting/databases/version_8.sql +++ /dev/null
@@ -1,35 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data INTEGER NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL,impression_site TEXT NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER NOT NULL,conversion_data INTEGER NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','8'); -INSERT INTO meta VALUES('last_compatible_version','8'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX impression_site_idx ON impressions(active,impression_site,source_type); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -COMMIT;
diff --git a/content/test/data/attribution_reporting/databases/version_9.sql b/content/test/data/attribution_reporting/databases/version_9.sql deleted file mode 100644 index c60db91..0000000 --- a/content/test/data/attribution_reporting/databases/version_9.sql +++ /dev/null
@@ -1,35 +0,0 @@ -PRAGMA foreign_keys=OFF; - -BEGIN TRANSACTION; - -CREATE TABLE impressions(impression_id INTEGER PRIMARY KEY,impression_data INTEGER NOT NULL,impression_origin TEXT NOT NULL,conversion_origin TEXT NOT NULL,reporting_origin TEXT NOT NULL,impression_time INTEGER NOT NULL,expiry_time INTEGER NOT NULL,num_conversions INTEGER DEFAULT 0,active INTEGER DEFAULT 1,conversion_destination TEXT NOT NULL,source_type INTEGER NOT NULL,attributed_truthfully INTEGER NOT NULL,priority INTEGER NOT NULL,impression_site TEXT NOT NULL); - -CREATE TABLE conversions(conversion_id INTEGER PRIMARY KEY,impression_id INTEGER NOT NULL,conversion_data INTEGER NOT NULL,conversion_time INTEGER NOT NULL,report_time INTEGER NOT NULL,priority INTEGER NOT NULL); - -CREATE TABLE rate_limits(rate_limit_id INTEGER PRIMARY KEY,attribution_type INTEGER NOT NULL,impression_id INTEGER NOT NULL,impression_site TEXT NOT NULL,impression_origin TEXT NOT NULL,conversion_destination TEXT NOT NULL,conversion_origin TEXT NOT NULL,conversion_time INTEGER NOT NULL); - -CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); - -INSERT INTO meta VALUES('mmap_status','-1'); -INSERT INTO meta VALUES('version','9'); -INSERT INTO meta VALUES('last_compatible_version','9'); - -CREATE INDEX conversion_destination_idx ON impressions(active,conversion_destination,reporting_origin); - -CREATE INDEX impression_expiry_idx ON impressions(expiry_time); - -CREATE INDEX impression_origin_idx ON impressions(impression_origin); - -CREATE INDEX impression_site_idx ON impressions(active,impression_site,source_type); - -CREATE INDEX conversion_report_idx ON conversions(report_time); - -CREATE INDEX conversion_impression_id_idx ON conversions(impression_id); - -CREATE INDEX rate_limit_impression_site_type_idx ON rate_limits(attribution_type,conversion_destination,impression_site,conversion_time); - -CREATE INDEX rate_limit_conversion_time_idx ON rate_limits(conversion_time); - -CREATE INDEX rate_limit_impression_id_idx ON rate_limits(impression_id); - -COMMIT;
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py index 0b1924a..d29cc17 100644 --- a/content/test/gpu/gpu_tests/gpu_helper.py +++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -9,16 +9,11 @@ # This set must be the union of the driver tags used in WebGL and WebGL2 # expectations files. +# Examples: +# intel_lt_25.20.100.6577 +# mesa_ge_20.1 EXPECTATIONS_DRIVER_TAGS = frozenset([ - 'intel_lt_25.20.100.6444', - 'intel_lt_25.20.100.6577', - 'intel_lt_26.20.100.7000', - 'intel_lt_26.20.100.7323', - 'intel_lt_26.20.100.7870', - 'intel_lt_26.20.100.8141', - 'intel_lt_27.20.100.8280', 'mesa_lt_19.1', - 'mesa_ge_20.1', ]) # Driver tag format: VENDOR_OPERATION_VERSION
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt index 26289d2..4e8d3b6 100644 --- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt index f2e5dd8..b08f9dff 100644 --- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt index 6f645563..2b29477 100644 --- a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt index 3dd3202a..82b1b42 100644 --- a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt index 6f645563..2b29477 100644 --- a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt index c8915b3..ea184ad 100644 --- a/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 6f9a0c9..b7ffbf523 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt index 7337524..3868cfe6 100644 --- a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt index 40db29d..e69d1fe 100644 --- a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt index da5d0c73..e32c02a 100644 --- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt index b84cf5b..cfadaccf 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index eba5481f..91d79d7 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 140822c..69faf34 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -46,11 +46,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/gpu/validate_tag_consistency.py b/content/test/gpu/validate_tag_consistency.py index cdd7625..6b84739 100755 --- a/content/test/gpu/validate_tag_consistency.py +++ b/content/test/gpu/validate_tag_consistency.py
@@ -59,11 +59,7 @@ # SwiftShader # tags: [ swiftshader-gl no-swiftshader-gl ] # Driver -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 -# intel_lt_26.20.100.7000 intel_lt_26.20.100.7870 -# intel_lt_26.20.100.7323 intel_lt_26.20.100.8141 -# intel_lt_27.20.100.8280 -# mesa_lt_19.1 mesa_ge_20.1 ] +# tags: [ mesa_lt_19.1 ] # ASan # tags: [ asan no-asan ] # Display Server
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index e49b1d5..36de614 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -136,6 +136,10 @@ heavy_ad_issue_cpu_peak_count_++; break; } + } else if (issue->code == + blink::mojom::InspectorIssueCode::kFederatedAuthRequestIssue) { + ++federated_auth_counts_[issue->details->federated_auth_request_details + ->status]; } RenderFrameHostImpl::ReportInspectorIssue(std::move(issue)); } @@ -236,6 +240,14 @@ } } +int TestRenderFrameHost::GetFederatedAuthRequestIssueCount( + blink::mojom::RequestIdTokenStatus status) { + auto it = federated_auth_counts_.find(status); + if (it == federated_auth_counts_.end()) + return 0; + return it->second; +} + void TestRenderFrameHost::SimulateManifestURLUpdate(const GURL& manifest_url) { // TODO(crbug.com/1222510): Add TestPage and use it. GetPage().UpdateManifestUrl(manifest_url);
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h index d86768d3b..c6592a8 100644 --- a/content/test/test_render_frame_host.h +++ b/content/test/test_render_frame_host.h
@@ -139,6 +139,11 @@ void DidEnforceInsecureRequestPolicy( blink::mojom::InsecureRequestPolicy policy); + // Returns the number of FedCM issues sent to DevTools with the given + // RequestIdTokenStatus. + int GetFederatedAuthRequestIssueCount( + blink::mojom::RequestIdTokenStatus status); + // If set, navigations will appear to have cleared the history list in the // RenderFrame (DidCommitProvisionalLoadParams::history_list_was_cleared). // False by default. @@ -292,6 +297,11 @@ int heavy_ad_issue_cpu_total_count_ = 0; int heavy_ad_issue_cpu_peak_count_ = 0; + // Keeps a count of federated authentication request issues sent to + // ReportInspectorIssue. + std::unordered_map<blink::mojom::RequestIdTokenStatus, int> + federated_auth_counts_; + TestRenderFrameHostCreationObserver child_creation_observer_; // See set_simulate_history_list_was_cleared() above.
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index c2112ab..b1731400 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn
@@ -386,40 +386,4 @@ deps += [ "//components/user_manager:test_support" ] } } - - # TODO(rockot) bug 505926: This should be deleted for the same reason as - # chrome_extensions_browsertests. - source_set("chrome_extensions_interactive_uitests") { - testonly = true - sources = [ "browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc" ] - - defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] - - # These are the deps from interactive_uitests minus some internal Chrome - # ones that aren't allowed to be included here and that aren't needed. - deps = [ - "//chrome/browser", - "//chrome/browser/devtools", - "//chrome/renderer", - "//chrome/test:test_support", - "//components/sync", - "//content/app/resources", - "//crypto:platform", - "//crypto:test_support", - "//google_apis:test_support", - "//net", - "//net:net_resources", - "//net:test_support", - "//skia", - "//testing/gmock", - "//testing/gtest", - "//third_party/hunspell", - "//third_party/icu", - "//third_party/libpng", - "//third_party/zlib", - "//ui/base:test_support", - "//ui/resources:ui_test_pak", - "//ui/web_dialogs:test_support", - ] - } }
diff --git a/extensions/DEPS b/extensions/DEPS index dbcdddc2..b4e90cc0 100644 --- a/extensions/DEPS +++ b/extensions/DEPS
@@ -41,8 +41,4 @@ ".*(test|test_util)\.(cc|h)$": [ "+content/public/test", ], - "mime_handler_view_interactive_uitest.cc": [ - "+chrome/browser/ui/exclusive_access/exclusive_access_test.h", - "+chrome/test/base/interactive_test_utils.h", - ], }
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index a0b24d59..ede7cb8c 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -435,6 +435,8 @@ "install_stage.h", "json_file_sanitizer.cc", "json_file_sanitizer.h", + "l10n_file_util.cc", + "l10n_file_util.h", "lazy_background_task_queue.cc", "lazy_background_task_queue.h", "lazy_background_task_queue_factory.cc",
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index a492eba..1153141 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -151,7 +151,7 @@ // static void EventRouter::DispatchExtensionMessage( - IPC::Sender* ipc_sender, + content::RenderProcessHost* rph, int worker_thread_id, content::BrowserContext* browser_context, const std::string& extension_id, @@ -169,7 +169,29 @@ params.is_user_gesture = user_gesture == USER_GESTURE_ENABLED; params.filtering_info = info->To<EventFilteringInfo>(); - ipc_sender->Send(new ExtensionMsg_DispatchEvent(params, *event_args)); + // TODO(crbug/1222550): Remove IPC->Send call after worker_thread_dispatcher + // is also mojofied. + if (worker_thread_id == kMainThreadId) { + Get(browser_context)->RouteDispatchEvent(rph, params.Clone(), *event_args); + } else { + rph->Send(new ExtensionMsg_DispatchEvent(params, *event_args)); + } +} + +void EventRouter::RouteDispatchEvent(content::RenderProcessHost* rph, + const mojom::DispatchEventParamsPtr params, + const ListValue& event_args) { + mojo::AssociatedRemote<mojom::EventDispatcher>& dispatcher = + rph_dispatcher_map_[rph]; + if (!dispatcher.is_bound()) { + IPC::ChannelProxy* channel = rph->GetChannel(); + if (!channel) { + return; + } + channel->GetRemoteAssociatedInterface( + dispatcher.BindNewEndpointAndPassReceiver()); + } + dispatcher->DispatchEvent(params.Clone(), event_args.Clone()); } // static @@ -185,7 +207,7 @@ // static void EventRouter::DispatchEventToSender( - IPC::Sender* ipc_sender, + content::RenderProcessHost* rph, content::BrowserContext* browser_context, const std::string& extension_id, events::HistogramValue histogram_value, @@ -202,8 +224,8 @@ browser_context, extension_id, event_id, render_process_id, service_worker_version_id, histogram_value, event_name); - DispatchExtensionMessage(ipc_sender, worker_thread_id, browser_context, - extension_id, event_id, event_name, event_args.get(), + DispatchExtensionMessage(rph, worker_thread_id, browser_context, extension_id, + event_id, event_name, event_args.get(), UserGestureState::USER_GESTURE_UNKNOWN, std::move(info)); } @@ -570,6 +592,7 @@ const content::ChildProcessTerminationInfo& info) { listeners_.RemoveListenersForProcess(host); observed_process_set_.erase(host); + rph_dispatcher_map_.erase(host); host->RemoveObserver(this); }
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h index f310f7a0..e4b87de 100644 --- a/extensions/browser/event_router.h +++ b/extensions/browser/event_router.h
@@ -30,10 +30,11 @@ #include "extensions/browser/lazy_context_task_queue.h" #include "extensions/common/constants.h" #include "extensions/common/features/feature.h" -#include "extensions/common/mojom/event_dispatcher.mojom-forward.h" +#include "extensions/common/mojom/event_dispatcher.mojom.h" #include "extensions/common/mojom/event_router.mojom.h" #include "ipc/ipc_sender.h" #include "mojo/public/cpp/bindings/associated_receiver_set.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "url/gurl.h" @@ -118,7 +119,7 @@ // methods BroadcastEvent or DispatchEventToExtension. // Note that this method will dispatch the event with // UserGestureState:USER_GESTURE_UNKNOWN. - static void DispatchEventToSender(IPC::Sender* ipc_sender, + static void DispatchEventToSender(content::RenderProcessHost* rph, content::BrowserContext* browser_context, const std::string& extension_id, events::HistogramValue histogram_value, @@ -356,7 +357,7 @@ // TODO(gdk): Document this. static void DispatchExtensionMessage( - IPC::Sender* ipc_sender, + content::RenderProcessHost* rph, int worker_thread_id, content::BrowserContext* browser_context, const std::string& extension_id, @@ -445,6 +446,10 @@ const std::string& event_name, int64_t service_worker_version_id); + void RouteDispatchEvent(content::RenderProcessHost* rph, + const mojom::DispatchEventParamsPtr params, + const base::ListValue& event_args); + // static static void DoDispatchEventToSenderBookkeeping( content::BrowserContext* context, @@ -494,6 +499,10 @@ EventAckData event_ack_data_; + std::map<content::RenderProcessHost*, + mojo::AssociatedRemote<mojom::EventDispatcher>> + rph_dispatcher_map_; + // All the Mojo receivers for the EventRouter. Keeps track of the render // process id. mojo::AssociatedReceiverSet<mojom::EventRouter, int /*render_process_id*/>
diff --git a/extensions/browser/extension_user_script_loader.cc b/extensions/browser/extension_user_script_loader.cc index 466e202..4ac6c6e 100644 --- a/extensions/browser/extension_user_script_loader.cc +++ b/extensions/browser/extension_user_script_loader.cc
@@ -38,10 +38,10 @@ #include "extensions/browser/extension_system.h" #include "extensions/browser/extension_util.h" #include "extensions/browser/extensions_browser_client.h" +#include "extensions/browser/l10n_file_util.h" #include "extensions/browser/state_store.h" #include "extensions/browser/user_script_loader.h" #include "extensions/common/api/content_scripts.h" -#include "extensions/common/file_util.h" #include "extensions/common/manifest_handlers/content_scripts_handler.h" #include "extensions/common/manifest_handlers/default_locale_handler.h" #include "extensions/common/message_bundle.h" @@ -199,7 +199,7 @@ } if (script->css_scripts().size() > 0) { std::unique_ptr<SubstitutionMap> localization_messages( - file_util::LoadMessageBundleSubstitutionMap( + l10n_file_util::LoadMessageBundleSubstitutionMap( host_info.file_path, script->host_id().id, host_info.default_locale, host_info.gzip_permission));
diff --git a/extensions/browser/l10n_file_util.cc b/extensions/browser/l10n_file_util.cc new file mode 100644 index 0000000..3d37974 --- /dev/null +++ b/extensions/browser/l10n_file_util.cc
@@ -0,0 +1,63 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/browser/l10n_file_util.h" + +#include <utility> + +#include "base/files/file_path.h" +#include "extensions/common/file_util.h" + +namespace extensions::l10n_file_util { + +MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMap( + const base::FilePath& extension_path, + const ExtensionId& extension_id, + const std::string& default_locale, + extension_l10n_util::GzippedMessagesPermission gzip_permission) { + return LoadMessageBundleSubstitutionMapFromPaths( + {extension_path}, extension_id, default_locale, gzip_permission); +} + +MessageBundle::SubstitutionMap* LoadNonLocalizedMessageBundleSubstitutionMap( + const ExtensionId& extension_id) { + MessageBundle::SubstitutionMap* return_value = + new MessageBundle::SubstitutionMap(); + + // Add @@extension_id reserved message here. + return_value->insert( + std::make_pair(MessageBundle::kExtensionIdKey, extension_id)); + + return return_value; +} + +MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths( + const std::vector<base::FilePath>& paths, + const ExtensionId& extension_id, + const std::string& default_locale, + extension_l10n_util::GzippedMessagesPermission gzip_permission) { + MessageBundle::SubstitutionMap* return_value = + LoadNonLocalizedMessageBundleSubstitutionMap(extension_id); + + // Touch disk only if extension is localized. + if (default_locale.empty()) + return return_value; + + std::string error; + for (const base::FilePath& path : paths) { + std::unique_ptr<MessageBundle> bundle(file_util::LoadMessageBundle( + path, default_locale, gzip_permission, &error)); + if (bundle) { + for (const auto& iter : *bundle->dictionary()) { + // |insert| only adds new entries, and does not replace entries in + // the main extension or previously processed imports. + return_value->insert(std::make_pair(iter.first, iter.second)); + } + } + } + + return return_value; +} + +} // namespace extensions::l10n_file_util
diff --git a/extensions/browser/l10n_file_util.h b/extensions/browser/l10n_file_util.h new file mode 100644 index 0000000..4bb5e0d --- /dev/null +++ b/extensions/browser/l10n_file_util.h
@@ -0,0 +1,54 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_BROWSER_L10N_FILE_UTIL_H_ +#define EXTENSIONS_BROWSER_L10N_FILE_UTIL_H_ + +#include <string> +#include <vector> + +#include "extensions/common/extension_id.h" +#include "extensions/common/message_bundle.h" + +namespace base { +class FilePath; +} + +namespace extension_l10n_util { +enum class GzippedMessagesPermission; +} + +namespace extensions::l10n_file_util { + +// TODO(devlin): All these methods return ownership of the object. Make them +// return unique_ptrs. + +// Loads the extension message bundle substitution map. Contains at least +// the extension_id item. Does not supported compressed locale files. Passes +// |gzip_permission| to extension_l10n_util::LoadMessageCatalogs (see +// extension_l10n_util.h). +MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMap( + const base::FilePath& extension_path, + const ExtensionId& extension_id, + const std::string& default_locale, + extension_l10n_util::GzippedMessagesPermission gzip_permission); + +// Loads the extension message bundle substitution map for a non-localized +// extension. Contains only the extension_id item. +// This doesn't require hitting disk, so it's safe to call on any thread. +MessageBundle::SubstitutionMap* LoadNonLocalizedMessageBundleSubstitutionMap( + const ExtensionId& extension_id); + +// Loads the extension message bundle substitution map from the specified paths. +// Contains at least the extension_id item. Passes |gzip_permission| to +// extension_l10n_util::LoadMessageCatalogs (see extension_l10n_util.h). +MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths( + const std::vector<base::FilePath>& paths, + const ExtensionId& extension_id, + const std::string& default_locale, + extension_l10n_util::GzippedMessagesPermission gzip_permission); + +} // namespace extensions::l10n_file_util + +#endif // EXTENSIONS_BROWSER_L10N_FILE_UTIL_H_
diff --git a/extensions/browser/load_and_localize_file.cc b/extensions/browser/load_and_localize_file.cc index 33b296c..2fe6546 100644 --- a/extensions/browser/load_and_localize_file.cc +++ b/extensions/browser/load_and_localize_file.cc
@@ -11,11 +11,11 @@ #include "extensions/browser/component_extension_resource_manager.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/file_reader.h" +#include "extensions/browser/l10n_file_util.h" #include "extensions/common/extension.h" #include "extensions/common/extension_id.h" #include "extensions/common/extension_l10n_util.h" #include "extensions/common/extension_resource.h" -#include "extensions/common/file_util.h" #include "extensions/common/manifest.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/message_bundle.h" @@ -39,9 +39,9 @@ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, base::BlockingType::MAY_BLOCK); std::unique_ptr<MessageBundle::SubstitutionMap> localization_messages( - file_util::LoadMessageBundleSubstitutionMap(extension_path, extension_id, - extension_default_locale, - gzip_permission)); + l10n_file_util::LoadMessageBundleSubstitutionMap( + extension_path, extension_id, extension_default_locale, + gzip_permission)); std::string error; MessageBundle::ReplaceMessagesWithExternalDictionary(*localization_messages,
diff --git a/extensions/common/file_util.cc b/extensions/common/file_util.cc index 35aa018..eab1b26be 100644 --- a/extensions/common/file_util.cc +++ b/extensions/common/file_util.cc
@@ -546,55 +546,6 @@ return message_bundle; } -MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMap( - const base::FilePath& extension_path, - const std::string& extension_id, - const std::string& default_locale, - extension_l10n_util::GzippedMessagesPermission gzip_permission) { - return LoadMessageBundleSubstitutionMapFromPaths( - {extension_path}, extension_id, default_locale, gzip_permission); -} - -MessageBundle::SubstitutionMap* LoadNonLocalizedMessageBundleSubstitutionMap( - const std::string& extension_id) { - MessageBundle::SubstitutionMap* return_value = - new MessageBundle::SubstitutionMap(); - - // Add @@extension_id reserved message here. - return_value->insert( - std::make_pair(MessageBundle::kExtensionIdKey, extension_id)); - - return return_value; -} - -MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths( - const std::vector<base::FilePath>& paths, - const std::string& extension_id, - const std::string& default_locale, - extension_l10n_util::GzippedMessagesPermission gzip_permission) { - MessageBundle::SubstitutionMap* return_value = - LoadNonLocalizedMessageBundleSubstitutionMap(extension_id); - - // Touch disk only if extension is localized. - if (default_locale.empty()) - return return_value; - - std::string error; - for (const base::FilePath& path : paths) { - std::unique_ptr<MessageBundle> bundle( - LoadMessageBundle(path, default_locale, gzip_permission, &error)); - if (bundle) { - for (const auto& iter : *bundle->dictionary()) { - // |insert| only adds new entries, and does not replace entries in - // the main extension or previously processed imports. - return_value->insert(std::make_pair(iter.first, iter.second)); - } - } - } - - return return_value; -} - base::FilePath GetVerifiedContentsPath(const base::FilePath& extension_path) { return extension_path.Append(kMetadataFolder) .Append(kVerifiedContentsFilename);
diff --git a/extensions/common/file_util.h b/extensions/common/file_util.h index 810c496..391b65e7 100644 --- a/extensions/common/file_util.h +++ b/extensions/common/file_util.h
@@ -147,31 +147,6 @@ extension_l10n_util::GzippedMessagesPermission gzip_permission, std::string* error); -// Loads the extension message bundle substitution map. Contains at least -// the extension_id item. Does not supported compressed locale files. Passes -// |gzip_permission| to extension_l10n_util::LoadMessageCatalogs (see -// extension_l10n_util.h). -MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMap( - const base::FilePath& extension_path, - const std::string& extension_id, - const std::string& default_locale, - extension_l10n_util::GzippedMessagesPermission gzip_permission); - -// Loads the extension message bundle substitution map for a non-localized -// extension. Contains only the extension_id item. -// This doesn't require hitting disk, so it's safe to call on any thread. -MessageBundle::SubstitutionMap* LoadNonLocalizedMessageBundleSubstitutionMap( - const std::string& extension_id); - -// Loads the extension message bundle substitution map from the specified paths. -// Contains at least the extension_id item. Passes |gzip_permission| to -// extension_l10n_util::LoadMessageCatalogs (see extension_l10n_util.h). -MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths( - const std::vector<base::FilePath>& paths, - const std::string& extension_id, - const std::string& default_locale, - extension_l10n_util::GzippedMessagesPermission gzip_permission); - // Helper functions for getting paths for files used in content verification. base::FilePath GetVerifiedContentsPath(const base::FilePath& extension_path); base::FilePath GetComputedHashesPath(const base::FilePath& extension_path);
diff --git a/extensions/common/mojom/event_dispatcher.mojom b/extensions/common/mojom/event_dispatcher.mojom index 413fdd9..825a671 100644 --- a/extensions/common/mojom/event_dispatcher.mojom +++ b/extensions/common/mojom/event_dispatcher.mojom
@@ -6,6 +6,17 @@ import "mojo/public/mojom/base/values.mojom"; import "url/mojom/url.mojom"; +// EventDispatch is a one-per-renderer-processs interface that is responsible +// for triggering API events that extensions have registered listeners for in +// the renderer (either the extension process renderer, for extension-origin +// pages, or a web renderer, for content script listeners). +// The interface is implemented in //extensions/renderer code, and is +// called on the browser side by the EventRouter. +interface EventDispatcher { + // Sent to the renderer to dispatch an event to a listener. + DispatchEvent(DispatchEventParams params, + mojo_base.mojom.ListValue event_args); +}; // Typemapped to extensions::EventFilteringInfo. // TODO(yochio): Convert extensions::EventFilteringInfo usage to
diff --git a/extensions/common/mojom/event_dispatcher_mojom_traits.h b/extensions/common/mojom/event_dispatcher_mojom_traits.h index fb2b9b5..9ba9ff3 100644 --- a/extensions/common/mojom/event_dispatcher_mojom_traits.h +++ b/extensions/common/mojom/event_dispatcher_mojom_traits.h
@@ -27,7 +27,7 @@ return filtering_info.instance_id.has_value(); } static int instance_id(const extensions::EventFilteringInfo& filtering_info) { - return filtering_info.instance_id.value(); + return filtering_info.instance_id.value_or(0); } static absl::optional<std::string> window_type( const extensions::EventFilteringInfo& filtering_info) { @@ -39,7 +39,7 @@ } static int window_exposed_by_default( const extensions::EventFilteringInfo& filtering_info) { - return filtering_info.window_exposed_by_default.value(); + return filtering_info.window_exposed_by_default.value_or(0); } static bool Read(extensions::mojom::EventFilteringInfoDataView data,
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 4728e57..306ec23 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -276,7 +276,8 @@ source_map_(&ui::ResourceBundle::GetSharedInstance()), v8_schema_registry_(new V8SchemaRegistry), activity_logging_enabled_(false), - receiver_(this) { + receiver_(this), + dispatcher_(this) { bindings_system_ = CreateBindingsSystem( IPCMessageSender::CreateMainThreadIPCMessageSender()); @@ -769,7 +770,7 @@ // |frame_helper| and |render_frame| might be dead by now. } -void Dispatcher::DispatchEvent( +void Dispatcher::DispatchEventHelper( const std::string& extension_id, const std::string& event_name, const base::ListValue& event_args, @@ -975,7 +976,6 @@ IPC_MESSAGE_HANDLER(ExtensionMsg_DeliverMessage, OnDeliverMessage) IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnConnect, OnDispatchOnConnect) IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchOnDisconnect, OnDispatchOnDisconnect) - IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchEvent, OnDispatchEvent) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -992,11 +992,14 @@ // never deleted). associated_interfaces->AddInterface(base::BindRepeating( &Dispatcher::OnRendererAssociatedRequest, base::Unretained(this))); + associated_interfaces->AddInterface(base::BindRepeating( + &Dispatcher::OnEventDispatcherRequest, base::Unretained(this))); } void Dispatcher::UnregisterMojoInterfaces( blink::AssociatedInterfaceRegistry* associated_interfaces) { associated_interfaces->RemoveInterface(mojom::Renderer::Name_); + associated_interfaces->RemoveInterface(mojom::EventDispatcher::Name_); } void Dispatcher::OnRendererAssociatedRequest( @@ -1004,6 +1007,11 @@ receiver_.Bind(std::move(receiver)); } +void Dispatcher::OnEventDispatcherRequest( + mojo::PendingAssociatedReceiver<mojom::EventDispatcher> dispatcher) { + dispatcher_.Bind(std::move(dispatcher)); +} + void Dispatcher::ActivateExtension(const std::string& extension_id) { TRACE_RENDERER_EXTENSION_EVENT("Dispatcher::ActivateExtension", extension_id); @@ -1174,13 +1182,14 @@ // the browser know when we are starting and stopping the event dispatch, so // that it still considers the extension idle despite any activity the suspend // event creates. - DispatchEvent(extension_id, kOnSuspendEvent, base::ListValue(), nullptr); + DispatchEventHelper(extension_id, kOnSuspendEvent, base::ListValue(), + nullptr); std::move(callback).Run(); } void Dispatcher::CancelSuspendExtension(const std::string& extension_id) { - DispatchEvent(extension_id, kOnSuspendCanceledEvent, base::ListValue(), - nullptr); + DispatchEventHelper(extension_id, kOnSuspendCanceledEvent, base::ListValue(), + nullptr); } void Dispatcher::SetSystemFont(const std::string& font_family, @@ -1296,10 +1305,10 @@ NULL); // All render frames. } -void Dispatcher::OnDispatchEvent(const mojom::DispatchEventParams& params, - const base::ListValue& event_args) { +void Dispatcher::DispatchEvent(mojom::DispatchEventParamsPtr params, + base::Value event_args) { content::RenderFrame* background_frame = - ExtensionFrameHelper::GetBackgroundPageFrame(params.extension_id); + ExtensionFrameHelper::GetBackgroundPageFrame(params->extension_id); // Synthesize a user gesture if this was in response to user action; this is // necessary if the gesture was e.g. by clicking on the extension toolbar @@ -1310,27 +1319,28 @@ // the user gesture. This is intentional, since frames other than the // background page should have their own user gestures, such as through button // clicks. - if (params.is_user_gesture && background_frame) { + if (params->is_user_gesture && background_frame) { ScriptContext* background_context = ScriptContextSet::GetMainWorldContextForFrame(background_frame); if (background_context && bindings_system_->HasEventListenerInContext( - params.event_name, background_context)) { + params->event_name, background_context)) { background_frame->GetWebFrame()->NotifyUserActivation( blink::mojom::UserActivationNotificationType::kExtensionEvent); } } - DispatchEvent(params.extension_id, params.event_name, event_args, - mojom::EventFilteringInfo::From(params.filtering_info)); + DispatchEventHelper(params->extension_id, params->event_name, + base::Value::AsListValue(event_args), + mojom::EventFilteringInfo::From(params->filtering_info)); if (background_frame) { // Tell the browser process when an event has been dispatched with a lazy // background page active. const Extension* extension = - RendererExtensionRegistry::Get()->GetByID(params.extension_id); + RendererExtensionRegistry::Get()->GetByID(params->extension_id); if (extension && BackgroundInfo::HasLazyBackgroundPage(extension)) { background_frame->Send(new ExtensionHostMsg_EventAck( - background_frame->GetRoutingID(), params.event_id)); + background_frame->GetRoutingID(), params->event_id)); } } }
diff --git a/extensions/renderer/dispatcher.h b/extensions/renderer/dispatcher.h index 35246a6..c8dcb1f 100644 --- a/extensions/renderer/dispatcher.h +++ b/extensions/renderer/dispatcher.h
@@ -74,7 +74,8 @@ // renderer extension related state. class Dispatcher : public content::RenderThreadObserver, public UserScriptSetManager::Observer, - public mojom::Renderer { + public mojom::Renderer, + public mojom::EventDispatcher { public: explicit Dispatcher(std::unique_ptr<DispatcherDelegate> delegate); @@ -166,10 +167,10 @@ void RunScriptsAtDocumentIdle(content::RenderFrame* render_frame); // Dispatches the event named |event_name| to all render views. - void DispatchEvent(const std::string& extension_id, - const std::string& event_name, - const base::ListValue& event_args, - mojom::EventFilteringInfoPtr filtering_info) const; + void DispatchEventHelper(const std::string& extension_id, + const std::string& event_name, + const base::ListValue& event_args, + mojom::EventFilteringInfoPtr filtering_info) const; // Shared implementation of the various MessageInvoke IPCs. void InvokeModuleSystemMethod(content::RenderFrame* render_frame, @@ -263,6 +264,8 @@ void OnRendererAssociatedRequest( mojo::PendingAssociatedReceiver<mojom::Renderer> receiver); + void OnEventDispatcherRequest( + mojo::PendingAssociatedReceiver<mojom::EventDispatcher> receiver); void OnDeliverMessage(int worker_thread_id, const PortId& target_port_id, const Message& message); @@ -274,8 +277,8 @@ void OnDispatchOnDisconnect(int worker_thread_id, const PortId& port_id, const std::string& error_message); - void OnDispatchEvent(const mojom::DispatchEventParams& params, - const base::ListValue& event_args); + void DispatchEvent(mojom::DispatchEventParamsPtr params, + base::Value event_args) override; // UserScriptSetManager::Observer implementation. void OnUserScriptsUpdated(const mojom::HostID& changed_host) override; @@ -371,6 +374,10 @@ // it is dependent on other messages sent on other associated channels. mojo::AssociatedReceiver<mojom::Renderer> receiver_; + // Extensions Dipsatch receiver. This is an associated receiver because + // it is dependent on other messages sent on other associated channels. + mojo::AssociatedReceiver<mojom::EventDispatcher> dispatcher_; + // Used to hold a service worker information which is ready to execute but the // onloaded message haven't been received yet. We need to defer service worker // execution until the ExtensionMsg_Loaded message is received because we can
diff --git a/google_apis/test/embedded_setup_chromeos.html b/google_apis/test/embedded_setup_chromeos.html index e493484..1ad956b 100644 --- a/google_apis/test/embedded_setup_chromeos.html +++ b/google_apis/test/embedded_setup_chromeos.html
@@ -69,6 +69,15 @@ }, '/'); }; +gaia.chromeOSLogin.confirmToken = function() { + // SAML credential passing api for password. + window.postMessage( + {type: 'gaia_saml_api', + call: {method: 'confirm', + token: 'token'} + }, '/'); +}; + gaia.chromeOSLogin.sendUserInfo = function(services) { msg = { 'method': 'userInfo', @@ -153,6 +162,8 @@ } if (services) gaia.chromeOSLogin.sendUserInfo(services); + + gaia.chromeOSLogin.confirmToken(); if (gaia.chromeOSLogin.shouldSendCloseView) gaia.chromeOSLogin.sendCloseView(); history.pushState({}, "", window.location.pathname + "#close");
diff --git a/infra/config/generated/builders/ci/android-web-platform-pie-x86-fyi-rel/properties.textpb b/infra/config/generated/builders/ci/android-chrome-pie-x86-wpt-fyi-rel/properties.textpb similarity index 100% rename from infra/config/generated/builders/ci/android-web-platform-pie-x86-fyi-rel/properties.textpb rename to infra/config/generated/builders/ci/android-chrome-pie-x86-wpt-fyi-rel/properties.textpb
diff --git a/infra/config/generated/builders/try/android-web-platform-pie-x86-fyi-rel/properties.textpb b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.textpb similarity index 100% rename from infra/config/generated/builders/try/android-web-platform-pie-x86-fyi-rel/properties.textpb rename to infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.textpb
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index ff8cc06..52cfbcf 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -307,6 +307,10 @@ location_regexp_exclude: ".+/[+]/infra/config/.+" } builders { + name: "chromium/try/android-chrome-pie-x86-wpt-fyi-rel" + includable_only: true + } + builders { name: "chromium/try/android-cronet-arm-dbg" location_regexp: ".+/[+]/components/cronet/.+" location_regexp: ".+/[+]/components/grpc_support/.+" @@ -486,10 +490,6 @@ includable_only: true } builders { - name: "chromium/try/android-web-platform-pie-x86-fyi-rel" - includable_only: true - } - builders { name: "chromium/try/android-weblayer-10-x86-rel-tests" includable_only: true }
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 47e1045..e5248bd 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -3412,7 +3412,7 @@ } } builders { - name: "Comparison Linux" + name: "Comparison Linux (reclient)" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "cores:8" @@ -3495,7 +3495,7 @@ } } builders { - name: "Comparison Windows" + name: "Comparison Windows (reclient)" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" dimensions: "cores:32" @@ -25074,6 +25074,89 @@ } } builders { + name: "android-chrome-pie-x86-wpt-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.ci" + dimensions: "ssd:0" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/ci/android-chrome-pie-x86-wpt-fyi-rel/properties.textpb",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.android.fyi",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium"' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + experiments { + key: "luci.use_realms" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://[^/]*blink_web_tests/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "android-code-coverage" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -27721,89 +27804,6 @@ } } builders { - name: "android-web-platform-pie-x86-fyi-rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-18.04" - dimensions: "pool:luci.chromium.ci" - dimensions: "ssd:0" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/ci/android-web-platform-pie-x86-fyi-rel/properties.textpb",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "chromium.android.fyi",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "luci.use_realms" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "ci_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://[^/]*blink_web_tests/.+" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - } - builders { name: "android-weblayer-10-x86-rel-tests" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -49295,6 +49295,100 @@ } } builders { + name: "android-chrome-pie-x86-wpt-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.try" + dimensions: "ssd:0" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.textpb",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.android",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium_trybot"' + '}' + execution_timeout_secs: 14400 + expiration_secs: 7200 + grace_period { + seconds: 120 + } + caches { + name: "win_toolchain" + path: "win_toolchain" + } + build_numbers: YES + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + experiments { + key: "luci.use_realms" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_try_test_results" + test_results { + predicate { + test_id_regexp: "ninja://[^/]*blink_web_tests/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "android-cronet-arm-dbg" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -52667,100 +52761,6 @@ } } builders { - name: "android-web-platform-pie-x86-fyi-rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-18.04" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:0" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/android-web-platform-pie-x86-fyi-rel/properties.textpb",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.android",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - caches { - name: "win_toolchain" - path: "win_toolchain" - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "luci.use_realms" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://[^/]*blink_web_tests/.+" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - } - builders { name: "android-weblayer-10-x86-rel-tests" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index a9edf8b..8b7242ca 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -3639,7 +3639,7 @@ short_name: "P-WPT" } builders { - name: "buildbucket/luci.chromium.ci/android-web-platform-pie-x86-fyi-rel" + name: "buildbucket/luci.chromium.ci/android-chrome-pie-x86-wpt-fyi-rel" category: "builder_tester|web-platform" short_name: "P" } @@ -6454,7 +6454,7 @@ category: "linux" } builders { - name: "buildbucket/luci.chromium.ci/Comparison Linux" + name: "buildbucket/luci.chromium.ci/Comparison Linux (reclient)" category: "linux" short_name: "cmp" } @@ -6641,7 +6641,7 @@ short_name: "win" } builders { - name: "buildbucket/luci.chromium.ci/Comparison Windows" + name: "buildbucket/luci.chromium.ci/Comparison Windows (reclient)" category: "win" short_name: "re" } @@ -14108,6 +14108,9 @@ name: "buildbucket/luci.chromium.try/android-binary-size" } builders { + name: "buildbucket/luci.chromium.try/android-chrome-pie-x86-wpt-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/android-cronet-arm-dbg" } builders { @@ -14216,9 +14219,6 @@ name: "buildbucket/luci.chromium.try/android-rust-arm-rel" } builders { - name: "buildbucket/luci.chromium.try/android-web-platform-pie-x86-fyi-rel" - } - builders { name: "buildbucket/luci.chromium.try/android-weblayer-10-x86-rel-tests" } builders { @@ -15231,6 +15231,9 @@ name: "buildbucket/luci.chromium.try/android-binary-size" } builders { + name: "buildbucket/luci.chromium.try/android-chrome-pie-x86-wpt-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/android-cronet-arm-dbg" } builders { @@ -15333,9 +15336,6 @@ name: "buildbucket/luci.chromium.try/android-pie-x86-rel" } builders { - name: "buildbucket/luci.chromium.try/android-web-platform-pie-x86-fyi-rel" - } - builders { name: "buildbucket/luci.chromium.try/android-weblayer-10-x86-rel-tests" } builders {
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index 77d00ec6..4342227 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -692,23 +692,23 @@ } } job { - id: "Comparison Linux" + id: "Comparison Linux (reclient)" realm: "ci" acl_sets: "ci" buildbucket { server: "cr-buildbucket.appspot.com" bucket: "luci.chromium.ci" - builder: "Comparison Linux" + builder: "Comparison Linux (reclient)" } } job { - id: "Comparison Windows" + id: "Comparison Windows (reclient)" realm: "ci" acl_sets: "ci" buildbucket { server: "cr-buildbucket.appspot.com" bucket: "luci.chromium.ci" - builder: "Comparison Windows" + builder: "Comparison Windows (reclient)" } } job { @@ -4241,6 +4241,16 @@ } } job { + id: "android-chrome-pie-x86-wpt-fyi-rel" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-chrome-pie-x86-wpt-fyi-rel" + } +} +job { id: "android-code-coverage" realm: "ci" schedule: "triggered" @@ -4565,16 +4575,6 @@ } } job { - id: "android-web-platform-pie-x86-fyi-rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.ci" - builder: "android-web-platform-pie-x86-fyi-rel" - } -} -job { id: "android-weblayer-10-x86-rel-tests" realm: "ci" acls { @@ -6941,8 +6941,8 @@ triggers: "ChromeOS FYI Release (amd64-generic)" triggers: "ChromeOS FYI Release (kevin)" triggers: "ChromiumOS ASAN Release" - triggers: "Comparison Linux" - triggers: "Comparison Windows" + triggers: "Comparison Linux (reclient)" + triggers: "Comparison Windows (reclient)" triggers: "CrWinAsan" triggers: "CrWinAsan(dll)" triggers: "Dawn Linux x64 Builder" @@ -7101,6 +7101,7 @@ triggers: "android-backuprefptr-arm64-fyi-rel" triggers: "android-bfcache-rel" triggers: "android-binary-size-generator" + triggers: "android-chrome-pie-x86-wpt-fyi-rel" triggers: "android-code-coverage-native" triggers: "android-cronet-arm-dbg" triggers: "android-cronet-arm-rel" @@ -7120,7 +7121,6 @@ triggers: "android-pie-arm64-wpt-rel-non-cq" triggers: "android-pie-x86-rel" triggers: "android-rust-arm-rel" - triggers: "android-web-platform-pie-x86-fyi-rel" triggers: "android-weblayer-pie-x86-wpt-fyi-rel" triggers: "android-weblayer-pie-x86-wpt-smoketest" triggers: "android-weblayer-with-aosp-webview-x86-fyi-rel"
diff --git a/infra/config/lib/bootstrap.star b/infra/config/lib/bootstrap.star index cde3be8..8ac7abe 100644 --- a/infra/config/lib/bootstrap.star +++ b/infra/config/lib/bootstrap.star
@@ -163,7 +163,7 @@ if bootstrap_node.props.bootstrap: non_bootstrapped_properties.update({ "$bootstrap/exe": { - "exe": builder.exe, + "exe": json.decode(proto.to_jsonpb(builder.exe, use_proto_names = True)), }, "led_builder_is_bootstrapped": True, })
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.fyi.star b/infra/config/subprojects/chromium/ci/chromium.android.fyi.star index d2eaf884..e96a3c1 100644 --- a/infra/config/subprojects/chromium/ci/chromium.android.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.android.fyi.star
@@ -48,7 +48,7 @@ ) ci.builder( - name = "android-web-platform-pie-x86-fyi-rel", + name = "android-chrome-pie-x86-wpt-fyi-rel", console_view_entry = consoles.console_view_entry( category = "builder_tester|web-platform", short_name = "P",
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 791071e..f77ccad 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -595,7 +595,7 @@ ) ci.builder( - name = "Comparison Linux", + name = "Comparison Linux (reclient)", console_view_entry = consoles.console_view_entry( category = "linux", short_name = "cmp", @@ -610,7 +610,7 @@ ) ci.builder( - name = "Comparison Windows", + name = "Comparison Windows (reclient)", builderless = True, console_view_entry = consoles.console_view_entry( category = "win",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star index db4f207..6a0f7de10e 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -329,7 +329,7 @@ ) try_.builder( - name = "android-web-platform-pie-x86-fyi-rel", + name = "android-chrome-pie-x86-wpt-fyi-rel", ) try_.builder(
diff --git a/ios/chrome/browser/infobars/overlays/BUILD.gn b/ios/chrome/browser/infobars/overlays/BUILD.gn index 563858ac..c949e70 100644 --- a/ios/chrome/browser/infobars/overlays/BUILD.gn +++ b/ios/chrome/browser/infobars/overlays/BUILD.gn
@@ -38,6 +38,7 @@ "//ios/chrome/browser/overlays/public/common/infobars", "//ios/chrome/browser/overlays/public/infobar_banner", "//ios/chrome/browser/overlays/public/infobar_modal", + "//ios/chrome/browser/overlays/public/infobar_modal/permissions", "//ios/chrome/browser/passwords:infobar_delegates", "//ios/web/public", ]
diff --git a/ios/chrome/browser/infobars/overlays/default_infobar_overlay_request_factory.mm b/ios/chrome/browser/infobars/overlays/default_infobar_overlay_request_factory.mm index bf6a073e..055f691 100644 --- a/ios/chrome/browser/infobars/overlays/default_infobar_overlay_request_factory.mm +++ b/ios/chrome/browser/infobars/overlays/default_infobar_overlay_request_factory.mm
@@ -17,6 +17,7 @@ #import "ios/chrome/browser/overlays/public/infobar_banner/translate_infobar_banner_overlay_request_config.h" #import "ios/chrome/browser/overlays/public/infobar_banner/update_password_infobar_banner_overlay.h" #import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h" +#import "ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.h" #import "ios/chrome/browser/overlays/public/infobar_modal/reading_list_modal_overlay_request_config.h" #import "ios/chrome/browser/overlays/public/infobar_modal/save_address_profile_infobar_modal_overlay_request_config.h" #import "ios/chrome/browser/overlays/public/infobar_modal/save_card_infobar_modal_overlay_request_config.h" @@ -140,6 +141,9 @@ case InfobarOverlayType::kBanner: return OverlayRequest::CreateWithConfig< PermissionsBannerRequestConfig>(infobar_ios); + case InfobarOverlayType::kModal: + return OverlayRequest::CreateWithConfig< + PermissionsInfobarModalOverlayRequestConfig>(infobar_ios); default: return nullptr; }
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/permissions/BUILD.gn b/ios/chrome/browser/overlays/public/infobar_modal/permissions/BUILD.gn new file mode 100644 index 0000000..26486d12 --- /dev/null +++ b/ios/chrome/browser/overlays/public/infobar_modal/permissions/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("permissions") { + sources = [ + "permissions_modal_overlay_request_config.h", + "permissions_modal_overlay_request_config.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + "//base", + "//ios/chrome/browser/infobars", + "//ios/chrome/browser/overlays", + "//ios/chrome/browser/overlays/public/common/infobars", + ] +}
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.h b/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.h new file mode 100644 index 0000000..7af14ef --- /dev/null +++ b/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.h
@@ -0,0 +1,36 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PERMISSIONS_PERMISSIONS_MODAL_OVERLAY_REQUEST_CONFIG_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PERMISSIONS_PERMISSIONS_MODAL_OVERLAY_REQUEST_CONFIG_H_ + +#include <CoreFoundation/CoreFoundation.h> + +#include "ios/chrome/browser/overlays/public/overlay_request_config.h" + +class InfoBarIOS; + +// Configuration object for OverlayRequests for the modal UI for an infobar. +class PermissionsInfobarModalOverlayRequestConfig + : public OverlayRequestConfig<PermissionsInfobarModalOverlayRequestConfig> { + public: + ~PermissionsInfobarModalOverlayRequestConfig() override; + + // The associated web state. + web::WebState* GetWebState() const; + + private: + OVERLAY_USER_DATA_SETUP(PermissionsInfobarModalOverlayRequestConfig); + explicit PermissionsInfobarModalOverlayRequestConfig(InfoBarIOS* infobar); + + // OverlayUserData: + void CreateAuxiliaryData(base::SupportsUserData* user_data) override; + + // The InfoBar causing this modal. + InfoBarIOS* infobar_ = nullptr; + + web::WebState* web_state_ = nullptr; +}; + +#endif // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PERMISSIONS_PERMISSIONS_MODAL_OVERLAY_REQUEST_CONFIG_H_
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.mm b/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.mm new file mode 100644 index 0000000..01a271af --- /dev/null +++ b/ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.mm
@@ -0,0 +1,36 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/overlays/public/infobar_modal/permissions/permissions_modal_overlay_request_config.h" + +#include "ios/chrome/browser/infobars/infobar_ios.h" +#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +OVERLAY_USER_DATA_SETUP_IMPL(PermissionsInfobarModalOverlayRequestConfig); + +PermissionsInfobarModalOverlayRequestConfig:: + PermissionsInfobarModalOverlayRequestConfig(InfoBarIOS* infobar) + : infobar_(infobar) { + DCHECK(infobar_); + // TODO(crbug.com/1289645): Retrieve the current webstate from the permissions + // delegate once implemented. +} + +PermissionsInfobarModalOverlayRequestConfig:: + ~PermissionsInfobarModalOverlayRequestConfig() = default; + +web::WebState* PermissionsInfobarModalOverlayRequestConfig::GetWebState() + const { + return web_state_; +} + +void PermissionsInfobarModalOverlayRequestConfig::CreateAuxiliaryData( + base::SupportsUserData* user_data) { + InfobarOverlayRequestConfig::CreateForUserData( + user_data, infobar_, InfobarOverlayType::kModal, false); +}
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm index 7c884d33e..3378499 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -1703,11 +1703,6 @@ ItemType itemType = static_cast<ItemType>([model itemTypeForIndexPath:indexPath]); switch (itemType) { - case ItemTypeLinkHeader: - case ItemTypeHeader: - case ItemTypeSavePasswordsSwitch: - case ItemTypeManagedSavePasswords: - break; case ItemTypePasswordsInOtherApps: [self.handler showPasswordsInOtherAppsPromo]; break; @@ -1758,8 +1753,12 @@ BlockToOpenURL(self, self.dispatcher)(url); break; } - case ItemTypeOnDeviceEncryptionOptInDescription: case ItemTypeLastCheckTimestampFooter: + case ItemTypeOnDeviceEncryptionOptInDescription: + case ItemTypeLinkHeader: + case ItemTypeHeader: + case ItemTypeSavePasswordsSwitch: + case ItemTypeManagedSavePasswords: NOTREACHED(); } [tableView deselectRowAtIndexPath:indexPath animated:YES];
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 7846893..0e1adf8 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -c2d83790d17590989d1efe9d66ecd67ee201785e \ No newline at end of file +d72acc13503097754c30dab2d7008b89d9aa1897 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 653acee..e6d3e66 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -240cc33f62e0945d83587979527706092caa045f \ No newline at end of file +aafd9a62f4ea760d4f15ace9dc2be1204b34dfa2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 52f2d3f..2799784 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -fbfbc9bfc286a6ae08944b69c94c20029f3bc00b \ No newline at end of file +202196c9ef7fee42d70bf7ffe9b80677b876ae91 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index a2f0a17..679a5ff 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -63e5c65b42f4c878baf969d0491b5f0339fae225 \ No newline at end of file +285816d1d62fe596af9603ea6a37d5ff8b16859c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index 8fb3030..088934b 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -2c1025f79ce5ad5d626c4fde0a6b843e9506ef1b \ No newline at end of file +fef5205011dd9bf55dac4e98d4c29790dddcfec6 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index 7e5426d..e051588 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -16e7f46bbe0b506d2e6bb0fdbd76e38857b14fc3 \ No newline at end of file +f3503a4a3161f581601e99a7172f39e23a58cc33 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 82046088..19c998a7 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -9d3f8844c5d73e34beabea01a98c194a9e9a04c6 \ No newline at end of file +946f5f5fbb5973e7f685555f042723182fa0ba61 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index a1977ef..0ad6ed0b 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -78e8fa82d2e0cab7642df83257ba41d301c0b1cf \ No newline at end of file +2912bdbd8f1fad18ec8a4beb13bb0f492b65a478 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index 3136959b..eaabffb 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -282cb5a6721879c733cb2bcdd61520605bdaa452 \ No newline at end of file +037e8e86ee27b9b62a88428c4ec59737be6c9d4a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 57dfda0..f4fb1dd 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -4e9100e23c75a9f40f62681deb749706162cb2eb \ No newline at end of file +4dc5165d2137baae13e945d92a8d9ff98c753330 \ No newline at end of file
diff --git a/media/base/decoder_status.cc b/media/base/decoder_status.cc index 869b3bc..9fffd5f 100644 --- a/media/base/decoder_status.cc +++ b/media/base/decoder_status.cc
@@ -22,6 +22,7 @@ STRINGIFY(DecoderStatus::Codes::kAborted); STRINGIFY(DecoderStatus::Codes::kInvalidArgument); STRINGIFY(DecoderStatus::Codes::kInterrupted); + STRINGIFY(DecoderStatus::Codes::kDisconnected); STRINGIFY(DecoderStatus::Codes::kNotInitialized); STRINGIFY(DecoderStatus::Codes::kMissingCDM); STRINGIFY(DecoderStatus::Codes::kFailedToGetVideoFrame);
diff --git a/media/base/decoder_status.h b/media/base/decoder_status.h index 5618777..edd2de6 100644 --- a/media/base/decoder_status.h +++ b/media/base/decoder_status.h
@@ -18,6 +18,7 @@ kAborted = 2, // TODO(*) document _why_ aborted is a thing kInvalidArgument = 3, kInterrupted = 4, + kDisconnected = 5, // Lost mojo connection, e.g remote crashed or teardown // Reasons for failing to decode kNotInitialized = 100,
diff --git a/media/mojo/clients/mojo_audio_decoder.cc b/media/mojo/clients/mojo_audio_decoder.cc index 60d2109..8855de0 100644 --- a/media/mojo/clients/mojo_audio_decoder.cc +++ b/media/mojo/clients/mojo_audio_decoder.cc
@@ -70,7 +70,7 @@ // This could happen during reinitialization. if (!remote_decoder_.is_connected()) { DVLOG(1) << __func__ << ": Connection error happened."; - FailInit(std::move(init_cb), DecoderStatus::Codes::kFailedToCreateDecoder); + FailInit(std::move(init_cb), DecoderStatus::Codes::kDisconnected); return; } @@ -103,9 +103,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!remote_decoder_.is_connected()) { - task_runner_->PostTask( - FROM_HERE, - base::BindOnce(std::move(decode_cb), DecoderStatus::Codes::kFailed)); + task_runner_->PostTask(FROM_HERE, + base::BindOnce(std::move(decode_cb), + DecoderStatus::Codes::kDisconnected)); return; } @@ -133,8 +133,8 @@ if (!remote_decoder_.is_connected()) { if (decode_cb_) { task_runner_->PostTask( - FROM_HERE, - base::BindOnce(std::move(decode_cb_), DecoderStatus::Codes::kFailed)); + FROM_HERE, base::BindOnce(std::move(decode_cb_), + DecoderStatus::Codes::kDisconnected)); } task_runner_->PostTask(FROM_HERE, std::move(closure)); @@ -188,12 +188,12 @@ DCHECK(!remote_decoder_.is_connected()); if (init_cb_) { - FailInit(std::move(init_cb_), DecoderStatus::Codes::kFailedToCreateDecoder); + FailInit(std::move(init_cb_), DecoderStatus::Codes::kDisconnected); return; } if (decode_cb_) - std::move(decode_cb_).Run(DecoderStatus::Codes::kFailed); + std::move(decode_cb_).Run(DecoderStatus::Codes::kDisconnected); if (reset_cb_) std::move(reset_cb_).Run(); }
diff --git a/media/mojo/clients/mojo_video_decoder.cc b/media/mojo/clients/mojo_video_decoder.cc index 9f860be..bc6b09e 100644 --- a/media/mojo/clients/mojo_video_decoder.cc +++ b/media/mojo/clients/mojo_video_decoder.cc
@@ -214,7 +214,7 @@ absl::optional<base::UnguessableToken> cdm_id) { if (has_connection_error_) { DCHECK(init_cb_); - FailInit(std::move(init_cb_), DecoderStatus::Codes::kFailedToCreateDecoder); + FailInit(std::move(init_cb_), DecoderStatus::Codes::kDisconnected); return; } @@ -244,9 +244,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (has_connection_error_) { - task_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(decode_cb), - DecoderStatus::Codes::kNotInitialized)); + task_runner_->PostTask(FROM_HERE, + base::BindOnce(std::move(decode_cb), + DecoderStatus::Codes::kDisconnected)); return; } @@ -495,14 +495,14 @@ base::WeakPtr<MojoVideoDecoder> weak_this = weak_this_; if (init_cb_) - std::move(init_cb_).Run(DecoderStatus::Codes::kFailedToCreateDecoder); + std::move(init_cb_).Run(DecoderStatus::Codes::kDisconnected); if (!weak_this) return; for (auto& pending_decode : pending_decodes_) { // It would be ideal if we could get a reason for the interruption. - std::move(pending_decode.second).Run(DecoderStatus::Codes::kInterrupted); + std::move(pending_decode.second).Run(DecoderStatus::Codes::kDisconnected); if (!weak_this) return; }
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.cc b/media/mojo/clients/win/media_foundation_renderer_client.cc index 3144f637..49cc4f65 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client.cc +++ b/media/mojo/clients/win/media_foundation_renderer_client.cc
@@ -288,19 +288,18 @@ mojo::WrapCallbackWithDefaultInvokeIfNotRun( base::BindOnce(&MediaFoundationRendererClient::OnDCOMPSurfaceReceived, weak_factory_.GetWeakPtr()), - absl::nullopt)); + absl::nullopt, "disconnection error")); } void MediaFoundationRendererClient::OnDCOMPSurfaceReceived( - const absl::optional<base::UnguessableToken>& token) { + const absl::optional<base::UnguessableToken>& token, + const std::string& error) { DVLOG_FUNC(1); DCHECK(has_video_); DCHECK(media_task_runner_->BelongsToCurrentThread()); if (!token) { - MEDIA_LOG(ERROR, media_log_) - << "Failed to initialize DCOMP mode or failed to get or " - "register DCOMP surface handle on remote renderer"; + MEDIA_LOG(ERROR, media_log_) << "GetDCOMPSurface failed: " + error; MediaFoundationRenderer::ReportErrorReason( MediaFoundationRenderer::ErrorReason::kOnDCompSurfaceReceivedError); OnError(PIPELINE_ERROR_COULD_NOT_RENDER);
diff --git a/media/mojo/clients/win/media_foundation_renderer_client.h b/media/mojo/clients/win/media_foundation_renderer_client.h index 26b1bf0f..608e7cb 100644 --- a/media/mojo/clients/win/media_foundation_renderer_client.h +++ b/media/mojo/clients/win/media_foundation_renderer_client.h
@@ -92,7 +92,8 @@ void OnSetOutputRectDone(const gfx::Size& output_size, bool success); void InitializeDCOMPRenderingIfNeeded(); void OnDCOMPSurfaceReceived( - const absl::optional<base::UnguessableToken>& token); + const absl::optional<base::UnguessableToken>& token, + const std::string& error); void OnDCOMPSurfaceHandleSet(bool success); void OnVideoFrameCreated(scoped_refptr<VideoFrame> video_frame); void OnCdmAttached(bool success);
diff --git a/media/mojo/mojom/renderer_extensions.mojom b/media/mojo/mojom/renderer_extensions.mojom index 9672c15..0cc5f1b6 100644 --- a/media/mojo/mojom/renderer_extensions.mojom +++ b/media/mojo/mojom/renderer_extensions.mojom
@@ -58,8 +58,9 @@ interface MediaFoundationRendererExtension { // Enables Direct Composition video rendering and gets the token associated // with the Direct Composition surface handle, which can be retrieved later - // in the GPU process using the token. Returns a null token on failures. - GetDCOMPSurface() => (mojo_base.mojom.UnguessableToken? token); + // in the GPU process using the token. Returns a null `token` on failures when + // `error` explains the failure reason. + GetDCOMPSurface() => (mojo_base.mojom.UnguessableToken? token, string error); // Notifies whether video is enabled. SetVideoStreamEnabled(bool enabled);
diff --git a/media/mojo/services/media_foundation_renderer_wrapper.cc b/media/mojo/services/media_foundation_renderer_wrapper.cc index 9cb3dd5..4d8f85cc 100644 --- a/media/mojo/services/media_foundation_renderer_wrapper.cc +++ b/media/mojo/services/media_foundation_renderer_wrapper.cc
@@ -131,9 +131,10 @@ void MediaFoundationRendererWrapper::OnReceiveDCOMPSurface( GetDCOMPSurfaceCallback callback, - base::win::ScopedHandle handle) { + base::win::ScopedHandle handle, + const std::string& error) { if (!handle.IsValid()) { - std::move(callback).Run(absl::nullopt); + std::move(callback).Run(absl::nullopt, "invalid handle: " + error); return; } @@ -155,12 +156,15 @@ void MediaFoundationRendererWrapper::OnDCOMPSurfaceHandleRegistered( GetDCOMPSurfaceCallback callback, const absl::optional<base::UnguessableToken>& token) { + std::string error; if (token) { DCHECK(dcomp_surface_token_.is_empty()); dcomp_surface_token_ = token.value(); + } else { + error = "dcomp surface handle registration failed"; } - std::move(callback).Run(token); + std::move(callback).Run(token, error); } } // namespace media
diff --git a/media/mojo/services/media_foundation_renderer_wrapper.h b/media/mojo/services/media_foundation_renderer_wrapper.h index 2678ec6..a0f5178f4 100644 --- a/media/mojo/services/media_foundation_renderer_wrapper.h +++ b/media/mojo/services/media_foundation_renderer_wrapper.h
@@ -65,7 +65,8 @@ private: void OnReceiveDCOMPSurface(GetDCOMPSurfaceCallback callback, - base::win::ScopedHandle handle); + base::win::ScopedHandle handle, + const std::string& error); void OnDCOMPSurfaceHandleRegistered( GetDCOMPSurfaceCallback callback, const absl::optional<base::UnguessableToken>& token);
diff --git a/media/renderers/audio_renderer_impl.cc b/media/renderers/audio_renderer_impl.cc index 3e16d803..6db95b4 100644 --- a/media/renderers/audio_renderer_impl.cc +++ b/media/renderers/audio_renderer_impl.cc
@@ -842,10 +842,13 @@ pending_read_ = false; if (result.has_error()) { - HandleAbortedReadOrDecodeError(result.code() == - DecoderStatus::Codes::kAborted - ? PIPELINE_OK - : PIPELINE_ERROR_DECODE); + auto status = PIPELINE_ERROR_DECODE; + if (result.code() == DecoderStatus::Codes::kAborted) + status = PIPELINE_OK; + else if (result.code() == DecoderStatus::Codes::kDisconnected) + status = PIPELINE_ERROR_DISCONNECTED; + + HandleAbortedReadOrDecodeError(status); return; }
diff --git a/media/renderers/video_renderer_impl.cc b/media/renderers/video_renderer_impl.cc index 8caba70..a6301e4 100644 --- a/media/renderers/video_renderer_impl.cc +++ b/media/renderers/video_renderer_impl.cc
@@ -573,12 +573,14 @@ // However, since it's a dcheck, this seems okay. return; default: - DCHECK(result.has_error()); // Anything other than `kOk` or `kAborted` is treated as an error. + DCHECK(result.has_error()); + auto status = result.code() == DecoderStatus::Codes::kDisconnected + ? PIPELINE_ERROR_DISCONNECTED + : PIPELINE_ERROR_DECODE; task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&VideoRendererImpl::OnPlaybackError, - weak_factory_.GetWeakPtr(), PIPELINE_ERROR_DECODE)); + FROM_HERE, base::BindOnce(&VideoRendererImpl::OnPlaybackError, + weak_factory_.GetWeakPtr(), status)); return; }
diff --git a/media/renderers/win/media_foundation_renderer.cc b/media/renderers/win/media_foundation_renderer.cc index 523d037c..b88f8c13 100644 --- a/media/renderers/win/media_foundation_renderer.cc +++ b/media/renderers/win/media_foundation_renderer.cc
@@ -69,6 +69,25 @@ return true; } +const std::string GetErrorReasonString( + const MediaFoundationRenderer::ErrorReason& reason) { +#define STRINGIFY(value) \ + case MediaFoundationRenderer::ErrorReason::value: \ + return #value + switch (reason) { + STRINGIFY(kUnknown); + STRINGIFY(kCdmProxyReceivedInInvalidState); + STRINGIFY(kFailedToSetSourceOnMediaEngine); + STRINGIFY(kFailedToSetCurrentTime); + STRINGIFY(kFailedToPlay); + STRINGIFY(kOnPlaybackError); + STRINGIFY(kOnDCompSurfaceReceivedError); + STRINGIFY(kOnDCompSurfaceHandleSetError); + STRINGIFY(kOnConnectionError); + } +#undef STRINGIFY +} + } // namespace // static @@ -375,9 +394,8 @@ DVLOG_FUNC(1); if (!waiting_for_mf_cdm_ || !content_protection_manager_) { - DLOG(ERROR) << "Failed in checking internal state."; - ReportErrorReason(ErrorReason::kCdmProxyReceivedInInvalidState); - renderer_client_->OnError(PIPELINE_ERROR_INVALID_STATE); + OnError(PIPELINE_ERROR_INVALID_STATE, + ErrorReason::kCdmProxyReceivedInInvalidState); return; } @@ -388,9 +406,8 @@ HRESULT hr = SetSourceOnMediaEngine(); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to set source on media engine: " << PrintHr(hr); - ReportErrorReason(ErrorReason::kFailedToSetSourceOnMediaEngine); - renderer_client_->OnError(PIPELINE_ERROR_COULD_NOT_RENDER); + OnError(PIPELINE_ERROR_COULD_NOT_RENDER, + ErrorReason::kFailedToSetSourceOnMediaEngine, hr); return; } } @@ -423,17 +440,14 @@ // MF_MEDIA_ENGINE_EVENT_SEEKED event. HRESULT hr = mf_media_engine_->SetCurrentTime(current_time); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to SetCurrentTime: " << PrintHr(hr); - ReportErrorReason(ErrorReason::kFailedToSetCurrentTime); - renderer_client_->OnError(PIPELINE_ERROR_COULD_NOT_RENDER); + OnError(PIPELINE_ERROR_COULD_NOT_RENDER, + ErrorReason::kFailedToSetCurrentTime, hr); return; } hr = mf_media_engine_->Play(); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to start playback: " << PrintHr(hr); - ReportErrorReason(ErrorReason::kFailedToPlay); - renderer_client_->OnError(PIPELINE_ERROR_COULD_NOT_RENDER); + OnError(PIPELINE_ERROR_COULD_NOT_RENDER, ErrorReason::kFailedToPlay, hr); return; } } @@ -451,16 +465,18 @@ HRESULT hr = SetDCompModeInternal(); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to set DComp mode: " << PrintHr(hr); - std::move(callback).Run(base::win::ScopedHandle()); + std::string error = "Failed to set DComp mode: " + PrintHr(hr); + DLOG(ERROR) << error; + std::move(callback).Run(base::win::ScopedHandle(), error); return; } HANDLE surface_handle = INVALID_HANDLE_VALUE; hr = GetDCompSurfaceInternal(&surface_handle); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to get DComp surface: " << PrintHr(hr); - std::move(callback).Run(base::win::ScopedHandle()); + std::string error = "Failed to get DComp surface: " + PrintHr(hr); + DLOG(ERROR) << error; + std::move(callback).Run(base::win::ScopedHandle(), error); return; } @@ -472,12 +488,14 @@ process, surface_handle, process, &duplicated_handle, GENERIC_READ | GENERIC_EXECUTE, false, DUPLICATE_CLOSE_SOURCE); if (!result) { - DLOG(ERROR) << "Duplicate surface_handle failed: " << ::GetLastError(); - std::move(callback).Run(base::win::ScopedHandle()); + std::string error = + "Duplicate surface_handle failed: " + PrintHr(::GetLastError()); + DLOG(ERROR) << error; + std::move(callback).Run(base::win::ScopedHandle(), error); return; } - std::move(callback).Run(base::win::ScopedHandle(duplicated_handle)); + std::move(callback).Run(base::win::ScopedHandle(duplicated_handle), ""); } // TODO(crbug.com/1070030): Investigate if we need to add @@ -658,21 +676,16 @@ if (status == PIPELINE_ERROR_HARDWARE_CONTEXT_RESET && cdm_proxy_) cdm_proxy_->OnHardwareContextReset(); - MEDIA_LOG(ERROR, media_log_) - << "MediaFoundationRenderer OnPlaybackError: " << status << ", " - << PrintHr(hr); - - ReportErrorReason(ErrorReason::kOnPlaybackError); - renderer_client_->OnError(status); StopSendingStatistics(); + OnError(status, ErrorReason::kOnPlaybackError, hr); } void MediaFoundationRenderer::OnPlaybackEnded() { DVLOG_FUNC(2); DCHECK(task_runner_->RunsTasksInCurrentSequence()); - renderer_client_->OnEnded(); StopSendingStatistics(); + renderer_client_->OnEnded(); } void MediaFoundationRenderer::OnFormatChange() { @@ -790,4 +803,16 @@ renderer_client_->OnVideoNaturalSizeChange(native_video_size_); } +void MediaFoundationRenderer::OnError(PipelineStatus status, + ErrorReason reason, + absl::optional<HRESULT> hresult) { + const std::string error = + "MediaFoundationRenderer error: " + GetErrorReasonString(reason) + + (hresult.has_value() ? (" (" + PrintHr(hresult.value()) + ")") : ""); + DLOG(ERROR) << error; + MEDIA_LOG(ERROR, media_log_) << error; + ReportErrorReason(reason); + renderer_client_->OnError(status); +} + } // namespace media
diff --git a/media/renderers/win/media_foundation_renderer.h b/media/renderers/win/media_foundation_renderer.h index 64b20d7..5a1805c8 100644 --- a/media/renderers/win/media_foundation_renderer.h +++ b/media/renderers/win/media_foundation_renderer.h
@@ -122,6 +122,9 @@ HRESULT PauseInternal(); HRESULT InitializeTexturePool(const gfx::Size& size); void OnVideoNaturalSizeChange(); + void OnError(PipelineStatus status, + ErrorReason reason, + absl::optional<HRESULT> hresult = absl::nullopt); // Renderer methods are running in the same sequence. scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/media/renderers/win/media_foundation_renderer_extension.h b/media/renderers/win/media_foundation_renderer_extension.h index 742aa5e..b1c7353 100644 --- a/media/renderers/win/media_foundation_renderer_extension.h +++ b/media/renderers/win/media_foundation_renderer_extension.h
@@ -23,8 +23,9 @@ // method names in a separate CL. // Enables Direct Composition video rendering and returns the Direct - // Composition Surface handle. - using GetDCompSurfaceCB = base::OnceCallback<void(base::win::ScopedHandle)>; + // Composition Surface handle. On failure, `error` explains the error reason. + using GetDCompSurfaceCB = base::OnceCallback<void(base::win::ScopedHandle, + const std::string& error)>; virtual void GetDCompSurface(GetDCompSurfaceCB callback) = 0; // Notifies renderer whether video is enabled.
diff --git a/media/renderers/win/media_foundation_renderer_unittest.cc b/media/renderers/win/media_foundation_renderer_unittest.cc index 1e5b46a..6e12a66 100644 --- a/media/renderers/win/media_foundation_renderer_unittest.cc +++ b/media/renderers/win/media_foundation_renderer_unittest.cc
@@ -233,7 +233,7 @@ EXPECT_CALL(renderer_init_cb_, Run(HasStatusCode(PIPELINE_OK))); // Ignore the DirectComposition handle value returned as our |pmp_server_| // has no real implementation. - EXPECT_CALL(get_dcomp_surface_cb, Run(_)); + EXPECT_CALL(get_dcomp_surface_cb, Run(_, _)); mf_renderer_->Initialize(&media_resource_, &renderer_client_, renderer_init_cb_.Get());
diff --git a/net/cookies/cookie_access_delegate.cc b/net/cookies/cookie_access_delegate.cc index 00e03e6..2fe07c5 100644 --- a/net/cookies/cookie_access_delegate.cc +++ b/net/cookies/cookie_access_delegate.cc
@@ -28,7 +28,10 @@ const CookieAccessDelegate* delegate, const CookiePartitionKey& cookie_partition_key, base::OnceCallback<void(absl::optional<CookiePartitionKey>)> callback) { - if (!delegate) { + // FirstPartySetify doesn't need to transform partition keys with a nonce, + // since those partitions are only available to a single fenced/anonymous + // iframe. + if (!delegate || cookie_partition_key.nonce()) { std::move(callback).Run(cookie_partition_key); return; }
diff --git a/net/cookies/cookie_partition_key.h b/net/cookies/cookie_partition_key.h index 46f0289..60ff48b 100644 --- a/net/cookies/cookie_partition_key.h +++ b/net/cookies/cookie_partition_key.h
@@ -72,7 +72,7 @@ // which were already created using Deserialize or FromNetworkIsolationKey. static CookiePartitionKey FromWire( const SchemefulSite& site, - absl::optional<base::UnguessableToken> nonce) { + absl::optional<base::UnguessableToken> nonce = absl::nullopt) { return CookiePartitionKey(site, nonce); }
diff --git a/net/cookies/cookie_partition_key_collection.cc b/net/cookies/cookie_partition_key_collection.cc index 778a3986..0058f69 100644 --- a/net/cookies/cookie_partition_key_collection.cc +++ b/net/cookies/cookie_partition_key_collection.cc
@@ -55,8 +55,16 @@ std::vector<SchemefulSite> sites; sites.reserve(PartitionKeys().size()); for (const CookiePartitionKey& key : PartitionKeys()) { + // Partition keys that have a nonce are not available across top-level sites + // in the same First-Party Set. + if (key.nonce()) + continue; sites.push_back(key.site()); } + if (sites.empty()) { + std::move(callback).Run(*this); + return; + } cookie_access_delegate->FindFirstPartySetOwners( sites, base::BindOnce( @@ -69,9 +77,10 @@ const auto first_party_set_owner_iter = sites_to_owners.find(key.site()); canonicalized_keys.push_back( - first_party_set_owner_iter != sites_to_owners.end() + !key.nonce() && + first_party_set_owner_iter != sites_to_owners.end() ? CookiePartitionKey::FromWire( - first_party_set_owner_iter->second, key.nonce()) + first_party_set_owner_iter->second) : key); } std::move(callback).Run(
diff --git a/net/cookies/cookie_partition_key_collection_unittest.cc b/net/cookies/cookie_partition_key_collection_unittest.cc index 29c585a..6b17db1f 100644 --- a/net/cookies/cookie_partition_key_collection_unittest.cc +++ b/net/cookies/cookie_partition_key_collection_unittest.cc
@@ -160,6 +160,22 @@ &delegate) .PartitionKeys(), UnorderedElementsAre(kOwnerPartitionKey, kNonMemberPartitionKey)); + + // Test that FirstPartySetify does not modify partition keys with nonces. + const CookiePartitionKey kNoncedPartitionKey = + CookiePartitionKey::FromURLForTesting(kMemberURL, + base::UnguessableToken::Create()); + EXPECT_THAT( + FirstPartySetifyAndWait( + CookiePartitionKeyCollection({kNoncedPartitionKey}), &delegate) + .PartitionKeys(), + UnorderedElementsAre(kNoncedPartitionKey)); + EXPECT_THAT( + FirstPartySetifyAndWait(CookiePartitionKeyCollection( + {kNoncedPartitionKey, kMemberPartitionKey}), + &delegate) + .PartitionKeys(), + UnorderedElementsAre(kNoncedPartitionKey, kOwnerPartitionKey)); } TEST(CookiePartitionKeyCollectionTest, Contains) {
diff --git a/ppapi/proxy/ppb_x509_certificate_private_proxy.cc b/ppapi/proxy/ppb_x509_certificate_private_proxy.cc index 1d4c130..86107af 100644 --- a/ppapi/proxy/ppb_x509_certificate_private_proxy.cc +++ b/ppapi/proxy/ppb_x509_certificate_private_proxy.cc
@@ -26,9 +26,6 @@ bool ParseDER(const std::vector<char>& der, PPB_X509Certificate_Fields* result) override; - - private: - void SendToBrowser(IPC::Message* msg); }; X509CertificatePrivate::X509CertificatePrivate(PP_Instance instance) @@ -44,10 +41,6 @@ result); } -void X509CertificatePrivate::SendToBrowser(IPC::Message* msg) { - PluginGlobals::Get()->GetBrowserSender()->Send(msg); -} - } // namespace //------------------------------------------------------------------------------
diff --git a/storage/browser/quota/quota_internals.mojom b/storage/browser/quota/quota_internals.mojom index 7c0d2c4..afa27a7 100644 --- a/storage/browser/quota/quota_internals.mojom +++ b/storage/browser/quota/quota_internals.mojom
@@ -5,7 +5,7 @@ module storage.mojom; // Interface for controlling Quota Internals. -// Hosted on chrome://quota-internals-2" for WebUI content::QuotaInternals2UI. +// Hosted on chrome://quota-internals" for WebUI content::QuotaInternalsUI. interface QuotaInternalsHandler { // Returns the total and available disk space in bits for a user, // which is then converted to bytes and displayed on the Quota Internals UI.
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h index 0dfea02d..dcf00634 100644 --- a/storage/browser/quota/quota_manager_impl.h +++ b/storage/browser/quota/quota_manager_impl.h
@@ -695,7 +695,7 @@ std::map<blink::StorageKey, QuotaOverride> devtools_overrides_; int next_override_handle_id_ = 0; - // Serve mojo connections for chrome://quota-internals-2 pages. + // Serve mojo connections for chrome://quota-internals pages. mojo::ReceiverSet<mojom::QuotaInternalsHandler> internals_handlers_receivers_ GUARDED_BY_CONTEXT(sequence_checker_);
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 58d4d6d3..260b947c 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -1772,7 +1772,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 9 + "shards": 20 }, "test": "content_browsertests", "test_id_prefix": "ninja://content/test:content_browsertests/" @@ -5305,51 +5305,7 @@ } ] }, - "android-pie-arm64-wpt-rel-non-cq": { - "isolated_scripts": [ - { - "experiment_percentage": 100, - "isolate_name": "system_webview_wpt", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "system_webview_wpt", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "dimension_sets": [ - { - "device_os": "PQ3A.190801.002", - "device_os_flavor": "google", - "device_os_type": "userdebug", - "device_type": "walleye", - "os": "Android" - } - ], - "expiration": 18000, - "hard_timeout": 14400, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 - }, - "test_id_prefix": "ninja://android_webview/test:system_webview_wpt/" - } - ] - }, - "android-web-platform-pie-x86-fyi-rel": { + "android-chrome-pie-x86-wpt-fyi-rel": { "isolated_scripts": [ { "args": [ @@ -5415,6 +5371,50 @@ } ] }, + "android-pie-arm64-wpt-rel-non-cq": { + "isolated_scripts": [ + { + "experiment_percentage": 100, + "isolate_name": "system_webview_wpt", + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "system_webview_wpt", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", + "device_os_type": "userdebug", + "device_type": "walleye", + "os": "Android" + } + ], + "expiration": 18000, + "hard_timeout": 14400, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 25 + }, + "test_id_prefix": "ninja://android_webview/test:system_webview_wpt/" + } + ] + }, "android-weblayer-10-x86-rel-tests": { "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 475219df..12f80c7b 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -40888,8 +40888,7 @@ "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android28.textpb", - "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_p.media_unittests.filter" + "--avd-config=../../tools/android/avd/proto/generic_android28.textpb" ], "merge": { "args": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 63a9a712..b17bbf0 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -1,12 +1,12 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, - "Comparison Linux": { + "Comparison Linux (reclient)": { "additional_compile_targets": [ "all" ] }, - "Comparison Windows": { + "Comparison Windows (reclient)": { "additional_compile_targets": [ "all" ]
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index b48c0f0..2f40fe2 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -885,7 +885,7 @@ "ignore_task_failure": false, "io_timeout": 21600, "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 + "shards": 12 }, "trigger_script": { "args": [
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index 5dd1993..8907008 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -328,7 +328,6 @@ data = [ "//testing/buildbot/filters/android.emulator_11_12.media_unittests.filter", "//testing/buildbot/filters/android.emulator_m.media_unittests.filter", - "//testing/buildbot/filters/android.emulator_p.media_unittests.filter", "//testing/buildbot/filters/fuchsia.debug.media_unittests.filter", "//testing/buildbot/filters/fuchsia.lsan.media_unittests.filter", ]
diff --git a/testing/buildbot/filters/android.emulator_m.media_unittests.filter b/testing/buildbot/filters/android.emulator_m.media_unittests.filter index 5e21e2d..94ad9fc 100644 --- a/testing/buildbot/filters/android.emulator_m.media_unittests.filter +++ b/testing/buildbot/filters/android.emulator_m.media_unittests.filter
@@ -1,8 +1,3 @@ -# https://crbug.com/1039873 --PaintCanvasVideoRendererWithGLTest.CopyVideoFrameTexturesToGLTextureI420 --PaintCanvasVideoRendererWithGLTest.PaintI420 --PaintCanvasVideoRendererWithGLTest.PaintI420NotSubset - # https://crbug.com/1081506 -AAudio/AudioOutputTest.Play200HzTone/0 -AudioAndroidOutputTest.StartOutputStreamCallbacks
diff --git a/testing/buildbot/filters/android.emulator_p.media_unittests.filter b/testing/buildbot/filters/android.emulator_p.media_unittests.filter deleted file mode 100644 index 1c01da1..0000000 --- a/testing/buildbot/filters/android.emulator_p.media_unittests.filter +++ /dev/null
@@ -1,4 +0,0 @@ -# https://crbug.com/1039873 --PaintCanvasVideoRendererWithGLTest.CopyVideoFrameTexturesToGLTextureI420 --PaintCanvasVideoRendererWithGLTest.PaintI420 --PaintCanvasVideoRendererWithGLTest.PaintI420NotSubset
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 9a06c5e..d9f6216 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1297,6 +1297,11 @@ ], }, }, + 'android-12-x64-fyi-rel': { + 'swarming': { + 'shards': 20, + }, + }, 'android-arm64-proguard-rel': { 'swarming': { 'shards': 16, @@ -2112,11 +2117,6 @@ '--gtest_filter=-AAudio/AudioOutputTest.Play200HzTone/0', # https://crbug.com/1034009 ], }, - 'android-pie-x86-rel': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_p.media_unittests.filter', - ], - }, 'fuchsia-code-coverage': { 'swarming': { 'shards': 3,
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 509ff5e4..0801675 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1155,19 +1155,7 @@ }, 'os_type': 'android', }, - 'android-pie-arm64-wpt-rel-non-cq': { - 'mixins': [ - 'has_native_resultdb_integration', - 'pie_fleet', - 'walleye', - ], - 'test_suites': { - 'isolated_scripts': 'system_webview_wpt', - }, - 'use_swarming': True, - 'os_type': 'android', - }, - 'android-web-platform-pie-x86-fyi-rel': { + 'android-chrome-pie-x86-wpt-fyi-rel': { 'mixins': [ 'has_native_resultdb_integration', 'pie-x86-emulator', @@ -1181,6 +1169,18 @@ 'use_swarming': True, 'os_type': 'android', }, + 'android-pie-arm64-wpt-rel-non-cq': { + 'mixins': [ + 'has_native_resultdb_integration', + 'pie_fleet', + 'walleye', + ], + 'test_suites': { + 'isolated_scripts': 'system_webview_wpt', + }, + 'use_swarming': True, + 'os_type': 'android', + }, 'android-weblayer-10-x86-rel-tests': { 'mixins': [ 'has_native_resultdb_integration', @@ -2538,7 +2538,7 @@ 'name': 'chromium.fyi', 'mixins': ['chromium-tester-service-account'], 'machines': { - 'Comparison Linux': { + 'Comparison Linux (reclient)': { 'mixins': [ 'isolate_profile_data', ], @@ -2546,7 +2546,7 @@ 'all' ], }, - 'Comparison Windows': { + 'Comparison Windows (reclient)': { 'mixins': [ 'isolate_profile_data', ],
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 5e753e0..677acf00a 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -171,28 +171,6 @@ ] } ], - "AndroidInProductHelpDownloadPage": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Tracking", - "params": { - "availability": ">=14", - "event_1": "name:user_has_seen_dino;comparator:>=1;window:90;storage:360", - "event_trigger": "name:download_page_iph_trigger;comparator:==0;window:90;storage:360", - "event_used": "name:download_page_started;comparator:==0;window:90;storage:360", - "session_rate": "<0" - }, - "enable_features": [ - "IPH_DownloadPage" - ] - } - ] - } - ], "AndroidInProductHelpPwaInstall": [ { "platforms": [ @@ -1525,33 +1503,6 @@ ] } ], - "ChromeOSKstaled": [ - { - "platforms": [ - "chromeos" - ], - "experiments": [ - { - "name": "MglruBehavior", - "params": { - "KstaledRatio": "1" - }, - "enable_features": [ - "KstaledSwap" - ] - }, - { - "name": "KswapdBehavior", - "params": { - "KstaledRatio": "0" - }, - "enable_features": [ - "KstaledSwap" - ] - } - ] - } - ], "ChromeOSRawPSIMetrics": [ { "platforms": [ @@ -5875,6 +5826,24 @@ ] } ], + "TabSwitchMetrics2": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "TabSwitchMetrics2" + ] + } + ] + } + ], "TabToGTSAnimation": [ { "platforms": [ @@ -5935,24 +5904,6 @@ ] } ], - "TopCat": [ - { - "platforms": [ - "chromeos" - ], - "experiments": [ - { - "name": "TopCat1_20190902", - "params": { - "use_topcat_ranker": "true" - }, - "enable_features": [ - "EnableAppRanker" - ] - } - ] - } - ], "TreatPreconnectAsDefault": [ { "platforms": [
diff --git a/third_party/androidx/build.gradle.template b/third_party/androidx/build.gradle.template index 7d4133a..8cc4848 100644 --- a/third_party/androidx/build.gradle.template +++ b/third_party/androidx/build.gradle.template
@@ -45,6 +45,7 @@ compile 'androidx.interpolator:interpolator:{{androidx_dependency_version}}' compile 'androidx.leanback:leanback:{{androidx_dependency_version}}' compile 'androidx.leanback:leanback-preference:{{androidx_dependency_version}}' + compile 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' compile 'androidx.media:media:{{androidx_dependency_version}}' compile 'androidx.mediarouter:mediarouter:{{androidx_dependency_version}}' compile 'androidx.preference:preference:{{androidx_dependency_version}}'
diff --git a/third_party/blink/common/page/content_to_visible_time_reporter.cc b/third_party/blink/common/page/content_to_visible_time_reporter.cc index cba388c..b64224e 100644 --- a/third_party/blink/common/page/content_to_visible_time_reporter.cc +++ b/third_party/blink/common/page/content_to_visible_time_reporter.cc
@@ -60,9 +60,7 @@ } // namespace -ContentToVisibleTimeReporter::ContentToVisibleTimeReporter() - : is_tab_switch_metric2_feature_enabled_( - base::FeatureList::IsEnabled(blink::features::kTabSwitchMetrics2)) {} +ContentToVisibleTimeReporter::ContentToVisibleTimeReporter() = default; ContentToVisibleTimeReporter::~ContentToVisibleTimeReporter() = default; @@ -71,14 +69,33 @@ bool has_saved_frames, mojom::RecordContentToVisibleTimeRequestPtr start_state) { DCHECK(!start_state->event_start_time.is_null()); + if (IsTabSwitchMetric2FeatureEnabled() && tab_switch_start_state_ && + tab_switch_start_state_->show_reason_tab_switching && + start_state->show_reason_tab_switching) { + // Missed a tab hide, so record an incomplete tab switch. As a side effect + // this will reset the state. + // + // This can happen when the tab is backgrounded, but still visible in a + // visible capturer or VR, so the widget is never notified to hide. + // TabWasHidden is only called correctly for *hidden* capturers (such as + // picture-in-picture). See WebContentsImpl::CalculatePageVisibilityState + // for more details. + // + // TODO(crbug.com/1289266): Refactor visibility states to call TabWasHidden + // every time a tab is backgrounded, even if the content is still visible. + RecordHistogramsAndTraceEvents(TabSwitchResult::kMissedTabHide, + true /* show_reason_tab_switching */, + false /* show_reason_unoccluded */, + false /* show_reason_bfcache_restore */, + gfx::PresentationFeedback::Failure()); + } DCHECK(!tab_switch_start_state_); // Invalidate previously issued callbacks, to avoid accessing a null // |tab_switch_start_state_|. // - // TODO(https://crbug.com/1121339): Make sure that TabWasShown() is never - // called twice without a call to TabWasHidden() in-between, and remove this - // mitigation. + // TODO(crbug.com/1289266): Make sure that TabWasShown() is never called twice + // without a call to TabWasHidden() in-between, and remove this mitigation. weak_ptr_factory_.InvalidateWeakPtrs(); has_saved_frames_ = has_saved_frames; @@ -88,7 +105,7 @@ // once the metrics have been emitted. return base::BindOnce( &ContentToVisibleTimeReporter::RecordHistogramsAndTraceEvents, - weak_ptr_factory_.GetWeakPtr(), false /* is_incomplete */, + weak_ptr_factory_.GetWeakPtr(), TabSwitchResult::kSuccess, tab_switch_start_state_->show_reason_tab_switching, tab_switch_start_state_->show_reason_unoccluded, tab_switch_start_state_->show_reason_bfcache_restore); @@ -110,7 +127,7 @@ void ContentToVisibleTimeReporter::TabWasHidden() { if (tab_switch_start_state_) { - RecordHistogramsAndTraceEvents(true /* is_incomplete */, + RecordHistogramsAndTraceEvents(TabSwitchResult::kIncomplete, true /* show_reason_tab_switching */, false /* show_reason_unoccluded */, false /* show_reason_bfcache_restore */, @@ -119,8 +136,16 @@ } } +bool ContentToVisibleTimeReporter::IsTabSwitchMetric2FeatureEnabled() { + if (!is_tab_switch_metric2_feature_enabled_) { + is_tab_switch_metric2_feature_enabled_ = + base::FeatureList::IsEnabled(blink::features::kTabSwitchMetrics2); + } + return *is_tab_switch_metric2_feature_enabled_; +} + void ContentToVisibleTimeReporter::RecordHistogramsAndTraceEvents( - bool is_incomplete, + TabSwitchResult tab_switch_result, bool show_reason_tab_switching, bool show_reason_unoccluded, bool show_reason_bfcache_restore, @@ -130,6 +155,9 @@ // for recording the event. DCHECK(show_reason_bfcache_restore || show_reason_unoccluded || show_reason_tab_switching); + // The kPresentationFailure result should only be used if `feedback` has a + // failure. + DCHECK_NE(tab_switch_result, TabSwitchResult::kPresentationFailure); if (show_reason_bfcache_restore) { RecordBackForwardCacheRestoreMetric( @@ -144,11 +172,10 @@ return; // Tab switching has occurred. - auto tab_switch_result = TabSwitchResult::kSuccess; - if (is_incomplete) - tab_switch_result = TabSwitchResult::kIncomplete; - else if (feedback.flags & gfx::PresentationFeedback::kFailure) + if (tab_switch_result == TabSwitchResult::kSuccess && + feedback.flags & gfx::PresentationFeedback::kFailure) { tab_switch_result = TabSwitchResult::kPresentationFailure; + } const auto tab_switch_duration = feedback.timestamp - tab_switch_start_state_->event_start_time; @@ -168,7 +195,7 @@ const char* suffix = GetHistogramSuffix(has_saved_frames_, *tab_switch_start_state_); - if (is_tab_switch_metric2_feature_enabled_) { + if (IsTabSwitchMetric2FeatureEnabled()) { // Record result histogram. base::UmaHistogramEnumeration( base::StrCat({"Browser.Tabs.TabSwitchResult2.", suffix}), @@ -176,22 +203,20 @@ // Record latency histogram. switch (tab_switch_result) { - case TabSwitchResult::kSuccess: { + case TabSwitchResult::kSuccess: base::UmaHistogramMediumTimes( base::StrCat({"Browser.Tabs.TotalSwitchDuration2.", suffix}), tab_switch_duration); break; - } - case TabSwitchResult::kIncomplete: { + case TabSwitchResult::kMissedTabHide: + case TabSwitchResult::kIncomplete: base::UmaHistogramMediumTimes( base::StrCat( {"Browser.Tabs.TotalIncompleteSwitchDuration2.", suffix}), tab_switch_duration); break; - } - case TabSwitchResult::kPresentationFailure: { + case TabSwitchResult::kPresentationFailure: break; - } } } @@ -211,21 +236,22 @@ // Record latency histogram. switch (tab_switch_result) { - case TabSwitchResult::kSuccess: { + case TabSwitchResult::kSuccess: base::UmaHistogramTimes( base::StrCat({"Browser.Tabs.TotalSwitchDuration.", suffix}), tab_switch_duration); break; - } - case TabSwitchResult::kIncomplete: { + case TabSwitchResult::kMissedTabHide: + // This was not included in the v1 histograms. + DCHECK(IsTabSwitchMetric2FeatureEnabled()); + [[fallthrough]]; + case TabSwitchResult::kIncomplete: base::UmaHistogramTimes( base::StrCat({"Browser.Tabs.TotalIncompleteSwitchDuration.", suffix}), tab_switch_duration); break; - } - case TabSwitchResult::kPresentationFailure: { + case TabSwitchResult::kPresentationFailure: break; - } } // Reset tab switch information.
diff --git a/third_party/blink/common/page/content_to_visible_time_reporter_unittest.cc b/third_party/blink/common/page/content_to_visible_time_reporter_unittest.cc index 31ee215..c0e5561 100644 --- a/third_party/blink/common/page/content_to_visible_time_reporter_unittest.cc +++ b/third_party/blink/common/page/content_to_visible_time_reporter_unittest.cc
@@ -2,15 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> #include <strstream> #include <utility> +#include <vector> #include "base/containers/contains.h" +#include "base/containers/extend.h" #include "base/rand_util.h" +#include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/page/content_to_visible_time_reporter.h" #include "ui/gfx/presentation_feedback.h" @@ -28,93 +34,167 @@ struct TabStateParams { bool has_saved_frames; bool destination_is_loaded; - const char* duration_histogram; - const char* incomplete_duration_histogram; - const char* result_histogram; + bool tab_switch_metrics2_enabled; + const char* histogram_suffix; }; constexpr TabStateParams kTabStatesToTest[] = { // WithSavedFrames - {.has_saved_frames = true, - .destination_is_loaded = true, - .duration_histogram = "Browser.Tabs.TotalSwitchDuration.WithSavedFrames", - .incomplete_duration_histogram = - "Browser.Tabs.TotalIncompleteSwitchDuration.WithSavedFrames", - .result_histogram = "Browser.Tabs.TabSwitchResult.WithSavedFrames"}, + { + .has_saved_frames = true, + .destination_is_loaded = true, + .tab_switch_metrics2_enabled = false, + .histogram_suffix = "WithSavedFrames", + }, + { + .has_saved_frames = true, + .destination_is_loaded = true, + .tab_switch_metrics2_enabled = true, + .histogram_suffix = "WithSavedFrames", + }, + // NoSavedFrames_Loaded - {.has_saved_frames = false, - .destination_is_loaded = true, - .duration_histogram = - "Browser.Tabs.TotalSwitchDuration.NoSavedFrames_Loaded", - .incomplete_duration_histogram = - "Browser.Tabs.TotalIncompleteSwitchDuration.NoSavedFrames_Loaded", - .result_histogram = "Browser.Tabs.TabSwitchResult.NoSavedFrames_Loaded"}, + { + .has_saved_frames = false, + .destination_is_loaded = true, + .tab_switch_metrics2_enabled = false, + .histogram_suffix = "NoSavedFrames_Loaded", + }, + { + .has_saved_frames = false, + .destination_is_loaded = true, + .tab_switch_metrics2_enabled = true, + .histogram_suffix = "NoSavedFrames_Loaded", + }, + // NoSavedFrames_NotLoaded - {.has_saved_frames = false, - .destination_is_loaded = false, - .duration_histogram = - "Browser.Tabs.TotalSwitchDuration.NoSavedFrames_NotLoaded", - .incomplete_duration_histogram = - "Browser.Tabs.TotalIncompleteSwitchDuration.NoSavedFrames_" - "NotLoaded", - .result_histogram = - "Browser.Tabs.TabSwitchResult.NoSavedFrames_NotLoaded"}, + { + .has_saved_frames = false, + .destination_is_loaded = false, + .tab_switch_metrics2_enabled = false, + .histogram_suffix = "NoSavedFrames_NotLoaded", + }, + { + .has_saved_frames = false, + .destination_is_loaded = false, + .tab_switch_metrics2_enabled = true, + .histogram_suffix = "NoSavedFrames_NotLoaded", + }, }; class ContentToVisibleTimeReporterTest : public ::testing::TestWithParam<TabStateParams> { protected: ContentToVisibleTimeReporterTest() : tab_state_(GetParam()) { + scoped_feature_list_.InitWithFeatureState( + blink::features::kTabSwitchMetrics2, + tab_state_.tab_switch_metrics2_enabled); + + duration_histograms_.push_back(base::StrCat( + {"Browser.Tabs.TotalSwitchDuration.", tab_state_.histogram_suffix})); + incomplete_duration_histograms_.push_back( + base::StrCat({"Browser.Tabs.TotalIncompleteSwitchDuration.", + tab_state_.histogram_suffix})); + result_histograms_.push_back(base::StrCat( + {"Browser.Tabs.TabSwitchResult.", tab_state_.histogram_suffix})); + + if (tab_state_.tab_switch_metrics2_enabled) { + // Additional metrics logged when the TabSwitchMetrics2 feature is + // enabled. + // TODO(crbug.com/1164477): When the feature is enabled both the old and + // new histograms are logged, so that the old histograms with and without + // the feature can be easily compared in an A/B test. When the feature + // ships by default remove the old histograms. + duration_histograms_.push_back(base::StrCat( + {"Browser.Tabs.TotalSwitchDuration2.", tab_state_.histogram_suffix})); + incomplete_duration_histograms_.push_back( + base::StrCat({"Browser.Tabs.TotalIncompleteSwitchDuration2.", + tab_state_.histogram_suffix})); + result_histograms_.push_back(base::StrCat( + {"Browser.Tabs.TabSwitchResult2.", tab_state_.histogram_suffix})); + } + // Expect all histograms to be empty. ExpectHistogramsEmptyExcept({}); } void ExpectHistogramsEmptyExcept( - std::vector<const char*> histograms_with_values) { + const std::vector<std::string>& histograms_with_values) { constexpr const char* kAllHistograms[] = { + // Pre-TabSwitchMetrics2 feature. "Browser.Tabs.TotalSwitchDuration.WithSavedFrames", "Browser.Tabs.TotalSwitchDuration.NoSavedFrames_Loaded", "Browser.Tabs.TotalSwitchDuration.NoSavedFrames_NotLoaded", "Browser.Tabs.TotalIncompleteSwitchDuration.WithSavedFrames", "Browser.Tabs.TotalIncompleteSwitchDuration.NoSavedFrames_Loaded", - "Browser.Tabs.TotalIncompleteSwitchDuration.NoSavedFrames_NotLoaded", + "Browser.Tabs.TotalIncompleteSwitchDuration.NoSavedFrames_" + "NotLoaded", "Browser.Tabs.TabSwitchResult.WithSavedFrames", "Browser.Tabs.TabSwitchResult.NoSavedFrames_Loaded", "Browser.Tabs.TabSwitchResult.NoSavedFrames_NotLoaded", - kWebContentsUnOccludedHistogram, - kBfcacheRestoreHistogram}; + // With TabSwitchMetrics2 feature. + "Browser.Tabs.TotalSwitchDuration2.WithSavedFrames", + "Browser.Tabs.TotalSwitchDuration2.NoSavedFrames_Loaded", + "Browser.Tabs.TotalSwitchDuration2.NoSavedFrames_NotLoaded", + "Browser.Tabs.TotalIncompleteSwitchDuration2.WithSavedFrames", + "Browser.Tabs.TotalIncompleteSwitchDuration2.NoSavedFrames_" + "Loaded", + "Browser.Tabs.TotalIncompleteSwitchDuration2.NoSavedFrames_" + "NotLoaded", + "Browser.Tabs.TabSwitchResult2.WithSavedFrames", + "Browser.Tabs.TabSwitchResult2.NoSavedFrames_Loaded", + "Browser.Tabs.TabSwitchResult2.NoSavedFrames_NotLoaded", + // Non-tab switch. + kWebContentsUnOccludedHistogram, kBfcacheRestoreHistogram}; + std::vector<std::string> unexpected_histograms; for (const char* histogram : kAllHistograms) { if (!base::Contains(histograms_with_values, histogram)) - ExpectTotalSamples(histogram, 0); + unexpected_histograms.push_back(histogram); + } + ExpectTotalSamples(unexpected_histograms, 0); + } + + void ExpectTotalSamples(const std::vector<std::string>& histogram_names, + int expected_count) { + for (const std::string& histogram_name : histogram_names) { + SCOPED_TRACE(base::StringPrintf("Expect %d samples in %s.", + expected_count, histogram_name.c_str())); + EXPECT_EQ(static_cast<int>( + histogram_tester_.GetAllSamples(histogram_name).size()), + expected_count); } } - void ExpectTotalSamples(const char* histogram_name, int expected_count) { - SCOPED_TRACE(base::StringPrintf("Expect %d samples in %s.", expected_count, - histogram_name)); - EXPECT_EQ(static_cast<int>( - histogram_tester_.GetAllSamples(histogram_name).size()), - expected_count); + void ExpectTimeBucketCounts(const std::vector<std::string>& histogram_names, + base::TimeDelta value, + int count) { + for (const std::string& histogram_name : histogram_names) { + histogram_tester_.ExpectTimeBucketCount(histogram_name, value, count); + } } - void ExpectTimeBucketCount(const char* histogram_name, - base::TimeDelta value, - int count) { - histogram_tester_.ExpectTimeBucketCount(histogram_name, value, count); - } - - void ExpectResultBucketCount( - const char* histogram_name, + void ExpectResultBucketCounts( + const std::vector<std::string>& histogram_names, ContentToVisibleTimeReporter::TabSwitchResult value, int count) { - histogram_tester_.ExpectBucketCount(histogram_name, value, count); + for (const std::string& histogram_name : histogram_names) { + histogram_tester_.ExpectBucketCount(histogram_name, value, count); + } } + // Create `feature_list_` before `task_environment_` and destroy it after to + // avoid a race in destruction. + base::test::ScopedFeatureList scoped_feature_list_; base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; ContentToVisibleTimeReporter tab_switch_time_recorder_; base::HistogramTester histogram_tester_; TabStateParams tab_state_; + + // Expected histogram names to be logged for the given TabStateParams. + std::vector<std::string> duration_histograms_; + std::vector<std::string> incomplete_duration_histograms_; + std::vector<std::string> result_histograms_; }; INSTANTIATE_TEST_SUITE_P(All, @@ -137,17 +217,19 @@ end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion); std::move(callback).Run(presentation_feedback); - ExpectHistogramsEmptyExcept( - {tab_state_.duration_histogram, tab_state_.result_histogram}); + std::vector<std::string> expected_histograms; + base::Extend(expected_histograms, duration_histograms_); + base::Extend(expected_histograms, result_histograms_); + ExpectHistogramsEmptyExcept(expected_histograms); // Duration. - ExpectTotalSamples(tab_state_.duration_histogram, 1); - ExpectTimeBucketCount(tab_state_.duration_histogram, kDuration, 1); + ExpectTotalSamples(duration_histograms_, 1); + ExpectTimeBucketCounts(duration_histograms_, kDuration, 1); // Result. - ExpectTotalSamples(tab_state_.result_histogram, 1); - ExpectResultBucketCount( - tab_state_.result_histogram, + ExpectTotalSamples(result_histograms_, 1); + ExpectResultBucketCounts( + result_histograms_, ContentToVisibleTimeReporter::TabSwitchResult::kSuccess, 1); } @@ -164,12 +246,12 @@ /* show_reason_bfcache_restore */ false)); std::move(callback).Run(gfx::PresentationFeedback::Failure()); - ExpectHistogramsEmptyExcept({tab_state_.result_histogram}); + ExpectHistogramsEmptyExcept(result_histograms_); // Result (no duration is recorded on presentation failure). - ExpectTotalSamples(tab_state_.result_histogram, 1); - ExpectResultBucketCount( - tab_state_.result_histogram, + ExpectTotalSamples(result_histograms_, 1); + ExpectResultBucketCounts( + result_histograms_, ContentToVisibleTimeReporter::TabSwitchResult::kPresentationFailure, 1); } @@ -188,17 +270,19 @@ task_environment_.FastForwardBy(kDuration); tab_switch_time_recorder_.TabWasHidden(); - ExpectHistogramsEmptyExcept( - {tab_state_.result_histogram, tab_state_.incomplete_duration_histogram}); + std::vector<std::string> expected_histograms; + base::Extend(expected_histograms, result_histograms_); + base::Extend(expected_histograms, incomplete_duration_histograms_); + ExpectHistogramsEmptyExcept(expected_histograms); // Duration. - ExpectTotalSamples(tab_state_.incomplete_duration_histogram, 1); - ExpectTimeBucketCount(tab_state_.incomplete_duration_histogram, kDuration, 1); + ExpectTotalSamples(incomplete_duration_histograms_, 1); + ExpectTimeBucketCounts(incomplete_duration_histograms_, kDuration, 1); // Result. - ExpectTotalSamples(tab_state_.result_histogram, 1); - ExpectResultBucketCount( - tab_state_.result_histogram, + ExpectTotalSamples(result_histograms_, 1); + ExpectResultBucketCounts( + result_histograms_, ContentToVisibleTimeReporter::TabSwitchResult::kIncomplete, 1); const auto start2 = base::TimeTicks::Now(); @@ -214,23 +298,81 @@ end2, end2 - start2, gfx::PresentationFeedback::Flags::kHWCompletion); std::move(callback2).Run(presentation_feedback); - ExpectHistogramsEmptyExcept({tab_state_.duration_histogram, - tab_state_.result_histogram, - tab_state_.incomplete_duration_histogram}); + // Now the tab switch completes, and adds a duration histogram. + base::Extend(expected_histograms, duration_histograms_); + ExpectHistogramsEmptyExcept(expected_histograms); // Duration. - ExpectTotalSamples(tab_state_.incomplete_duration_histogram, 1); - ExpectTimeBucketCount(tab_state_.incomplete_duration_histogram, kDuration, 1); - ExpectTotalSamples(tab_state_.duration_histogram, 1); - ExpectTimeBucketCount(tab_state_.duration_histogram, kOtherDuration, 1); + ExpectTotalSamples(incomplete_duration_histograms_, 1); + ExpectTimeBucketCounts(incomplete_duration_histograms_, kDuration, 1); + ExpectTotalSamples(duration_histograms_, 1); + ExpectTimeBucketCounts(duration_histograms_, kOtherDuration, 1); // Result. - ExpectTotalSamples(tab_state_.result_histogram, 2); - ExpectResultBucketCount( - tab_state_.result_histogram, + ExpectTotalSamples(result_histograms_, 2); + ExpectResultBucketCounts( + result_histograms_, ContentToVisibleTimeReporter::TabSwitchResult::kIncomplete, 1); - ExpectResultBucketCount( - tab_state_.result_histogram, + ExpectResultBucketCounts( + result_histograms_, + ContentToVisibleTimeReporter::TabSwitchResult::kSuccess, 1); +} + +// When the TabSwitchMetrics2 feature is enabled, if TabWasHidden is not called +// an incomplete tab switch is reported. +// TODO(crbug.com/1289266): Find and remove all cases where TabWasHidden is not +// called. +TEST_P(ContentToVisibleTimeReporterTest, MissingTabWasHidden) { + if (!tab_state_.tab_switch_metrics2_enabled) + GTEST_SKIP(); + + const auto start1 = base::TimeTicks::Now(); + auto callback1 = tab_switch_time_recorder_.TabWasShown( + tab_state_.has_saved_frames, + blink::mojom::RecordContentToVisibleTimeRequest::New( + start1, tab_state_.destination_is_loaded, + /* show_reason_tab_switching */ true, + /* show_reason_unoccluded */ false, + /* show_reason_bfcache_restore */ false)); + + task_environment_.FastForwardBy(kDuration); + + ExpectHistogramsEmptyExcept({}); + + const auto start2 = base::TimeTicks::Now(); + auto callback2 = tab_switch_time_recorder_.TabWasShown( + tab_state_.has_saved_frames, + blink::mojom::RecordContentToVisibleTimeRequest::New( + start2, tab_state_.destination_is_loaded, + /* show_reason_tab_switching */ true, + /* show_reason_unoccluded */ false, + /* show_reason_bfcache_restore */ false)); + const auto end2 = start2 + kOtherDuration; + auto presentation_feedback = gfx::PresentationFeedback( + end2, end2 - start2, gfx::PresentationFeedback::Flags::kHWCompletion); + std::move(callback2).Run(presentation_feedback); + + // IncompleteDuration should be logged for the first TabWasShown, and Duration + // for the second. + std::vector<std::string> expected_histograms; + base::Extend(expected_histograms, duration_histograms_); + base::Extend(expected_histograms, result_histograms_); + base::Extend(expected_histograms, incomplete_duration_histograms_); + ExpectHistogramsEmptyExcept(expected_histograms); + + // Duration. + ExpectTotalSamples({incomplete_duration_histograms_}, 1); + ExpectTimeBucketCounts({incomplete_duration_histograms_}, kDuration, 1); + ExpectTotalSamples({duration_histograms_}, 1); + ExpectTimeBucketCounts({duration_histograms_}, kOtherDuration, 1); + + // Result. + ExpectTotalSamples({result_histograms_}, 2); + ExpectResultBucketCounts( + {result_histograms_}, + ContentToVisibleTimeReporter::TabSwitchResult::kMissedTabHide, 1); + ExpectResultBucketCounts( + {result_histograms_}, ContentToVisibleTimeReporter::TabSwitchResult::kSuccess, 1); } @@ -252,8 +394,8 @@ ExpectHistogramsEmptyExcept({kWebContentsUnOccludedHistogram}); // UnOccluded. - ExpectTotalSamples(kWebContentsUnOccludedHistogram, 1); - ExpectTimeBucketCount(kWebContentsUnOccludedHistogram, kDuration, 1); + ExpectTotalSamples({kWebContentsUnOccludedHistogram}, 1); + ExpectTimeBucketCounts({kWebContentsUnOccludedHistogram}, kDuration, 1); } // Time is properly recorded to histogram when we have unoccluded event @@ -273,23 +415,24 @@ end, end - start, gfx::PresentationFeedback::Flags::kHWCompletion); std::move(callback).Run(presentation_feedback); - ExpectHistogramsEmptyExcept({tab_state_.duration_histogram, - tab_state_.result_histogram, - kWebContentsUnOccludedHistogram}); + std::vector<std::string> expected_histograms{kWebContentsUnOccludedHistogram}; + base::Extend(expected_histograms, duration_histograms_); + base::Extend(expected_histograms, result_histograms_); + ExpectHistogramsEmptyExcept(expected_histograms); // Duration. - ExpectTotalSamples(tab_state_.duration_histogram, 1); - ExpectTimeBucketCount(tab_state_.duration_histogram, kDuration, 1); + ExpectTotalSamples(duration_histograms_, 1); + ExpectTimeBucketCounts(duration_histograms_, kDuration, 1); // Result. - ExpectTotalSamples(tab_state_.result_histogram, 1); - ExpectResultBucketCount( - tab_state_.result_histogram, + ExpectTotalSamples(result_histograms_, 1); + ExpectResultBucketCounts( + result_histograms_, ContentToVisibleTimeReporter::TabSwitchResult::kSuccess, 1); // UnOccluded. - ExpectTotalSamples(kWebContentsUnOccludedHistogram, 1); - ExpectTimeBucketCount(kWebContentsUnOccludedHistogram, kDuration, 1); + ExpectTotalSamples({kWebContentsUnOccludedHistogram}, 1); + ExpectTimeBucketCounts({kWebContentsUnOccludedHistogram}, kDuration, 1); } // Time is properly recorded to histogram when we have bfcache restore event. @@ -310,8 +453,8 @@ ExpectHistogramsEmptyExcept({kBfcacheRestoreHistogram}); // Bfcache restore. - ExpectTotalSamples(kBfcacheRestoreHistogram, 1); - ExpectTimeBucketCount(kBfcacheRestoreHistogram, kDuration, 1); + ExpectTotalSamples({kBfcacheRestoreHistogram}, 1); + ExpectTimeBucketCounts({kBfcacheRestoreHistogram}, kDuration, 1); } } // namespace blink
diff --git a/third_party/blink/public/common/page/content_to_visible_time_reporter.h b/third_party/blink/public/common/page/content_to_visible_time_reporter.h index 38f6998..569d4811 100644 --- a/third_party/blink/public/common/page/content_to_visible_time_reporter.h +++ b/third_party/blink/public/common/page/content_to_visible_time_reporter.h
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/common_export.h" #include "third_party/blink/public/mojom/widget/record_content_to_visible_time_request.mojom.h" @@ -30,7 +31,10 @@ kIncomplete = 1, // Compositor reported a failure after a tab switch. kPresentationFailure = 2, - kMaxValue = kPresentationFailure, + // TabWasShown called twice for a frame without TabWasHidden between. Treat + // the first TabWasShown as an incomplete tab switch. + kMissedTabHide = 3, + kMaxValue = kMissedTabHide, }; ContentToVisibleTimeReporter(); @@ -58,9 +62,13 @@ void TabWasHidden(); private: - // Records histograms and trace events for the current tab switch. + bool IsTabSwitchMetric2FeatureEnabled(); + + // Records histograms and trace events for the current tab switch. If + // `tab_switch_result` is kSuccess but `feedback` contains a failure flag, the + // result will be overridden with kPresentationFailure. void RecordHistogramsAndTraceEvents( - bool is_incomplete, + TabSwitchResult tab_switch_result, bool show_reason_tab_switching, bool show_reason_unoccluded, bool show_reason_bfcache_restore, @@ -74,7 +82,7 @@ mojom::RecordContentToVisibleTimeRequestPtr tab_switch_start_state_; // Cache the feature value for faster lookups. - bool is_tab_switch_metric2_feature_enabled_; + absl::optional<bool> is_tab_switch_metric2_feature_enabled_; base::WeakPtrFactory<ContentToVisibleTimeReporter> weak_ptr_factory_{this}; };
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 13a7e61..b5345d9 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -773,6 +773,36 @@ # are respected. Any injected via javascript (or other means) are ignored. MetaTagModifiedHTML + type FederatedAuthRequestIssueDetails extends object + properties + FederatedAuthRequestIssueReason federatedAuthRequestIssueReason + + # Represents the failure reason when a federated authentication reason fails. + # Should be updated alongside RequestIdTokenStatus in + # third_party/blink/public/mojom/webid/federated_auth_request.mojom to include + # all cases except for success. + type FederatedAuthRequestIssueReason extends string + enum + ApprovalDeclined + TooManyRequests + WellKnownHttpNotFound + WellKnownNoResponse + WellKnownInvalidResponse + ClientIdMetadataHttpNotFound + ClientIdMetadataNoResponse + ClientIdMetadataInvalidResponse + ErrorFetchingSignin + InvalidSigninResponse + AccountsHttpNotFound + AccountsNoResponse + AccountsInvalidResponse + IdTokenHttpNotFound + IdTokenNoResponse + IdTokenInvalidResponse + IdTokenInvalidRequest + ErrorIdToken + Canceled + # This issue tracks client hints related issues. It's used to deprecate old # features, encourage the use of new ones, and provide general guidance. type ClientHintIssueDetails extends object @@ -800,6 +830,7 @@ GenericIssue DeprecationIssue ClientHintIssue + FederatedAuthRequestIssue # This struct holds a list of optional fields with additional information # specific to the kind of issue. When adding a new issue code, please also @@ -821,6 +852,7 @@ optional GenericIssueDetails genericIssueDetails optional DeprecationIssueDetails deprecationIssueDetails optional ClientHintIssueDetails clientHintIssueDetails + optional FederatedAuthRequestIssueDetails federatedAuthRequestIssueDetails # A unique id for a DevTools inspector issue. Allows other entities (e.g. # exceptions, CDP message, console messages, etc.) to reference an issue.
diff --git a/third_party/blink/public/mojom/devtools/inspector_issue.mojom b/third_party/blink/public/mojom/devtools/inspector_issue.mojom index d0231f50..34b623d 100644 --- a/third_party/blink/public/mojom/devtools/inspector_issue.mojom +++ b/third_party/blink/public/mojom/devtools/inspector_issue.mojom
@@ -8,6 +8,7 @@ import "services/network/public/mojom/cookie_manager.mojom"; import "services/network/public/mojom/blocked_by_response_reason.mojom"; import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom"; +import "third_party/blink/public/mojom/webid/federated_auth_request.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; // A code that uniquely identifies an issue. This type should be descriptive @@ -21,6 +22,7 @@ kTrustedWebActivityIssue, kHeavyAdIssue, kLowTextContrastIssue, + kFederatedAuthRequestIssue, kGenericIssue, }; @@ -175,6 +177,10 @@ string font_weight; }; +struct FederatedAuthRequestIssueDetails { + RequestIdTokenStatus status; +}; + enum GenericIssueErrorType { kCrossOriginPortalPostMessageError, }; @@ -195,6 +201,7 @@ TrustedWebActivityIssueDetails? twa_issue_details; HeavyAdIssueDetails? heavy_ad_issue_details; LowTextContrastIssue? low_text_contrast_details; + FederatedAuthRequestIssueDetails? federated_auth_request_details; GenericIssueDetails? generic_issue_details; mojo_base.mojom.UnguessableToken? issue_id; };
diff --git a/third_party/blink/public/mojom/webid/federated_auth_request.mojom b/third_party/blink/public/mojom/webid/federated_auth_request.mojom index d5d345b..3c1303a 100644 --- a/third_party/blink/public/mojom/webid/federated_auth_request.mojom +++ b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
@@ -10,6 +10,10 @@ // // Proposal: https://github.com/WICG/WebID +// Represents the fetch result from a federated authentication request. Should +// be updated alongside FederatedAuthRequestIssueReason in +// third_party/blink/public/devtools_protocol/browser_protocol.pdl, which +// includes all cases except for kSuccess. enum RequestIdTokenStatus { kSuccess, kApprovalDeclined,
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h index c165309..d9a7195 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h
@@ -75,8 +75,10 @@ kReadableStreamTransferTag = 'r', // index:uint32_t kTransformStreamTransferTag = 'm', // index:uint32_t kWritableStreamTransferTag = 'w', // index:uint32_t - kDOMPointTag = 'Q', // x:Double, y:Double, z:Double, w:Double - kDOMPointReadOnlyTag = 'W', // x:Double, y:Double, z:Double, w:Double + // TODO(crbug.com/1288839): document format as soon as it is determined. + kMediaStreamTrack = 's', + kDOMPointTag = 'Q', // x:Double, y:Double, z:Double, w:Double + kDOMPointReadOnlyTag = 'W', // x:Double, y:Double, z:Double, w:Double kDOMRectTag = 'E', // x:Double, y:Double, width:Double, height:Double kDOMRectReadOnlyTag = 'R', // x:Double, y:Double, width:Double, height:Double kDOMQuadTag = 'T', // p1:Double, p2:Double, p3:Double, p4:Double
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h b/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h index c0fea6a..24a4546d 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/transferables.h
@@ -21,6 +21,7 @@ class ReadableStream; class WritableStream; class TransformStream; +class MediaStreamTrack; using ArrayBufferArray = HeapVector<Member<DOMArrayBufferBase>>; using ImageBitmapArray = HeapVector<Member<ImageBitmap>>; @@ -30,6 +31,7 @@ using ReadableStreamArray = HeapVector<Member<ReadableStream>>; using WritableStreamArray = HeapVector<Member<WritableStream>>; using TransformStreamArray = HeapVector<Member<TransformStream>>; +using MediaStreamTrackArray = HeapVector<Member<MediaStreamTrack>>; class CORE_EXPORT Transferables final { STACK_ALLOCATED(); @@ -50,6 +52,7 @@ ReadableStreamArray readable_streams; WritableStreamArray writable_streams; TransformStreamArray transform_streams; + MediaStreamTrackArray media_stream_tracks; class CORE_EXPORT TransferList : public GarbageCollectedMixin { public:
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index 29b2887..3484f0d 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -379,8 +379,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_validity_state_flags.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_wheel_event_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_wheel_event_init.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_controls_overlay_geometry_change_event_init.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_controls_overlay_geometry_change_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_post_message_options.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_post_message_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_worker_options.cc", @@ -1473,10 +1471,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_wheel_event.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_controls_overlay.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_controls_overlay.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_controls_overlay_geometry_change_event.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_window_controls_overlay_geometry_change_event.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_worker.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_worker.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_worker_global_scope.cc",
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 3d430a3..0f2ce99 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -2655,6 +2655,26 @@ ] } +# WindowControlsOverlay +# This uses target_os rather than current_os (which is what is_android is set +# from) for the case of generating the v8 context snapshot for android. When +# generating the snapshot for android, blink is compiled with +# current_os="linux" and target_os="android". Using target_os is necessary as +# we need to compile in the same way as would happen when current_os="android". +if (target_os != "android") { + generated_dictionary_sources_in_modules += [ + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_window_controls_overlay_geometry_change_event_init.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_window_controls_overlay_geometry_change_event_init.h", + ] + + generated_enumeration_sources_in_modules += [ + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_window_controls_overlay.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_window_controls_overlay.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_window_controls_overlay_geometry_change_event.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_window_controls_overlay_geometry_change_event.h", + ] +} + generated_interface_sources_in_modules += [ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/init_idl_interfaces.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/init_idl_interfaces.h",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index 48afc56e..11e30d7 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -302,7 +302,6 @@ "//third_party/blink/renderer/core/frame/navigator_ua_brand_version.idl", "//third_party/blink/renderer/core/frame/navigator_ua_data.idl", "//third_party/blink/renderer/core/frame/navigator_user_activation.idl", - "//third_party/blink/renderer/core/frame/navigator_window_controls_overlay.idl", "//third_party/blink/renderer/core/frame/permissions_policy_violation_report_body.idl", "//third_party/blink/renderer/core/frame/report.idl", "//third_party/blink/renderer/core/frame/report_body.idl", @@ -320,9 +319,6 @@ "//third_party/blink/renderer/core/frame/visual_viewport.idl", "//third_party/blink/renderer/core/frame/window.idl", "//third_party/blink/renderer/core/frame/window_attribution_reporting.idl", - "//third_party/blink/renderer/core/frame/window_controls_overlay.idl", - "//third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.idl", - "//third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event_init.idl", "//third_party/blink/renderer/core/frame/window_event_handlers.idl", "//third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl", "//third_party/blink/renderer/core/frame/window_post_message_options.idl",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index a0b21ce..91f11ff 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -1185,6 +1185,23 @@ "abspath") } +# WindowControlsOverlay +# This uses target_os rather than current_os (which is what is_android is set +# from) for the case of generating the v8 context snapshot for android. When +# generating the snapshot for android, blink is compiled with +# current_os="linux" and target_os="android". Using target_os is necessary as +# we need to compile in the same way as would happen when current_os="android". +if (target_os != "android") { + static_idl_files_in_modules += get_path_info( + [ + "//third_party/blink/renderer/modules/window_controls_overlay/navigator_window_controls_overlay.idl", + "//third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.idl", + "//third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.idl", + "//third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event_init.idl", + ], + "abspath") +} + # Statically-defined (not runtime-generated) IDL files in 'modules' component. # These IDL definitions are used only for testing. static_idl_files_in_modules_for_testing = get_path_info(
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc index 53a691e..cf11e8d 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -17,6 +17,7 @@ #include "third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.h" #include "third_party/blink/renderer/modules/file_system_access/file_system_file_handle.h" #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h" +#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h" @@ -89,6 +90,8 @@ return ReadEncodedAudioChunk(); case kEncodedVideoChunkTag: return ReadEncodedVideoChunk(); + case kMediaStreamTrack: + return ReadMediaStreamTrack(); default: break; } @@ -522,4 +525,13 @@ return MakeGarbageCollected<EncodedVideoChunk>(buffers[index]); } +MediaStreamTrack* V8ScriptValueDeserializerForModules::ReadMediaStreamTrack() { + if (!RuntimeEnabledFeatures::MediaStreamTrackTransferEnabled( + ExecutionContext::From(GetScriptState()))) { + return nullptr; + } + + return MediaStreamTrack::Create(ExecutionContext::From(GetScriptState())); +} + } // namespace blink
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h index 2e2e0776e..af56602e 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h
@@ -56,6 +56,7 @@ VideoFrame* ReadVideoFrame(); EncodedAudioChunk* ReadEncodedAudioChunk(); EncodedVideoChunk* ReadEncodedVideoChunk(); + MediaStreamTrack* ReadMediaStreamTrack(); }; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc index 510b6984..8a0527a 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/public/platform/web_crypto_key.h" #include "third_party/blink/public/platform/web_crypto_key_algorithm.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_read_only.h" #include "third_party/blink/renderer/bindings/modules/v8/serialization/web_crypto_sub_tags.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data.h" @@ -19,6 +20,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_handle.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_file_handle.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_landmark.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_point_2d.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_audio_frame.h" @@ -28,6 +30,7 @@ #include "third_party/blink/renderer/modules/crypto/crypto_key.h" #include "third_party/blink/renderer/modules/file_system_access/file_system_handle.h" #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h" +#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame_delegate.h" @@ -76,6 +79,23 @@ transfer_list->video_frames.push_back(video_frame); return true; } + + if (V8MediaStreamTrack::HasInstance(object, isolate) && + RuntimeEnabledFeatures::MediaStreamTrackTransferEnabled( + CurrentExecutionContext(isolate))) { + MediaStreamTrack* track = + V8MediaStreamTrack::ToImpl(v8::Local<v8::Object>::Cast(object)); + if (transferables.media_stream_tracks.Contains(track)) { + exception_state.ThrowDOMException( + DOMExceptionCode::kDataCloneError, + "MediaStreamTrack at index " + String::Number(object_index) + + " is a duplicate of an earlier MediaStreamTrack."); + return false; + } + transferables.media_stream_tracks.push_back(track); + return true; + } + return false; } @@ -204,6 +224,18 @@ auto data = wrappable->ToImpl<EncodedVideoChunk>()->buffer(); return WriteDecoderBuffer(std::move(data), /*for_audio=*/false); } + if (wrapper_type_info == V8MediaStreamTrack::GetWrapperTypeInfo() && + RuntimeEnabledFeatures::MediaStreamTrackTransferEnabled( + ExecutionContext::From(GetScriptState()))) { + if (IsForStorage()) { + exception_state.ThrowDOMException( + DOMExceptionCode::kDataCloneError, + "A MediaStreamTrack cannot be serialized for storage."); + return false; + } + + return WriteMediaStreamTrack(); + } return false; } @@ -473,4 +505,10 @@ return true; } +bool V8ScriptValueSerializerForModules::WriteMediaStreamTrack() { + WriteTag(kMediaStreamTrack); + + return true; +} + } // namespace blink
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h index b0566a3..63a59b8b 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h
@@ -53,6 +53,7 @@ bool WriteMediaAudioBuffer(scoped_refptr<media::AudioBuffer>); bool WriteDecoderBuffer(scoped_refptr<media::DecoderBuffer> data, bool for_audio); + bool WriteMediaStreamTrack(); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc index 18bfff86..6ed84d9 100644 --- a/third_party/blink/renderer/core/animation/animation.cc +++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -593,7 +593,6 @@ int compositor_group, const PaintArtifactCompositor* paint_artifact_compositor, bool start_on_compositor) { - bool soft_change = compositor_state_ && (Paused() || compositor_state_->playback_rate != EffectivePlaybackRate()); @@ -637,6 +636,12 @@ RecordCompositorAnimationFailureReasons(failure_reasons); if (failure_reasons == CompositorAnimations::kNoFailure) { + // We could still have a stale compositor keyframe model ID if + // a previous cancel failed due to not having a layout object at the + // time of the cancel operation. The start and stop of an animation + // for a marquee element does not depend on having a layout object. + if (HasActiveAnimationsOnCompositor()) + CancelAnimationOnCompositor(); CreateCompositorAnimation(); StartAnimationOnCompositor(paint_artifact_compositor); compositor_state_ = std::make_unique<CompositorState>(*this); @@ -2320,10 +2325,6 @@ if (reason == kTimingUpdateForAnimationFrame) { if (idle || CalculateAnimationPlayState() == kFinished) { - // TODO(crbug.com/1029348): Per spec, we should have a microtask - // checkpoint right after the update cycle. Once this is fixed we should - // no longer need to force a synchronous resolution here. - AsyncFinishMicrotask(); finished_ = true; } } @@ -2659,10 +2660,8 @@ // 1. The existence of the animation is not prescribed by markup. That is, it // is not a CSS animation with an owning element, nor a CSS transition with // an owning element. - if (IsCSSAnimation() || IsCSSTransition()) { - // TODO(crbug.com/981905): Add OwningElement method to Animation and - // override in CssAnimations and CssTransitions. Only bail here if the - // animation has an owning element. + if ((IsCSSAnimation() || IsCSSTransition()) && OwningElement()) { + // A CSS animation or transition that is bound to markup is not replaceable. return false; }
diff --git a/third_party/blink/renderer/core/animation/document_animations.cc b/third_party/blink/renderer/core/animation/document_animations.cc index 91c12b1..9e128f81 100644 --- a/third_party/blink/renderer/core/animation/document_animations.cc +++ b/third_party/blink/renderer/core/animation/document_animations.cc
@@ -52,6 +52,7 @@ #include "third_party/blink/renderer/core/page/page_animator.h" #include "third_party/blink/renderer/core/style/computed_style.h" #include "third_party/blink/renderer/platform/bindings/microtask.h" +#include "third_party/blink/renderer/platform/heap/persistent.h" namespace blink { @@ -280,10 +281,13 @@ // The list of animations for removal is constructed in reverse composite // ordering for efficiency. Flip the ordering to ensure that events are - // dispatched in composite order. + // dispatched in composite order. Queue as a microtask so that the finished + // event is dispatched ahead of the remove event. for (auto it = animations_to_remove.rbegin(); it != animations_to_remove.rend(); it++) { - (*it)->RemoveReplacedAnimation(); + Animation* animation = *it; + Microtask::EnqueueMicrotask(WTF::Bind(&Animation::RemoveReplacedAnimation, + WrapWeakPersistent(animation))); } }
diff --git a/third_party/blink/renderer/core/animation/interpolable_length.cc b/third_party/blink/renderer/core/animation/interpolable_length.cc index aa41b2c0..7813104 100644 --- a/third_party/blink/renderer/core/animation/interpolable_length.cc +++ b/third_party/blink/renderer/core/animation/interpolable_length.cc
@@ -166,7 +166,7 @@ DEFINE_STATIC_LOCAL(Persistent<CSSMathExpressionNode>, zero_percent, {PercentageNode(0)}); - SetExpression(*CSSMathExpressionBinaryOperation::Create( + SetExpression(*CSSMathExpressionOperation::CreateArithmeticOperation( expression_, zero_percent, CSSMathOperator::kAdd)); } @@ -181,8 +181,9 @@ DEFINE_STATIC_LOCAL(Persistent<CSSMathExpressionNode>, hundred_percent, {PercentageNode(100)}); - SetExpression(*CSSMathExpressionBinaryOperation::CreateSimplified( - hundred_percent, expression_, CSSMathOperator::kSubtract)); + SetExpression( + *CSSMathExpressionOperation::CreateArithmeticOperationSimplified( + hundred_percent, expression_, CSSMathOperator::kSubtract)); } static double ClampToRange(double x, Length::ValueRange range) { @@ -301,7 +302,7 @@ if (!root_node) { root_node = current_node; } else { - root_node = CSSMathExpressionBinaryOperation::Create( + root_node = CSSMathExpressionOperation::CreateArithmeticOperation( root_node, current_node, CSSMathOperator::kAdd); } } @@ -320,8 +321,9 @@ } DCHECK(IsExpression()); - SetExpression(*CSSMathExpressionBinaryOperation::CreateSimplified( - expression_, NumberNode(scale), CSSMathOperator::kMultiply)); + SetExpression( + *CSSMathExpressionOperation::CreateArithmeticOperationSimplified( + expression_, NumberNode(scale), CSSMathOperator::kMultiply)); } void InterpolableLength::Add(const InterpolableValue& other) { @@ -336,7 +338,7 @@ } CSSMathExpressionNode* result = - CSSMathExpressionBinaryOperation::CreateSimplified( + CSSMathExpressionOperation::CreateArithmeticOperationSimplified( &AsExpression(), &other_length.AsExpression(), CSSMathOperator::kAdd); SetExpression(*result); } @@ -354,10 +356,10 @@ } CSSMathExpressionNode* scaled = - CSSMathExpressionBinaryOperation::CreateSimplified( + CSSMathExpressionOperation::CreateArithmeticOperationSimplified( &AsExpression(), NumberNode(scale), CSSMathOperator::kMultiply); CSSMathExpressionNode* result = - CSSMathExpressionBinaryOperation::CreateSimplified( + CSSMathExpressionOperation::CreateArithmeticOperationSimplified( scaled, &other_length.AsExpression(), CSSMathOperator::kAdd); SetExpression(*result); } @@ -394,15 +396,15 @@ } CSSMathExpressionNode* blended_from = - CSSMathExpressionBinaryOperation::CreateSimplified( + CSSMathExpressionOperation::CreateArithmeticOperationSimplified( &AsExpression(), NumberNode(1 - progress), CSSMathOperator::kMultiply); CSSMathExpressionNode* blended_to = - CSSMathExpressionBinaryOperation::CreateSimplified( + CSSMathExpressionOperation::CreateArithmeticOperationSimplified( &to_length.AsExpression(), NumberNode(progress), CSSMathOperator::kMultiply); CSSMathExpressionNode* result_expression = - CSSMathExpressionBinaryOperation::CreateSimplified( + CSSMathExpressionOperation::CreateArithmeticOperationSimplified( blended_from, blended_to, CSSMathOperator::kAdd); result_length.SetExpression(*result_expression);
diff --git a/third_party/blink/renderer/core/animation/keyframe.h b/third_party/blink/renderer/core/animation/keyframe.h index 8c0e8a2..d5b943f4 100644 --- a/third_party/blink/renderer/core/animation/keyframe.h +++ b/third_party/blink/renderer/core/animation/keyframe.h
@@ -7,10 +7,10 @@ #include "base/memory/scoped_refptr.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/blink/renderer/core/animation/animation_effect.h" #include "third_party/blink/renderer/core/animation/effect_model.h" #include "third_party/blink/renderer/core/animation/property_handle.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/animation/timing_function.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc index d7e7de0a..b47bb47 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.cc +++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -396,11 +396,8 @@ // ------ Start of CSSMathExpressionOperation member functions ------ -// TODO(pjh0718): Integrate CSSMathExpressionBinary/VariadicOperation to -// CSSMathExpressionOperation. - // static -CSSMathExpressionNode* CSSMathExpressionBinaryOperation::Create( +CSSMathExpressionNode* CSSMathExpressionOperation::CreateArithmeticOperation( const CSSMathExpressionNode* left_side, const CSSMathExpressionNode* right_side, CSSMathOperator op) { @@ -412,12 +409,12 @@ if (new_category == kCalcOther) return nullptr; - return MakeGarbageCollected<CSSMathExpressionBinaryOperation>( - left_side, right_side, op, new_category); + return MakeGarbageCollected<CSSMathExpressionOperation>(left_side, right_side, + op, new_category); } // static -CSSMathExpressionVariadicOperation* CSSMathExpressionVariadicOperation::Create( +CSSMathExpressionNode* CSSMathExpressionOperation::CreateComparisonFunction( Operands&& operands, CSSMathOperator op) { DCHECK(op == CSSMathOperator::kMin || op == CSSMathOperator::kMax); @@ -434,17 +431,18 @@ if (category == kCalcOther) return nullptr; } - return MakeGarbageCollected<CSSMathExpressionVariadicOperation>( + return MakeGarbageCollected<CSSMathExpressionOperation>( category, std::move(operands), op); } // static -CSSMathExpressionNode* CSSMathExpressionBinaryOperation::CreateSimplified( +CSSMathExpressionNode* +CSSMathExpressionOperation::CreateArithmeticOperationSimplified( const CSSMathExpressionNode* left_side, const CSSMathExpressionNode* right_side, CSSMathOperator op) { if (left_side->IsMathFunction() || right_side->IsMathFunction()) - return Create(left_side, right_side, op); + return CreateArithmeticOperation(left_side, right_side, op); CalculationCategory left_category = left_side->Category(); CalculationCategory right_category = right_side->Category(); @@ -454,7 +452,7 @@ // Simplify numbers. if (left_category == kCalcNumber && right_category == kCalcNumber) { return CSSMathExpressionNumericLiteral::Create( - EvaluateOperator(left_side->DoubleValue(), right_side->DoubleValue(), + EvaluateOperator({left_side->DoubleValue(), right_side->DoubleValue()}, op), CSSPrimitiveValue::UnitType::kNumber); } @@ -467,8 +465,8 @@ CSSPrimitiveValue::UnitType right_type = right_side->ResolvedUnitType(); if (left_type == right_type) { return CSSMathExpressionNumericLiteral::Create( - EvaluateOperator(left_side->DoubleValue(), - right_side->DoubleValue(), op), + EvaluateOperator( + {left_side->DoubleValue(), right_side->DoubleValue()}, op), left_type); } CSSPrimitiveValue::UnitCategory left_unit_category = @@ -489,7 +487,8 @@ CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor( right_type)); return CSSMathExpressionNumericLiteral::Create( - EvaluateOperator(left_value, right_value, op), canonical_type); + EvaluateOperator({left_value, right_value}, op), + canonical_type); } } } @@ -500,7 +499,7 @@ const CSSMathExpressionNode* number_side = GetNumberSide(left_side, right_side); if (!number_side) - return Create(left_side, right_side, op); + return CreateArithmeticOperation(left_side, right_side, op); if (number_side == left_side && op == CSSMathOperator::kDivide) return nullptr; const CSSMathExpressionNode* other_side = @@ -518,14 +517,15 @@ CSSPrimitiveValue::UnitType other_type = other_side->ResolvedUnitType(); if (HasDoubleValue(other_type)) { return CSSMathExpressionNumericLiteral::Create( - EvaluateOperator(other_side->DoubleValue(), number, op), other_type); + EvaluateOperator({other_side->DoubleValue(), number}, op), + other_type); } } - return Create(left_side, right_side, op); + return CreateArithmeticOperation(left_side, right_side, op); } -CSSMathExpressionBinaryOperation::CSSMathExpressionBinaryOperation( +CSSMathExpressionOperation::CSSMathExpressionOperation( const CSSMathExpressionNode* left_side, const CSSMathExpressionNode* right_side, CSSMathOperator op, @@ -533,40 +533,46 @@ : CSSMathExpressionNode( category, left_side->HasComparisons() || right_side->HasComparisons()), - left_side_(left_side), - right_side_(right_side), + operands_({left_side, right_side}), operator_(op) {} -CSSMathExpressionVariadicOperation::CSSMathExpressionVariadicOperation( +static bool AnyOperandHasComparisons( + CSSMathExpressionOperation::Operands& operands) { + for (const auto& operand : operands) { + if (operand->HasComparisons()) + return true; + } + return false; +} + +CSSMathExpressionOperation::CSSMathExpressionOperation( CalculationCategory category, Operands&& operands, CSSMathOperator op) - : CSSMathExpressionNode(category, true /* has_comparisons */), + : CSSMathExpressionNode( + category, + IsComparison(op) || AnyOperandHasComparisons(operands)), operands_(std::move(operands)), operator_(op) {} -bool CSSMathExpressionBinaryOperation::IsZero() const { - return !DoubleValue(); -} - -bool CSSMathExpressionVariadicOperation::IsZero() const { +bool CSSMathExpressionOperation::IsZero() const { absl::optional<double> maybe_value = ComputeValueInCanonicalUnit(); return maybe_value && !*maybe_value; } -absl::optional<PixelsAndPercent> -CSSMathExpressionBinaryOperation::ToPixelsAndPercent( +absl::optional<PixelsAndPercent> CSSMathExpressionOperation::ToPixelsAndPercent( const CSSToLengthConversionData& conversion_data) const { absl::optional<PixelsAndPercent> result; switch (operator_) { case CSSMathOperator::kAdd: case CSSMathOperator::kSubtract: { - result = left_side_->ToPixelsAndPercent(conversion_data); + DCHECK_EQ(operands_.size(), 2u); + result = operands_[0]->ToPixelsAndPercent(conversion_data); if (!result) return absl::nullopt; absl::optional<PixelsAndPercent> other_side = - right_side_->ToPixelsAndPercent(conversion_data); + operands_[1]->ToPixelsAndPercent(conversion_data); if (!other_side) return absl::nullopt; if (operator_ == CSSMathOperator::kAdd) { @@ -580,10 +586,11 @@ } case CSSMathOperator::kMultiply: case CSSMathOperator::kDivide: { + DCHECK_EQ(operands_.size(), 2u); const CSSMathExpressionNode* number_side = - GetNumberSide(left_side_, right_side_); + GetNumberSide(operands_[0], operands_[1]); const CSSMathExpressionNode* other_side = - left_side_ == number_side ? right_side_ : left_side_; + operands_[0] == number_side ? operands_[1] : operands_[0]; result = other_side->ToPixelsAndPercent(conversion_data); if (!result) return absl::nullopt; @@ -594,90 +601,85 @@ result->percent *= number; break; } - default: + case CSSMathOperator::kMin: + case CSSMathOperator::kMax: + return absl::nullopt; + case CSSMathOperator::kInvalid: NOTREACHED(); } return result; } -absl::optional<PixelsAndPercent> -CSSMathExpressionVariadicOperation::ToPixelsAndPercent( - const CSSToLengthConversionData& conversion_data) const { - return absl::nullopt; -} - scoped_refptr<const CalculationExpressionNode> -CSSMathExpressionBinaryOperation::ToCalculationExpression( +CSSMathExpressionOperation::ToCalculationExpression( const CSSToLengthConversionData& conversion_data) const { switch (operator_) { case CSSMathOperator::kAdd: + DCHECK_EQ(operands_.size(), 2u); return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {left_side_->ToCalculationExpression(conversion_data), - right_side_->ToCalculationExpression(conversion_data)}), + {operands_[0]->ToCalculationExpression(conversion_data), + operands_[1]->ToCalculationExpression(conversion_data)}), CalculationOperator::kAdd); case CSSMathOperator::kSubtract: + DCHECK_EQ(operands_.size(), 2u); return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {left_side_->ToCalculationExpression(conversion_data), - right_side_->ToCalculationExpression(conversion_data)}), + {operands_[0]->ToCalculationExpression(conversion_data), + operands_[1]->ToCalculationExpression(conversion_data)}), CalculationOperator::kSubtract); case CSSMathOperator::kMultiply: - DCHECK_NE((left_side_->Category() == kCalcNumber), - (right_side_->Category() == kCalcNumber)); - if (left_side_->Category() == kCalcNumber) { + DCHECK_EQ(operands_.size(), 2u); + DCHECK_NE((operands_[0]->Category() == kCalcNumber), + (operands_[1]->Category() == kCalcNumber)); + if (operands_[0]->Category() == kCalcNumber) { return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {right_side_->ToCalculationExpression(conversion_data), + {operands_[1]->ToCalculationExpression(conversion_data), base::MakeRefCounted<CalculationExpressionNumberNode>( - left_side_->DoubleValue())}), + operands_[0]->DoubleValue())}), CalculationOperator::kMultiply); } return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {left_side_->ToCalculationExpression(conversion_data), + {operands_[0]->ToCalculationExpression(conversion_data), base::MakeRefCounted<CalculationExpressionNumberNode>( - right_side_->DoubleValue())}), + operands_[1]->DoubleValue())}), CalculationOperator::kMultiply); case CSSMathOperator::kDivide: - DCHECK_EQ(right_side_->Category(), kCalcNumber); + DCHECK_EQ(operands_.size(), 2u); + DCHECK_EQ(operands_[1]->Category(), kCalcNumber); return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {left_side_->ToCalculationExpression(conversion_data), + {operands_[0]->ToCalculationExpression(conversion_data), base::MakeRefCounted<CalculationExpressionNumberNode>( - 1.0 / right_side_->DoubleValue())}), + 1.0 / operands_[1]->DoubleValue())}), CalculationOperator::kMultiply); - default: + case CSSMathOperator::kMin: + case CSSMathOperator::kMax: { + Vector<scoped_refptr<const CalculationExpressionNode>> operands; + operands.ReserveCapacity(operands_.size()); + for (const auto& operand : operands_) + operands.push_back(operand->ToCalculationExpression(conversion_data)); + auto expression_operator = operator_ == CSSMathOperator::kMin + ? CalculationOperator::kMin + : CalculationOperator::kMax; + return CalculationExpressionOperationNode::CreateSimplified( + std::move(operands), expression_operator); + } + case CSSMathOperator::kInvalid: NOTREACHED(); return nullptr; } } -scoped_refptr<const CalculationExpressionNode> -CSSMathExpressionVariadicOperation::ToCalculationExpression( - const CSSToLengthConversionData& data) const { - Vector<scoped_refptr<const CalculationExpressionNode>> operands; - operands.ReserveCapacity(operands_.size()); - for (const auto& operand : operands_) - operands.push_back(operand->ToCalculationExpression(data)); - auto expression_operator = operator_ == CSSMathOperator::kMin - ? CalculationOperator::kMin - : CalculationOperator::kMax; - return CalculationExpressionOperationNode::CreateSimplified( - std::move(operands), expression_operator); -} - -double CSSMathExpressionBinaryOperation::DoubleValue() const { +double CSSMathExpressionOperation::DoubleValue() const { DCHECK(HasDoubleValue(ResolvedUnitType())) << CustomCSSText(); - return Evaluate(left_side_->DoubleValue(), right_side_->DoubleValue()); -} - -double CSSMathExpressionVariadicOperation::DoubleValue() const { - DCHECK(HasDoubleValue(ResolvedUnitType())); - double result = operands_.front()->DoubleValue(); - for (const auto& operand : SecondToLastOperands()) - result = EvaluateBinary(result, operand->DoubleValue()); - return result; + Vector<double> double_values; + double_values.ReserveCapacity(operands_.size()); + for (auto& operand : operands_) + double_values.push_back(operand->DoubleValue()); + return Evaluate(double_values); } static bool HasCanonicalUnit(CalculationCategory category) { @@ -686,134 +688,92 @@ category == kCalcTime || category == kCalcFrequency; } -absl::optional<double> -CSSMathExpressionBinaryOperation::ComputeValueInCanonicalUnit() const { +absl::optional<double> CSSMathExpressionOperation::ComputeValueInCanonicalUnit() + const { if (!HasCanonicalUnit(category_)) return absl::nullopt; - absl::optional<double> left_value = left_side_->ComputeValueInCanonicalUnit(); - if (!left_value) - return absl::nullopt; - - absl::optional<double> right_value = - right_side_->ComputeValueInCanonicalUnit(); - if (!right_value) - return absl::nullopt; - - return Evaluate(*left_value, *right_value); -} - -absl::optional<double> -CSSMathExpressionVariadicOperation::ComputeValueInCanonicalUnit() const { - absl::optional<double> first_value = - operands_.front()->ComputeValueInCanonicalUnit(); - if (!first_value) - return absl::nullopt; - - double result = *first_value; - for (const auto& operand : SecondToLastOperands()) { + Vector<double> double_values; + double_values.ReserveCapacity(operands_.size()); + for (auto& operand : operands_) { absl::optional<double> maybe_value = operand->ComputeValueInCanonicalUnit(); if (!maybe_value) return absl::nullopt; - result = EvaluateBinary(result, *maybe_value); + double_values.push_back(*maybe_value); } - return result; + return Evaluate(double_values); } -double CSSMathExpressionBinaryOperation::ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const { - DCHECK_EQ(kCalcLength, Category()); - double left_value; - if (left_side_->Category() == kCalcLength) { - left_value = left_side_->ComputeLengthPx(conversion_data); - } else { - DCHECK_EQ(kCalcNumber, left_side_->Category()); - left_value = left_side_->DoubleValue(); - } - double right_value; - if (right_side_->Category() == kCalcLength) { - right_value = right_side_->ComputeLengthPx(conversion_data); - } else { - DCHECK_EQ(kCalcNumber, right_side_->Category()); - right_value = right_side_->DoubleValue(); - } - return Evaluate(left_value, right_value); -} - -double CSSMathExpressionVariadicOperation::ComputeLengthPx( +double CSSMathExpressionOperation::ComputeLengthPx( const CSSToLengthConversionData& data) const { DCHECK_EQ(kCalcLength, Category()); - double result = operands_.front()->ComputeLengthPx(data); - for (const auto& operand : SecondToLastOperands()) - result = EvaluateBinary(result, operand->ComputeLengthPx(data)); - return result; + Vector<double> double_values; + double_values.ReserveCapacity(operands_.size()); + for (const auto& operand : operands_) { + if (operand->Category() == kCalcLength) { + double_values.push_back(operand->ComputeLengthPx(data)); + } else { + DCHECK_EQ(operand->Category(), kCalcNumber); + double_values.push_back(operand->DoubleValue()); + } + } + return Evaluate(double_values); } -bool CSSMathExpressionBinaryOperation::AccumulateLengthArray( +bool CSSMathExpressionOperation::AccumulateLengthArray( CSSLengthArray& length_array, double multiplier) const { switch (operator_) { case CSSMathOperator::kAdd: - if (!left_side_->AccumulateLengthArray(length_array, multiplier)) + DCHECK_EQ(operands_.size(), 2u); + if (!operands_[0]->AccumulateLengthArray(length_array, multiplier)) return false; - if (!right_side_->AccumulateLengthArray(length_array, multiplier)) + if (!operands_[1]->AccumulateLengthArray(length_array, multiplier)) return false; return true; case CSSMathOperator::kSubtract: - if (!left_side_->AccumulateLengthArray(length_array, multiplier)) + DCHECK_EQ(operands_.size(), 2u); + if (!operands_[0]->AccumulateLengthArray(length_array, multiplier)) return false; - if (!right_side_->AccumulateLengthArray(length_array, -multiplier)) + if (!operands_[1]->AccumulateLengthArray(length_array, -multiplier)) return false; return true; case CSSMathOperator::kMultiply: - DCHECK_NE((left_side_->Category() == kCalcNumber), - (right_side_->Category() == kCalcNumber)); - if (left_side_->Category() == kCalcNumber) { - return right_side_->AccumulateLengthArray( - length_array, multiplier * left_side_->DoubleValue()); + DCHECK_EQ(operands_.size(), 2u); + DCHECK_NE((operands_[0]->Category() == kCalcNumber), + (operands_[1]->Category() == kCalcNumber)); + if (operands_[0]->Category() == kCalcNumber) { + return operands_[1]->AccumulateLengthArray( + length_array, multiplier * operands_[0]->DoubleValue()); } else { - return left_side_->AccumulateLengthArray( - length_array, multiplier * right_side_->DoubleValue()); + return operands_[0]->AccumulateLengthArray( + length_array, multiplier * operands_[1]->DoubleValue()); } case CSSMathOperator::kDivide: - DCHECK_EQ(right_side_->Category(), kCalcNumber); - return left_side_->AccumulateLengthArray( - length_array, multiplier / right_side_->DoubleValue()); - default: + DCHECK_EQ(operands_.size(), 2u); + DCHECK_EQ(operands_[1]->Category(), kCalcNumber); + return operands_[0]->AccumulateLengthArray( + length_array, multiplier / operands_[1]->DoubleValue()); + case CSSMathOperator::kMin: + case CSSMathOperator::kMax: + // When comparison functions are involved, we can't resolve the expression + // into a length array. + return false; + case CSSMathOperator::kInvalid: NOTREACHED(); return false; } } -bool CSSMathExpressionVariadicOperation::AccumulateLengthArray(CSSLengthArray&, - double) const { - // When comparison function are involved, we can't resolve the expression into - // a length array. - // TODO(crbug.com/991672): We need a more general length interpolation - // implementation that doesn't rely on CSSLengthArray. - return false; -} - -void CSSMathExpressionBinaryOperation::AccumulateLengthUnitTypes( - CSSPrimitiveValue::LengthTypeFlags& types) const { - left_side_->AccumulateLengthUnitTypes(types); - right_side_->AccumulateLengthUnitTypes(types); -} - -void CSSMathExpressionVariadicOperation::AccumulateLengthUnitTypes( +void CSSMathExpressionOperation::AccumulateLengthUnitTypes( CSSPrimitiveValue::LengthTypeFlags& types) const { for (const auto& operand : operands_) operand->AccumulateLengthUnitTypes(types); } -bool CSSMathExpressionBinaryOperation::IsComputationallyIndependent() const { +bool CSSMathExpressionOperation::IsComputationallyIndependent() const { if (Category() != kCalcLength && Category() != kCalcPercentLength) return true; - return left_side_->IsComputationallyIndependent() && - right_side_->IsComputationallyIndependent(); -} - -bool CSSMathExpressionVariadicOperation::IsComputationallyIndependent() const { for (const auto& operand : operands_) { if (!operand->IsComputationallyIndependent()) return false; @@ -821,55 +781,74 @@ return true; } -String CSSMathExpressionBinaryOperation::CustomCSSText() const { - StringBuilder result; +String CSSMathExpressionOperation::CustomCSSText() const { + switch (operator_) { + case CSSMathOperator::kAdd: + case CSSMathOperator::kSubtract: + case CSSMathOperator::kMultiply: + case CSSMathOperator::kDivide: { + DCHECK_EQ(operands_.size(), 2u); + StringBuilder result; - const bool left_side_needs_parentheses = - left_side_->IsBinaryOperation() && operator_ != CSSMathOperator::kAdd; - if (left_side_needs_parentheses) - result.Append('('); - result.Append(left_side_->CustomCSSText()); - if (left_side_needs_parentheses) - result.Append(')'); + const bool left_side_needs_parentheses = + (operands_[0]->IsOperation() && !operands_[0]->IsMathFunction()) && + operator_ != CSSMathOperator::kAdd; + if (left_side_needs_parentheses) + result.Append('('); + result.Append(operands_[0]->CustomCSSText()); + if (left_side_needs_parentheses) + result.Append(')'); - result.Append(' '); - result.Append(ToString(operator_)); - result.Append(' '); + result.Append(' '); + result.Append(ToString(operator_)); + result.Append(' '); - const bool right_side_needs_parentheses = - right_side_->IsBinaryOperation() && operator_ != CSSMathOperator::kAdd; - if (right_side_needs_parentheses) - result.Append('('); - result.Append(right_side_->CustomCSSText()); - if (right_side_needs_parentheses) - result.Append(')'); + const bool right_side_needs_parentheses = + (operands_[1]->IsOperation() && !operands_[1]->IsMathFunction()) && + operator_ != CSSMathOperator::kAdd; + if (right_side_needs_parentheses) + result.Append('('); + result.Append(operands_[1]->CustomCSSText()); + if (right_side_needs_parentheses) + result.Append(')'); - return result.ReleaseString(); -} + return result.ReleaseString(); + } + case CSSMathOperator::kMin: + case CSSMathOperator::kMax: { + // TODO(pjh0718): Change clamp representation from max(min()) to single + // clamp() node and remove CSSTextAsClamp(). + if (is_clamp_) + return CSSTextAsClamp(); -String CSSMathExpressionVariadicOperation::CustomCSSText() const { - if (is_clamp_) - return CSSTextAsClamp(); + StringBuilder result; + result.Append(ToString(operator_)); + result.Append('('); + result.Append(operands_.front()->CustomCSSText()); + for (const auto& operand : SecondToLastOperands()) { + result.Append(", "); + result.Append(operand->CustomCSSText()); + } + result.Append(')'); - StringBuilder result; - result.Append(ToString(operator_)); - result.Append('('); - result.Append(operands_.front()->CustomCSSText()); - for (const auto& operand : SecondToLastOperands()) { - result.Append(", "); - result.Append(operand->CustomCSSText()); + return result.ReleaseString(); + } + case CSSMathOperator::kInvalid: + NOTREACHED(); + return String(); } - result.Append(')'); - - return result.ReleaseString(); } -String CSSMathExpressionVariadicOperation::CSSTextAsClamp() const { +String CSSMathExpressionOperation::CSSTextAsClamp() const { DCHECK(is_clamp_); DCHECK_EQ(CSSMathOperator::kMax, operator_); DCHECK_EQ(2u, operands_.size()); - DCHECK(operands_[1]->IsVariadicOperation()); - const auto& nested = To<CSSMathExpressionVariadicOperation>(*operands_[1]); + // TODO(pjh0718): Actually we should IsMinOrMax() check here, + // but currently it is not a virtual function and CSSTextAsClamp() will be + // removed anyway during changing clamp representation from max(min()) to + // single clamp() node. + DCHECK(operands_[1]->IsMathFunction()); + const auto& nested = To<CSSMathExpressionOperation>(*operands_[1]); DCHECK(!nested.is_clamp_); DCHECK_EQ(CSSMathOperator::kMin, nested.operator_); DCHECK_EQ(2u, nested.operands_.size()); @@ -885,24 +864,12 @@ return result.ReleaseString(); } -bool CSSMathExpressionBinaryOperation::operator==( +bool CSSMathExpressionOperation::operator==( const CSSMathExpressionNode& exp) const { - if (!exp.IsBinaryOperation()) + if (!exp.IsOperation()) return false; - const CSSMathExpressionBinaryOperation& other = - To<CSSMathExpressionBinaryOperation>(exp); - return base::ValuesEquivalent(left_side_, other.left_side_) && - base::ValuesEquivalent(right_side_, other.right_side_) && - operator_ == other.operator_; -} - -bool CSSMathExpressionVariadicOperation::operator==( - const CSSMathExpressionNode& exp) const { - if (!exp.IsVariadicOperation()) - return false; - const CSSMathExpressionVariadicOperation& other = - To<CSSMathExpressionVariadicOperation>(exp); + const CSSMathExpressionOperation& other = To<CSSMathExpressionOperation>(exp); if (operator_ != other.operator_) return false; if (operands_.size() != other.operands_.size()) @@ -914,21 +881,39 @@ return true; } -CSSPrimitiveValue::UnitType CSSMathExpressionBinaryOperation::ResolvedUnitType() +CSSPrimitiveValue::UnitType CSSMathExpressionOperation::ResolvedUnitType() const { + // TODO(pjh0718): Merge this if statement into switch-case below. + if (IsMinOrMax()) { + if (category_ == kCalcNumber) + return CSSPrimitiveValue::UnitType::kNumber; + + CSSPrimitiveValue::UnitType result = operands_.front()->ResolvedUnitType(); + if (result == CSSPrimitiveValue::UnitType::kUnknown) + return CSSPrimitiveValue::UnitType::kUnknown; + for (const auto& operand : SecondToLastOperands()) { + CSSPrimitiveValue::UnitType next = operand->ResolvedUnitType(); + if (next == CSSPrimitiveValue::UnitType::kUnknown || next != result) + return CSSPrimitiveValue::UnitType::kUnknown; + } + return result; + } + + DCHECK_EQ(operands_.size(), 2u); + switch (category_) { case kCalcNumber: - DCHECK_EQ(left_side_->Category(), kCalcNumber); - DCHECK_EQ(right_side_->Category(), kCalcNumber); + DCHECK_EQ(operands_[0]->Category(), kCalcNumber); + DCHECK_EQ(operands_[1]->Category(), kCalcNumber); return CSSPrimitiveValue::UnitType::kNumber; case kCalcLength: case kCalcPercent: { - if (left_side_->Category() == kCalcNumber) - return right_side_->ResolvedUnitType(); - if (right_side_->Category() == kCalcNumber) - return left_side_->ResolvedUnitType(); - CSSPrimitiveValue::UnitType left_type = left_side_->ResolvedUnitType(); - if (left_type == right_side_->ResolvedUnitType()) + if (operands_[0]->Category() == kCalcNumber) + return operands_[1]->ResolvedUnitType(); + if (operands_[1]->Category() == kCalcNumber) + return operands_[0]->ResolvedUnitType(); + CSSPrimitiveValue::UnitType left_type = operands_[0]->ResolvedUnitType(); + if (left_type == operands_[1]->ResolvedUnitType()) return left_type; return CSSPrimitiveValue::UnitType::kUnknown; } @@ -942,39 +927,18 @@ case kCalcOther: return CSSPrimitiveValue::UnitType::kUnknown; } + NOTREACHED(); return CSSPrimitiveValue::UnitType::kUnknown; } -CSSPrimitiveValue::UnitType -CSSMathExpressionVariadicOperation::ResolvedUnitType() const { - if (Category() == kCalcNumber) - return CSSPrimitiveValue::UnitType::kNumber; - - CSSPrimitiveValue::UnitType result = operands_.front()->ResolvedUnitType(); - if (result == CSSPrimitiveValue::UnitType::kUnknown) - return CSSPrimitiveValue::UnitType::kUnknown; - for (const auto& operand : SecondToLastOperands()) { - CSSPrimitiveValue::UnitType next = operand->ResolvedUnitType(); - if (next == CSSPrimitiveValue::UnitType::kUnknown || next != result) - return CSSPrimitiveValue::UnitType::kUnknown; - } - return result; -} - -void CSSMathExpressionBinaryOperation::Trace(Visitor* visitor) const { - visitor->Trace(left_side_); - visitor->Trace(right_side_); - CSSMathExpressionNode::Trace(visitor); -} - -void CSSMathExpressionVariadicOperation::Trace(Visitor* visitor) const { +void CSSMathExpressionOperation::Trace(Visitor* visitor) const { visitor->Trace(operands_); CSSMathExpressionNode::Trace(visitor); } // static -const CSSMathExpressionNode* CSSMathExpressionBinaryOperation::GetNumberSide( +const CSSMathExpressionNode* CSSMathExpressionOperation::GetNumberSide( const CSSMathExpressionNode* left_side, const CSSMathExpressionNode* right_side) { if (left_side->Category() == kCalcNumber) @@ -985,60 +949,59 @@ } // static -double CSSMathExpressionBinaryOperation::EvaluateOperator(double left_value, - double right_value, - CSSMathOperator op) { +double CSSMathExpressionOperation::EvaluateOperator( + const Vector<double>& operands, + CSSMathOperator op) { // Design doc for infinity and NaN: https://bit.ly/349gXjq switch (op) { case CSSMathOperator::kAdd: + DCHECK_EQ(operands.size(), 2u); if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) - return left_value + right_value; - return ClampTo<double>(left_value + right_value); + return operands[0] + operands[1]; + return ClampTo<double>(operands[0] + operands[1]); case CSSMathOperator::kSubtract: + DCHECK_EQ(operands.size(), 2u); if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) - return left_value - right_value; - return ClampTo<double>(left_value - right_value); + return operands[0] - operands[1]; + return ClampTo<double>(operands[0] - operands[1]); case CSSMathOperator::kMultiply: + DCHECK_EQ(operands.size(), 2u); if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) - return left_value * right_value; - return ClampTo<double>(left_value * right_value); + return operands[0] * operands[1]; + return ClampTo<double>(operands[0] * operands[1]); case CSSMathOperator::kDivide: + DCHECK(operands.size() == 1u || operands.size() == 2u); if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) - return left_value / right_value; - if (right_value) - return ClampTo<double>(left_value / right_value); + return operands[0] / operands[1]; + if (operands[1]) + return ClampTo<double>(operands[0] / operands[1]); return std::numeric_limits<double>::quiet_NaN(); - default: + case CSSMathOperator::kMin: { + if (operands.IsEmpty()) + return std::numeric_limits<double>::quiet_NaN(); + double minimum = operands[0]; + for (auto operand : operands) + minimum = std::min(minimum, operand); + return minimum; + } + case CSSMathOperator::kMax: { + if (operands.IsEmpty()) + return std::numeric_limits<double>::quiet_NaN(); + double maximum = operands[0]; + for (auto operand : operands) + maximum = std::max(maximum, operand); + return maximum; + } + case CSSMathOperator::kInvalid: NOTREACHED(); break; } return 0; } -double CSSMathExpressionVariadicOperation::EvaluateBinary(double lhs, - double rhs) const { - if (std::isnan(lhs) || std::isnan(rhs)) - return std::numeric_limits<double>::quiet_NaN(); - - switch (operator_) { - case CSSMathOperator::kMin: - return std::min(lhs, rhs); - case CSSMathOperator::kMax: - return std::max(lhs, rhs); - default: - NOTREACHED(); - return 0; - } -} - #if DCHECK_IS_ON() -bool CSSMathExpressionBinaryOperation::InvolvesPercentageComparisons() const { - return left_side_->InvolvesPercentageComparisons() || - right_side_->InvolvesPercentageComparisons(); -} - -bool CSSMathExpressionVariadicOperation::InvolvesPercentageComparisons() const { - if (Category() == kCalcPercent && operands_.size() > 1u) +bool CSSMathExpressionOperation::InvolvesPercentageComparisons() const { + if (IsMinOrMax() && Category() == kCalcPercent && operands_.size() > 1u) return true; for (const auto& operand : operands_) { if (operand->InvolvesPercentageComparisons()) @@ -1056,6 +1019,27 @@ public: CSSMathExpressionNodeParser() {} + CSSMathExpressionNode* ParseMathFunction(CSSValueID function_id, + const CSSParserTokenRange& tokens, + int depth) { + switch (function_id) { + case CSSValueID::kCalc: + case CSSValueID::kWebkitCalc: + return ParseCalc(tokens); + case CSSValueID::kMin: + return ParseMinOrMax(tokens, CSSMathOperator::kMin, depth); + case CSSValueID::kMax: + return ParseMinOrMax(tokens, CSSMathOperator::kMax, depth); + case CSSValueID::kClamp: + return ParseClamp(tokens, depth); + // TODO(crbug.com/1284199): Support other math functions. + default: + return nullptr; + } + } + + // TODO(pjh0718) : Integrate ParseCalc and ParseMinOrMaxOrClamp to + // ParseMathFunction. CSSMathExpressionNode* ParseCalc(CSSParserTokenRange tokens) { tokens.ConsumeWhitespace(); CSSMathExpressionNode* result = ParseValueExpression(tokens, 0); @@ -1071,7 +1055,7 @@ if (tokens.AtEnd()) return nullptr; - CSSMathExpressionVariadicOperation::Operands operands; + CSSMathExpressionOperation::Operands operands; bool last_token_is_comma = false; while (!tokens.AtEnd()) { tokens.ConsumeWhitespace(); @@ -1090,7 +1074,8 @@ if (operands.IsEmpty() || !tokens.AtEnd() || last_token_is_comma) return nullptr; - return CSSMathExpressionVariadicOperation::Create(std::move(operands), op); + return CSSMathExpressionOperation::CreateComparisonFunction( + std::move(operands), op); } CSSMathExpressionNode* ParseClamp(CSSParserTokenRange tokens, int depth) { @@ -1120,12 +1105,12 @@ // clamp(MIN, VAL, MAX) is identical to max(MIN, min(VAL, MAX)) - auto* nested = CSSMathExpressionVariadicOperation::Create( + auto* nested = CSSMathExpressionOperation::CreateComparisonFunction( {val_operand, max_operand}, CSSMathOperator::kMin); if (!nested) return nullptr; - auto* result = CSSMathExpressionVariadicOperation::Create( + auto* result = CSSMathExpressionOperation::CreateComparisonFunction( {min_operand, nested}, CSSMathOperator::kMax); if (!result) return nullptr; @@ -1225,7 +1210,7 @@ if (!rhs) return nullptr; - result = CSSMathExpressionBinaryOperation::CreateSimplified( + result = CSSMathExpressionOperation::CreateArithmeticOperationSimplified( result, rhs, math_operator); if (!result) @@ -1263,7 +1248,7 @@ if (!rhs) return nullptr; - result = CSSMathExpressionBinaryOperation::CreateSimplified( + result = CSSMathExpressionOperation::CreateArithmeticOperationSimplified( result, rhs, math_operator); if (!result) @@ -1331,7 +1316,7 @@ pixels = -pixels; op = CSSMathOperator::kSubtract; } - return CSSMathExpressionBinaryOperation::Create( + return CSSMathExpressionOperation::CreateArithmeticOperation( CSSMathExpressionNumericLiteral::Create(CSSNumericLiteralValue::Create( percent, CSSPrimitiveValue::UnitType::kPercentage)), CSSMathExpressionNumericLiteral::Create(CSSNumericLiteralValue::Create( @@ -1361,7 +1346,7 @@ auto& number_node = children[0]->IsNumber() ? children[0] : children[1]; const auto& number = To<CalculationExpressionNumberNode>(*number_node); double number_value = number.Value(); - return CSSMathExpressionBinaryOperation::Create( + return CSSMathExpressionOperation::CreateArithmeticOperation( Create(*pixels_and_percent_node), CSSMathExpressionNumericLiteral::Create( CSSNumericLiteralValue::Create( @@ -1376,19 +1361,20 @@ CSSMathOperator op = (calc_op == CalculationOperator::kAdd) ? CSSMathOperator::kAdd : CSSMathOperator::kSubtract; - return CSSMathExpressionBinaryOperation::Create(lhs, rhs, op); + return CSSMathExpressionOperation::CreateArithmeticOperation(lhs, rhs, + op); } case CalculationOperator::kMin: case CalculationOperator::kMax: { DCHECK(children.size()); - CSSMathExpressionVariadicOperation::Operands operands; + CSSMathExpressionOperation::Operands operands; for (const auto& child : children) operands.push_back(Create(*child)); CSSMathOperator op = (calc_op == CalculationOperator::kMin) ? CSSMathOperator::kMin : CSSMathOperator::kMax; - return CSSMathExpressionVariadicOperation::Create(std::move(operands), - op); + return CSSMathExpressionOperation::CreateComparisonFunction( + std::move(operands), op); } default: NOTREACHED(); @@ -1404,24 +1390,15 @@ } // static -CSSMathExpressionNode* CSSMathExpressionNode::ParseMin( +CSSMathExpressionNode* CSSMathExpressionNode::ParseMathFunction( + CSSValueID function_id, const CSSParserTokenRange& tokens) { CSSMathExpressionNodeParser parser; - return parser.ParseMinOrMax(tokens, CSSMathOperator::kMin, 0); -} + CSSMathExpressionNode* result = + parser.ParseMathFunction(function_id, tokens, 0); -// static -CSSMathExpressionNode* CSSMathExpressionNode::ParseMax( - const CSSParserTokenRange& tokens) { - CSSMathExpressionNodeParser parser; - return parser.ParseMinOrMax(tokens, CSSMathOperator::kMax, 0); -} - -// static -CSSMathExpressionNode* CSSMathExpressionNode::ParseClamp( - const CSSParserTokenRange& tokens) { - CSSMathExpressionNodeParser parser; - return parser.ParseClamp(tokens, 0); + // TODO(pjh0718): Do simplificiation for result above. + return result; } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.h b/third_party/blink/renderer/core/css/css_math_expression_node.h index c02c4ca..f51deaba 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.h +++ b/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -69,17 +69,18 @@ static CSSMathExpressionNode* Create(const CalculationExpressionNode& node); static CSSMathExpressionNode* ParseCalc(const CSSParserTokenRange& tokens); - static CSSMathExpressionNode* ParseMin(const CSSParserTokenRange& tokens); - static CSSMathExpressionNode* ParseMax(const CSSParserTokenRange& tokens); - static CSSMathExpressionNode* ParseClamp(const CSSParserTokenRange& tokens); + static CSSMathExpressionNode* ParseMathFunction( + CSSValueID function_id, + const CSSParserTokenRange& tokens); virtual bool IsNumericLiteral() const { return false; } - virtual bool IsBinaryOperation() const { return false; } - virtual bool IsVariadicOperation() const { return false; } + virtual bool IsOperation() const { return false; } - bool IsMathFunction() const { - return !IsNumericLiteral() && !IsBinaryOperation(); - } + virtual bool IsMathFunction() const { return false; } + + // TODO(pjh0718): Change clamp representation from max(min()) to single + // clamp() node and remove this clamp specific method. + virtual void SetIsClamp() = 0; virtual bool IsZero() const = 0; @@ -172,6 +173,10 @@ bool IsNumericLiteral() const final { return true; } + // TODO(pjh0718): Change clamp representation from max(min()) to single + // clamp() node and remove this clamp specific method. + void SetIsClamp() final {} + bool IsZero() const final; String CustomCSSText() const final; scoped_refptr<const CalculationExpressionNode> ToCalculationExpression( @@ -206,29 +211,49 @@ } }; -class CORE_EXPORT CSSMathExpressionBinaryOperation final +class CORE_EXPORT CSSMathExpressionOperation final : public CSSMathExpressionNode { public: - static CSSMathExpressionNode* Create(const CSSMathExpressionNode* left_side, - const CSSMathExpressionNode* right_side, - CSSMathOperator op); - static CSSMathExpressionNode* CreateSimplified( + using Operands = HeapVector<Member<const CSSMathExpressionNode>>; + + static CSSMathExpressionNode* CreateArithmeticOperation( const CSSMathExpressionNode* left_side, const CSSMathExpressionNode* right_side, CSSMathOperator op); - CSSMathExpressionBinaryOperation(const CSSMathExpressionNode* left_side, - const CSSMathExpressionNode* right_side, - CSSMathOperator op, - CalculationCategory category); + static CSSMathExpressionNode* CreateComparisonFunction(Operands&& operands, + CSSMathOperator op); - const CSSMathExpressionNode* LeftExpressionNode() const { return left_side_; } - const CSSMathExpressionNode* RightExpressionNode() const { - return right_side_; - } + static CSSMathExpressionNode* CreateArithmeticOperationSimplified( + const CSSMathExpressionNode* left_side, + const CSSMathExpressionNode* right_side, + CSSMathOperator op); + + CSSMathExpressionOperation(const CSSMathExpressionNode* left_side, + const CSSMathExpressionNode* right_side, + CSSMathOperator op, + CalculationCategory category); + + CSSMathExpressionOperation(CalculationCategory category, + Operands&& operands, + CSSMathOperator op); + + const Operands& GetOperands() const { return operands_; } CSSMathOperator OperatorType() const { return operator_; } - bool IsBinaryOperation() const final { return true; } + bool IsOperation() const final { return true; } + bool IsMinOrMax() const { + return operator_ == CSSMathOperator::kMin || + operator_ == CSSMathOperator::kMax; + } + + // TODO(crbug.com/1284199): Check other math functions too(clamp, etc). + bool IsMathFunction() const final { return IsMinOrMax(); } + + // TODO(pjh0718): Change clamp representation from max(min()) to single + // clamp() node and remove these clamp specific methods. + void SetIsClamp() final { is_clamp_ = true; } + String CSSTextAsClamp() const; bool IsZero() const final; scoped_refptr<const CalculationExpressionNode> ToCalculationExpression( @@ -258,86 +283,30 @@ const CSSMathExpressionNode* left_side, const CSSMathExpressionNode* right_side); - double Evaluate(double left_side, double right_side) const { - return EvaluateOperator(left_side, right_side, operator_); + double Evaluate(const Vector<double>& operands) const { + return EvaluateOperator(operands, operator_); } - static double EvaluateOperator(double left_value, - double right_value, + static double EvaluateOperator(const Vector<double>& operands, CSSMathOperator op); - const Member<const CSSMathExpressionNode> left_side_; - const Member<const CSSMathExpressionNode> right_side_; - const CSSMathOperator operator_; -}; - -template <> -struct DowncastTraits<CSSMathExpressionBinaryOperation> { - static bool AllowFrom(const CSSMathExpressionNode& node) { - return node.IsBinaryOperation(); - } -}; - -class CSSMathExpressionVariadicOperation final : public CSSMathExpressionNode { - public: - using Operands = HeapVector<Member<const CSSMathExpressionNode>>; - - static CSSMathExpressionVariadicOperation* Create(Operands&& operands, - CSSMathOperator op); - - CSSMathExpressionVariadicOperation(CalculationCategory category, - Operands&& operands, - CSSMathOperator op); - - const Operands& GetOperands() const { return operands_; } - CSSMathOperator OperatorType() const { return operator_; } - - bool IsVariadicOperation() const final { return true; } - - void SetIsClamp() { is_clamp_ = true; } - String CSSTextAsClamp() const; - - bool IsZero() const final; - String CustomCSSText() const final; - scoped_refptr<const CalculationExpressionNode> ToCalculationExpression( - const CSSToLengthConversionData&) const final; - absl::optional<PixelsAndPercent> ToPixelsAndPercent( - const CSSToLengthConversionData&) const final; - double DoubleValue() const final; - double ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const final; - bool AccumulateLengthArray(CSSLengthArray& length_array, - double multiplier) const final; - void AccumulateLengthUnitTypes( - CSSPrimitiveValue::LengthTypeFlags& types) const final; - absl::optional<double> ComputeValueInCanonicalUnit() const final; - bool IsComputationallyIndependent() const final; - bool operator==(const CSSMathExpressionNode& other) const final; - CSSPrimitiveValue::UnitType ResolvedUnitType() const final; - void Trace(Visitor* visitor) const final; - -#if DCHECK_IS_ON() - bool InvolvesPercentageComparisons() const final; -#endif - - private: // Helper for iterating from the 2nd to the last operands base::span<const Member<const CSSMathExpressionNode>> SecondToLastOperands() const { return base::make_span(std::next(operands_.begin()), operands_.end()); } - double EvaluateBinary(double lhs, double rhs) const; - Operands operands_; const CSSMathOperator operator_; + // TODO(pjh0718): Change clamp representation from max(min()) to single + // clamp() node and remove this clamp specific member; bool is_clamp_ = false; }; template <> -struct DowncastTraits<CSSMathExpressionVariadicOperation> { +struct DowncastTraits<CSSMathExpressionOperation> { static bool AllowFrom(const CSSMathExpressionNode& node) { - return node.IsVariadicOperation(); + return node.IsOperation(); } };
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node_test.cc b/third_party/blink/renderer/core/css/css_math_expression_node_test.cc index 3cfc3c2..b54b353 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node_test.cc +++ b/third_party/blink/renderer/core/css/css_math_expression_node_test.cc
@@ -105,7 +105,7 @@ TestAccumulatePixelsAndPercent( conversion_data, - CSSMathExpressionBinaryOperation::Create( + CSSMathExpressionOperation::CreateArithmeticOperation( CSSMathExpressionNumericLiteral::Create( CSSNumericLiteralValue::Create( 10, CSSPrimitiveValue::UnitType::kPixels)), @@ -117,7 +117,7 @@ TestAccumulatePixelsAndPercent( conversion_data, - CSSMathExpressionBinaryOperation::Create( + CSSMathExpressionOperation::CreateArithmeticOperation( CSSMathExpressionNumericLiteral::Create( CSSNumericLiteralValue::Create( 1, CSSPrimitiveValue::UnitType::kInches)), @@ -129,8 +129,8 @@ TestAccumulatePixelsAndPercent( conversion_data, - CSSMathExpressionBinaryOperation::Create( - CSSMathExpressionBinaryOperation::Create( + CSSMathExpressionOperation::CreateArithmeticOperation( + CSSMathExpressionOperation::CreateArithmeticOperation( CSSMathExpressionNumericLiteral::Create( CSSNumericLiteralValue::Create( 50, CSSPrimitiveValue::UnitType::kPixels)), @@ -138,7 +138,7 @@ CSSNumericLiteralValue::Create( 0.25, CSSPrimitiveValue::UnitType::kNumber)), CSSMathOperator::kMultiply), - CSSMathExpressionBinaryOperation::Create( + CSSMathExpressionOperation::CreateArithmeticOperation( CSSMathExpressionNumericLiteral::Create( CSSNumericLiteralValue::Create( 20, CSSPrimitiveValue::UnitType::kPixels)),
diff --git a/third_party/blink/renderer/core/css/css_math_operator.cc b/third_party/blink/renderer/core/css/css_math_operator.cc index 91bc89a..4a58fe3 100644 --- a/third_party/blink/renderer/core/css/css_math_operator.cc +++ b/third_party/blink/renderer/core/css/css_math_operator.cc
@@ -46,4 +46,8 @@ } } +bool IsComparison(CSSMathOperator op) { + return op == CSSMathOperator::kMin || op == CSSMathOperator::kMax; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_math_operator.h b/third_party/blink/renderer/core/css/css_math_operator.h index ffe5738..9117113e 100644 --- a/third_party/blink/renderer/core/css/css_math_operator.h +++ b/third_party/blink/renderer/core/css/css_math_operator.h
@@ -24,6 +24,8 @@ CSSMathOperator ParseCSSArithmeticOperator(const CSSParserToken& token); String ToString(CSSMathOperator); +bool IsComparison(CSSMathOperator); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_MATH_OPERATOR_H_
diff --git a/third_party/blink/renderer/core/css/css_primitive_value_test.cc b/third_party/blink/renderer/core/css/css_primitive_value_test.cc index 9f40d57..f73f80fd 100644 --- a/third_party/blink/renderer/core/css/css_primitive_value_test.cc +++ b/third_party/blink/renderer/core/css/css_primitive_value_test.cc
@@ -33,15 +33,16 @@ } CSSPrimitiveValue* CreateAddition(UnitValue a, UnitValue b) { - return CSSMathFunctionValue::Create(CSSMathExpressionBinaryOperation::Create( - CSSMathExpressionNumericLiteral::Create(Create(a)), - CSSMathExpressionNumericLiteral::Create(Create(b)), - CSSMathOperator::kAdd)); + return CSSMathFunctionValue::Create( + CSSMathExpressionOperation::CreateArithmeticOperation( + CSSMathExpressionNumericLiteral::Create(Create(a)), + CSSMathExpressionNumericLiteral::Create(Create(b)), + CSSMathOperator::kAdd)); } CSSPrimitiveValue* CreateNonNegativeSubtraction(UnitValue a, UnitValue b) { return CSSMathFunctionValue::Create( - CSSMathExpressionBinaryOperation::Create( + CSSMathExpressionOperation::CreateArithmeticOperation( CSSMathExpressionNumericLiteral::Create(Create(a)), CSSMathExpressionNumericLiteral::Create(Create(b)), CSSMathOperator::kSubtract),
diff --git a/third_party/blink/renderer/core/css/cssom/css_math_invert.cc b/third_party/blink/renderer/core/css/cssom/css_math_invert.cc index 4e7f257..68e2617 100644 --- a/third_party/blink/renderer/core/css/cssom/css_math_invert.cc +++ b/third_party/blink/renderer/core/css/cssom/css_math_invert.cc
@@ -47,7 +47,7 @@ CSSMathExpressionNode* right_side = value_->ToCalcExpressionNode(); if (!right_side) return nullptr; - return CSSMathExpressionBinaryOperation::Create( + return CSSMathExpressionOperation::CreateArithmeticOperation( CSSMathExpressionNumericLiteral::Create( 1, CSSPrimitiveValue::UnitType::kNumber), right_side, CSSMathOperator::kDivide);
diff --git a/third_party/blink/renderer/core/css/cssom/css_math_max.cc b/third_party/blink/renderer/core/css/cssom/css_math_max.cc index c2fa7aa7..1f16f7f 100644 --- a/third_party/blink/renderer/core/css/cssom/css_math_max.cc +++ b/third_party/blink/renderer/core/css/cssom/css_math_max.cc
@@ -72,7 +72,7 @@ } CSSMathExpressionNode* CSSMathMax::ToCalcExpressionNode() const { - CSSMathExpressionVariadicOperation::Operands operands; + CSSMathExpressionOperation::Operands operands; operands.ReserveCapacity(NumericValues().size()); for (const auto& value : NumericValues()) { CSSMathExpressionNode* operand = value->ToCalcExpressionNode(); @@ -90,8 +90,8 @@ NOTREACHED(); return nullptr; } - return CSSMathExpressionVariadicOperation::Create(std::move(operands), - CSSMathOperator::kMax); + return CSSMathExpressionOperation::CreateComparisonFunction( + std::move(operands), CSSMathOperator::kMax); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/css_math_min.cc b/third_party/blink/renderer/core/css/cssom/css_math_min.cc index 42d889f..733b6c50 100644 --- a/third_party/blink/renderer/core/css/cssom/css_math_min.cc +++ b/third_party/blink/renderer/core/css/cssom/css_math_min.cc
@@ -71,7 +71,7 @@ } CSSMathExpressionNode* CSSMathMin::ToCalcExpressionNode() const { - CSSMathExpressionVariadicOperation::Operands operands; + CSSMathExpressionOperation::Operands operands; operands.ReserveCapacity(NumericValues().size()); for (const auto& value : NumericValues()) { CSSMathExpressionNode* operand = value->ToCalcExpressionNode(); @@ -89,8 +89,8 @@ NOTREACHED(); return nullptr; } - return CSSMathExpressionVariadicOperation::Create(std::move(operands), - CSSMathOperator::kMin); + return CSSMathExpressionOperation::CreateComparisonFunction( + std::move(operands), CSSMathOperator::kMin); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/css_math_negate.cc b/third_party/blink/renderer/core/css/cssom/css_math_negate.cc index eba620bc..a3685b4 100644 --- a/third_party/blink/renderer/core/css/cssom/css_math_negate.cc +++ b/third_party/blink/renderer/core/css/cssom/css_math_negate.cc
@@ -42,7 +42,7 @@ CSSMathExpressionNode* right_side = value_->ToCalcExpressionNode(); if (!right_side) return nullptr; - return CSSMathExpressionBinaryOperation::CreateSimplified( + return CSSMathExpressionOperation::CreateArithmeticOperationSimplified( CSSMathExpressionNumericLiteral::Create( -1, CSSPrimitiveValue::UnitType::kNumber), right_side, CSSMathOperator::kMultiply);
diff --git a/third_party/blink/renderer/core/css/cssom/css_math_variadic.h b/third_party/blink/renderer/core/css/cssom/css_math_variadic.h index 8bc64cb40..ef26379 100644 --- a/third_party/blink/renderer/core/css/cssom/css_math_variadic.h +++ b/third_party/blink/renderer/core/css/cssom/css_math_variadic.h
@@ -72,7 +72,8 @@ NumericValues()[i]->ToCalcExpressionNode(); if (!next_arg) return nullptr; - node = CSSMathExpressionBinaryOperation::Create(node, next_arg, op); + node = CSSMathExpressionOperation::CreateArithmeticOperation( + node, next_arg, op); } return node; }
diff --git a/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc b/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc index 60f87cb..6a42b7f 100644 --- a/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc +++ b/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc
@@ -91,15 +91,14 @@ bool CanCombineNodes(const CSSMathExpressionNode& root, const CSSMathExpressionNode& node) { - DCHECK(root.IsBinaryOperation()); - if (!node.IsBinaryOperation()) + DCHECK(root.IsOperation()); + if (!node.IsOperation()) return false; if (node.IsNestedCalc()) return false; return CanonicalOperator( - To<CSSMathExpressionBinaryOperation>(root).OperatorType()) == - CanonicalOperator( - To<CSSMathExpressionBinaryOperation>(node).OperatorType()); + To<CSSMathExpressionOperation>(root).OperatorType()) == + CanonicalOperator(To<CSSMathExpressionOperation>(node).OperatorType()); } CSSNumericValue* NegateOrInvertIfRequired(CSSMathOperator parent_op, @@ -130,21 +129,23 @@ return CSSMathSum::Create(std::move(values)); } + DCHECK(root.IsOperation()); + CSSNumericValueVector values; // When the node is a variadic operation, we return either a CSSMathMin or a // CSSMathMax. - if (root.IsVariadicOperation()) { - const auto& node = To<CSSMathExpressionVariadicOperation>(root); + if (const auto& node = To<CSSMathExpressionOperation>(root); + (node.IsMinOrMax())) { for (const auto& operand : node.GetOperands()) values.push_back(CalcToNumericValue(*operand)); if (node.OperatorType() == CSSMathOperator::kMin) return CSSMathMin::Create(std::move(values)); - DCHECK(node.OperatorType() == CSSMathOperator::kMax); - return CSSMathMax::Create(std::move(values)); + if (node.OperatorType() == CSSMathOperator::kMax) + return CSSMathMax::Create(std::move(values)); } - DCHECK(root.IsBinaryOperation()); + DCHECK_EQ(To<CSSMathExpressionOperation>(root).GetOperands().size(), 2u); // When the node is a binary operator, we return either a CSSMathSum or a // CSSMathProduct. // For cases like calc(1 + 2 + 3), the calc expression tree looks like: @@ -165,19 +166,23 @@ // the nodes that we encounter. const CSSMathExpressionNode* cur_node = &root; do { - DCHECK(cur_node->IsBinaryOperation()); - const CSSMathExpressionBinaryOperation* binary_op = - To<CSSMathExpressionBinaryOperation>(cur_node); - DCHECK(binary_op->LeftExpressionNode()); - DCHECK(binary_op->RightExpressionNode()); + DCHECK(cur_node->IsOperation()); + const CSSMathExpressionOperation* binary_op = + To<CSSMathExpressionOperation>(cur_node); + CSSMathExpressionOperation::Operands operands = binary_op->GetOperands(); + DCHECK_EQ(operands.size(), 2u); + const auto* left_node = operands[0].Get(); + const auto* right_node = operands[1].Get(); + DCHECK(left_node); + DCHECK(right_node); - auto* const value = CalcToNumericValue(*binary_op->RightExpressionNode()); + auto* const value = CalcToNumericValue(*right_node); // If the current node is a '-' or '/', it's really just a '+' or '*' with // the right child negated or inverted, respectively. values.push_back( NegateOrInvertIfRequired(binary_op->OperatorType(), value)); - cur_node = binary_op->LeftExpressionNode(); + cur_node = left_node; } while (CanCombineNodes(root, *cur_node)); DCHECK(cur_node); @@ -187,7 +192,7 @@ // the values. std::reverse(values.begin(), values.end()); CSSMathOperator operator_type = - To<CSSMathExpressionBinaryOperation>(root).OperatorType(); + To<CSSMathExpressionOperation>(root).OperatorType(); if (operator_type == CSSMathOperator::kAdd || operator_type == CSSMathOperator::kSubtract) return CSSMathSum::Create(std::move(values));
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 6fbd06f..e2738d6 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -659,30 +659,11 @@ CSSPrimitiveValue::ValueRange value_range) : source_range_(range), range_(range) { const CSSParserToken& token = range.Peek(); - switch (token.FunctionId()) { - case CSSValueID::kCalc: - case CSSValueID::kWebkitCalc: - calc_value_ = CSSMathFunctionValue::Create( - CSSMathExpressionNode::ParseCalc(ConsumeFunction(range_)), - value_range); - break; - case CSSValueID::kMin: - calc_value_ = CSSMathFunctionValue::Create( - CSSMathExpressionNode::ParseMin(ConsumeFunction(range_)), - value_range); - break; - case CSSValueID::kMax: - calc_value_ = CSSMathFunctionValue::Create( - CSSMathExpressionNode::ParseMax(ConsumeFunction(range_)), - value_range); - break; - case CSSValueID::kClamp: - calc_value_ = CSSMathFunctionValue::Create( - CSSMathExpressionNode::ParseClamp(ConsumeFunction(range_)), - value_range); - break; - default: - break; + if (token.GetType() == kFunctionToken) { + calc_value_ = CSSMathFunctionValue::Create( + CSSMathExpressionNode::ParseMathFunction(token.FunctionId(), + ConsumeFunction(range_)), + value_range); } if (calc_value_ && calc_value_->HasComparisons()) context.Count(WebFeature::kCSSComparisonFunctions);
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 810b3ea..6b5cbdd7 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -5348,4 +5348,25 @@ ASSERT_EQ(0U, element_count); } +TEST_F(StyleEngineTest, CSSComparisonFunctionsUseCount) { + ClearUseCounter(WebFeature::kCSSComparisonFunctions); + GetDocument().body()->setInnerHTML(R"HTML( + <style> + div { width: calc(10px + 20%); } + </style> + )HTML"); + UpdateAllLifecyclePhases(); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSComparisonFunctions)); + ClearUseCounter(WebFeature::kCSSComparisonFunctions); + + GetDocument().body()->setInnerHTML(R"HTML( + <style> + div { width: calc(min(10px, 20%) + max(20px, 10%)); } + </style> + )HTML"); + UpdateAllLifecyclePhases(); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSComparisonFunctions)); + ClearUseCounter(WebFeature::kCSSComparisonFunctions); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/events/event_target_names.json5 b/third_party/blink/renderer/core/events/event_target_names.json5 index a81bd07..90e7e05 100644 --- a/third_party/blink/renderer/core/events/event_target_names.json5 +++ b/third_party/blink/renderer/core/events/event_target_names.json5
@@ -51,6 +51,5 @@ "Worker", "XMLHttpRequest", "XMLHttpRequestUpload", - "WindowControlsOverlay", ], }
diff --git a/third_party/blink/renderer/core/frame/build.gni b/third_party/blink/renderer/core/frame/build.gni index f4d59de..e5dd511c 100644 --- a/third_party/blink/renderer/core/frame/build.gni +++ b/third_party/blink/renderer/core/frame/build.gni
@@ -223,10 +223,19 @@ "web_local_frame_client.cc", "web_remote_frame_impl.h", "window_event_handlers.h", - "window_controls_overlay.cc", - "window_controls_overlay.h", - "window_controls_overlay_geometry_change_event.cc", - "window_controls_overlay_geometry_change_event.h", "window_or_worker_global_scope.cc", "window_or_worker_global_scope.h", ] + +# WindowControlsOverlay +# This uses target_os rather than current_os (which is what is_android is set +# from) for the case of generating the v8 context snapshot for android. When +# generating the snapshot for android, blink is compiled with +# current_os="linux" and target_os="android". Using target_os is necessary as +# we need to compile in the same way as would happen when current_os="android". +if (target_os != "android") { + blink_core_sources_frame += [ + "window_controls_overlay_changed_delegate.cc", + "window_controls_overlay_changed_delegate.h", + ] +}
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index d02022a6..b1050c8b 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -133,7 +133,6 @@ #include "third_party/blink/renderer/core/frame/visual_viewport.h" #include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" -#include "third_party/blink/renderer/core/frame/window_controls_overlay.h" #include "third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h" #include "third_party/blink/renderer/core/html/html_frame_element_base.h" #include "third_party/blink/renderer/core/html/html_link_element.h" @@ -215,6 +214,10 @@ #include "ui/gfx/range/range.h" #endif +#if !BUILDFLAG(IS_ANDROID) +#include "third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.h" +#endif + namespace blink { namespace { @@ -401,6 +404,9 @@ visitor->Trace(background_color_paint_image_generator_); visitor->Trace(box_shadow_paint_image_generator_); visitor->Trace(clip_path_paint_image_generator_); +#if !BUILDFLAG(IS_ANDROID) + visitor->Trace(window_controls_overlay_changed_delegate_); +#endif Frame::Trace(visitor); Supplementable<LocalFrame>::Trace(visitor); } @@ -2679,6 +2685,7 @@ } #endif +#if !BUILDFLAG(IS_ANDROID) void LocalFrame::UpdateWindowControlsOverlay( const gfx::Rect& bounding_rect_in_dips) { if (!RuntimeEnabledFeatures::WebAppWindowControlsOverlayEnabled( @@ -2737,17 +2744,18 @@ } } - if (fire_event) { - auto* window_controls_overlay = - WindowControlsOverlay::FromIfExists(*DomWindow()->navigator()); - - if (window_controls_overlay) { - window_controls_overlay->WindowControlsOverlayChanged( - window_controls_overlay_rect_); - } + if (fire_event && window_controls_overlay_changed_delegate_) { + window_controls_overlay_changed_delegate_->WindowControlsOverlayChanged( + window_controls_overlay_rect_); } } +void LocalFrame::RegisterWindowControlsOverlayChangedDelegate( + WindowControlsOverlayChangedDelegate* delegate) { + window_controls_overlay_changed_delegate_ = delegate; +} +#endif + HitTestResult LocalFrame::HitTestResultForVisualViewportPos( const gfx::Point& pos_in_viewport) { gfx::Point root_frame_point(
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index ffd2aabd..0184ce5 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -142,6 +142,10 @@ class WebURLLoaderFactory; struct BlinkTransferableMessage; +#if !BUILDFLAG(IS_ANDROID) +class WindowControlsOverlayChangedDelegate; +#endif + extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<LocalFrame>; // A LocalFrame is a frame hosted inside this process. @@ -646,7 +650,12 @@ #if BUILDFLAG(IS_MAC) void GetCharacterIndexAtPoint(const gfx::Point& point); #endif + +#if !BUILDFLAG(IS_ANDROID) void UpdateWindowControlsOverlay(const gfx::Rect& bounding_rect_in_dips); + void RegisterWindowControlsOverlayChangedDelegate( + WindowControlsOverlayChangedDelegate*); +#endif SystemClipboard* GetSystemClipboard(); @@ -684,6 +693,7 @@ bool SwapIn(); +#if !BUILDFLAG(IS_ANDROID) // For PWAs with display_overrides, these getters are information about the // titlebar bounds sent over from the browser via UpdateWindowControlsOverlay // in LocalMainFrame that are needed to persist the lifetime of the frame. @@ -693,6 +703,7 @@ const gfx::Rect& GetWindowControlsOverlayRect() const { return window_controls_overlay_rect_; } +#endif void LoadJavaScriptURL(const KURL& url); @@ -926,8 +937,12 @@ PaymentRequestToken payment_request_token_; +#if !BUILDFLAG(IS_ANDROID) bool is_window_controls_overlay_visible_ = false; gfx::Rect window_controls_overlay_rect_; + WeakMember<WindowControlsOverlayChangedDelegate> + window_controls_overlay_changed_delegate_; +#endif // The evidence for or against a frame being an ad frame. `absl::nullopt` if // not yet set or if the frame is a top-level frame. (Only subframes can be
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index 9ffbdb8..0b5eb64 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -1521,8 +1521,10 @@ visual_properties.browser_controls_params); } +#if !BUILDFLAG(IS_ANDROID) LocalRootImpl()->GetFrame()->UpdateWindowControlsOverlay( visual_properties.window_controls_overlay_rect); +#endif } else { // Widgets in a WebView's frame tree without a local main frame
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.cc b/third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.cc new file mode 100644 index 0000000..d5e779fa --- /dev/null +++ b/third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.cc
@@ -0,0 +1,17 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.h" + +#include "third_party/blink/renderer/core/frame/local_frame.h" + +namespace blink { + +WindowControlsOverlayChangedDelegate::WindowControlsOverlayChangedDelegate( + LocalFrame* frame) { + if (frame) + frame->RegisterWindowControlsOverlayChangedDelegate(this); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.h b/third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.h new file mode 100644 index 0000000..ee0a337 --- /dev/null +++ b/third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.h
@@ -0,0 +1,39 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_CHANGED_DELEGATE_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_CHANGED_DELEGATE_H_ + +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/heap/garbage_collected.h" + +namespace gfx { +class Rect; +} + +namespace blink { + +class LocalFrame; + +// Extension point for observing changes to Window Controls Overlay geometry +// (e.g. the titlebar area); only supported on desktop platforms. +class CORE_EXPORT WindowControlsOverlayChangedDelegate + : public GarbageCollectedMixin { + public: + // Notifies about a change to the Window Controls Overlay geometry. + // `titlebar_area_rect` is the updated available titlebar area in the viewport + // coordinate space. + virtual void WindowControlsOverlayChanged( + const gfx::Rect& titlebar_area_rect) = 0; + + protected: + // If `LocalFrame` not null, `this` will be registered to observe window + // controls overlay geometry changes. Otherwise, no notifications will be + // dispatched. + explicit WindowControlsOverlayChangedDelegate(LocalFrame*); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_CHANGED_DELEGATE_H_
diff --git a/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc b/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc index 287cea3..d4abd16 100644 --- a/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc +++ b/third_party/blink/renderer/core/inspector/inspector_issue_conversion.cc
@@ -60,6 +60,9 @@ return ""; case mojom::blink::InspectorIssueCode::kLowTextContrastIssue: return protocol::Audits::InspectorIssueCodeEnum::LowTextContrastIssue; + case mojom::blink::InspectorIssueCode::kFederatedAuthRequestIssue: + CHECK(false); + return ""; case mojom::blink::InspectorIssueCode::kGenericIssue: NOTREACHED(); return "";
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc index 57813d5..afd08f0 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -166,8 +166,7 @@ const MinMaxSizes grid_min_max = NGTableAlgorithmHelpers::ComputeGridInlineMinMax( table, column_constraints, undistributable_space, is_fixed_layout, - /* is_layout_pass */ true, - /* skip_collapsed_columns */ false); + /* is_layout_pass */ true); // Standard: "used width of the table". LayoutUnit used_table_inline_size = ComputeUsedInlineSizeForTableFragment( @@ -594,8 +593,7 @@ const MinMaxSizes grid_min_max = NGTableAlgorithmHelpers::ComputeGridInlineMinMax( Node(), *column_constraints, undistributable_space, is_fixed_layout, - /* is_layout_pass */ false, - /* skip_collapsed_columns */ false); + /* is_layout_pass */ false); MinMaxSizes min_max{ std::max(grid_min_max.min_size, caption_constraint.min_size),
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc index 17a5f44..0f796660 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc
@@ -893,8 +893,7 @@ const NGTableTypes::Columns& column_constraints, LayoutUnit undistributable_space, bool is_fixed_layout, - bool is_layout_pass, - bool skip_collapsed_columns) { + bool is_layout_pass) { MinMaxSizes min_max; // https://www.w3.org/TR/css-tables-3/#computing-the-table-width // Compute standard GRID_MIN/GRID_MAX. They are sum of column_constraints. @@ -919,8 +918,6 @@ LayoutUnit non_percent_max_size_sum; float percent_sum = 0; for (const NGTableTypes::Column& column : column_constraints.data) { - if (skip_collapsed_columns && column.is_collapsed) - continue; if (column.min_inline_size) { // In fixed layout, constrained cells minimum inline size is their // maximum.
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.h index 1213933..79b05f4 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.h +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.h
@@ -33,8 +33,7 @@ const NGTableTypes::Columns& column_constraints, LayoutUnit undistributable_space, bool is_fixed_layout, - bool is_layout_pass, - bool skip_collapsed_columns); + bool is_layout_pass); static void DistributeColspanCellsToColumns( const NGTableTypes::ColspanCells& colspan_cells,
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers_test.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers_test.cc index 944028de..987df25 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers_test.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers_test.cc
@@ -194,7 +194,6 @@ LayoutUnit undistributable_space; bool is_fixed_layout = false; bool is_layout_pass = true; - bool skip_collapsed_columns = false; // No percentages, just sums up min/max. column_constraints->data.push_back(MakeColumn(10, 100)); @@ -203,7 +202,7 @@ MinMaxSizes minmax = NGTableAlgorithmHelpers::ComputeGridInlineMinMax( node, *column_constraints, undistributable_space, is_fixed_layout, - is_layout_pass, skip_collapsed_columns); + is_layout_pass); EXPECT_EQ(minmax.min_size, LayoutUnit(60)); EXPECT_EQ(minmax.max_size, LayoutUnit(600)); @@ -215,14 +214,14 @@ column_constraints->data.push_back(MakeColumn(10, 10)); minmax = NGTableAlgorithmHelpers::ComputeGridInlineMinMax( node, *column_constraints, undistributable_space, is_fixed_layout, - is_layout_pass, skip_collapsed_columns); + is_layout_pass); EXPECT_EQ(minmax.min_size, LayoutUnit(30)); EXPECT_EQ(minmax.max_size, LayoutUnit(990)); is_layout_pass = false; minmax = NGTableAlgorithmHelpers::ComputeGridInlineMinMax( node, *column_constraints, undistributable_space, is_fixed_layout, - is_layout_pass, skip_collapsed_columns); + is_layout_pass); EXPECT_EQ(minmax.min_size, LayoutUnit(30)); EXPECT_EQ(minmax.max_size, LayoutUnit(119)); @@ -235,7 +234,7 @@ column_constraints->data.push_back(MakeColumn(10, 800)); minmax = NGTableAlgorithmHelpers::ComputeGridInlineMinMax( node, *column_constraints, undistributable_space, is_fixed_layout, - is_layout_pass, skip_collapsed_columns); + is_layout_pass); EXPECT_EQ(minmax.min_size, LayoutUnit(30)); EXPECT_EQ(minmax.max_size, LayoutUnit(1000)); }
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc index c676c2d..9428302 100644 --- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc +++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
@@ -156,10 +156,11 @@ if (auto* image = DynamicTo<HTMLImageElement>(node); image && image->WillRespondToMouseClickEvents()) { return true; + } else if (auto* anchor = DynamicTo<HTMLAnchorElement>(node); + anchor && !anchor->Href().IsEmpty()) { + return true; } - return IsA<HTMLFormControlElement>(node) || - (IsA<HTMLAnchorElement>(node) && - !To<HTMLAnchorElement>(node)->Href().IsEmpty()); + return IsA<HTMLFormControlElement>(node); } // Skip the whole subtree if the object is invisible. Some elements in subtree
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index a332d16b..a4baa48 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -174,6 +174,7 @@ sub_modules += [ "//third_party/blink/renderer/modules/direct_sockets", "//third_party/blink/renderer/modules/serial", + "//third_party/blink/renderer/modules/window_controls_overlay", ] }
diff --git a/third_party/blink/renderer/modules/event_target_modules_names.json5 b/third_party/blink/renderer/modules/event_target_modules_names.json5 index 2bfc220..a88cfd8c 100644 --- a/third_party/blink/renderer/modules/event_target_modules_names.json5 +++ b/third_party/blink/renderer/modules/event_target_modules_names.json5
@@ -85,5 +85,6 @@ }, "USB", "WakeLockSentinel", + "WindowControlsOverlay", ], }
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc index 7afb0ae2..a6edf3c 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -220,6 +220,15 @@ } // namespace +MediaStreamTrack* MediaStreamTrack::Create(ExecutionContext* context) { + MediaStreamSource* source = MakeGarbageCollected<MediaStreamSource>( + "dummy", MediaStreamSource::StreamType::kTypeVideo, "dummy", + false /* remote */); + MediaStreamComponent* component = + MakeGarbageCollected<MediaStreamComponent>(source); + return MakeGarbageCollected<MediaStreamTrack>(context, component); +} + MediaStreamTrack::MediaStreamTrack(ExecutionContext* context, MediaStreamComponent* component) : MediaStreamTrack(context,
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.h b/third_party/blink/renderer/modules/mediastream/media_stream_track.h index 593f9ff..40a14cf 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track.h +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.h
@@ -64,6 +64,9 @@ virtual void TrackChangedState() = 0; }; + // TODO(1288839): Implement to recreate MST after transfer + static MediaStreamTrack* Create(ExecutionContext* context); + MediaStreamTrack(ExecutionContext*, MediaStreamComponent*); MediaStreamTrack(ExecutionContext*, MediaStreamComponent*,
diff --git a/third_party/blink/renderer/modules/window_controls_overlay/BUILD.gn b/third_party/blink/renderer/modules/window_controls_overlay/BUILD.gn new file mode 100644 index 0000000..7bbaf93 --- /dev/null +++ b/third_party/blink/renderer/modules/window_controls_overlay/BUILD.gn
@@ -0,0 +1,18 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/blink/renderer/modules/modules.gni") + +# The WindowControlsOverlay API will not be supported on Android. Assert here to +# ensure it doesn't sneak back into the build. +assert(!is_android) + +blink_modules_sources("window_controls_overlay") { + sources = [ + "window_controls_overlay.cc", + "window_controls_overlay.h", + "window_controls_overlay_geometry_change_event.cc", + "window_controls_overlay_geometry_change_event.h", + ] +}
diff --git a/third_party/blink/renderer/core/frame/navigator_window_controls_overlay.idl b/third_party/blink/renderer/modules/window_controls_overlay/navigator_window_controls_overlay.idl similarity index 100% rename from third_party/blink/renderer/core/frame/navigator_window_controls_overlay.idl rename to third_party/blink/renderer/modules/window_controls_overlay/navigator_window_controls_overlay.idl
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay.cc b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.cc similarity index 85% rename from third_party/blink/renderer/core/frame/window_controls_overlay.cc rename to third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.cc index c7e7ca4..8682abd 100644 --- a/third_party/blink/renderer/core/frame/window_controls_overlay.cc +++ b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.cc
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/core/frame/window_controls_overlay.h" +#include "third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/navigator.h" -#include "third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.h" +#include "third_party/blink/renderer/modules/event_target_modules.h" +#include "third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" namespace blink { @@ -38,7 +39,10 @@ } WindowControlsOverlay::WindowControlsOverlay(Navigator& navigator) - : Supplement<Navigator>(navigator) {} + : Supplement<Navigator>(navigator), + WindowControlsOverlayChangedDelegate( + navigator.DomWindow() ? navigator.DomWindow()->GetFrame() : nullptr) { +} WindowControlsOverlay::~WindowControlsOverlay() = default;
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay.h b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.h similarity index 73% rename from third_party/blink/renderer/core/frame/window_controls_overlay.h rename to third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.h index 116d75e..4b59c50 100644 --- a/third_party/blink/renderer/core/frame/window_controls_overlay.h +++ b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WINDOW_CONTROLS_OVERLAY_WINDOW_CONTROLS_OVERLAY_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WINDOW_CONTROLS_OVERLAY_WINDOW_CONTROLS_OVERLAY_H_ #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" -#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" +#include "third_party/blink/renderer/core/frame/window_controls_overlay_changed_delegate.h" #include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -17,9 +17,10 @@ class Navigator; -class CORE_EXPORT WindowControlsOverlay final +class WindowControlsOverlay final : public EventTargetWithInlineData, - public Supplement<Navigator> { + public Supplement<Navigator>, + public WindowControlsOverlayChangedDelegate { DEFINE_WRAPPERTYPEINFO(); public: @@ -44,11 +45,11 @@ bool visible() const; DOMRect* getTitlebarAreaRect() const; - void WindowControlsOverlayChanged(const gfx::Rect& rect); + void WindowControlsOverlayChanged(const gfx::Rect&) final; void Trace(Visitor*) const override; }; } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WINDOW_CONTROLS_OVERLAY_WINDOW_CONTROLS_OVERLAY_H_
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay.idl b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.idl similarity index 100% rename from third_party/blink/renderer/core/frame/window_controls_overlay.idl rename to third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay.idl
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.cc b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.cc similarity index 86% rename from third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.cc rename to third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.cc index 3eb3d0a..cee10a0d 100644 --- a/third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.cc +++ b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.h" +#include "third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_window_controls_overlay_geometry_change_event_init.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_window_controls_overlay_geometry_change_event_init.h" #include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "ui/gfx/geometry/rect.h"
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.h b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.h similarity index 72% rename from third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.h rename to third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.h index 1f4a9c7..2a250cc 100644 --- a/third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.h +++ b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_GEOMETRY_CHANGE_EVENT_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_GEOMETRY_CHANGE_EVENT_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WINDOW_CONTROLS_OVERLAY_WINDOW_CONTROLS_OVERLAY_GEOMETRY_CHANGE_EVENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WINDOW_CONTROLS_OVERLAY_WINDOW_CONTROLS_OVERLAY_GEOMETRY_CHANGE_EVENT_H_ -#include "third_party/blink/renderer/core/dom/events/event.h" +#include "third_party/blink/renderer/modules/event_modules.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" namespace blink { @@ -40,4 +40,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WINDOW_CONTROLS_OVERLAY_GEOMETRY_CHANGE_EVENT_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WINDOW_CONTROLS_OVERLAY_WINDOW_CONTROLS_OVERLAY_GEOMETRY_CHANGE_EVENT_H_
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.idl b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.idl similarity index 100% rename from third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event.idl rename to third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event.idl
diff --git a/third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event_init.idl b/third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event_init.idl similarity index 100% rename from third_party/blink/renderer/core/frame/window_controls_overlay_geometry_change_event_init.idl rename to third_party/blink/renderer/modules/window_controls_overlay/window_controls_overlay_geometry_change_event_init.idl
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 14099f59..0ae85e7 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -708,7 +708,7 @@ }, { name: "CSSMixBlendModePlusLighter", - status: "test" + status: "stable" }, { name: "CSSModules", @@ -1508,6 +1508,10 @@ name: "MediaStreamTrackInWorker", status: "test", }, + { + name: "MediaStreamTrackTransfer", + status: "test", + }, // This is enabled by default on Windows only. The only part that's // "experimental" is the support on other platforms. {
diff --git a/third_party/blink/tools/blinkpy/common/config/builders.json b/third_party/blink/tools/blinkpy/common/config/builders.json index 7c410eb7..9f2b2a6 100644 --- a/third_party/blink/tools/blinkpy/common/config/builders.json +++ b/third_party/blink/tools/blinkpy/common/config/builders.json
@@ -185,7 +185,7 @@ ], "is_try_builder": true }, - "android-web-platform-pie-x86-fyi-rel": { + "android-chrome-pie-x86-wpt-fyi-rel": { "port_name": "android-android-pie", "master": "chromium.android.fyi", "specifiers": [
diff --git a/third_party/blink/tools/diff_wpt_results.py b/third_party/blink/tools/diff_wpt_results.py index 50955da..b4a53bc 100755 --- a/third_party/blink/tools/diff_wpt_results.py +++ b/third_party/blink/tools/diff_wpt_results.py
@@ -54,7 +54,7 @@ PRODUCTS_TO_BUILDER_NAME = { 'android_weblayer': 'android-weblayer-pie-x86-wpt-fyi-rel', 'android_webview': 'android-webview-pie-x86-wpt-fyi-rel', - 'chrome_android': 'android-web-platform-pie-x86-fyi-rel', + 'chrome_android': 'android-chrome-pie-x86-wpt-fyi-rel', 'chrome_linux': 'linux-wpt-fyi-rel', 'content_shell': "Linux Tests"}
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 47b15b27..5b2a929 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3177,6 +3177,27 @@ crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-flexbox/flexbox_flow-column-wrap.html [ Crash Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-text/hyphens/hyphens-vertical-001.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-text/hyphens/hyphens-vertical-001.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-text/hyphens/hyphens-vertical-002.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-text/hyphens/hyphens-vertical-002.html [ Failure ] +crbug.com/626703 external/wpt/css/css-text/hyphens/hyphens-vertical-003.html [ Failure ] +crbug.com/626703 external/wpt/css/css-text/hyphens/hyphens-vertical-004.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/svg/geometry/reftests/circle-002.svg [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/mediastreamaudiosourcenode-routing.html [ Timeout ] +crbug.com/626703 [ Linux ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Timeout ] +crbug.com/626703 [ Mac ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Timeout ] +crbug.com/626703 [ Win7 ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Timeout ] +crbug.com/626703 [ Linux ] virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Timeout ] +crbug.com/626703 [ Mac ] virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Timeout ] +crbug.com/626703 [ Win7 ] virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Timeout ] +crbug.com/626703 [ Mac10.14 ] virtual/prerender/external/wpt/speculation-rules/prerender/cache-storage.https.html [ Skip Timeout ] +crbug.com/626703 [ Mac10.15 ] virtual/prerender/external/wpt/speculation-rules/prerender/fetch-blob.html [ Skip Timeout ] +crbug.com/626703 [ Mac11 ] virtual/prerender/external/wpt/speculation-rules/prerender/fetch-blob.html [ Skip Timeout ] +crbug.com/626703 [ Mac10.14 ] virtual/prerender/external/wpt/speculation-rules/prerender/indexeddb.html [ Skip Timeout ] +crbug.com/626703 [ Mac11 ] virtual/prerender/external/wpt/speculation-rules/prerender/indexeddb.html [ Skip Timeout ] +crbug.com/626703 [ Mac11-arm64 ] virtual/threaded/external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ] crbug.com/626703 external/wpt/css/compositing/background-blending/background-blend-mode-plus-lighter.html [ Failure ] crbug.com/626703 external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-plus-lighter-svg-basic.html [ Failure ] crbug.com/626703 external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-plus-lighter-svg.html [ Failure ] @@ -7546,7 +7567,7 @@ crbug.com/1286944 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/parse-input-arguments-011.https.html [ Failure Pass ] # Sheriff 2022-01-17 -crbug.com/1287928 [ Mac ] external/wpt/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html [ Failure Pass ] +crbug.com/1287928 external/wpt/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html [ Skip ] crbug.com/1233938 http/tests/notifications/click-shared-worker.html [ Pass Timeout ] # Temporarily disable test to allow fixing of devtools path escaping crbug.com/1094436 http/tests/devtools/overrides/project-added-with-existing-files-bind.js [ Failure Skip Timeout ] @@ -7556,7 +7577,8 @@ crbug.com/1288136 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/registered-property-value-005.https.html [ Failure Pass ] # Sheriff 2022-01-18 -crbug.com/1287067 virtual/fenced-frame-mparch/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Failure Pass ] +crbug.com/1287067 [ Fuchsia ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Failure Pass ] +crbug.com/1287067 [ Win10.20h2 ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/embedder-require-corp.https.html [ Failure Pass ] crbug.com/1288264 [ Win ] http/tests/fetch/serviceworker-proxied/thorough/redirect-loop-base-https-other-https.html [ Pass Skip Timeout ] crbug.com/1288264 [ Win ] http/tests/fetch/window/thorough/cors-preflight2-base-https-other-https.html [ Pass Skip Timeout ] crbug.com/1288264 [ Win ] http/tests/fetch/serviceworker/thorough/nocors-base-https-other-https.html [ Pass Skip Timeout ] @@ -7593,10 +7615,13 @@ # Sheriff 2022-01-26 crbug.com/1290978 [ Win ] external/wpt/css/CSS2/normal-flow/crashtests/block-in-inline-ax-crash.html [ Crash Failure Pass Timeout ] crbug.com/1290978 [ Mac ] external/wpt/css/CSS2/normal-flow/crashtests/block-in-inline-ax-crash.html [ Crash Failure Pass Timeout ] -crbug.com/1290978 [ Win7 ] http/tests/devtools/elements/accessibility/edit-aria-attributes.js [ Crash Failure Pass Timeout Skip ] +crbug.com/1290978 [ Win7 ] http/tests/devtools/elements/accessibility/edit-aria-attributes.js [ Crash Failure Pass Skip Timeout ] crbug.com/1291246 [ Mac ] virtual/dark-system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance.html [ Failure Pass ] crbug.com/1291246 [ Mac ] virtual/system-color-picker-appearance/fast/forms/color-scheme/color/color-picker-appearance.html [ Failure Pass ] crbug.com/1291274 [ Mac ] virtual/document-transition/wpt_internal/document-transition/transition-waits-for-animations.html [ Crash ] crbug.com/1291383 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html [ Skip ] crbug.com/1291383 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html [ Skip ] crbug.com/1291383 virtual/shared_array_buffer_on_desktop/fast/peerconnection/RTCPeerConnection-addMultipleTransceivers.html [ Skip ] + +# Sheriff 2022-01-27 Flaky test +crbug.com/1291488 virtual/shared_array_buffer_on_desktop/fast/peerconnection/RTCPeerConnection-addMultipleTracks.html [ Skip ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 4e19f863..c5337e4 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -790,6 +790,7 @@ { "prefix": "third-party-storage-partitioning", "bases": [ + "external/wpt/web-locks/partitioned-web-locks.tentative.https.html", "external/wpt/workers/shared-worker-partitioned.tentative.html", "external/wpt/service-workers/service-worker/partitioned-service-worker.tentative.https.html", "external/wpt/service-workers/service-worker/partitioned-service-worker-getRegistrations.tentative.https.html",
diff --git a/third_party/blink/web_tests/animations/direction-and-fill/fill-mode-iteration-count-non-integer.html b/third_party/blink/web_tests/animations/direction-and-fill/fill-mode-iteration-count-non-integer.html index 52348c9c..e155d8d2 100644 --- a/third_party/blink/web_tests/animations/direction-and-fill/fill-mode-iteration-count-non-integer.html +++ b/third_party/blink/web_tests/animations/direction-and-fill/fill-mode-iteration-count-non-integer.html
@@ -10,6 +10,7 @@ animation-duration: 0.1s; animation-timing-function: linear; animation-name: anim; + animation-play-state: paused; } @keyframes anim { from { left: 200px; } @@ -47,6 +48,9 @@ animation-iteration-count: 2.4; animation-direction: alternate-reverse; } +.running { + animation-play-state: running; +} </style> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> @@ -65,8 +69,7 @@ async_test(t => { function assertAnimatedValue(expected, actual, isStart, id) { var identifier = (isStart ? 'Start' : 'End') + ' of animation for element \'' + id + '\''; - var diff = Math.abs(expected - actual); - assert_less_than(diff, 5, identifier + ': Saw something close to ' + expected); + assert_equals(actual, expected, identifier); } function endTest() { @@ -85,6 +88,7 @@ var expectedValue = expectedValues[i].start; var realValue = parseFloat(window.getComputedStyle(el).left); assertAnimatedValue(expectedValue, realValue, true, expectedValues[i].id); + el.classList.add('running'); } document.addEventListener("animationend", t.step_func(() => { if (++animsFinished == numAnims) {
diff --git a/third_party/blink/web_tests/animations/stability/marquee-element-move-and-toggle-visibility-crash.html b/third_party/blink/web_tests/animations/stability/marquee-element-move-and-toggle-visibility-crash.html new file mode 100644 index 0000000..36e1eac --- /dev/null +++ b/third_party/blink/web_tests/animations/stability/marquee-element-move-and-toggle-visibility-crash.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Moving a marquee element and toggle the visibility state should not + crash</title> +</head> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<body> + <marquee id="target">Don't crash me</marquee> + <div id="container" style = "display: none;"></div> +</body> +<script> + test(function() { + const target = document.getElementById('target'); + const container = document.getElementById('container'); + requestAnimationFrame(() => { + requestAnimationFrame(() => { + // Removing the element pauses the animation in Blink. + target.parentElement.removeChild(target); + requestAnimationFrame(() => { + // Reattaching the element resumes the animation regardless of + // visibility. + container.appendChild(target); + requestAnimationFrame(() => { + container.style = "display: block"; + }); + }); + }); + }); + }, 'Check that toggling visibility of a moved marquee element does not crash'); +</script> +</html>
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index 758cd28..e5b97a9 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: 165e350edf37719726d3240af2935cdec43d1447 +Version: 4600dd75e59f1fee349913b2633a8795aacc6490
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 a94e1fa3..ab861bceb 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
@@ -367,6 +367,13 @@ {} ] ], + "chrome-bug-1289999-crash.https.html": [ + "fab89f06d95b76d3fc63a8d4d784ffb93f3624de", + [ + null, + {} + ] + ], "flexbox": { "fixed-flex-item-inside-abs-flex-in-multicol-crash.html": [ "29ba56748f9a81615977ded26f4299fa744475f0", @@ -3196,6 +3203,13 @@ null, {} ] + ], + "scroll-timeline-in-removed-iframe-crash.html": [ + "07edbd83f1c791b1e71afde9919f9f69aa42f05d", + [ + null, + {} + ] ] } }, @@ -155922,6 +155936,58 @@ {} ] ], + "hyphens-vertical-001.html": [ + "baececdb0a94588af996175e0f2253d932f727a1", + [ + null, + [ + [ + "/css/css-text/hyphens/reference/hyphens-vertical-001-ref.html", + "==" + ] + ], + {} + ] + ], + "hyphens-vertical-002.html": [ + "e449526344d25562769b472698126b00829ead05", + [ + null, + [ + [ + "/css/css-text/hyphens/reference/hyphens-vertical-002-ref.html", + "==" + ] + ], + {} + ] + ], + "hyphens-vertical-003.html": [ + "2b1c6271c2e201a5b3af9e933f2bd02ca548844e", + [ + null, + [ + [ + "/css/css-text/hyphens/reference/hyphens-vertical-003-ref.html", + "==" + ] + ], + {} + ] + ], + "hyphens-vertical-004.html": [ + "cee7718b9d8fdebb30f0db39dad95a5fb8bcefeb", + [ + null, + [ + [ + "/css/css-text/hyphens/reference/hyphens-vertical-004-ref.html", + "==" + ] + ], + {} + ] + ], "shy-styling-001.html": [ "98348d92a6987607cd2d591fd385f9e303a4471a", [ @@ -228530,7 +228596,7 @@ [] ], "META.yml": [ - "7df27e1f40b09a70c9dcee46e9b1e40bbf355595", + "dbfac71522fa59318abb52edc530dc850fe66936", [] ], "OWNERS": [ @@ -228678,7 +228744,7 @@ [] ], "META.yml": [ - "c3f69ba181e69906ebeb1fe42f1e4255f17c47c5", + "e173970b5d77af1fcff868fa026dc2787d7a3cc0", [] ], "OWNERS": [ @@ -228823,10 +228889,6 @@ "98b7dd0fb58b4142f90eca341356eb0efbd09d2f", [] ], - "notify-top-early.html": [ - "0dd796f609c0659bd489e10cb02ac4816a88960b", - [] - ], "page-with-base-url-common.html": [ "8d9fedcc2b40d2eaeff55727ffa476a6e7c0e479", [] @@ -228886,6 +228948,18 @@ [] ] } + }, + "ordering": { + "README.md": [ + "9ae6c7b19ff77cac170dd8234aa11ea8f37a1200", + [] + ], + "resources": { + "notify-top-early.html": [ + "0dd796f609c0659bd489e10cb02ac4816a88960b", + [] + ] + } } }, "appmanifest": { @@ -229628,7 +229702,7 @@ [] ], "META.yml": [ - "a069984ddb226b6f07cd5f1408e159634dfec7f4", + "77d19a828dcfe6f0f19d367b0b9c809d2b6b21c1", [] ], "OWNERS": [ @@ -233049,14 +233123,6 @@ "b8a1d0a6098492b615dfae8a1e5e44ade8a2f3db", [] ], - "cookieListItem_attributes.https.any-expected.txt": [ - "084f511984369c8f1ef7b06bf6a46f4cc037d930", - [] - ], - "cookieListItem_attributes.https.any.serviceworker-expected.txt": [ - "084f511984369c8f1ef7b06bf6a46f4cc037d930", - [] - ], "resources": { "always_changing_sw.sub.js": [ "9fdf99848fa50316e275cd6636a5755270a9bb1e", @@ -233113,24 +233179,24 @@ ], "path": { "one.html": [ - "1b53e773a18b5f55c6a790cd33ace6508041dd81", + "5ff90b9f15ffe68f02efffc31e3fb4f10f6821b2", [] ], "three.html": [ - "1b53e773a18b5f55c6a790cd33ace6508041dd81", + "5ff90b9f15ffe68f02efffc31e3fb4f10f6821b2", [] ], "two.html": [ - "1b53e773a18b5f55c6a790cd33ace6508041dd81", + "5ff90b9f15ffe68f02efffc31e3fb4f10f6821b2", [] ] }, "path-redirect-shared.js": [ - "7144e651e11c643a5a45f82c1295ede85b7a7bae", + "777d0abd3381b821e9097a9fd7607d0613418d3b", [] ], "path.html": [ - "1b53e773a18b5f55c6a790cd33ace6508041dd81", + "5ff90b9f15ffe68f02efffc31e3fb4f10f6821b2", [] ], "path.html.headers": [ @@ -233139,16 +233205,16 @@ ], "pathfakeout": { "one.html": [ - "1b53e773a18b5f55c6a790cd33ace6508041dd81", + "5ff90b9f15ffe68f02efffc31e3fb4f10f6821b2", [] ] }, "pathfakeout.html": [ - "1b53e773a18b5f55c6a790cd33ace6508041dd81", + "5ff90b9f15ffe68f02efffc31e3fb4f10f6821b2", [] ], "secure-non-secure-child.html": [ - "443b0a17f74e9b4cbf4ae9e70232f9adf9f5b22d", + "e5d68b8d07e6f590861d7851149e24804f057122", [] ] } @@ -233205,7 +233271,7 @@ [] ], "cookie-test.js": [ - "2e435ddc5b52f1448c1e776eb9eb956650bf1ebd", + "7c3b8619eeafac3885c69917e3cc5d0687d8f73e", [] ], "cookie.py": [ @@ -233233,7 +233299,7 @@ [] ], "echo-cookie.html": [ - "172020c5fb955a8371527829a3b5cd7848f1519f", + "ab78af8325969b3eb6627d4aa58bfaa44028f94a", [] ], "echo-json.py": [ @@ -265248,6 +265314,22 @@ "7b3f8206417ffeff05a522c07f1efad9176cde9b", [] ], + "hyphens-vertical-001-ref.html": [ + "5be7a840d893f7e18c1e01f20a7e3f1a96627968", + [] + ], + "hyphens-vertical-002-ref.html": [ + "cb240212bcae4adaf06fb6549a86f0be311923ca", + [] + ], + "hyphens-vertical-003-ref.html": [ + "6d3ea15845585523e66ce53fe71eed6bdfa125f1", + [] + ], + "hyphens-vertical-004-ref.html": [ + "63c751165f873060027c809cb3fc165b8974fa99", + [] + ], "shy-styling-001-alt-ref.html": [ "c86cb5002867c899f54a59d25c0a0572e7658cd7", [] @@ -270926,7 +271008,7 @@ ], "resources": { "testhelper.js": [ - "e4b0ddb8b42c2fb00c74681ec37b7219fbd3eb60", + "2792ee51febe3e8ea98f953568a7291a543b6b3f", [] ] }, @@ -283492,6 +283574,14 @@ "a69aab487239021088f944b0a8cee2dad4b3d111", [] ], + "nested-worker.https.window-expected.txt": [ + "8718ffde7bc70a2802ec04ecd5c1e3b42e0dca32", + [] + ], + "nested-worker.window-expected.txt": [ + "8718ffde7bc70a2802ec04ecd5c1e3b42e0dca32", + [] + ], "resources": { "fetcher.html": [ "000a5cc25bb72b334d41ff05e7b8f22691f48f30", @@ -283526,13 +283616,17 @@ [] ], "support.sub.js": [ - "9fcba9d8edeaffd71f393097e6859232de12e29d", + "98ae1f3457cd5a1e5cf431b8150542b1eb4322a0", [] ], "worker-fetcher.html": [ "bd155a532bd2d9dd2b5f96383cb8bde27a289856", [] ], + "worker-fetcher.js": [ + "aab49afe6f47c752884d407cfa48ef38e3b4a847", + [] + ], "xhr-sender.html": [ "b131fa41f9a8bf14c5c0a1aac8fcc2593bec6c42", [] @@ -285184,7 +285278,7 @@ [] ], "META.yml": [ - "bf48f80f8083f0ca13f432d16a7b3b22b3435526", + "916bc8074f1c4321d850cec54abcb3f388959938", [] ], "OWNERS": [ @@ -285356,7 +285450,7 @@ [] ], "META.yml": [ - "6a48535e3c7416eb1d54b1a6e6837230ba498b39", + "8f553a86ca3bf19fe429f4a31f20d97ed8b1babd", [] ], "OWNERS": [ @@ -289347,6 +289441,10 @@ "377c7296a781adb8ce5792cda50a4ded28472339", [] ], + "fenced-frame-bypass.tentative.https.window-expected.txt": [ + "dc538e12907885d23b2fa5b3a6f9c6364b88fdc4", + [] + ], "fenced-frame.tentative.https.window-expected.txt": [ "dc538e12907885d23b2fa5b3a6f9c6364b88fdc4", [] @@ -289357,7 +289455,7 @@ ], "resources": { "common.js": [ - "1378f3e9a75ff7b0587887792e626cc92772f4e6", + "e83bd094670dd4a8541031c4a66d738045484dc1", [] ], "serviceworker-partitioning-helper.js": [ @@ -290454,6 +290552,18 @@ "a5f7b3fd0a08e60729192a62902a9e9f07805821", [] ], + "render-blocking-mechanism": { + "support": { + "target-red.css": [ + "a387acd4ecb17a0a0419fb5b3c90a1f0b2f1b0ea", + [] + ], + "test-render-blocking.js": [ + "3cd3b7d39045ff8c81ef599bdff46324c2dec5a9", + [] + ] + } + }, "resources": { "self-origin-subframe.html": [ "8759362bdf006f09472ca105c02f37115d4f6a15", @@ -301028,7 +301138,7 @@ [] ], "META.yml": [ - "3dd015f3ecb7d95f6677031448823cf5028f546f", + "ecbf633fd5e887d1c90aa5afbe571b0b8af9156f", [] ], "OWNERS": [ @@ -303562,7 +303672,7 @@ [] ], "META.yml": [ - "d7d395ee8f2a942327858b189dd8a6b2a249c14e", + "9193c0d4590c36fe0c5efc3d7eeca8205c434ed5", [] ], "Magnetometer-disabled-by-feature-policy.https-expected.txt": [ @@ -305066,7 +305176,7 @@ [] ], "dictionary-manual.https-expected.txt": [ - "2b6107ccb8ba8253418492763f08bb7fc5c017d1", + "f99d27a7bc153a8e9a8e2cc6086f3bbfe61680e2", [] ] }, @@ -305117,6 +305227,10 @@ "0dbcc32d0b271f9772ee5664ba9f5fee35e95a41", [] ], + "service-worker.js": [ + "05a8b99ad8a95f347abb7190b753440629284594", + [] + ], "shared-worker.js": [ "61ff67bcff03099cbf93fbb594e9b188d85a9f11", [] @@ -306112,7 +306226,7 @@ [] ], "META.yml": [ - "427385826fca7a770a816abc5d98cc324f647f68", + "b780d2c90cbd27ee3387d5207d8584f74f725b64", [] ], "OWNERS": [ @@ -309735,6 +309849,10 @@ "a256bb2dc766a40f21115049572246bf003499ba", [] ], + "ping-rt-entries-expected.txt": [ + "9655aed4059d9f60b88d16dac3b03c05a39f15af", + [] + ], "resource-timing-level1.js": [ "95b5cdfb1ed0ca2bbfd6b692ad565512218dd7a4", [] @@ -309776,6 +309894,10 @@ "31f0e3ab417a69079f20748751b2d6be9a7d5552", [] ], + "close.html": [ + "02c275f37b66e8a0b434c6fa57b347994d523118", + [] + ], "connection-reuse-test.js": [ "453fbd34051067480139058d40541368bce2207c", [] @@ -310036,6 +310158,10 @@ "test_resource_timing.js": [ "598a727bf88e7f47556d509f6929a86b64b0506c", [] + ], + "worklet-rt-entries-expected.txt": [ + "6943681e3c437dd9a97ac11a7bf38d7cac44b68f", + [] ] }, "resources": { @@ -316750,7 +316876,7 @@ [] ], "META.yml": [ - "91cd8c9d8056e8512e049280b7c1a43a76b3074f", + "411450e0b142931544fbaac5669352201ee37328", [] ] }, @@ -338078,7 +338204,7 @@ ] ], "currentchange-app-history-back-forward-same-doc.html": [ - "85a93a21bd0f4a708dc99b751c533342743410ce", + "9b1b777614b9d263ff7efcaa3f8e2fc8731840e9", [ null, {} @@ -338154,13 +338280,6 @@ {} ] ], - "currentchange-dispose-ordering.html": [ - "f9d23f7dd5da79afb95bd998c618685c225c9e6a", - [ - null, - {} - ] - ], "currentchange-history-back-same-doc.html": [ "7cfecb15b8ef9e4dc4e2cf678262e889b8d02550", [ @@ -338324,13 +338443,6 @@ {} ] ], - "navigate-cross-document-event-order.html": [ - "1c1758a002eb8ac5e8ba8945dc6163d32a1a70f4", - [ - null, - {} - ] - ], "navigate-history-state-replace.html": [ "b4b9559fb56cb782941210eefbaef379afdb7e5a", [ @@ -338373,13 +338485,6 @@ {} ] ], - "navigate-same-document-event-order.html": [ - "4be537fb7ae1c2223fa536b476da614f54d8e3e4", - [ - null, - {} - ] - ], "navigate-same-document.html": [ "bad420272c40b7e0ccf4df73e0c4cea38615debd", [ @@ -338408,13 +338513,6 @@ {} ] ], - "navigate-transitionWhile-reject-event-order.html": [ - "96e742766cccc8430c03f1446f15a2a3a98cf923", - [ - null, - {} - ] - ], "reload-base-url.html": [ "35b29b9d2fb032f97f7bd8ba607f928aec60571e", [ @@ -339437,41 +339535,6 @@ {} ] ], - "navigateerror-ordering-cross-document.html": [ - "ba1edceead52cb79b9bcb77c317dca5e2636d817", - [ - null, - {} - ] - ], - "navigateerror-ordering-location-api-reentrant.html": [ - "435690fcbc7ade816d52c91c80372a7449755916", - [ - null, - {} - ] - ], - "navigateerror-ordering-location-api.html": [ - "92b76ad5ff0a502b48dff59f49ad6547c3749cc7", - [ - null, - {} - ] - ], - "navigateerror-ordering-transitionWhile-reentrant.html": [ - "f5b4f84e8b6911dc38be308603254550d391b971", - [ - null, - {} - ] - ], - "navigateerror-ordering-transitionWhile.html": [ - "8f99d8a8a021e6eeae90c0f46e360d05129614ad", - [ - null, - {} - ] - ], "navigatesuccess-cross-document.html": [ "1d528c1f5f9154c1bc089315a0ae11d72b7d3820", [ @@ -339529,7 +339592,7 @@ ] ], "transitionWhile-and-navigate.html": [ - "66a43b25ec2a9f251e2183cd4373e99fa56a13c7", + "65e9d0492784368687dc53d4ae75716d279073fe", [ null, {} @@ -339620,6 +339683,106 @@ ] ] }, + "ordering": { + "back-same-document.html": [ + "f4a2c382b8b9fd7d642cd943ade4fc69f1e5a668", + [ + "app-history/ordering/back-same-document.html?", + {} + ], + [ + "app-history/ordering/back-same-document.html?currentchange", + {} + ], + [ + "app-history/ordering/back-same-document.html?transitionWhile", + {} + ], + [ + "app-history/ordering/back-same-document.html?transitionWhile¤tChange", + {} + ] + ], + "currentchange-dispose-ordering.html": [ + "f9d23f7dd5da79afb95bd998c618685c225c9e6a", + [ + null, + {} + ] + ], + "navigate-cross-document-event-order.html": [ + "1c1758a002eb8ac5e8ba8945dc6163d32a1a70f4", + [ + null, + {} + ] + ], + "navigate-same-document-transitionWhile-reject.html": [ + "84e95eea75259541c0a943cccec5fd5161de8b0d", + [ + "app-history/ordering/navigate-same-document-transitionWhile-reject.html?", + {} + ], + [ + "app-history/ordering/navigate-same-document-transitionWhile-reject.html?currentchange", + {} + ] + ], + "navigate-same-document.html": [ + "0d30eeddfb67da3c1d5efaef8a7b7af938db0c38", + [ + "app-history/ordering/navigate-same-document.html?", + {} + ], + [ + "app-history/ordering/navigate-same-document.html?currentchange", + {} + ], + [ + "app-history/ordering/navigate-same-document.html?transitionWhile", + {} + ], + [ + "app-history/ordering/navigate-same-document.html?transitionWhile¤tChange", + {} + ] + ], + "navigateerror-ordering-location-api-reentrant.html": [ + "435690fcbc7ade816d52c91c80372a7449755916", + [ + null, + {} + ] + ], + "navigateerror-ordering-location-api.html": [ + "92b76ad5ff0a502b48dff59f49ad6547c3749cc7", + [ + null, + {} + ] + ], + "navigateerror-ordering-navigate-cross-document.html": [ + "ba1edceead52cb79b9bcb77c317dca5e2636d817", + [ + null, + {} + ] + ], + "navigateerror-ordering-transitionWhile-reentrant.html": [ + "f5b4f84e8b6911dc38be308603254550d391b971", + [ + null, + {} + ] + ], + "navigateerror-ordering-transitionWhile.html": [ + "8f99d8a8a021e6eeae90c0f46e360d05129614ad", + [ + null, + {} + ] + ] + }, "per-entry-events": { "dispose-cross-document.html": [ "22ea15bae9846d0075ef3c8092f62a732c727d2b", @@ -354981,7 +355144,7 @@ ] ], "cookieListItem_attributes.https.any.js": [ - "e46d6b6caa594d722f7502d06c18c13513e97213", + "88ec4e98a28e4f638687a20aada6f45a665202f5", [ "cookie-store/cookieListItem_attributes.https.any.html", { @@ -379131,7 +379294,7 @@ ] ], "get-shorthand.html": [ - "0355e3995f7de61a1a650bcc1380e3ed2b73b4b6", + "6ce318d5995cd10c1fd15d3d3c24ae7863783364", [ null, {} @@ -385990,13 +386153,6 @@ {} ] ], - "has-specificity.html": [ - "186d35fdd97286d5dcd6e5d7fddc3bd2c541349e", - [ - null, - {} - ] - ], "hover-002.html": [ "02cee99bf6cd161eb95806854cb12e39504a359e", [ @@ -417263,6 +417419,42 @@ } ] ], + "nested-worker.https.window.js": [ + "3eeb435badb2d00404e0e214e1d42c4be2817f8a", + [ + "fetch/private-network-access/nested-worker.https.window.html", + { + "script_metadata": [ + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/support.sub.js" + ] + ] + } + ] + ], + "nested-worker.window.js": [ + "6d246e1c76d6c5f603c3e29430ae0586fdb9f5ad", + [ + "fetch/private-network-access/nested-worker.window.html", + { + "script_metadata": [ + [ + "script", + "/common/utils.js" + ], + [ + "script", + "resources/support.sub.js" + ] + ] + } + ] + ], "service-worker-fetch.https.window.js": [ "edb20c04940e3fa76a2dd99e71785f97285c31c6", [ @@ -443544,6 +443736,41 @@ } ] ], + "fenced-frame-bypass.tentative.https.window.js": [ + "f2c3090750661536774e00794d25db5887b9cfcb", + [ + "html/cross-origin-embedder-policy/anonymous-iframe/fenced-frame-bypass.tentative.https.window.html", + { + "script_metadata": [ + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "/common/utils.js" + ], + [ + "script", + "/common/dispatcher/dispatcher.js" + ], + [ + "script", + "../credentialless/resources/common.js" + ], + [ + "script", + "./resources/common.js" + ], + [ + "timeout", + "long" + ] + ], + "timeout": "long" + } + ] + ], "fenced-frame.tentative.https.window.js": [ "8f6bfd35d761a69725f88efe484a31555c5d5b8a", [ @@ -446805,6 +447032,22 @@ } ] ], + "render-blocking-mechanism": { + "parser-inserted-style-element.tentative.html": [ + "9a358aa4938e762b31b43fb38381a763c2222c33", + [ + null, + {} + ] + ], + "parser-inserted-stylesheet-link.tentative.html": [ + "0a771448fd2d4152619f9f420e2d5c30efcd9626", + [ + null, + {} + ] + ] + }, "self-origin.any.js": [ "c103a32144fb96b9b76b91fd440e3725e9a5838d", [ @@ -451736,6 +451979,41 @@ {} ] ], + "canvas-descendants-focusability-001.html": [ + "327c9f49d6aeffc2b3eef49cc38c8a00ebf15f95", + [ + null, + {} + ] + ], + "canvas-descendants-focusability-002.html": [ + "aa607365d56faa320ee74da362b54a1f326e5c29", + [ + null, + {} + ] + ], + "canvas-descendants-focusability-003.tentative.html": [ + "98d60cfe9898447d41625c34c3ff4bcd1cec3788", + [ + null, + {} + ] + ], + "canvas-descendants-focusability-004.tentative.html": [ + "5d8dfcd2f4272b2cfb7981ac0d2cc4c67adaa296", + [ + null, + {} + ] + ], + "canvas-descendants-focusability-005.html": [ + "f3bee6b06bc1273dea3d2d9de6645a0c2b5aa1b7", + [ + null, + {} + ] + ], "context.arguments.missing.html": [ "eb4d69aed09c3989ececac9929e46f8b15b9aed1", [ @@ -456686,7 +456964,7 @@ ] ], "popup-light-dismiss.tentative.html": [ - "e0012587fd217a935409b6c70af4db5c94a73332", + "2b37c2d64510efd1e9dcb5bb7c0d877fd450fe36", [ null, { @@ -466217,6 +466495,13 @@ {} ] ], + "inert-canvas-fallback-content.tentative.html": [ + "f22549b50377f17b3e03cb6c26c996122b7c8e2b", + [ + null, + {} + ] + ], "inert-computed-style.html": [ "a68eb7465128937801d5417cbe4ed2ca1bfc3757", [ @@ -471972,6 +472257,13 @@ } ] ], + "MediaStreamTrackGenerator-in-service-worker.https.html": [ + "389a30d0d940e12bda9f520886d2dbed68532bd0", + [ + null, + {} + ] + ], "MediaStreamTrackGenerator-in-shared-worker.https.html": [ "deecfccad16f5df61028b9fc65e0e65e5f825e64", [ @@ -472046,7 +472338,7 @@ ] ], "MediaRecorder-destroy-script-execution.html": [ - "6375004d36b2816c1a5e54c403d33e24fe386e1a", + "3ea5a4c952c5ae3715a39901c1c0410221ac4012", [ null, {} @@ -495206,8 +495498,15 @@ {} ] ], + "input.html": [ + "a46d416671c1c6a14f979846cf3afd460d0cb0c9", + [ + null, + {} + ] + ], "link.html": [ - "6213ed8b45d72aca175384ba2fd6e4b6edbd0848", + "c49576a8e650bc5525bf35c3c2ca07c6ec64009e", [ null, {} @@ -495254,6 +495553,13 @@ null, {} ] + ], + "workers.html": [ + "3a23ad71a31555849bb8bf0a0161315cdd806785", + [ + null, + {} + ] ] }, "initiator-type-for-script.html": [ @@ -495263,6 +495569,13 @@ {} ] ], + "input-sequence-of-events.html": [ + "446e24a0bca8a48cc0ef7e62ddf3a84017e8e6f5", + [ + null, + {} + ] + ], "nested-context-navigations-embed.html": [ "5c8a62a9ae281d7f4823e27ae7fe37032de8cb2e", [ @@ -495332,6 +495645,13 @@ {} ] ], + "ping-rt-entries.html": [ + "34dad10b9f28b6b3dc9724f571aa3db7a82ad32c", + [ + null, + {} + ] + ], "redirects.html": [ "ba69907a5f6e46a3e8a79041da17039d14d20feb", [ @@ -495425,6 +495745,13 @@ {} ] ], + "script-rt-entries.html": [ + "cdd72bd1e25199085c8178b618a00200c86a3de9", + [ + null, + {} + ] + ], "sizes-cache.any.js": [ "af70e5a6ded3e63d158fd929feacf0827b3cafc9", [ @@ -495636,6 +495963,13 @@ {} ] ], + "worklet-rt-entries.html": [ + "8ed280be1706b60ff2f8942a503ab7e79e08bd15", + [ + null, + {} + ] + ], "xhr-resource-timing.html": [ "6f8f3331861062aa96b533cd94d9add21ea7e382", [ @@ -506780,6 +507114,13 @@ } ] ], + "cross-realm-crash.window.js": [ + "5fc7ce37a5f6d2dbd90b5f898bcd7b198f0c50b0", + [ + "streams/readable-streams/cross-realm-crash.window.html", + {} + ] + ], "default-reader.any.js": [ "664853e28cfb9f432631ac444dab9836f869bdec", [
diff --git a/third_party/blink/web_tests/external/wpt/accelerometer/META.yml b/third_party/blink/web_tests/external/wpt/accelerometer/META.yml index 7df27e1f..dbfac71 100644 --- a/third_party/blink/web_tests/external/wpt/accelerometer/META.yml +++ b/third_party/blink/web_tests/external/wpt/accelerometer/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/accelerometer/ suggested_reviewers: - - zqzhang - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/ambient-light/META.yml b/third_party/blink/web_tests/external/wpt/ambient-light/META.yml index c3f69ba..e173970 100644 --- a/third_party/blink/web_tests/external/wpt/ambient-light/META.yml +++ b/third_party/blink/web_tests/external/wpt/ambient-light/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/ambient-light/ suggested_reviewers: - - zqzhang - riju - rakuco - Honry
diff --git a/third_party/blink/web_tests/external/wpt/battery-status/META.yml b/third_party/blink/web_tests/external/wpt/battery-status/META.yml index a069984d..77d19a82 100644 --- a/third_party/blink/web_tests/external/wpt/battery-status/META.yml +++ b/third_party/blink/web_tests/external/wpt/battery-status/META.yml
@@ -1,5 +1,4 @@ spec: https://w3c.github.io/battery/ suggested_reviewers: - anssiko - - zqzhang - Honry
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-001.html new file mode 100644 index 0000000..baececd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-001.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text test: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#hyphenation"> +<link rel="match" href="reference/hyphens-vertical-001-ref.html"> +<meta name="assert" content="Check rendering of soft-hyphen character in vertical writing mode"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen­ation +</div> + +<div> + hyphen‐<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-002.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-002.html new file mode 100644 index 0000000..e449526 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-002.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text test: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#hyphenation"> +<link rel="match" href="reference/hyphens-vertical-002-ref.html"> +<meta name="assert" content="Check rendering of soft-hyphen character in vertical writing mode"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + text-orientation: upright; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen­ation +</div> + +<div> + hyphen‐<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-003.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-003.html new file mode 100644 index 0000000..2b1c6271 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-003.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text test: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#hyphenation"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#hyphenate-character"> +<link rel="match" href="reference/hyphens-vertical-003-ref.html"> +<meta name="assert" content="Check rendering of soft-hyphen character in vertical writing mode"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + hyphenate-character: "+="; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen­ation +</div> + +<div> + hyphen+=<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-004.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-004.html new file mode 100644 index 0000000..cee7718 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/hyphens-vertical-004.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text test: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#hyphenation"> +<link rel="help" href="https://drafts.csswg.org/css-text-4/#hyphenate-character"> +<link rel="match" href="reference/hyphens-vertical-004-ref.html"> +<meta name="assert" content="Check rendering of soft-hyphen character in vertical writing mode"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + text-orientation: upright; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + hyphenate-character: "+="; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen­ation +</div> + +<div> + hyphen+=<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-001-ref.html new file mode 100644 index 0000000..5be7a840 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-001-ref.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text reference: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen‐<br>ation +</div> + +<div> + hyphen‐<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-002-ref.html new file mode 100644 index 0000000..cb24021 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-002-ref.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text reference: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + text-orientation: upright; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen‐<br>ation +</div> + +<div> + hyphen‐<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-003-ref.html new file mode 100644 index 0000000..6d3ea15 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-003-ref.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text reference: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + hyphenate-character: "+="; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen+=<br>ation +</div> + +<div> + hyphen+=<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-004-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-004-ref.html new file mode 100644 index 0000000..63c7511 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/hyphens/reference/hyphens-vertical-004-ref.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text reference: soft hyphens in vertical writing mode</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> + +<style> + div { + font: 16px monospace; + writing-mode: vertical-rl; + text-orientation: upright; + border: 1px solid gray; + margin: 10px; + padding: 2px; + hyphens: manual; + width: 3em; + height: 9ch; + hyphenate-character: "+="; + } +</style> + +<p>Test passes if the two boxes look the same:</p> + +<div> + hyphen+=<br>ation +</div> + +<div> + hyphen+=<br>ation +</div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml b/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml index bf48f80..916bc80 100644 --- a/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml +++ b/third_party/blink/web_tests/external/wpt/generic-sensor/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/sensors/ suggested_reviewers: - - zqzhang - riju - rakuco - Honry
diff --git a/third_party/blink/web_tests/external/wpt/gyroscope/META.yml b/third_party/blink/web_tests/external/wpt/gyroscope/META.yml index 6a48535..8f553a8 100644 --- a/third_party/blink/web_tests/external/wpt/gyroscope/META.yml +++ b/third_party/blink/web_tests/external/wpt/gyroscope/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/gyroscope/ suggested_reviewers: - - zqzhang - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml b/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml index 3dd015f..ecbf633f 100644 --- a/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml +++ b/third_party/blink/web_tests/external/wpt/html-media-capture/META.yml
@@ -1,3 +1,3 @@ spec: https://w3c.github.io/html-media-capture/ suggested_reviewers: - - zqzhang + - anssiko
diff --git a/third_party/blink/web_tests/external/wpt/magnetometer/META.yml b/third_party/blink/web_tests/external/wpt/magnetometer/META.yml index d7d395e..9193c0d 100644 --- a/third_party/blink/web_tests/external/wpt/magnetometer/META.yml +++ b/third_party/blink/web_tests/external/wpt/magnetometer/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/magnetometer/ suggested_reviewers: - - zqzhang - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-transfer.https-expected.txt b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-transfer.https-expected.txt deleted file mode 100644 index 52a0b41..0000000 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-transfer.https-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL MediaStreamTrack transfer to Worker promise_test: Unhandled rejection with value: object "DataCloneError: Failed to execute 'postMessage' on 'Worker': Value at index 0 does not have a transferable type." -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml b/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml index 4273858..b780d2c9 100644 --- a/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml +++ b/third_party/blink/web_tests/external/wpt/orientation-sensor/META.yml
@@ -1,6 +1,5 @@ spec: https://w3c.github.io/orientation-sensor/ suggested_reviewers: - - zqzhang - riju - Honry - rakuco
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/input.html b/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/input.html new file mode 100644 index 0000000..a46d416 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/input.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing initiator type: input</title> +<link rel="author" title="Google" href="http://www.google.com/" /> +<link rel="help" href="https://www.w3.org/TR/resource-timing-2/#dom-performanceresourcetiming-initiatortype"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resource-timing/resources/observe-entry.js"></script> +<script src="resources/initiator-type-test.js"></script> +</head> +<body> +<input type="image" src="/resource-timing/resources/resource_timing_test0.png"> +<script> + initiator_type_test("resource_timing_test0.png", "input", "<input type=image>"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/link.html b/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/link.html index 6213ed8..c49576a 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/link.html +++ b/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/link.html
@@ -18,6 +18,7 @@ href="/resource-timing/resources/resource_timing_test0.css?id=preload"> <link rel="prerender" href="/resource-timing/resources/green.html?id=prerender"> <link rel="manifest" href="/resource-timing/resources/manifest.json"> +<link rel="modulepreload" href="resources/empty.js?id=modulePreload"> <script> initiator_type_test("nested.css", "link", "<link>"); @@ -30,6 +31,7 @@ initiator_type_test("resource_timing_test0.css?id=preload", "link", "<link preload>"); initiator_type_test("green.html?id=prerender", "link", "<link prerender>"); initiator_type_test("manifest.json", "link", "<link manifest>"); + initiator_type_test("resources/empty.js?id=modulePreload", "other", "module preload"); </script> <ol>This content forces a font to get fetched</ol> </body>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/workers.html b/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/workers.html new file mode 100644 index 0000000..3a23ad71 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/initiator-type/workers.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing initiatorType: worker resources</title> +<link rel="help" href="https://www.w3.org/TR/resource-timing-2/#dom-performanceresourcetiming-initiatortype"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resource-timing/resources/observe-entry.js"></script> +<script src="resources/initiator-type-test.js"></script> + +</head> + +<script> + const moduleWorkerURL = 'resources/empty.js?moduleWorker'; + const workerURL = 'resources/empty.js?worker'; + new Worker(moduleWorkerURL, {type: "module"}); + new Worker(workerURL, {type: "classic"}); + initiator_type_test(workerURL, "other", "classic worker"); + initiator_type_test(moduleWorkerURL, "other", "module worker"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/input-sequence-of-events.html b/third_party/blink/web_tests/external/wpt/resource-timing/input-sequence-of-events.html new file mode 100644 index 0000000..446e24a0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/input-sequence-of-events.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test the sequence of events when reporting input timing.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> + async_test(t => { + const input = document.createElement('input'); + input.type = "image"; + const absoluteURL = new URL('resources/blue.png', location.href).toString(); + t.add_cleanup(() => input.remove()); + input.addEventListener('load', t.step_func(() => { + assert_equals(performance.getEntriesByName(absoluteURL).length, 1); + t.done(); + })); + input.src = absoluteURL; + document.body.appendChild(input); + }, "An image input element should receive its load event after the ResourceTiming entry is available"); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/ping-rt-entries-expected.txt b/third_party/blink/web_tests/external/wpt/resource-timing/ping-rt-entries-expected.txt new file mode 100644 index 0000000..9655aed4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/ping-rt-entries-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Hyperlink auditing (<a ping>) should have a resource timing entry promise_test: Unhandled rejection with value: object "Error: observe_entry: timeout" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/ping-rt-entries.html b/third_party/blink/web_tests/external/wpt/resource-timing/ping-rt-entries.html new file mode 100644 index 0000000..34dad10b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/ping-rt-entries.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing Entry For hyperlink audit (ping)</title> +<link rel="help" href="https://w3c.github.io/resource-timing/"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resource-timing/resources/observe-entry.js"></script> +</head> +<body> +<script> + promise_test(async t => { + const link = document.createElement('a'); + const delay = 500; + const ping = `/xhr/resources/delay.py?ms=${delay}`; + link.setAttribute('href', 'resources/close.html'); + link.setAttribute('target', '_blank'); + link.setAttribute('ping', ping); + link.innerText = 'Link'; + document.body.appendChild(link); + link.click(); + const entry = await observe_entry(ping); + assert_equals(entry.initiatorType, 'ping'); + assert_greater_than(entry.duration, delay); + }, "Hyperlink auditing (<a ping>) should have a resource timing entry"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/close.html b/third_party/blink/web_tests/external/wpt/resource-timing/resources/close.html new file mode 100644 index 0000000..02c275f3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/close.html
@@ -0,0 +1 @@ +<script>window.close()</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/script-rt-entries.html b/third_party/blink/web_tests/external/wpt/resource-timing/script-rt-entries.html new file mode 100644 index 0000000..cdd72bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/script-rt-entries.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing Entry Sequence of Events for Scripts</title> +<link rel="help" href="https://w3c.github.io/resource-timing/"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + async_test(t => { + const script = document.createElement("script"); + const url = new URL('resources/empty.js', location.href).toString(); + script.addEventListener('load', t.step_func(() => { + assert_equals(performance.getEntriesByName(url).length, 1); + t.done(); + })); + script.src = url; + document.body.appendChild(script); + t.add_cleanup(() => script.remove()); + }, "The RT entry for script should be available when the script 'load' event fires"); + + async_test(t => { + const script = document.createElement("script"); + const url = new URL('resources/non-existent.js', location.href).toString(); + script.addEventListener('error', t.step_func(() => { + assert_equals(performance.getEntriesByName(url).length, 1); + t.done(); + })); + script.src = url; + document.body.appendChild(script); + t.add_cleanup(() => script.remove()); + }, "The RT entry for a non-existent script should be available when the script 'error' event fires"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/worklet-rt-entries-expected.txt b/third_party/blink/web_tests/external/wpt/resource-timing/worklet-rt-entries-expected.txt new file mode 100644 index 0000000..6943681 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/worklet-rt-entries-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Worklets should generate Resource Timing Entries promise_test: Unhandled rejection with value: object "TypeError: Cannot read properties of undefined (reading 'addModule')" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/worklet-rt-entries.html b/third_party/blink/web_tests/external/wpt/resource-timing/worklet-rt-entries.html new file mode 100644 index 0000000..8ed280b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resource-timing/worklet-rt-entries.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8" /> +<title>Resource Timing Entry Sequence of Events for Worklets</title> +<link rel="help" href="https://w3c.github.io/resource-timing/"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + promise_test(async() => { + const url = new URL("/worklets/resources/empty-worklet-script.js", location.href).toString(); + await CSS.paintWorklet.addModule(url); + assert_equals(performance.getEntriesByName(url).length, 1); + }, "Worklets should generate Resource Timing Entries"); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/vibration/META.yml b/third_party/blink/web_tests/external/wpt/vibration/META.yml index 91cd8c9d..411450e 100644 --- a/third_party/blink/web_tests/external/wpt/vibration/META.yml +++ b/third_party/blink/web_tests/external/wpt/vibration/META.yml
@@ -1,3 +1,3 @@ spec: https://w3c.github.io/vibration/ suggested_reviewers: - - zqzhang + - anssiko
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/update-and-send-events-replacement-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/update-and-send-events-replacement-expected.txt deleted file mode 100644 index 8c99926e..0000000 --- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/update-and-send-events-replacement-expected.txt +++ /dev/null
@@ -1,45 +0,0 @@ -This is a testharness.js-based test. -PASS Removes an animation when another covers the same properties -PASS Removes an animation after another animation finishes -PASS Removes an animation after multiple other animations finish -PASS Removes an animation after it finishes -PASS Removes an animation after seeking another animation -PASS Removes an animation after seeking it -PASS Removes an animation after updating the fill mode of another animation -PASS Removes an animation after updating its fill mode -PASS Removes an animation after updating another animation's effect to one with different timing -PASS Removes an animation after updating its effect to one with different timing -PASS Removes an animation after updating another animation's timeline -PASS Removes an animation after updating its timeline -PASS Removes an animation after updating another animation's effect's properties -PASS Removes an animation after updating its effect's properties -PASS Removes an animation after updating another animation's effect to one with different properties -PASS Removes an animation after updating its effect to one with different properties -PASS Removes an animation when another animation uses a shorthand -PASS Removes an animation that uses a shorthand -PASS Removes an animation by another animation using logical properties -PASS Removes an animation using logical properties -PASS Removes an animation by another animation using logical properties after updating the context -PASS Removes an animation after updating another animation's effect's target -PASS Removes an animation after updating its effect's target -PASS Removes an animation after updating another animation's effect to one with a different target -PASS Removes an animation after updating its effect to one with a different target -PASS Does NOT remove a CSS animation tied to markup -FAIL Removes a CSS animation no longer tied to markup assert_equals: expected "removed" but got "active" -PASS Does NOT remove a CSS transition tied to markup -FAIL Removes a CSS transition no longer tied to markup assert_equals: expected "removed" but got "active" -PASS Dispatches an event when removing -PASS Does NOT dispatch a remove event twice -PASS Does NOT remove an animation after making a redundant change to another animation's current time -PASS Does NOT remove an animation after making a redundant change to its current time -PASS Does NOT remove an animation after making a redundant change to another animation's timeline -PASS Does NOT remove an animation after making a redundant change to its timeline -PASS Does NOT remove an animation after making a redundant change to another animation's effect's properties -PASS Does NOT remove an animation after making a redundant change to its effect's properties -PASS Updates ALL timelines before checking for replacement -PASS Dispatches remove events after finish events -PASS Fires remove event before requestAnimationFrame -PASS Queues all remove events before running them -PASS Performs removal in deeply nested iframes -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https-expected.txt b/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https-expected.txt new file mode 100644 index 0000000..225cd82b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL WebLocks of an iframe under a 3rd-party site are partitioned assert_equals: The 1p iframe failed to acquire the lock expected (undefined) undefined but got (boolean) true +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https.html b/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https.html new file mode 100644 index 0000000..eb4e8d0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-locks/partitioned-web-locks.tentative.https.html
@@ -0,0 +1,64 @@ + +< !DOCTYPE html > +<meta charset="utf-8"/> +<title>Web Locks API: Partitioned WebLocks</title> + +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="/cookies/resources/cookie-helper.sub.js"></script> +<script src="../credentialless/resources/common.js"></script> +<script src="resources/helpers.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> +<body> +<script> + +const { HTTPS_ORIGIN, HTTPS_NOTSAMESITE_ORIGIN } = get_host_info(); +// Map of lock_id => function that releases a lock. +const held = new Map(); +let next_lock_id = 1; + +async function run_test(t) { + let target_url = HTTPS_ORIGIN + '/web-locks/resources/iframe.html'; + target_url = new URL( + `./resources/partitioned-parent.html?target=${encodeURIComponent(target_url)}`, + HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname); + + navigator.locks.request('testLock', {mode: 'exclusive', ifAvailable: true}, + lock => { + if (lock === null) { + assert_true(false) + return; + } + let lock_id = next_lock_id++; + let release; + const promise = new Promise(r => { release = r; }); + held.set(lock_id, release); + return promise; + }); + + const w = window.open(target_url); + const result = await new Promise(resolve => window.onmessage = resolve); + + // When 3rd party storage partitioning is enabled, the iFrame should be able + // to aquire a lock with the same name as one exclusively held by the opener + // of its top window, even when that opener has the same origin. + assert_equals(result.data.failed, undefined, + 'The 1p iframe failed to acquire the lock'); + + t.add_cleanup(() => { + w.close() + for(let i = 1; i < next_lock_id; i++){ + held.get(i)(); + } + }); +} + +promise_test(t => { + return run_test(t); +}, 'WebLocks of an iframe under a 3rd-party site are partitioned'); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/resources/partitioned-parent.html b/third_party/blink/web_tests/external/wpt/web-locks/resources/partitioned-parent.html new file mode 100644 index 0000000..5dafce49 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-locks/resources/partitioned-parent.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="utf-8"/> +<meta name="referrer" content="origin"> +<script> +async function onLoad() { + self.addEventListener('message', evt => { + if (self.opener) + self.opener.postMessage(evt.data, '*'); + else + self.top.postMessage(evt.data, '*'); + }, { once: true }); + + const params = new URLSearchParams(self.location.search); + const frame = document.createElement('iframe'); + frame.src = params.get('target'); + document.body.appendChild(frame); + + frame.addEventListener('load', function(){ + frame.contentWindow.postMessage({op: 'request', + name: 'testLock', ifAvailable: true}, '*'); + }); +} +self.addEventListener('load', onLoad); +</script>
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-default-value-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-default-value-expected.png index 701a374..a3addc5 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-default-value-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-default-value-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-gradient-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-gradient-image-expected.png index fb37361..5d07654 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-gradient-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-gradient-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-color-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-color-expected.png index fe96bac..9ab503d 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-color-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-color-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-image-expected.png index 2cdea910..228c5d60 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-svg-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-svg-expected.png index 5d5574517..3645797b 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-svg-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-image-svg-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-multiple-background-layers-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-multiple-background-layers-expected.png index 6e462b0..d261b79 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-multiple-background-layers-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-multiple-background-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-single-layer-no-blending-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-single-layer-no-blending-expected.png index 26de77179..53bd4dd 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-single-layer-no-blending-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-single-layer-no-blending-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-tiled-gradient-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-tiled-gradient-expected.png index 5b2cb7d..9eb2088 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-tiled-gradient-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/background-blend-mode-tiled-gradient-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-expected.png index 02d7f3c..c660ac5 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-stacking-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-stacking-expected.png index 6eef91e..762f1fa 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-stacking-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/effect-background-blend-mode-stacking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-1-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-1-expected.png index 57e7c10..2a4cf3a 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-1-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-1-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-2-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-2-expected.png index 7ae21576..5e7dd22 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-2-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-3-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-3-expected.png index 089ff7c..4cfeeac5 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-3-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/css3/blending/mix-blend-mode-isolated-group-3-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-background-image-space-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-background-image-space-expected.png index 2549378..35bcf31e 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-background-image-space-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-background-image-space-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-border-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-border-image-expected.png index 14cd13b..ddf6c04 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-border-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-border-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-image-filter-all-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-image-filter-all-expected.png index 6283ca4..bca87bc 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-image-filter-all-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-image-filter-all-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-mask-image-svg-expected.png index ed88c12..8b69fc1b 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-mask-image-svg-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-mask-image-svg-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-object-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-object-expected.png index 46483da..c3e811c 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-object-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-object-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-svg-fill-text-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-svg-fill-text-expected.png index ee8d50e..feaee0d 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-svg-fill-text-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/color-profile-svg-fill-text-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/ycbcr-with-cmyk-color-profile-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/ycbcr-with-cmyk-color-profile-expected.png index 5d040c7..5d56b945 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/ycbcr-with-cmyk-color-profile-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/ycbcr-with-cmyk-color-profile-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-border-radius-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-border-radius-expected.png index d1db2ab..6045346 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-border-radius-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-border-radius-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-expected.png index 04a3919..9ae0ecc 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png b/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png index 9042d25..3958a23e 100644 --- a/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-gl/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-default-value-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-default-value-expected.png index 701a374..a3addc5 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-default-value-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-default-value-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-gradient-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-gradient-image-expected.png index fb37361..c2634a3 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-gradient-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-gradient-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-color-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-color-expected.png index fe96bac..9ab503d 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-color-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-color-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-svg-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-svg-expected.png index 5d5574517..a9b7fbf 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-svg-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-image-svg-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-multiple-background-layers-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-multiple-background-layers-expected.png index 6e462b0..d261b79 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-multiple-background-layers-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-multiple-background-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-single-layer-no-blending-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-single-layer-no-blending-expected.png index 26de77179..53bd4dd 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-single-layer-no-blending-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-single-layer-no-blending-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-tiled-gradient-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-tiled-gradient-expected.png index 5b2cb7d..9eb2088 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-tiled-gradient-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/background-blend-mode-tiled-gradient-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-expected.png index 02d7f3c..c660ac5 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-stacking-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-stacking-expected.png index 6eef91e..762f1fa 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-stacking-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/effect-background-blend-mode-stacking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-1-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-1-expected.png index 57e7c10..2a4cf3a 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-1-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-1-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-2-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-2-expected.png index 7ae21576..5e7dd22 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-2-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-3-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-3-expected.png index 089ff7c..4cfeeac5 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-3-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/css3/blending/mix-blend-mode-isolated-group-3-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-cover-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-cover-expected.png index d0e95e9..f31f678 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-cover-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-cover-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-repeat-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-repeat-expected.png index 6efe026..29fa56d 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-repeat-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-background-image-repeat-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-border-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-border-image-expected.png index 14cd13b..ddf6c04 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-border-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-border-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-group-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-group-expected.png index 47123e2..8561c37 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-group-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-group-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-object-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-object-expected.png index 46483da..0ce0793 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-object-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/color-profile-object-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/rgb-png-with-cmyk-color-profile-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/rgb-png-with-cmyk-color-profile-expected.png index e8709c5..ed95cd22 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/rgb-png-with-cmyk-color-profile-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/rgb-png-with-cmyk-color-profile-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/ycbcr-with-cmyk-color-profile-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/ycbcr-with-cmyk-color-profile-expected.png index 5d040c7..f978852 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/ycbcr-with-cmyk-color-profile-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/ycbcr-with-cmyk-color-profile-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-border-radius-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-border-radius-expected.png index d1db2ab..6045346 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-border-radius-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-border-radius-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-expected.png index 04a3919..9ae0ecc 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png index 9042d25..a770804 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/images/yuv-decode-eligible/color-profile-image-profile-match-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/media/color-profile-video-poster-image-expected.png b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/media/color-profile-video-poster-image-expected.png index 4545b78..149fc763 100644 --- a/third_party/blink/web_tests/flag-specific/skia-vulkan-native/media/color-profile-video-poster-image-expected.png +++ b/third_party/blink/web_tests/flag-specific/skia-vulkan-native/media/color-profile-video-poster-image-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/css/css-pseudo/idlharness-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/css/css-pseudo/idlharness-expected.txt deleted file mode 100644 index f76169b..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/css/css-pseudo/idlharness-expected.txt +++ /dev/null
@@ -1,29 +0,0 @@ -This is a testharness.js-based test. -FAIL idl_test setup promise_test: Unhandled rejection with value: object "TypeError: window.getPseudoElements is not a function" -PASS idl_test validation -PASS Partial interface Element: original interface defined -PASS Partial interface Element: member names are unique -PASS Element includes ParentNode: member names are unique -PASS Element includes NonDocumentTypeChildNode: member names are unique -PASS Element includes ChildNode: member names are unique -PASS Element includes Slottable: member names are unique -FAIL CSSPseudoElement interface: existence and properties of interface object assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface object length assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface object name assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: existence and properties of interface prototype object assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: attribute type assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: attribute element assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: attribute parent assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: operation pseudo(CSSOMString) assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement must be primary interface of beforeElements.item(0) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL Stringification of beforeElements.item(0) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL CSSPseudoElement interface: beforeElements.item(0) must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL CSSPseudoElement interface: beforeElements.item(0) must inherit property "element" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL CSSPseudoElement interface: beforeElements.item(0) must inherit property "parent" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL CSSPseudoElement interface: beforeElements.item(0) must inherit property "pseudo(CSSOMString)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL CSSPseudoElement interface: calling pseudo(CSSOMString) on beforeElements.item(0) with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL Element interface: operation pseudo(CSSOMString) assert_own_property: interface prototype object missing non-static operation expected property "pseudo" missing -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element-expected.txt deleted file mode 100644 index 314db574..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element-expected.txt +++ /dev/null
@@ -1,752 +0,0 @@ -This is a testharness.js-based test. -Found 736 tests; 389 PASS, 347 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS Loading data… -PASS Parsing: <http://example . -org> against <http://example.org/foo/bar> -PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar> -PASS Parsing: <https://test:@test> against <about:blank> -PASS Parsing: <https://:@test> against <about:blank> -FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x" -FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x" -PASS Parsing: <http:foo.com> against <http://example.org/foo/bar> -PASS Parsing: < :foo.com -> against <http://example.org/foo/bar> -PASS Parsing: < foo.com > against <http://example.org/foo/bar> -PASS Parsing: <a: foo.com> against <http://example.org/foo/bar> -PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar> -PASS Parsing: <lolscheme:x x#x x> against <about:blank> -PASS Parsing: <http://f:/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:00000000000000000000080/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:b/c> against <http://example.org/foo/bar> -FAIL Parsing: <http://f: /c> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://f: /c" but got "http://f:%20/c" -PASS Parsing: <http://f: -/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar> -FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://f: 21 / b ? d # e " but got "http://f:%2021%20/%20b%20?%20d%20#%20e" -PASS Parsing: <> against <http://example.org/foo/bar> -PASS Parsing: < > against <http://example.org/foo/bar> -PASS Parsing: <:foo.com/> against <http://example.org/foo/bar> -PASS Parsing: <:foo.com\> against <http://example.org/foo/bar> -PASS Parsing: <:> against <http://example.org/foo/bar> -PASS Parsing: <:a> against <http://example.org/foo/bar> -PASS Parsing: <:/> against <http://example.org/foo/bar> -PASS Parsing: <:\> against <http://example.org/foo/bar> -PASS Parsing: <:#> against <http://example.org/foo/bar> -PASS Parsing: <#> against <http://example.org/foo/bar> -PASS Parsing: <#/> against <http://example.org/foo/bar> -PASS Parsing: <#\> against <http://example.org/foo/bar> -PASS Parsing: <#;?> against <http://example.org/foo/bar> -PASS Parsing: <?> against <http://example.org/foo/bar> -PASS Parsing: </> against <http://example.org/foo/bar> -PASS Parsing: <:23> against <http://example.org/foo/bar> -PASS Parsing: </:23> against <http://example.org/foo/bar> -PASS Parsing: <\x> against <http://example.org/foo/bar> -PASS Parsing: <\\x\hello> against <http://example.org/foo/bar> -PASS Parsing: <::> against <http://example.org/foo/bar> -PASS Parsing: <::23> against <http://example.org/foo/bar> -FAIL Parsing: <foo://> against <http://example.org/foo/bar> assert_equals: pathname expected "" but got "//" -PASS Parsing: <http://a:b@c:29/d> against <http://example.org/foo/bar> -PASS Parsing: <http::@c:29> against <http://example.org/foo/bar> -PASS Parsing: <http://&a:foo(b]c@d:2/> against <http://example.org/foo/bar> -PASS Parsing: <http://::@c@d:2> against <http://example.org/foo/bar> -PASS Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar> -PASS Parsing: <http://foo.com/\@> against <http://example.org/foo/bar> -PASS Parsing: <http:\\foo.com\> against <http://example.org/foo/bar> -PASS Parsing: <http:\\a\b:c\d@foo.com\> against <http://example.org/foo/bar> -PASS Parsing: <foo:/> against <http://example.org/foo/bar> -PASS Parsing: <foo:/bar.com/> against <http://example.org/foo/bar> -FAIL Parsing: <foo://///////> against <http://example.org/foo/bar> assert_equals: pathname expected "///////" but got "/////////" -FAIL Parsing: <foo://///////bar.com/> against <http://example.org/foo/bar> assert_equals: pathname expected "///////bar.com/" but got "/////////bar.com/" -FAIL Parsing: <foo:////://///> against <http://example.org/foo/bar> assert_equals: pathname expected "//://///" but got "////://///" -PASS Parsing: <c:/foo> against <http://example.org/foo/bar> -PASS Parsing: <//foo/bar> against <http://example.org/foo/bar> -PASS Parsing: <http://foo/path;a??e#f#g> against <http://example.org/foo/bar> -PASS Parsing: <http://foo/abcd?efgh?ijkl> against <http://example.org/foo/bar> -PASS Parsing: <http://foo/abcd#foo?bar> against <http://example.org/foo/bar> -PASS Parsing: <[61:24:74]:98> against <http://example.org/foo/bar> -PASS Parsing: <http:[61:27]/:foo> against <http://example.org/foo/bar> -FAIL Parsing: <http://[1::2]:3:4> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://[1::2]:3:4" but got "http://[1::2]:3:4/" -FAIL Parsing: <http://2001::1> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://2001::1" but got "http://2001::1/" -FAIL Parsing: <http://2001::1]> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://2001::1]" but got "http://2001::1]/" -FAIL Parsing: <http://2001::1]:80> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://2001::1]:80" but got "http://2001::1]/" -PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar> -PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar> -PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar> -PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar> -PASS Parsing: <http:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ftp:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <https:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <madeupscheme:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <file://example:1/> against <about:blank> -PASS Parsing: <file://example:test/> against <about:blank> -FAIL Parsing: <file://example%/> against <about:blank> assert_equals: failure should set href to input expected "file://example%/" but got "file://example%25/" -PASS Parsing: <file://[example]/> against <about:blank> -PASS Parsing: <ftps:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <gopher:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ws:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <wss:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <data:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <http:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ftp:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <https:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <madeupscheme:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ftps:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <gopher:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ws:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <wss:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <data:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar> -PASS Parsing: </a/b/c> against <http://example.org/foo/bar> -PASS Parsing: </a/ /c> against <http://example.org/foo/bar> -PASS Parsing: </a%2fc> against <http://example.org/foo/bar> -PASS Parsing: </a/%2f/c> against <http://example.org/foo/bar> -PASS Parsing: <#β> against <http://example.org/foo/bar> -PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar> -PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar> -FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got "" -FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html" -FAIL Parsing: < File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html" -FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar" -FAIL Parsing: </C|\foo\bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///C%7C/foo/bar" -FAIL Parsing: <//C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file://c%7C/foo/bar" -PASS Parsing: <//server/file> against <file:///tmp/mock/path> -PASS Parsing: <\\server\file> against <file:///tmp/mock/path> -PASS Parsing: </\server/file> against <file:///tmp/mock/path> -PASS Parsing: <file:///foo/bar.txt> against <file:///tmp/mock/path> -PASS Parsing: <file:///home/me> against <file:///tmp/mock/path> -PASS Parsing: <//> against <file:///tmp/mock/path> -PASS Parsing: <///> against <file:///tmp/mock/path> -PASS Parsing: <///test> against <file:///tmp/mock/path> -PASS Parsing: <file://test> against <file:///tmp/mock/path> -FAIL Parsing: <file://localhost> against <file:///tmp/mock/path> assert_equals: href expected "file:///" but got "file://localhost/" -FAIL Parsing: <file://localhost/> against <file:///tmp/mock/path> assert_equals: href expected "file:///" but got "file://localhost/" -FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test" -PASS Parsing: <test> against <file:///tmp/mock/path> -PASS Parsing: <file:test> against <file:///tmp/mock/path> -PASS Parsing: <http://example.com/././foo> against <about:blank> -PASS Parsing: <http://example.com/./.foo> against <about:blank> -PASS Parsing: <http://example.com/foo/.> against <about:blank> -PASS Parsing: <http://example.com/foo/./> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/..> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/../> against <about:blank> -PASS Parsing: <http://example.com/foo/..bar> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> -PASS Parsing: <http://example.com/foo/../../..> against <about:blank> -PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> -PASS Parsing: <http://example.com/foo/%2e> against <about:blank> -FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2" -FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar" -PASS Parsing: <http://example.com////../..> against <about:blank> -PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> -PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> -PASS Parsing: <http://example.com/foo> against <about:blank> -PASS Parsing: <http://example.com/%20foo> against <about:blank> -PASS Parsing: <http://example.com/foo%> against <about:blank> -PASS Parsing: <http://example.com/foo%2> against <about:blank> -PASS Parsing: <http://example.com/foo%2zbar> against <about:blank> -PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank> -FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz" -PASS Parsing: <http://example.com/foo %91> against <about:blank> -FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> assert_equals: href expected "http://example.com/foo%00%51" but got "http://example.com/foo%00Q" -PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank> -PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank> -PASS Parsing: <http://example.com/foo bar> against <about:blank> -PASS Parsing: <http://example.com\\foo\\bar> against <about:blank> -PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank> -PASS Parsing: <http://example.com/@asdf%40> against <about:blank> -PASS Parsing: <http://example.com/你好你好> against <about:blank> -PASS Parsing: <http://example.com/‥/foo> against <about:blank> -PASS Parsing: <http://example.com//foo> against <about:blank> -PASS Parsing: <http://example.com//foo//bar> against <about:blank> -PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank> -PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank> -PASS Parsing: <data:test# »> against <about:blank> -PASS Parsing: <http://www.google.com> against <about:blank> -PASS Parsing: <http://192.0x00A80001> against <about:blank> -FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html" -PASS Parsing: <http://www/foo/%2E/html> against <about:blank> -PASS Parsing: <http://user:pass@/> against <about:blank> -PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> -PASS Parsing: <http:\\www.google.com\foo> against <about:blank> -PASS Parsing: <http://foo:80/> against <about:blank> -PASS Parsing: <http://foo:81/> against <about:blank> -FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got "" -PASS Parsing: <http://foo:-80/> against <about:blank> -PASS Parsing: <https://foo:443/> against <about:blank> -PASS Parsing: <https://foo:80/> against <about:blank> -PASS Parsing: <ftp://foo:21/> against <about:blank> -PASS Parsing: <ftp://foo:80/> against <about:blank> -FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got "" -FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got "" -PASS Parsing: <ws://foo:80/> against <about:blank> -PASS Parsing: <ws://foo:81/> against <about:blank> -PASS Parsing: <ws://foo:443/> against <about:blank> -PASS Parsing: <ws://foo:815/> against <about:blank> -PASS Parsing: <wss://foo:80/> against <about:blank> -PASS Parsing: <wss://foo:81/> against <about:blank> -PASS Parsing: <wss://foo:443/> against <about:blank> -PASS Parsing: <wss://foo:815/> against <about:blank> -PASS Parsing: <http:/example.com/> against <about:blank> -PASS Parsing: <ftp:/example.com/> against <about:blank> -PASS Parsing: <https:/example.com/> against <about:blank> -PASS Parsing: <madeupscheme:/example.com/> against <about:blank> -PASS Parsing: <file:/example.com/> against <about:blank> -PASS Parsing: <ftps:/example.com/> against <about:blank> -PASS Parsing: <gopher:/example.com/> against <about:blank> -PASS Parsing: <ws:/example.com/> against <about:blank> -PASS Parsing: <wss:/example.com/> against <about:blank> -PASS Parsing: <data:/example.com/> against <about:blank> -PASS Parsing: <javascript:/example.com/> against <about:blank> -PASS Parsing: <mailto:/example.com/> against <about:blank> -PASS Parsing: <http:example.com/> against <about:blank> -PASS Parsing: <ftp:example.com/> against <about:blank> -PASS Parsing: <https:example.com/> against <about:blank> -PASS Parsing: <madeupscheme:example.com/> against <about:blank> -PASS Parsing: <ftps:example.com/> against <about:blank> -PASS Parsing: <gopher:example.com/> against <about:blank> -PASS Parsing: <ws:example.com/> against <about:blank> -PASS Parsing: <wss:example.com/> against <about:blank> -PASS Parsing: <data:example.com/> against <about:blank> -PASS Parsing: <javascript:example.com/> against <about:blank> -PASS Parsing: <mailto:example.com/> against <about:blank> -PASS Parsing: <http:@www.example.com> against <about:blank> -PASS Parsing: <http:/@www.example.com> against <about:blank> -PASS Parsing: <http://@www.example.com> against <about:blank> -PASS Parsing: <http:a:b@www.example.com> against <about:blank> -PASS Parsing: <http:/a:b@www.example.com> against <about:blank> -PASS Parsing: <http://a:b@www.example.com> against <about:blank> -PASS Parsing: <http://@pple.com> against <about:blank> -PASS Parsing: <http::b@www.example.com> against <about:blank> -PASS Parsing: <http:/:b@www.example.com> against <about:blank> -PASS Parsing: <http://:b@www.example.com> against <about:blank> -FAIL Parsing: <http:/:@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/:@/www.example.com" but got "http:///www.example.com" -PASS Parsing: <http://user@/www.example.com> against <about:blank> -FAIL Parsing: <http:@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:@/www.example.com" but got "http:///www.example.com" -FAIL Parsing: <http:/@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/@/www.example.com" but got "http:///www.example.com" -FAIL Parsing: <http://@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http://@/www.example.com" but got "http:///www.example.com" -FAIL Parsing: <https:@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "https:@/www.example.com" but got "https:///www.example.com" -FAIL Parsing: <http:a:b@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:a:b@/www.example.com" but got "http://a:b@/www.example.com" -FAIL Parsing: <http:/a:b@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/a:b@/www.example.com" but got "http://a:b@/www.example.com" -PASS Parsing: <http://a:b@/www.example.com> against <about:blank> -FAIL Parsing: <http::@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http::@/www.example.com" but got "http:///www.example.com" -PASS Parsing: <http:a:@www.example.com> against <about:blank> -PASS Parsing: <http:/a:@www.example.com> against <about:blank> -PASS Parsing: <http://a:@www.example.com> against <about:blank> -PASS Parsing: <http://www.@pple.com> against <about:blank> -FAIL Parsing: <http:@:www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:@:www.example.com" but got "http://:www.example.com/" -FAIL Parsing: <http:/@:www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/@:www.example.com" but got "http://:www.example.com/" -FAIL Parsing: <http://@:www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http://@:www.example.com" but got "http://:www.example.com/" -PASS Parsing: <http://:@www.example.com> against <about:blank> -PASS Parsing: </> against <http://www.example.com/test> -PASS Parsing: </test.txt> against <http://www.example.com/test> -PASS Parsing: <.> against <http://www.example.com/test> -PASS Parsing: <..> against <http://www.example.com/test> -PASS Parsing: <test.txt> against <http://www.example.com/test> -PASS Parsing: <./test.txt> against <http://www.example.com/test> -PASS Parsing: <../test.txt> against <http://www.example.com/test> -PASS Parsing: <../aaa/test.txt> against <http://www.example.com/test> -PASS Parsing: <../../test.txt> against <http://www.example.com/test> -PASS Parsing: <中/test.txt> against <http://www.example.com/test> -PASS Parsing: <http://www.example2.com> against <http://www.example.com/test> -PASS Parsing: <//www.example2.com> against <http://www.example.com/test> -PASS Parsing: <file:...> against <http://www.example.com/test> -PASS Parsing: <file:..> against <http://www.example.com/test> -PASS Parsing: <file:a> against <http://www.example.com/test> -PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/> -FAIL Parsing: <http://example example.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://[]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[]" but got "http://[]/" -FAIL Parsing: <http://[:]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[:]" but got "http://[:]/" -FAIL Parsing: <http://GOO goo.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://GOOgoo.com> against <http://other.com/> -PASS Parsing: <\0 http://example.com/ \r > against <about:blank> -PASS Parsing: <http://www.foo。bar.com> against <http://other.com/> -FAIL Parsing: <http://zyx.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://zyx.com" but got "http://%EF%BF%BDzyx.com/" -FAIL Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%ef%b7%90zyx.com" but got "http://%EF%BF%BDzyx.com/" -FAIL Parsing: <https://�> against <about:blank> assert_equals: failure should set href to input expected "https://\ufffd" but got "https://%EF%BF%BD/" -FAIL Parsing: <https://%EF%BF%BD> against <about:blank> assert_equals: failure should set href to input expected "https://%EF%BF%BD" but got "https://%EF%BF%BD/" -PASS Parsing: <https://x/�?�#�> against <about:blank> -FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://Go.com> against <http://other.com/> -FAIL Parsing: <http://%41.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://%00.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%00.com" but got "http://%00.com/" -FAIL Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%ef%bc%85%ef%bc%90%ef%bc%90.com" but got "http://%00.com/" -PASS Parsing: <http://你好你好> against <http://other.com/> -FAIL Parsing: <https://faß.ExAmPlE/> against <about:blank> assert_equals: href expected "https://xn--fa-hia.example/" but got "https://fass.example/" -FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got "" -FAIL Parsing: <http://%zz%66%a.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%zz%66%a.com" but got "http://%25zzf%25a.com/" -FAIL Parsing: <http://%25> against <http://other.com/> assert_equals: failure should set href to input expected "http://%25" but got "http://%25/" -FAIL Parsing: <http://hello%00> against <http://other.com/> assert_equals: failure should set href to input expected "http://hello%00" but got "http://hello%00/" -PASS Parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/> -PASS Parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/> -FAIL Parsing: <http://192.168.0.257> against <http://other.com/> assert_equals: failure should set href to input expected "http://192.168.0.257" but got "http://192.168.0.257/" -FAIL Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/> assert_equals: failure should set href to input expected "http://%3g%78%63%30%2e%30%32%35%30%2E.01" but got "http://%253gxc0.0250..01/" -FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <https://x x:12> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/> -PASS Parsing: <http://./> against <about:blank> -PASS Parsing: <http://../> against <about:blank> -PASS Parsing: <http://[www.google.com]/> against <about:blank> -FAIL Parsing: <http://[google.com]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[google.com]" but got "http://[google.com]/" -FAIL Parsing: <http://[::1.2.3.4x]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[::1.2.3.4x]" but got "http://[::1.2.3.4x]/" -FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/> -PASS Parsing: <#> against <test:test> -PASS Parsing: <#x> against <mailto:x@x.com> -FAIL Parsing: <#x> against <data:,> assert_equals: href expected "data:,#x" but got "mailto:x@x.com#x" -PASS Parsing: <#x> against <about:blank> -PASS Parsing: <#> against <test:test?test> -PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/> -PASS Parsing: <https://@@@example> against <http://doesnotmatter/> -PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/> -PASS Parsing: <http://host/?'> against <about:blank> -FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27" -PASS Parsing: </some/path> against <http://user@example.org/smth> -PASS Parsing: <> against <http://user:pass@example.org:21/smth> -PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth> -FAIL Parsing: <i> against <sc:sd> assert_equals: failure should set href to input expected "i" but got "" -FAIL Parsing: <i> against <sc:sd/sd> assert_equals: failure should set href to input expected "i" but got "" -PASS Parsing: <i> against <sc:/pa/pa> -FAIL Parsing: <i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/i" but got "///pa/i" -FAIL Parsing: <../i> against <sc:sd> assert_equals: failure should set href to input expected "../i" but got "" -FAIL Parsing: <../i> against <sc:sd/sd> assert_equals: failure should set href to input expected "../i" but got "" -PASS Parsing: <../i> against <sc:/pa/pa> -FAIL Parsing: <../i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <../i> against <sc:///pa/pa> assert_equals: href expected "sc:///i" but got "sc:///pa/i" -FAIL Parsing: </i> against <sc:sd> assert_equals: failure should set href to input expected "/i" but got "" -FAIL Parsing: </i> against <sc:sd/sd> assert_equals: failure should set href to input expected "/i" but got "" -PASS Parsing: </i> against <sc:/pa/pa> -FAIL Parsing: </i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: </i> against <sc:///pa/pa> assert_equals: href expected "sc:///i" but got "sc:///pa/i" -FAIL Parsing: <?i> against <sc:sd> assert_equals: failure should set href to input expected "?i" but got "" -FAIL Parsing: <?i> against <sc:sd/sd> assert_equals: failure should set href to input expected "?i" but got "" -PASS Parsing: <?i> against <sc:/pa/pa> -FAIL Parsing: <?i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <?i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa" -PASS Parsing: <#i> against <sc:sd> -PASS Parsing: <#i> against <sc:sd/sd> -PASS Parsing: <#i> against <sc:/pa/pa> -FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa" -FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../" -FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../" -FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../" -FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../" -FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got "" -FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got "" -FAIL Parsing: <sc://@/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://:/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://:12/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <x> against <sc://ñ> assert_equals: href expected "sc://%C3%B1/x" but got "sc://%C3%B1" -PASS Parsing: <sc:\../> against <about:blank> -PASS Parsing: <sc::a@example.net> against <about:blank> -PASS Parsing: <wow:%NBD> against <about:blank> -PASS Parsing: <wow:%1G> against <about:blank> -FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" -FAIL Parsing: <http://example.com/U+d800U+dfff﷏ﷰ?U+d800U+dfff﷏ﷰ> against <about:blank> assert_equals: href expected "http://example.com/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF" but got "http://example.com/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%BF%BD%EF%B7%8F%EF%BF%BD%EF%B7%B0%EF%BF%BD%EF%BF%BD?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%BF%BD%EF%B7%8F%EF%BF%BD%EF%B7%B0%EF%BF%BD%EF%BF%BD" -FAIL Parsing: <sc://a\0b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a<b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a>b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a[b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a\b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a]b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a^b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://a|b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <foo://ho st/> against <about:blank> assert_equals: host expected "host" but got "" -FAIL Parsing: <foo://ho -st/> against <about:blank> assert_equals: host expected "host" but got "" -FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got "" -FAIL Parsing: <http://a\0b/> against <about:blank> assert_equals: failure should set href to input expected "http://a\0b/" but got "http://a%00b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x01b/" but got "http://a%01b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x02b/" but got "http://a%02b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x03b/" but got "http://a%03b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x04b/" but got "http://a%04b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x05b/" but got "http://a%05b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x06b/" but got "http://a%06b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x07b/" but got "http://a%07b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\bb/" but got "http://a%08b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\vb/" but got "http://a%0Bb/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\fb/" but got "http://a%0Cb/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x0eb/" but got "http://a%0Eb/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x0fb/" but got "http://a%0Fb/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x10b/" but got "http://a%10b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x11b/" but got "http://a%11b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x12b/" but got "http://a%12b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x13b/" but got "http://a%13b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x14b/" but got "http://a%14b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x15b/" but got "http://a%15b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x16b/" but got "http://a%16b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x17b/" but got "http://a%17b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x18b/" but got "http://a%18b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x19b/" but got "http://a%19b/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x1ab/" but got "http://a%1Ab/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x1bb/" but got "http://a%1Bb/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x1cb/" but got "http://a%1Cb/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x1db/" but got "http://a%1Db/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x1eb/" but got "http://a%1Eb/" -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://a\x1fb/" but got "http://a%1Fb/" -FAIL Parsing: <http://a b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a%b/> against <about:blank> assert_equals: failure should set href to input expected "http://a%b/" but got "http://a%25b/" -FAIL Parsing: <http://a<b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a>b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://a[b/> against <about:blank> -PASS Parsing: <http://a]b/> against <about:blank> -FAIL Parsing: <http://a^b> against <about:blank> assert_equals: failure should set href to input expected "http://a^b" but got "http://a%5Eb/" -FAIL Parsing: <http://a|b/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ab/> against <about:blank> assert_equals: href expected "http://ab/" but got "http://a%7Fb/" -PASS Parsing: <http://ho st/> against <about:blank> -PASS Parsing: <http://ho -st/> against <about:blank> -PASS Parsing: <http://ho\rst/> against <about:blank> -PASS Parsing: <http://ho%00st/> against <about:blank> -FAIL Parsing: <http://ho%01st/> against <about:blank> assert_equals: href expected "http://ho\x01st/" but got "http://ho%01st/" -FAIL Parsing: <http://ho%02st/> against <about:blank> assert_equals: href expected "http://ho\x02st/" but got "http://ho%02st/" -FAIL Parsing: <http://ho%03st/> against <about:blank> assert_equals: href expected "http://ho\x03st/" but got "http://ho%03st/" -FAIL Parsing: <http://ho%04st/> against <about:blank> assert_equals: href expected "http://ho\x04st/" but got "http://ho%04st/" -FAIL Parsing: <http://ho%05st/> against <about:blank> assert_equals: href expected "http://ho\x05st/" but got "http://ho%05st/" -FAIL Parsing: <http://ho%06st/> against <about:blank> assert_equals: href expected "http://ho\x06st/" but got "http://ho%06st/" -FAIL Parsing: <http://ho%07st/> against <about:blank> assert_equals: href expected "http://ho\x07st/" but got "http://ho%07st/" -FAIL Parsing: <http://ho%08st/> against <about:blank> assert_equals: href expected "http://ho\bst/" but got "http://ho%08st/" -PASS Parsing: <http://ho%09st/> against <about:blank> -PASS Parsing: <http://ho%0Ast/> against <about:blank> -FAIL Parsing: <http://ho%0Bst/> against <about:blank> assert_equals: href expected "http://ho\vst/" but got "http://ho%0Bst/" -FAIL Parsing: <http://ho%0Cst/> against <about:blank> assert_equals: href expected "http://ho\fst/" but got "http://ho%0Cst/" -PASS Parsing: <http://ho%0Dst/> against <about:blank> -FAIL Parsing: <http://ho%0Est/> against <about:blank> assert_equals: href expected "http://ho\x0est/" but got "http://ho%0Est/" -FAIL Parsing: <http://ho%0Fst/> against <about:blank> assert_equals: href expected "http://ho\x0fst/" but got "http://ho%0Fst/" -FAIL Parsing: <http://ho%10st/> against <about:blank> assert_equals: href expected "http://ho\x10st/" but got "http://ho%10st/" -FAIL Parsing: <http://ho%11st/> against <about:blank> assert_equals: href expected "http://ho\x11st/" but got "http://ho%11st/" -FAIL Parsing: <http://ho%12st/> against <about:blank> assert_equals: href expected "http://ho\x12st/" but got "http://ho%12st/" -FAIL Parsing: <http://ho%13st/> against <about:blank> assert_equals: href expected "http://ho\x13st/" but got "http://ho%13st/" -FAIL Parsing: <http://ho%14st/> against <about:blank> assert_equals: href expected "http://ho\x14st/" but got "http://ho%14st/" -FAIL Parsing: <http://ho%15st/> against <about:blank> assert_equals: href expected "http://ho\x15st/" but got "http://ho%15st/" -FAIL Parsing: <http://ho%16st/> against <about:blank> assert_equals: href expected "http://ho\x16st/" but got "http://ho%16st/" -FAIL Parsing: <http://ho%17st/> against <about:blank> assert_equals: href expected "http://ho\x17st/" but got "http://ho%17st/" -FAIL Parsing: <http://ho%18st/> against <about:blank> assert_equals: href expected "http://ho\x18st/" but got "http://ho%18st/" -FAIL Parsing: <http://ho%19st/> against <about:blank> assert_equals: href expected "http://ho\x19st/" but got "http://ho%19st/" -FAIL Parsing: <http://ho%1Ast/> against <about:blank> assert_equals: href expected "http://ho\x1ast/" but got "http://ho%1Ast/" -FAIL Parsing: <http://ho%1Bst/> against <about:blank> assert_equals: href expected "http://ho\x1bst/" but got "http://ho%1Bst/" -FAIL Parsing: <http://ho%1Cst/> against <about:blank> assert_equals: href expected "http://ho\x1cst/" but got "http://ho%1Cst/" -FAIL Parsing: <http://ho%1Dst/> against <about:blank> assert_equals: href expected "http://ho\x1dst/" but got "http://ho%1Dst/" -FAIL Parsing: <http://ho%1Est/> against <about:blank> assert_equals: href expected "http://ho\x1est/" but got "http://ho%1Est/" -FAIL Parsing: <http://ho%1Fst/> against <about:blank> assert_equals: href expected "http://ho\x1fst/" but got "http://ho%1Fst/" -FAIL Parsing: <http://ho%20st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ho%23st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://ho%25st/> against <about:blank> -PASS Parsing: <http://ho%2Fst/> against <about:blank> -FAIL Parsing: <http://ho%3Ast/> against <about:blank> assert_equals: failure should set href to input expected "http://ho%3Ast/" but got "http://ho:st/" -FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://ho%3Fst/> against <about:blank> -FAIL Parsing: <http://ho%40st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ho%5Bst/> against <about:blank> assert_equals: failure should set href to input expected "http://ho%5Bst/" but got "http://ho[st/" -PASS Parsing: <http://ho%5Cst/> against <about:blank> -FAIL Parsing: <http://ho%5Dst/> against <about:blank> assert_equals: failure should set href to input expected "http://ho%5Dst/" but got "http://ho]st/" -FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ho%7Fst/> against <about:blank> assert_equals: href expected "http://host/" but got "http://ho%7Fst/" -FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: href expected "http://\x01\x02\x03\x04\x05\x06\x07\b\v\f\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!\"$&'()*+,-.;=_`{}~/" but got "http://%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F%21%22%24%26%27%28%29%2A+%2C-.%3B%3D_%60%7B%7D%7E/" -FAIL Parsing: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~" but got "" -FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" -FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" -FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/" -FAIL Parsing: <https://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%A0/" but got "https://example.com%EF%BF%BD/" -PASS Parsing: <ftp://%e2%98%83> against <about:blank> -PASS Parsing: <https://%e2%98%83> against <about:blank> -PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank> -PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank> -PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank> -PASS Parsing: <h t -t\rp://h o -s\rt:9 0 -0\r0/p a -t\rh?q u -e\rry#f r -a\rg> against <about:blank> -PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing: <http:> against <http://example.org/foo/bar> -PASS Parsing: <http:> against <https://example.org/foo/bar> -PASS Parsing: <sc:> against <https://example.org/foo/bar> -PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank> -PASS Parsing: <http://1.2.3.4/> against <http://other.com/> -PASS Parsing: <http://1.2.3.4./> against <http://other.com/> -PASS Parsing: <http://192.168.257> against <http://other.com/> -PASS Parsing: <http://192.168.257.> against <http://other.com/> -PASS Parsing: <http://192.168.257.com> against <http://other.com/> -PASS Parsing: <http://256> against <http://other.com/> -PASS Parsing: <http://256.com> against <http://other.com/> -PASS Parsing: <http://999999999> against <http://other.com/> -PASS Parsing: <http://999999999.> against <http://other.com/> -PASS Parsing: <http://999999999.com> against <http://other.com/> -FAIL Parsing: <http://10000000000> against <http://other.com/> assert_equals: failure should set href to input expected "http://10000000000" but got "http://10000000000/" -PASS Parsing: <http://10000000000.com> against <http://other.com/> -PASS Parsing: <http://4294967295> against <http://other.com/> -FAIL Parsing: <http://4294967296> against <http://other.com/> assert_equals: failure should set href to input expected "http://4294967296" but got "http://4294967296/" -PASS Parsing: <http://0xffffffff> against <http://other.com/> -FAIL Parsing: <http://0xffffffff1> against <http://other.com/> assert_equals: failure should set href to input expected "http://0xffffffff1" but got "http://0xffffffff1/" -FAIL Parsing: <http://256.256.256.256> against <http://other.com/> assert_equals: failure should set href to input expected "http://256.256.256.256" but got "http://256.256.256.256/" -PASS Parsing: <https://0x.0x.0> against <about:blank> -PASS Parsing: <https://0x100000000/test> against <about:blank> -PASS Parsing: <https://256.0.0.1/test> against <about:blank> -PASS Parsing: <file:///C%3A/> against <about:blank> -PASS Parsing: <file:///C%7C/> against <about:blank> -FAIL Parsing: <file://%43%3A> against <about:blank> assert_equals: failure should set href to input expected "file://%43%3A" but got "file://c:/" -FAIL Parsing: <file://%43%7C> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <file://%43|> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <file://C%7C> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <file://%43%7C/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <https://%43%7C/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <asdf://%43|/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got "" -PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html> -FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///" -PASS Parsing: <..> against <file:///> -FAIL Parsing: </> against <file:///C:/a/b> assert_equals: href expected "file:///C:/" but got "file:///" -FAIL Parsing: </> against <file://h/C:/a/b> assert_equals: href expected "file://h/C:/" but got "file://h/" -PASS Parsing: </> against <file://h/a/b> -FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file://d:/" -FAIL Parsing: <//d:/..> against <file:///C:/a/b> assert_equals: href expected "file:///d:/" but got "file://d:/" -PASS Parsing: <..> against <file:///ab:/> -PASS Parsing: <..> against <file:///1:/> -PASS Parsing: <> against <file:///test?test#test> -PASS Parsing: <file:> against <file:///test?test#test> -PASS Parsing: <?x> against <file:///test?test#test> -PASS Parsing: <file:?x> against <file:///test?test#test> -PASS Parsing: <#x> against <file:///test?test#test> -PASS Parsing: <file:#x> against <file:///test?test#test> -FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///" -FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///" -FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox" -FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy" -PASS Parsing: <file://spider///> against <about:blank> -FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//" -PASS Parsing: <file:///localhost//cat> against <about:blank> -FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat" -FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///" -FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse" -PASS Parsing: <\//pig> against <file://lion/> -FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig" -FAIL Parsing: <//localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig" -PASS Parsing: </..//localhost//pig> against <file://lion/> -PASS Parsing: <file://> against <file://ape/> -PASS Parsing: </rooibos> against <file://tea/> -PASS Parsing: </?chai> against <file://tea/> -FAIL Parsing: <C|> against <file://host/dir/file> assert_equals: href expected "file://host/C:" but got "file://host/dir/C%7C" -FAIL Parsing: <C|> against <file://host/D:/dir1/dir2/file> assert_equals: href expected "file://host/C:" but got "file://host/D:/dir1/dir2/C%7C" -FAIL Parsing: <C|#> against <file://host/dir/file> assert_equals: href expected "file://host/C:#" but got "file://host/dir/C%7C#" -FAIL Parsing: <C|?> against <file://host/dir/file> assert_equals: href expected "file://host/C:?" but got "file://host/dir/C%7C?" -FAIL Parsing: <C|/> against <file://host/dir/file> assert_equals: href expected "file://host/C:/" but got "file://host/dir/C%7C/" -FAIL Parsing: <C| -/> against <file://host/dir/file> assert_equals: href expected "file://host/C:/" but got "file://host/dir/C%7C/" -FAIL Parsing: <C|\> against <file://host/dir/file> assert_equals: href expected "file://host/C:/" but got "file://host/dir/C%7C/" -PASS Parsing: <C> against <file://host/dir/file> -FAIL Parsing: <C|a> against <file://host/dir/file> assert_equals: href expected "file://host/dir/C|a" but got "file://host/dir/C%7Ca" -PASS Parsing: </c:/foo/bar> against <file:///c:/baz/qux> -FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar" -PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux> -PASS Parsing: </c:/foo/bar> against <file://host/path> -PASS Parsing: <file://example.net/C:/> against <about:blank> -PASS Parsing: <file://1.2.3.4/C:/> against <about:blank> -PASS Parsing: <file://[1::8]/C:/> against <about:blank> -FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/" -PASS Parsing: </C:/> against <file://host/> -PASS Parsing: <file:C:/> against <file://host/> -PASS Parsing: <file:/C:/> against <file://host/> -FAIL Parsing: <//C:/> against <file://host/> assert_equals: href expected "file:///C:/" but got "file://c:/" -FAIL Parsing: <file://C:/> against <file://host/> assert_equals: href expected "file:///C:/" but got "file://c:/" -PASS Parsing: <///C:/> against <file://host/> -PASS Parsing: <file:///C:/> against <file://host/> -FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/" -FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/" -PASS Parsing: <file:> against <about:blank> -PASS Parsing: <file:?q=v> against <about:blank> -PASS Parsing: <file:#frag> against <about:blank> -PASS Parsing: <file:///Y:> against <about:blank> -PASS Parsing: <file:///Y:/> against <about:blank> -PASS Parsing: <file:///./Y> against <about:blank> -PASS Parsing: <file:///./Y:> against <about:blank> -FAIL Parsing: <\\\.\Y:> against <about:blank> assert_equals: failure should set href to input expected "\\\\\\.\\Y:" but got "" -PASS Parsing: <file:///y:> against <about:blank> -PASS Parsing: <file:///y:/> against <about:blank> -PASS Parsing: <file:///./y> against <about:blank> -PASS Parsing: <file:///./y:> against <about:blank> -FAIL Parsing: <\\\.\y:> against <about:blank> assert_equals: failure should set href to input expected "\\\\\\.\\y:" but got "" -FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo" -FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo" -FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo" -PASS Parsing: <file:///one/two> against <file:///> -FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two" -PASS Parsing: <//one/two> against <file:///> -PASS Parsing: <///one/two> against <file:///> -FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two" -PASS Parsing: <file:///.//> against <file:////> -PASS Parsing: <file:.//p> against <about:blank> -PASS Parsing: <file:/.//p> against <about:blank> -PASS Parsing: <http://[1:0::]> against <http://example.net/> -FAIL Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/> assert_equals: failure should set href to input expected "http://[0:1:2:3:4:5:6:7:8]" but got "http://[0:1:2:3:4:5:6:7:8]/" -FAIL Parsing: <https://[0::0::0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0::0::0]" but got "https://[0::0::0]/" -FAIL Parsing: <https://[0:.0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:.0]" but got "https://[0:.0]/" -FAIL Parsing: <https://[0:0:]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:0:]" but got "https://[0:0:]/" -FAIL Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1:2:3:4:5:6:7.0.0.0.1]" but got "https://[0:1:2:3:4:5:6:7.0.0.0.1]/" -FAIL Parsing: <https://[0:1.00.0.0.0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1.00.0.0.0]" but got "https://[0:1.00.0.0.0]/" -FAIL Parsing: <https://[0:1.290.0.0.0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1.290.0.0.0]" but got "https://[0:1.290.0.0.0]/" -FAIL Parsing: <https://[0:1.23.23]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1.23.23]" but got "https://[0:1.23.23]/" -FAIL Parsing: <http://?> against <about:blank> assert_equals: failure should set href to input expected "http://?" but got "http:/?" -FAIL Parsing: <http://#> against <about:blank> assert_equals: failure should set href to input expected "http://#" but got "http:/#" -PASS Parsing: <http://f:4294967377/c> against <http://example.org/> -PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/> -PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/> -FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got "" -FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got "" -FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got "" -FAIL Parsing: <#x> against <sc://ñ> assert_equals: href expected "sc://%C3%B1#x" but got "sc://%C3%B1" -FAIL Parsing: <?x> against <sc://ñ> assert_equals: href expected "sc://%C3%B1?x" but got "sc://%C3%B1" -FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//" -FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//" -FAIL Parsing: <///> against <sc://x/> assert_equals: href expected "sc:///" but got "sc:" -FAIL Parsing: <////> against <sc://x/> assert_equals: href expected "sc:////" but got "sc:" -FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/" -FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got "" -FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got "" -FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got "" -FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got "" -FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got "" -FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got "" -FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got "" -FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got "" -FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got "" -FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got "" -PASS Parsing: <urn:ietf:rfc:2648> against <about:blank> -PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank> -FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//" -FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//" -FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//" -FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path" -FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path" -FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path" -FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: <a/..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p" -FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path" -FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path" -FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got "" -FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got "" -FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/" -FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/" -FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got "" -FAIL Parsing: <non-special://[:80/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <blob:https://example.com:443/> against <about:blank> -PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank> -PASS Parsing: <blob:> against <about:blank> -PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank> -PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank> -FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/" -PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank> -PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank> -PASS Parsing: <http://example.org/test?"> against <about:blank> -PASS Parsing: <http://example.org/test?#> against <about:blank> -PASS Parsing: <http://example.org/test?<> against <about:blank> -PASS Parsing: <http://example.org/test?>> against <about:blank> -PASS Parsing: <http://example.org/test?⌣> against <about:blank> -PASS Parsing: <http://example.org/test?%23%23> against <about:blank> -PASS Parsing: <http://example.org/test?%GH> against <about:blank> -PASS Parsing: <http://example.org/test?a#%EF> against <about:blank> -PASS Parsing: <http://example.org/test?a#%GH> against <about:blank> -FAIL Parsing: <a> against <about:blank> assert_equals: failure should set href to input expected "a" but got "" -FAIL Parsing: <a/> against <about:blank> assert_equals: failure should set href to input expected "a/" but got "" -FAIL Parsing: <a//> against <about:blank> assert_equals: failure should set href to input expected "a//" but got "" -FAIL Parsing: <test-a-colon.html> against <a:> assert_equals: failure should set href to input expected "test-a-colon.html" but got "" -FAIL Parsing: <test-a-colon-b.html> against <a:b> assert_equals: failure should set href to input expected "test-a-colon-b.html" but got "" -PASS Parsing: <test-a-colon-slash.html> against <a:/> -FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> assert_equals: href expected "a:///test-a-colon-slash-slash.html" but got "" -PASS Parsing: <test-a-colon-slash-b.html> against <a:/b> -FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> assert_equals: href expected "a://b/test-a-colon-slash-slash-b.html" but got "a://b" -PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank> -FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got "" -PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank> -PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html> -PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html> -PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file> -PASS Parsing: <file://ab/p> against <about:blank> -PASS Parsing: <file://a%C2%ADb/p> against <about:blank> -FAIL Parsing: <file:///p> against <about:blank> assert_equals: failure should set href to input expected "file:///p" but got "file://%C2%AD/p" -PASS Parsing: <file://%C2%AD/p> against <about:blank> -FAIL Parsing: <file://xn--/p> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <#link> against <https://example.org/##link> -PASS Parsing: <non-special:cannot-be-a-base-url-\0~> against <about:blank> -PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank> -PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org> -FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/" -FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" -FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/" -FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" -FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got "" -FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: href expected "wss://!\"$&'()*+,-.;=_`{}~/" but got "wss://%21%22%24%26%27%28%29%2A+%2C-.%3B%3D_%60%7B%7D%7E/" -FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~" -FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~" -FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~" -PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got "" -PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless" -FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless" -PASS Parsing: <abc:rootless> against <abc:path> -FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted" -FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/" -FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./" -PASS Parsing: <http://0..0x300/> against <about:blank> -PASS Parsing: <http://0..0x300./> against <about:blank> -FAIL Parsing: <http://256.256.256.256.256> against <http://other.com/> assert_equals: failure should set href to input expected "http://256.256.256.256.256" but got "http://256.256.256.256.256/" -FAIL Parsing: <http://256.256.256.256.256.> against <http://other.com/> assert_equals: failure should set href to input expected "http://256.256.256.256.256." but got "http://256.256.256.256.256./" -FAIL Parsing: <http://1.2.3.08> against <about:blank> assert_equals: failure should set href to input expected "http://1.2.3.08" but got "http://1.2.3.08/" -FAIL Parsing: <http://1.2.3.08.> against <about:blank> assert_equals: failure should set href to input expected "http://1.2.3.08." but got "http://1.2.3.08./" -FAIL Parsing: <http://1.2.3.09> against <about:blank> assert_equals: failure should set href to input expected "http://1.2.3.09" but got "http://1.2.3.09/" -FAIL Parsing: <http://09.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://09.2.3.4" but got "http://09.2.3.4/" -FAIL Parsing: <http://09.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://09.2.3.4." but got "http://09.2.3.4./" -FAIL Parsing: <http://01.2.3.4.5> against <about:blank> assert_equals: failure should set href to input expected "http://01.2.3.4.5" but got "http://01.2.3.4.5/" -FAIL Parsing: <http://01.2.3.4.5.> against <about:blank> assert_equals: failure should set href to input expected "http://01.2.3.4.5." but got "http://01.2.3.4.5./" -FAIL Parsing: <http://0x100.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://0x100.2.3.4" but got "http://0x100.2.3.4/" -FAIL Parsing: <http://0x100.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://0x100.2.3.4." but got "http://0x100.2.3.4./" -FAIL Parsing: <http://0x1.2.3.4.5> against <about:blank> assert_equals: failure should set href to input expected "http://0x1.2.3.4.5" but got "http://0x1.2.3.4.5/" -FAIL Parsing: <http://0x1.2.3.4.5.> against <about:blank> assert_equals: failure should set href to input expected "http://0x1.2.3.4.5." but got "http://0x1.2.3.4.5./" -FAIL Parsing: <http://foo.1.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://foo.1.2.3.4" but got "http://foo.1.2.3.4/" -FAIL Parsing: <http://foo.1.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.1.2.3.4." but got "http://foo.1.2.3.4./" -FAIL Parsing: <http://foo.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://foo.2.3.4" but got "http://foo.2.3.4/" -FAIL Parsing: <http://foo.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.2.3.4." but got "http://foo.2.3.4./" -FAIL Parsing: <http://foo.09> against <about:blank> assert_equals: failure should set href to input expected "http://foo.09" but got "http://foo.09/" -FAIL Parsing: <http://foo.09.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.09." but got "http://foo.09./" -FAIL Parsing: <http://foo.0x4> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0x4" but got "http://foo.0x4/" -FAIL Parsing: <http://foo.0x4.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0x4." but got "http://foo.0x4./" -PASS Parsing: <http://foo.09..> against <about:blank> -PASS Parsing: <http://0999999999999999999/> against <about:blank> -FAIL Parsing: <http://foo.0x> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0x" but got "http://foo.0x/" -FAIL Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0XFfFfFfFfFfFfFfFfFfAcE123" but got "http://foo.0xfffffffffffffffffface123/" -FAIL Parsing: <http://💩.123/> against <about:blank> assert_equals: failure should set href to input expected "http://💩.123/" but got "http://xn--ls8h.123/" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element-origin-expected.txt deleted file mode 100644 index 89bc28a..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/url/a-element-origin-expected.txt +++ /dev/null
@@ -1,342 +0,0 @@ -This is a testharness.js-based test. -Found 329 tests; 324 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS Loading data… -PASS Parsing origin: <http://example . -org> against <http://example.org/foo/bar> -PASS Parsing origin: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar> -PASS Parsing origin: <https://test:@test> against <about:blank> -PASS Parsing origin: <https://:@test> against <about:blank> -PASS Parsing origin: <non-special://test:@test/x> against <about:blank> -PASS Parsing origin: <non-special://:@test/x> against <about:blank> -PASS Parsing origin: <http:foo.com> against <http://example.org/foo/bar> -PASS Parsing origin: < :foo.com -> against <http://example.org/foo/bar> -PASS Parsing origin: < foo.com > against <http://example.org/foo/bar> -PASS Parsing origin: <a: foo.com> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:21/ b ? d # e > against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:0/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:00000000000000/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:00000000000000000000080/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f: -/c> against <http://example.org/foo/bar> -PASS Parsing origin: <> against <http://example.org/foo/bar> -PASS Parsing origin: < > against <http://example.org/foo/bar> -PASS Parsing origin: <:foo.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <:foo.com\> against <http://example.org/foo/bar> -PASS Parsing origin: <:> against <http://example.org/foo/bar> -PASS Parsing origin: <:a> against <http://example.org/foo/bar> -PASS Parsing origin: <:/> against <http://example.org/foo/bar> -PASS Parsing origin: <:\> against <http://example.org/foo/bar> -PASS Parsing origin: <:#> against <http://example.org/foo/bar> -PASS Parsing origin: <#> against <http://example.org/foo/bar> -PASS Parsing origin: <#/> against <http://example.org/foo/bar> -PASS Parsing origin: <#\> against <http://example.org/foo/bar> -PASS Parsing origin: <#;?> against <http://example.org/foo/bar> -PASS Parsing origin: <?> against <http://example.org/foo/bar> -PASS Parsing origin: </> against <http://example.org/foo/bar> -PASS Parsing origin: <:23> against <http://example.org/foo/bar> -PASS Parsing origin: </:23> against <http://example.org/foo/bar> -PASS Parsing origin: <\x> against <http://example.org/foo/bar> -PASS Parsing origin: <\\x\hello> against <http://example.org/foo/bar> -PASS Parsing origin: <::> against <http://example.org/foo/bar> -PASS Parsing origin: <::23> against <http://example.org/foo/bar> -PASS Parsing origin: <foo://> against <http://example.org/foo/bar> -PASS Parsing origin: <http://a:b@c:29/d> against <http://example.org/foo/bar> -PASS Parsing origin: <http::@c:29> against <http://example.org/foo/bar> -PASS Parsing origin: <http://&a:foo(b]c@d:2/> against <http://example.org/foo/bar> -PASS Parsing origin: <http://::@c@d:2> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo.com:b@d/> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo.com/\@> against <http://example.org/foo/bar> -PASS Parsing origin: <http:\\foo.com\> against <http://example.org/foo/bar> -PASS Parsing origin: <http:\\a\b:c\d@foo.com\> against <http://example.org/foo/bar> -PASS Parsing origin: <foo:/> against <http://example.org/foo/bar> -PASS Parsing origin: <foo:/bar.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <foo://///////> against <http://example.org/foo/bar> -PASS Parsing origin: <foo://///////bar.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <foo:////://///> against <http://example.org/foo/bar> -PASS Parsing origin: <c:/foo> against <http://example.org/foo/bar> -PASS Parsing origin: <//foo/bar> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo/path;a??e#f#g> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo/abcd?efgh?ijkl> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo/abcd#foo?bar> against <http://example.org/foo/bar> -PASS Parsing origin: <[61:24:74]:98> against <http://example.org/foo/bar> -PASS Parsing origin: <http:[61:27]/:foo> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[2001::1]> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[::127.0.0.1]> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[2001::1]:80> against <http://example.org/foo/bar> -PASS Parsing origin: <http:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftp:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <https:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <madeupscheme:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftps:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <gopher:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ws:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <wss:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <data:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <javascript:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <mailto:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <http:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftp:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <https:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <madeupscheme:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftps:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <gopher:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ws:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <wss:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <data:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <javascript:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <mailto:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: </a/b/c> against <http://example.org/foo/bar> -PASS Parsing origin: </a/ /c> against <http://example.org/foo/bar> -PASS Parsing origin: </a%2fc> against <http://example.org/foo/bar> -PASS Parsing origin: </a/%2f/c> against <http://example.org/foo/bar> -PASS Parsing origin: <#β> against <http://example.org/foo/bar> -PASS Parsing origin: <data:text/html,test#test> against <http://example.org/foo/bar> -PASS Parsing origin: <tel:1234567890> against <http://example.org/foo/bar> -PASS Parsing origin: <ssh://example.com/foo/bar.git> against <http://example.org/> -PASS Parsing origin: <http://example.com/././foo> against <about:blank> -PASS Parsing origin: <http://example.com/./.foo> against <about:blank> -PASS Parsing origin: <http://example.com/foo/.> against <about:blank> -PASS Parsing origin: <http://example.com/foo/./> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/../> against <about:blank> -PASS Parsing origin: <http://example.com/foo/..bar> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/../ton> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/../ton/../../a> against <about:blank> -PASS Parsing origin: <http://example.com/foo/../../..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/../../../ton> against <about:blank> -PASS Parsing origin: <http://example.com/foo/%2e> against <about:blank> -PASS Parsing origin: <http://example.com/foo/%2e%2> against <about:blank> -PASS Parsing origin: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> -PASS Parsing origin: <http://example.com////../..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar//../..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar//..> against <about:blank> -PASS Parsing origin: <http://example.com/foo> against <about:blank> -PASS Parsing origin: <http://example.com/%20foo> against <about:blank> -PASS Parsing origin: <http://example.com/foo%> against <about:blank> -PASS Parsing origin: <http://example.com/foo%2> against <about:blank> -PASS Parsing origin: <http://example.com/foo%2zbar> against <about:blank> -PASS Parsing origin: <http://example.com/foo%2©zbar> against <about:blank> -PASS Parsing origin: <http://example.com/foo%41%7a> against <about:blank> -PASS Parsing origin: <http://example.com/foo %91> against <about:blank> -FAIL Parsing origin: <http://example.com/foo%00%51> against <about:blank> assert_equals: origin expected "http://example.com" but got "null" -PASS Parsing origin: <http://example.com/(%28:%3A%29)> against <about:blank> -PASS Parsing origin: <http://example.com/%3A%3a%3C%3c> against <about:blank> -PASS Parsing origin: <http://example.com/foo bar> against <about:blank> -PASS Parsing origin: <http://example.com\\foo\\bar> against <about:blank> -PASS Parsing origin: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank> -PASS Parsing origin: <http://example.com/@asdf%40> against <about:blank> -PASS Parsing origin: <http://example.com/你好你好> against <about:blank> -PASS Parsing origin: <http://example.com/‥/foo> against <about:blank> -PASS Parsing origin: <http://example.com//foo> against <about:blank> -PASS Parsing origin: <http://example.com//foo//bar> against <about:blank> -PASS Parsing origin: <http://www.google.com/foo?bar=baz#> against <about:blank> -PASS Parsing origin: <http://www.google.com/foo?bar=baz# »> against <about:blank> -PASS Parsing origin: <data:test# »> against <about:blank> -PASS Parsing origin: <http://www.google.com> against <about:blank> -PASS Parsing origin: <http://192.0x00A80001> against <about:blank> -PASS Parsing origin: <http://www/foo%2Ehtml> against <about:blank> -PASS Parsing origin: <http://www/foo/%2E/html> against <about:blank> -PASS Parsing origin: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> -PASS Parsing origin: <http:\\www.google.com\foo> against <about:blank> -PASS Parsing origin: <http://foo:80/> against <about:blank> -PASS Parsing origin: <http://foo:81/> against <about:blank> -PASS Parsing origin: <httpa://foo:80/> against <about:blank> -PASS Parsing origin: <https://foo:443/> against <about:blank> -PASS Parsing origin: <https://foo:80/> against <about:blank> -PASS Parsing origin: <ftp://foo:21/> against <about:blank> -PASS Parsing origin: <ftp://foo:80/> against <about:blank> -PASS Parsing origin: <gopher://foo:70/> against <about:blank> -PASS Parsing origin: <gopher://foo:443/> against <about:blank> -PASS Parsing origin: <ws://foo:80/> against <about:blank> -PASS Parsing origin: <ws://foo:81/> against <about:blank> -PASS Parsing origin: <ws://foo:443/> against <about:blank> -PASS Parsing origin: <ws://foo:815/> against <about:blank> -PASS Parsing origin: <wss://foo:80/> against <about:blank> -PASS Parsing origin: <wss://foo:81/> against <about:blank> -PASS Parsing origin: <wss://foo:443/> against <about:blank> -PASS Parsing origin: <wss://foo:815/> against <about:blank> -PASS Parsing origin: <http:/example.com/> against <about:blank> -PASS Parsing origin: <ftp:/example.com/> against <about:blank> -PASS Parsing origin: <https:/example.com/> against <about:blank> -PASS Parsing origin: <madeupscheme:/example.com/> against <about:blank> -PASS Parsing origin: <ftps:/example.com/> against <about:blank> -PASS Parsing origin: <gopher:/example.com/> against <about:blank> -PASS Parsing origin: <ws:/example.com/> against <about:blank> -PASS Parsing origin: <wss:/example.com/> against <about:blank> -PASS Parsing origin: <data:/example.com/> against <about:blank> -PASS Parsing origin: <javascript:/example.com/> against <about:blank> -PASS Parsing origin: <mailto:/example.com/> against <about:blank> -PASS Parsing origin: <http:example.com/> against <about:blank> -PASS Parsing origin: <ftp:example.com/> against <about:blank> -PASS Parsing origin: <https:example.com/> against <about:blank> -PASS Parsing origin: <madeupscheme:example.com/> against <about:blank> -PASS Parsing origin: <ftps:example.com/> against <about:blank> -PASS Parsing origin: <gopher:example.com/> against <about:blank> -PASS Parsing origin: <ws:example.com/> against <about:blank> -PASS Parsing origin: <wss:example.com/> against <about:blank> -PASS Parsing origin: <data:example.com/> against <about:blank> -PASS Parsing origin: <javascript:example.com/> against <about:blank> -PASS Parsing origin: <mailto:example.com/> against <about:blank> -PASS Parsing origin: <http:@www.example.com> against <about:blank> -PASS Parsing origin: <http:/@www.example.com> against <about:blank> -PASS Parsing origin: <http://@www.example.com> against <about:blank> -PASS Parsing origin: <http:a:b@www.example.com> against <about:blank> -PASS Parsing origin: <http:/a:b@www.example.com> against <about:blank> -PASS Parsing origin: <http://a:b@www.example.com> against <about:blank> -PASS Parsing origin: <http://@pple.com> against <about:blank> -PASS Parsing origin: <http::b@www.example.com> against <about:blank> -PASS Parsing origin: <http:/:b@www.example.com> against <about:blank> -PASS Parsing origin: <http://:b@www.example.com> against <about:blank> -PASS Parsing origin: <http:a:@www.example.com> against <about:blank> -PASS Parsing origin: <http:/a:@www.example.com> against <about:blank> -PASS Parsing origin: <http://a:@www.example.com> against <about:blank> -PASS Parsing origin: <http://www.@pple.com> against <about:blank> -PASS Parsing origin: <http://:@www.example.com> against <about:blank> -PASS Parsing origin: </> against <http://www.example.com/test> -PASS Parsing origin: </test.txt> against <http://www.example.com/test> -PASS Parsing origin: <.> against <http://www.example.com/test> -PASS Parsing origin: <..> against <http://www.example.com/test> -PASS Parsing origin: <test.txt> against <http://www.example.com/test> -PASS Parsing origin: <./test.txt> against <http://www.example.com/test> -PASS Parsing origin: <../test.txt> against <http://www.example.com/test> -PASS Parsing origin: <../aaa/test.txt> against <http://www.example.com/test> -PASS Parsing origin: <../../test.txt> against <http://www.example.com/test> -PASS Parsing origin: <中/test.txt> against <http://www.example.com/test> -PASS Parsing origin: <http://www.example2.com> against <http://www.example.com/test> -PASS Parsing origin: <//www.example2.com> against <http://www.example.com/test> -PASS Parsing origin: <http://ExAmPlE.CoM> against <http://other.com/> -PASS Parsing origin: <http://GOOgoo.com> against <http://other.com/> -PASS Parsing origin: <\0 http://example.com/ \r > against <about:blank> -PASS Parsing origin: <http://www.foo。bar.com> against <http://other.com/> -PASS Parsing origin: <https://x/�?�#�> against <about:blank> -PASS Parsing origin: <http://Go.com> against <http://other.com/> -PASS Parsing origin: <http://你好你好> against <http://other.com/> -FAIL Parsing origin: <https://faß.ExAmPlE/> against <about:blank> assert_equals: origin expected "https://xn--fa-hia.example" but got "https://fass.example" -PASS Parsing origin: <sc://faß.ExAmPlE/> against <about:blank> -PASS Parsing origin: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/> -PASS Parsing origin: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/> -PASS Parsing origin: <http://0Xc0.0250.01> against <http://other.com/> -PASS Parsing origin: <http://./> against <about:blank> -PASS Parsing origin: <http://../> against <about:blank> -PASS Parsing origin: <http://foo:💩@example.com/bar> against <http://other.com/> -PASS Parsing origin: <#> against <test:test> -PASS Parsing origin: <#x> against <mailto:x@x.com> -PASS Parsing origin: <#x> against <data:,> -PASS Parsing origin: <#x> against <about:blank> -PASS Parsing origin: <#> against <test:test?test> -PASS Parsing origin: <https://@test@test@example:800/> against <http://doesnotmatter/> -PASS Parsing origin: <https://@@@example> against <http://doesnotmatter/> -PASS Parsing origin: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/> -PASS Parsing origin: <http://host/?'> against <about:blank> -PASS Parsing origin: <notspecial://host/?'> against <about:blank> -PASS Parsing origin: </some/path> against <http://user@example.org/smth> -PASS Parsing origin: <> against <http://user:pass@example.org:21/smth> -PASS Parsing origin: </some/path> against <http://user:pass@example.org:21/smth> -PASS Parsing origin: <i> against <sc:/pa/pa> -PASS Parsing origin: <i> against <sc://ho/pa> -PASS Parsing origin: <i> against <sc:///pa/pa> -PASS Parsing origin: <../i> against <sc:/pa/pa> -PASS Parsing origin: <../i> against <sc://ho/pa> -PASS Parsing origin: <../i> against <sc:///pa/pa> -PASS Parsing origin: </i> against <sc:/pa/pa> -PASS Parsing origin: </i> against <sc://ho/pa> -PASS Parsing origin: </i> against <sc:///pa/pa> -PASS Parsing origin: <?i> against <sc:/pa/pa> -PASS Parsing origin: <?i> against <sc://ho/pa> -PASS Parsing origin: <?i> against <sc:///pa/pa> -PASS Parsing origin: <#i> against <sc:sd> -PASS Parsing origin: <#i> against <sc:sd/sd> -PASS Parsing origin: <#i> against <sc:/pa/pa> -PASS Parsing origin: <#i> against <sc://ho/pa> -PASS Parsing origin: <#i> against <sc:///pa/pa> -PASS Parsing origin: <about:/../> against <about:blank> -PASS Parsing origin: <data:/../> against <about:blank> -PASS Parsing origin: <javascript:/../> against <about:blank> -PASS Parsing origin: <mailto:/../> against <about:blank> -PASS Parsing origin: <sc://ñ.test/> against <about:blank> -PASS Parsing origin: <x> against <sc://ñ> -PASS Parsing origin: <sc:\../> against <about:blank> -PASS Parsing origin: <sc::a@example.net> against <about:blank> -PASS Parsing origin: <wow:%NBD> against <about:blank> -PASS Parsing origin: <wow:%1G> against <about:blank> -PASS Parsing origin: <wow:> against <about:blank> -FAIL Parsing origin: <http://example.com/U+d800U+dfff﷏ﷰ?U+d800U+dfff﷏ﷰ> against <about:blank> assert_equals: origin expected "http://example.com" but got "null" -FAIL Parsing origin: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: origin expected "http://\x01\x02\x03\x04\x05\x06\x07\b\v\f\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!\"$&'()*+,-.;=_`{}~" but got "null" -PASS Parsing origin: <sc://!"$%&'()*+,-.;=_`{}~/> against <about:blank> -PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> -PASS Parsing origin: <https://%e2%98%83> against <about:blank> -PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank> -PASS Parsing origin: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank> -PASS Parsing origin: <https://localhost:3000/jqueryui@1.2.3> against <about:blank> -PASS Parsing origin: <h t -t\rp://h o -s\rt:9 0 -0\r0/p a -t\rh?q u -e\rry#f r -a\rg> against <about:blank> -PASS Parsing origin: <?a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing origin: <??a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing origin: <http:> against <http://example.org/foo/bar> -PASS Parsing origin: <sc:> against <https://example.org/foo/bar> -PASS Parsing origin: <http://foo.bar/baz?qux#foobar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo"bar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo<bar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo>bar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo`bar> against <about:blank> -PASS Parsing origin: <http://1.2.3.4/> against <http://other.com/> -PASS Parsing origin: <http://1.2.3.4./> against <http://other.com/> -PASS Parsing origin: <http://192.168.257> against <http://other.com/> -PASS Parsing origin: <http://192.168.257.> against <http://other.com/> -PASS Parsing origin: <http://192.168.257.com> against <http://other.com/> -PASS Parsing origin: <http://256> against <http://other.com/> -PASS Parsing origin: <http://256.com> against <http://other.com/> -PASS Parsing origin: <http://999999999> against <http://other.com/> -PASS Parsing origin: <http://999999999.> against <http://other.com/> -PASS Parsing origin: <http://999999999.com> against <http://other.com/> -PASS Parsing origin: <http://10000000000.com> against <http://other.com/> -PASS Parsing origin: <http://4294967295> against <http://other.com/> -PASS Parsing origin: <http://0xffffffff> against <http://other.com/> -PASS Parsing origin: <https://0x.0x.0> against <about:blank> -PASS Parsing origin: <asdf://%43%7C/> against <about:blank> -PASS Parsing origin: <http://[1:0::]> against <http://example.net/> -PASS Parsing origin: <sc://ñ> against <about:blank> -PASS Parsing origin: <sc://ñ?x> against <about:blank> -PASS Parsing origin: <sc://ñ#x> against <about:blank> -PASS Parsing origin: <#x> against <sc://ñ> -PASS Parsing origin: <?x> against <sc://ñ> -PASS Parsing origin: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> -PASS Parsing origin: <telnet://user:pass@foobar.com:23/> against <about:blank> -PASS Parsing origin: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> -PASS Parsing origin: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> -PASS Parsing origin: <rsync://foo@host:911/sup> against <about:blank> -PASS Parsing origin: <git://github.com/foo/bar.git> against <about:blank> -PASS Parsing origin: <irc://myserver.com:6999/channel?passwd> against <about:blank> -PASS Parsing origin: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> -PASS Parsing origin: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> -PASS Parsing origin: <git+https://github.com/foo/bar> against <about:blank> -PASS Parsing origin: <urn:ietf:rfc:2648> against <about:blank> -PASS Parsing origin: <tag:joe@example.org,2001:foo/bar> against <about:blank> -PASS Parsing origin: <blob:https://example.com:443/> against <about:blank> -PASS Parsing origin: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank> -PASS Parsing origin: <blob:> against <about:blank> -PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~> against <about:blank> -PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank> -PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org> -PASS Parsing origin: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> -FAIL Parsing origin: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: origin expected "wss://!\"$&'()*+,-.;=_`{}~" but got "null" -PASS Parsing origin: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-pseudo/idlharness-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-pseudo/idlharness-expected.txt deleted file mode 100644 index 46168b2..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/css/css-pseudo/idlharness-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -This is a testharness.js-based test. -FAIL idl_test setup promise_test: Unhandled rejection with value: object "TypeError: window.getPseudoElements is not a function" -PASS idl_test validation -PASS Partial interface Element: original interface defined -PASS Partial interface Element: member names are unique -PASS Element includes ParentNode: member names are unique -PASS Element includes NonDocumentTypeChildNode: member names are unique -PASS Element includes ChildNode: member names are unique -PASS Element includes Slottable: member names are unique -FAIL CSSPseudoElement interface: existence and properties of interface object assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface object length assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface object name assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: existence and properties of interface prototype object assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: attribute type assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement interface: attribute element assert_own_property: self does not have own property "CSSPseudoElement" expected property "CSSPseudoElement" missing -FAIL CSSPseudoElement must be primary interface of beforeElements.item(0) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL Stringification of beforeElements.item(0) assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL CSSPseudoElement interface: beforeElements.item(0) must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL CSSPseudoElement interface: beforeElements.item(0) must inherit property "element" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: beforeElements is not defined" -FAIL Element interface: operation pseudo(CSSOMString) assert_own_property: interface prototype object missing non-static operation expected property "pseudo" missing -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/url/a-element-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/url/a-element-expected.txt deleted file mode 100644 index f4e57be3..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/url/a-element-expected.txt +++ /dev/null
@@ -1,684 +0,0 @@ -This is a testharness.js-based test. -Found 669 tests; 383 PASS, 286 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS Loading data… -PASS Parsing: <http://example . -org> against <http://example.org/foo/bar> -PASS Parsing: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar> -PASS Parsing: <https://test:@test> against <about:blank> -PASS Parsing: <https://:@test> against <about:blank> -FAIL Parsing: <non-special://test:@test/x> against <about:blank> assert_equals: href expected "non-special://test@test/x" but got "non-special://test:@test/x" -FAIL Parsing: <non-special://:@test/x> against <about:blank> assert_equals: href expected "non-special://test/x" but got "non-special://:@test/x" -PASS Parsing: <http:foo.com> against <http://example.org/foo/bar> -PASS Parsing: < :foo.com -> against <http://example.org/foo/bar> -PASS Parsing: < foo.com > against <http://example.org/foo/bar> -PASS Parsing: <a: foo.com> against <http://example.org/foo/bar> -PASS Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar> -PASS Parsing: <lolscheme:x x#x x> against <about:blank> -PASS Parsing: <http://f:/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:0/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:00000000000000/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:00000000000000000000080/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:b/c> against <http://example.org/foo/bar> -FAIL Parsing: <http://f: /c> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://f: /c" but got "http://f:%20/c" -PASS Parsing: <http://f: -/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:fifty-two/c> against <http://example.org/foo/bar> -PASS Parsing: <http://f:999999/c> against <http://example.org/foo/bar> -FAIL Parsing: <non-special://f:999999/c> against <http://example.org/foo/bar> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://f: 21 / b ? d # e > against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://f: 21 / b ? d # e " but got "http://f:%2021%20/%20b%20?%20d%20#%20e" -PASS Parsing: <> against <http://example.org/foo/bar> -PASS Parsing: < > against <http://example.org/foo/bar> -PASS Parsing: <:foo.com/> against <http://example.org/foo/bar> -PASS Parsing: <:foo.com\> against <http://example.org/foo/bar> -PASS Parsing: <:> against <http://example.org/foo/bar> -PASS Parsing: <:a> against <http://example.org/foo/bar> -PASS Parsing: <:/> against <http://example.org/foo/bar> -PASS Parsing: <:\> against <http://example.org/foo/bar> -PASS Parsing: <:#> against <http://example.org/foo/bar> -PASS Parsing: <#> against <http://example.org/foo/bar> -PASS Parsing: <#/> against <http://example.org/foo/bar> -PASS Parsing: <#\> against <http://example.org/foo/bar> -PASS Parsing: <#;?> against <http://example.org/foo/bar> -PASS Parsing: <?> against <http://example.org/foo/bar> -PASS Parsing: </> against <http://example.org/foo/bar> -PASS Parsing: <:23> against <http://example.org/foo/bar> -PASS Parsing: </:23> against <http://example.org/foo/bar> -PASS Parsing: <\x> against <http://example.org/foo/bar> -PASS Parsing: <\\x\hello> against <http://example.org/foo/bar> -PASS Parsing: <::> against <http://example.org/foo/bar> -PASS Parsing: <::23> against <http://example.org/foo/bar> -FAIL Parsing: <foo://> against <http://example.org/foo/bar> assert_equals: pathname expected "" but got "//" -PASS Parsing: <http://a:b@c:29/d> against <http://example.org/foo/bar> -PASS Parsing: <http::@c:29> against <http://example.org/foo/bar> -PASS Parsing: <http://&a:foo(b]c@d:2/> against <http://example.org/foo/bar> -PASS Parsing: <http://::@c@d:2> against <http://example.org/foo/bar> -PASS Parsing: <http://foo.com:b@d/> against <http://example.org/foo/bar> -PASS Parsing: <http://foo.com/\@> against <http://example.org/foo/bar> -PASS Parsing: <http:\\foo.com\> against <http://example.org/foo/bar> -PASS Parsing: <http:\\a\b:c\d@foo.com\> against <http://example.org/foo/bar> -PASS Parsing: <foo:/> against <http://example.org/foo/bar> -PASS Parsing: <foo:/bar.com/> against <http://example.org/foo/bar> -FAIL Parsing: <foo://///////> against <http://example.org/foo/bar> assert_equals: pathname expected "///////" but got "/////////" -FAIL Parsing: <foo://///////bar.com/> against <http://example.org/foo/bar> assert_equals: pathname expected "///////bar.com/" but got "/////////bar.com/" -FAIL Parsing: <foo:////://///> against <http://example.org/foo/bar> assert_equals: pathname expected "//://///" but got "////://///" -PASS Parsing: <c:/foo> against <http://example.org/foo/bar> -PASS Parsing: <//foo/bar> against <http://example.org/foo/bar> -PASS Parsing: <http://foo/path;a??e#f#g> against <http://example.org/foo/bar> -PASS Parsing: <http://foo/abcd?efgh?ijkl> against <http://example.org/foo/bar> -PASS Parsing: <http://foo/abcd#foo?bar> against <http://example.org/foo/bar> -PASS Parsing: <[61:24:74]:98> against <http://example.org/foo/bar> -PASS Parsing: <http:[61:27]/:foo> against <http://example.org/foo/bar> -FAIL Parsing: <http://[1::2]:3:4> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://[1::2]:3:4" but got "http://[1::2]:3:4/" -FAIL Parsing: <http://2001::1> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://2001::1" but got "http://2001::1/" -FAIL Parsing: <http://2001::1]> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://2001::1]" but got "http://2001::1]/" -FAIL Parsing: <http://2001::1]:80> against <http://example.org/foo/bar> assert_equals: failure should set href to input expected "http://2001::1]:80" but got "http://2001::1]/" -PASS Parsing: <http://[2001::1]> against <http://example.org/foo/bar> -PASS Parsing: <http://[::127.0.0.1]> against <http://example.org/foo/bar> -PASS Parsing: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar> -PASS Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar> -PASS Parsing: <http:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ftp:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <https:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <madeupscheme:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <file:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <file://example:1/> against <about:blank> -PASS Parsing: <file://example:test/> against <about:blank> -FAIL Parsing: <file://example%/> against <about:blank> assert_equals: failure should set href to input expected "file://example%/" but got "file://example%25/" -PASS Parsing: <file://[example]/> against <about:blank> -PASS Parsing: <ftps:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <gopher:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ws:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <wss:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <data:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <javascript:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <mailto:/example.com/> against <http://example.org/foo/bar> -PASS Parsing: <http:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ftp:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <https:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <madeupscheme:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ftps:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <gopher:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <ws:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <wss:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <data:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <javascript:example.com/> against <http://example.org/foo/bar> -PASS Parsing: <mailto:example.com/> against <http://example.org/foo/bar> -PASS Parsing: </a/b/c> against <http://example.org/foo/bar> -PASS Parsing: </a/ /c> against <http://example.org/foo/bar> -PASS Parsing: </a%2fc> against <http://example.org/foo/bar> -PASS Parsing: </a/%2f/c> against <http://example.org/foo/bar> -PASS Parsing: <#β> against <http://example.org/foo/bar> -PASS Parsing: <data:text/html,test#test> against <http://example.org/foo/bar> -PASS Parsing: <tel:1234567890> against <http://example.org/foo/bar> -FAIL Parsing: <ssh://example.com/foo/bar.git> against <http://example.org/> assert_equals: host expected "example.com" but got "" -FAIL Parsing: <file:c:\foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:/foo/bar.html" but got "file:///tmp/mock/c:/foo/bar.html" -FAIL Parsing: < File:c|////foo\bar.html> against <file:///tmp/mock/path> assert_equals: href expected "file:///c:////foo/bar.html" but got "file:///tmp/mock/c%7C////foo/bar.html" -FAIL Parsing: <C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///tmp/mock/C%7C/foo/bar" -FAIL Parsing: </C|\foo\bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file:///C%7C/foo/bar" -FAIL Parsing: <//C|/foo/bar> against <file:///tmp/mock/path> assert_equals: href expected "file:///C:/foo/bar" but got "file://c%7C/foo/bar" -PASS Parsing: <//server/file> against <file:///tmp/mock/path> -PASS Parsing: <\\server\file> against <file:///tmp/mock/path> -PASS Parsing: </\server/file> against <file:///tmp/mock/path> -PASS Parsing: <file:///foo/bar.txt> against <file:///tmp/mock/path> -PASS Parsing: <file:///home/me> against <file:///tmp/mock/path> -PASS Parsing: <//> against <file:///tmp/mock/path> -PASS Parsing: <///> against <file:///tmp/mock/path> -PASS Parsing: <///test> against <file:///tmp/mock/path> -PASS Parsing: <file://test> against <file:///tmp/mock/path> -FAIL Parsing: <file://localhost> against <file:///tmp/mock/path> assert_equals: href expected "file:///" but got "file://localhost/" -FAIL Parsing: <file://localhost/> against <file:///tmp/mock/path> assert_equals: href expected "file:///" but got "file://localhost/" -FAIL Parsing: <file://localhost/test> against <file:///tmp/mock/path> assert_equals: href expected "file:///test" but got "file://localhost/test" -PASS Parsing: <test> against <file:///tmp/mock/path> -PASS Parsing: <file:test> against <file:///tmp/mock/path> -PASS Parsing: <http://example.com/././foo> against <about:blank> -PASS Parsing: <http://example.com/./.foo> against <about:blank> -PASS Parsing: <http://example.com/foo/.> against <about:blank> -PASS Parsing: <http://example.com/foo/./> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/..> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/../> against <about:blank> -PASS Parsing: <http://example.com/foo/..bar> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/../ton> against <about:blank> -PASS Parsing: <http://example.com/foo/bar/../ton/../../a> against <about:blank> -PASS Parsing: <http://example.com/foo/../../..> against <about:blank> -PASS Parsing: <http://example.com/foo/../../../ton> against <about:blank> -PASS Parsing: <http://example.com/foo/%2e> against <about:blank> -FAIL Parsing: <http://example.com/foo/%2e%2> against <about:blank> assert_equals: href expected "http://example.com/foo/%2e%2" but got "http://example.com/foo/.%2" -FAIL Parsing: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> assert_equals: href expected "http://example.com/%2e.bar" but got "http://example.com/..bar" -PASS Parsing: <http://example.com////../..> against <about:blank> -PASS Parsing: <http://example.com/foo/bar//../..> against <about:blank> -PASS Parsing: <http://example.com/foo/bar//..> against <about:blank> -PASS Parsing: <http://example.com/foo> against <about:blank> -PASS Parsing: <http://example.com/%20foo> against <about:blank> -PASS Parsing: <http://example.com/foo%> against <about:blank> -PASS Parsing: <http://example.com/foo%2> against <about:blank> -PASS Parsing: <http://example.com/foo%2zbar> against <about:blank> -PASS Parsing: <http://example.com/foo%2©zbar> against <about:blank> -FAIL Parsing: <http://example.com/foo%41%7a> against <about:blank> assert_equals: href expected "http://example.com/foo%41%7a" but got "http://example.com/fooAz" -PASS Parsing: <http://example.com/foo %91> against <about:blank> -FAIL Parsing: <http://example.com/foo%00%51> against <about:blank> assert_equals: href expected "http://example.com/foo%00%51" but got "http://example.com/foo%00Q" -PASS Parsing: <http://example.com/(%28:%3A%29)> against <about:blank> -PASS Parsing: <http://example.com/%3A%3a%3C%3c> against <about:blank> -PASS Parsing: <http://example.com/foo bar> against <about:blank> -PASS Parsing: <http://example.com\\foo\\bar> against <about:blank> -PASS Parsing: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank> -PASS Parsing: <http://example.com/@asdf%40> against <about:blank> -PASS Parsing: <http://example.com/你好你好> against <about:blank> -PASS Parsing: <http://example.com/‥/foo> against <about:blank> -PASS Parsing: <http://example.com//foo> against <about:blank> -PASS Parsing: <http://example.com//foo//bar> against <about:blank> -PASS Parsing: <http://www.google.com/foo?bar=baz#> against <about:blank> -PASS Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank> -PASS Parsing: <data:test# »> against <about:blank> -PASS Parsing: <http://www.google.com> against <about:blank> -PASS Parsing: <http://192.0x00A80001> against <about:blank> -FAIL Parsing: <http://www/foo%2Ehtml> against <about:blank> assert_equals: href expected "http://www/foo%2Ehtml" but got "http://www/foo.html" -PASS Parsing: <http://www/foo/%2E/html> against <about:blank> -PASS Parsing: <http://user:pass@/> against <about:blank> -PASS Parsing: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> -PASS Parsing: <http:\\www.google.com\foo> against <about:blank> -PASS Parsing: <http://foo:80/> against <about:blank> -PASS Parsing: <http://foo:81/> against <about:blank> -FAIL Parsing: <httpa://foo:80/> against <about:blank> assert_equals: host expected "foo:80" but got "" -PASS Parsing: <http://foo:-80/> against <about:blank> -PASS Parsing: <https://foo:443/> against <about:blank> -PASS Parsing: <https://foo:80/> against <about:blank> -PASS Parsing: <ftp://foo:21/> against <about:blank> -PASS Parsing: <ftp://foo:80/> against <about:blank> -FAIL Parsing: <gopher://foo:70/> against <about:blank> assert_equals: host expected "foo:70" but got "" -FAIL Parsing: <gopher://foo:443/> against <about:blank> assert_equals: host expected "foo:443" but got "" -PASS Parsing: <ws://foo:80/> against <about:blank> -PASS Parsing: <ws://foo:81/> against <about:blank> -PASS Parsing: <ws://foo:443/> against <about:blank> -PASS Parsing: <ws://foo:815/> against <about:blank> -PASS Parsing: <wss://foo:80/> against <about:blank> -PASS Parsing: <wss://foo:81/> against <about:blank> -PASS Parsing: <wss://foo:443/> against <about:blank> -PASS Parsing: <wss://foo:815/> against <about:blank> -PASS Parsing: <http:/example.com/> against <about:blank> -PASS Parsing: <ftp:/example.com/> against <about:blank> -PASS Parsing: <https:/example.com/> against <about:blank> -PASS Parsing: <madeupscheme:/example.com/> against <about:blank> -PASS Parsing: <file:/example.com/> against <about:blank> -PASS Parsing: <ftps:/example.com/> against <about:blank> -PASS Parsing: <gopher:/example.com/> against <about:blank> -PASS Parsing: <ws:/example.com/> against <about:blank> -PASS Parsing: <wss:/example.com/> against <about:blank> -PASS Parsing: <data:/example.com/> against <about:blank> -PASS Parsing: <javascript:/example.com/> against <about:blank> -PASS Parsing: <mailto:/example.com/> against <about:blank> -PASS Parsing: <http:example.com/> against <about:blank> -PASS Parsing: <ftp:example.com/> against <about:blank> -PASS Parsing: <https:example.com/> against <about:blank> -PASS Parsing: <madeupscheme:example.com/> against <about:blank> -PASS Parsing: <ftps:example.com/> against <about:blank> -PASS Parsing: <gopher:example.com/> against <about:blank> -PASS Parsing: <ws:example.com/> against <about:blank> -PASS Parsing: <wss:example.com/> against <about:blank> -PASS Parsing: <data:example.com/> against <about:blank> -PASS Parsing: <javascript:example.com/> against <about:blank> -PASS Parsing: <mailto:example.com/> against <about:blank> -PASS Parsing: <http:@www.example.com> against <about:blank> -PASS Parsing: <http:/@www.example.com> against <about:blank> -PASS Parsing: <http://@www.example.com> against <about:blank> -PASS Parsing: <http:a:b@www.example.com> against <about:blank> -PASS Parsing: <http:/a:b@www.example.com> against <about:blank> -PASS Parsing: <http://a:b@www.example.com> against <about:blank> -PASS Parsing: <http://@pple.com> against <about:blank> -PASS Parsing: <http::b@www.example.com> against <about:blank> -PASS Parsing: <http:/:b@www.example.com> against <about:blank> -PASS Parsing: <http://:b@www.example.com> against <about:blank> -FAIL Parsing: <http:/:@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/:@/www.example.com" but got "http:///www.example.com" -PASS Parsing: <http://user@/www.example.com> against <about:blank> -FAIL Parsing: <http:@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:@/www.example.com" but got "http:///www.example.com" -FAIL Parsing: <http:/@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/@/www.example.com" but got "http:///www.example.com" -FAIL Parsing: <http://@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http://@/www.example.com" but got "http:///www.example.com" -FAIL Parsing: <https:@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "https:@/www.example.com" but got "https:///www.example.com" -FAIL Parsing: <http:a:b@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:a:b@/www.example.com" but got "http://a:b@/www.example.com" -FAIL Parsing: <http:/a:b@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/a:b@/www.example.com" but got "http://a:b@/www.example.com" -PASS Parsing: <http://a:b@/www.example.com> against <about:blank> -FAIL Parsing: <http::@/www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http::@/www.example.com" but got "http:///www.example.com" -PASS Parsing: <http:a:@www.example.com> against <about:blank> -PASS Parsing: <http:/a:@www.example.com> against <about:blank> -PASS Parsing: <http://a:@www.example.com> against <about:blank> -PASS Parsing: <http://www.@pple.com> against <about:blank> -FAIL Parsing: <http:@:www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:@:www.example.com" but got "http://:www.example.com/" -FAIL Parsing: <http:/@:www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http:/@:www.example.com" but got "http://:www.example.com/" -FAIL Parsing: <http://@:www.example.com> against <about:blank> assert_equals: failure should set href to input expected "http://@:www.example.com" but got "http://:www.example.com/" -PASS Parsing: <http://:@www.example.com> against <about:blank> -PASS Parsing: </> against <http://www.example.com/test> -PASS Parsing: </test.txt> against <http://www.example.com/test> -PASS Parsing: <.> against <http://www.example.com/test> -PASS Parsing: <..> against <http://www.example.com/test> -PASS Parsing: <test.txt> against <http://www.example.com/test> -PASS Parsing: <./test.txt> against <http://www.example.com/test> -PASS Parsing: <../test.txt> against <http://www.example.com/test> -PASS Parsing: <../aaa/test.txt> against <http://www.example.com/test> -PASS Parsing: <../../test.txt> against <http://www.example.com/test> -PASS Parsing: <中/test.txt> against <http://www.example.com/test> -PASS Parsing: <http://www.example2.com> against <http://www.example.com/test> -PASS Parsing: <//www.example2.com> against <http://www.example.com/test> -PASS Parsing: <file:...> against <http://www.example.com/test> -PASS Parsing: <file:..> against <http://www.example.com/test> -PASS Parsing: <file:a> against <http://www.example.com/test> -PASS Parsing: <http://ExAmPlE.CoM> against <http://other.com/> -FAIL Parsing: <http://example example.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://Goo%20 goo%7C|.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://[]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[]" but got "http://[]/" -FAIL Parsing: <http://[:]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[:]" but got "http://[:]/" -FAIL Parsing: <http://GOO goo.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://GOOgoo.com> against <http://other.com/> -PASS Parsing: <\0 http://example.com/ \r > against <about:blank> -PASS Parsing: <http://www.foo。bar.com> against <http://other.com/> -FAIL Parsing: <http://zyx.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://zyx.com" but got "http://%EF%BF%BDzyx.com/" -FAIL Parsing: <http://%ef%b7%90zyx.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%ef%b7%90zyx.com" but got "http://%EF%BF%BDzyx.com/" -FAIL Parsing: <https://�> against <about:blank> assert_equals: failure should set href to input expected "https://\ufffd" but got "https://%EF%BF%BD/" -FAIL Parsing: <https://%EF%BF%BD> against <about:blank> assert_equals: failure should set href to input expected "https://%EF%BF%BD" but got "https://%EF%BF%BD/" -PASS Parsing: <https://x/�?�#�> against <about:blank> -FAIL Parsing: <http://a.b.c.xn--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://10.0.0.xn--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a.b.c.XN--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a.b.c.Xn--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://10.0.0.XN--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://10.0.0.xN--pokxncvks> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://Go.com> against <http://other.com/> -FAIL Parsing: <http://%41.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://%ef%bc%85%ef%bc%94%ef%bc%91.com> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://%00.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%00.com" but got "http://%00.com/" -FAIL Parsing: <http://%ef%bc%85%ef%bc%90%ef%bc%90.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%ef%bc%85%ef%bc%90%ef%bc%90.com" but got "http://%00.com/" -PASS Parsing: <http://你好你好> against <http://other.com/> -FAIL Parsing: <https://faß.ExAmPlE/> against <about:blank> assert_equals: href expected "https://xn--fa-hia.example/" but got "https://fass.example/" -FAIL Parsing: <sc://faß.ExAmPlE/> against <about:blank> assert_equals: host expected "fa%C3%9F.ExAmPlE" but got "" -FAIL Parsing: <http://%zz%66%a.com> against <http://other.com/> assert_equals: failure should set href to input expected "http://%zz%66%a.com" but got "http://%25zzf%25a.com/" -FAIL Parsing: <http://%25> against <http://other.com/> assert_equals: failure should set href to input expected "http://%25" but got "http://%25/" -FAIL Parsing: <http://hello%00> against <http://other.com/> assert_equals: failure should set href to input expected "http://hello%00" but got "http://hello%00/" -PASS Parsing: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/> -PASS Parsing: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/> -FAIL Parsing: <http://192.168.0.257> against <http://other.com/> assert_equals: failure should set href to input expected "http://192.168.0.257" but got "http://192.168.0.257/" -FAIL Parsing: <http://%3g%78%63%30%2e%30%32%35%30%2E.01> against <http://other.com/> assert_equals: failure should set href to input expected "http://%3g%78%63%30%2e%30%32%35%30%2E.01" but got "http://%253gxc0.0250..01/" -FAIL Parsing: <http://192.168.0.1 hello> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <https://x x:12> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://0Xc0.0250.01> against <http://other.com/> -PASS Parsing: <http://./> against <about:blank> -PASS Parsing: <http://../> against <about:blank> -PASS Parsing: <http://[www.google.com]/> against <about:blank> -FAIL Parsing: <http://[google.com]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[google.com]" but got "http://[google.com]/" -FAIL Parsing: <http://[::1.2.3.4x]> against <http://other.com/> assert_equals: failure should set href to input expected "http://[::1.2.3.4x]" but got "http://[::1.2.3.4x]/" -FAIL Parsing: <http://[::1.2.3.]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://[::1.2.]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://[::1.]> against <http://other.com/> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://foo:💩@example.com/bar> against <http://other.com/> -PASS Parsing: <#> against <test:test> -PASS Parsing: <#x> against <mailto:x@x.com> -FAIL Parsing: <#x> against <data:,> assert_equals: href expected "data:,#x" but got "mailto:x@x.com#x" -PASS Parsing: <#x> against <about:blank> -PASS Parsing: <#> against <test:test?test> -PASS Parsing: <https://@test@test@example:800/> against <http://doesnotmatter/> -PASS Parsing: <https://@@@example> against <http://doesnotmatter/> -PASS Parsing: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/> -PASS Parsing: <http://host/?'> against <about:blank> -FAIL Parsing: <notspecial://host/?'> against <about:blank> assert_equals: href expected "notspecial://host/?'" but got "notspecial://host/?%27" -PASS Parsing: </some/path> against <http://user@example.org/smth> -PASS Parsing: <> against <http://user:pass@example.org:21/smth> -PASS Parsing: </some/path> against <http://user:pass@example.org:21/smth> -FAIL Parsing: <i> against <sc:sd> assert_equals: failure should set href to input expected "i" but got "" -FAIL Parsing: <i> against <sc:sd/sd> assert_equals: failure should set href to input expected "i" but got "" -PASS Parsing: <i> against <sc:/pa/pa> -FAIL Parsing: <i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/i" but got "///pa/i" -FAIL Parsing: <../i> against <sc:sd> assert_equals: failure should set href to input expected "../i" but got "" -FAIL Parsing: <../i> against <sc:sd/sd> assert_equals: failure should set href to input expected "../i" but got "" -PASS Parsing: <../i> against <sc:/pa/pa> -FAIL Parsing: <../i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <../i> against <sc:///pa/pa> assert_equals: href expected "sc:///i" but got "sc:///pa/i" -FAIL Parsing: </i> against <sc:sd> assert_equals: failure should set href to input expected "/i" but got "" -FAIL Parsing: </i> against <sc:sd/sd> assert_equals: failure should set href to input expected "/i" but got "" -PASS Parsing: </i> against <sc:/pa/pa> -FAIL Parsing: </i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: </i> against <sc:///pa/pa> assert_equals: href expected "sc:///i" but got "sc:///pa/i" -FAIL Parsing: <?i> against <sc:sd> assert_equals: failure should set href to input expected "?i" but got "" -FAIL Parsing: <?i> against <sc:sd/sd> assert_equals: failure should set href to input expected "?i" but got "" -PASS Parsing: <?i> against <sc:/pa/pa> -FAIL Parsing: <?i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <?i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa" -PASS Parsing: <#i> against <sc:sd> -PASS Parsing: <#i> against <sc:sd/sd> -PASS Parsing: <#i> against <sc:/pa/pa> -FAIL Parsing: <#i> against <sc://ho/pa> assert_equals: host expected "ho" but got "" -FAIL Parsing: <#i> against <sc:///pa/pa> assert_equals: pathname expected "/pa/pa" but got "///pa/pa" -FAIL Parsing: <about:/../> against <about:blank> assert_equals: href expected "about:/" but got "about:/../" -FAIL Parsing: <data:/../> against <about:blank> assert_equals: href expected "data:/" but got "data:/../" -FAIL Parsing: <javascript:/../> against <about:blank> assert_equals: href expected "javascript:/" but got "javascript:/../" -FAIL Parsing: <mailto:/../> against <about:blank> assert_equals: href expected "mailto:/" but got "mailto:/../" -FAIL Parsing: <sc://ñ.test/> against <about:blank> assert_equals: host expected "%C3%B1.test" but got "" -FAIL Parsing: <sc://\0/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc:// /> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://%/> against <about:blank> assert_equals: host expected "%" but got "" -FAIL Parsing: <sc://@/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://te@s:t@/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://:/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://:12/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://[/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://\/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <sc://]/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <x> against <sc://ñ> assert_equals: href expected "sc://%C3%B1/x" but got "sc://%C3%B1" -PASS Parsing: <sc:\../> against <about:blank> -PASS Parsing: <sc::a@example.net> against <about:blank> -PASS Parsing: <wow:%NBD> against <about:blank> -PASS Parsing: <wow:%1G> against <about:blank> -FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" -FAIL Parsing: <http://example.com/U+d800U+dfff﷏ﷰ?U+d800U+dfff﷏ﷰ> against <about:blank> assert_equals: href expected "http://example.com/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%B7%90%EF%B7%8F%EF%B7%AF%EF%B7%B0%EF%BF%BE%EF%BF%BF" but got "http://example.com/%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%BF%BD%EF%B7%8F%EF%BF%BD%EF%B7%B0%EF%BF%BD%EF%BF%BD?%EF%BF%BD%F0%90%9F%BE%EF%BF%BD%EF%BF%BD%EF%B7%8F%EF%BF%BD%EF%B7%B0%EF%BF%BD%EF%BF%BD" -FAIL Parsing: <http://a<b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a>b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://a^b> against <about:blank> assert_equals: failure should set href to input expected "http://a^b" but got "http://a%5Eb/" -FAIL Parsing: <non-special://a<b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <non-special://a>b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <non-special://a^b> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <foo://ho\0st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <foo://ho|st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <foo://ho st/> against <about:blank> assert_equals: host expected "host" but got "" -FAIL Parsing: <foo://ho -st/> against <about:blank> assert_equals: host expected "host" but got "" -FAIL Parsing: <foo://ho\rst/> against <about:blank> assert_equals: host expected "host" but got "" -PASS Parsing: <http://ho%00st/> against <about:blank> -PASS Parsing: <http://ho%09st/> against <about:blank> -PASS Parsing: <http://ho%0Ast/> against <about:blank> -PASS Parsing: <http://ho%0Dst/> against <about:blank> -FAIL Parsing: <http://ho%20st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ho%23st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://ho%2Fst/> against <about:blank> -FAIL Parsing: <http://ho%3Ast/> against <about:blank> assert_equals: failure should set href to input expected "http://ho%3Ast/" but got "http://ho:st/" -FAIL Parsing: <http://ho%3Cst/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ho%3Est/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <http://ho%3Fst/> against <about:blank> -FAIL Parsing: <http://ho%40st/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://ho%5Bst/> against <about:blank> assert_equals: failure should set href to input expected "http://ho%5Bst/" but got "http://ho[st/" -PASS Parsing: <http://ho%5Cst/> against <about:blank> -FAIL Parsing: <http://ho%5Dst/> against <about:blank> assert_equals: failure should set href to input expected "http://ho%5Dst/" but got "http://ho]st/" -FAIL Parsing: <http://ho%7Cst/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: href expected "http://\x1f!\"$&'()*+,-.;=_`{}~/" but got "http://%1F%21%22%24%26%27%28%29%2A+%2C-.%3B%3D_%60%7B%7D%7E/" -FAIL Parsing: <sc://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "%1F!\"$&'()*+,-.;=_`{}~" but got "" -FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" -FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" -FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/" -FAIL Parsing: <https://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%A0/" but got "https://example.com%EF%BF%BD/" -PASS Parsing: <ftp://%e2%98%83> against <about:blank> -PASS Parsing: <https://%e2%98%83> against <about:blank> -PASS Parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank> -PASS Parsing: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank> -PASS Parsing: <https://localhost:3000/jqueryui@1.2.3> against <about:blank> -PASS Parsing: <h t -t\rp://h o -s\rt:9 0 -0\r0/p a -t\rh?q u -e\rry#f r -a\rg> against <about:blank> -PASS Parsing: <?a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing: <??a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing: <http:> against <http://example.org/foo/bar> -PASS Parsing: <http:> against <https://example.org/foo/bar> -PASS Parsing: <sc:> against <https://example.org/foo/bar> -PASS Parsing: <http://foo.bar/baz?qux#foobar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank> -PASS Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank> -PASS Parsing: <http://1.2.3.4/> against <http://other.com/> -PASS Parsing: <http://1.2.3.4./> against <http://other.com/> -PASS Parsing: <http://192.168.257> against <http://other.com/> -PASS Parsing: <http://192.168.257.> against <http://other.com/> -PASS Parsing: <http://192.168.257.com> against <http://other.com/> -PASS Parsing: <http://256> against <http://other.com/> -PASS Parsing: <http://256.com> against <http://other.com/> -PASS Parsing: <http://999999999> against <http://other.com/> -PASS Parsing: <http://999999999.> against <http://other.com/> -PASS Parsing: <http://999999999.com> against <http://other.com/> -FAIL Parsing: <http://10000000000> against <http://other.com/> assert_equals: failure should set href to input expected "http://10000000000" but got "http://10000000000/" -PASS Parsing: <http://10000000000.com> against <http://other.com/> -PASS Parsing: <http://4294967295> against <http://other.com/> -FAIL Parsing: <http://4294967296> against <http://other.com/> assert_equals: failure should set href to input expected "http://4294967296" but got "http://4294967296/" -PASS Parsing: <http://0xffffffff> against <http://other.com/> -FAIL Parsing: <http://0xffffffff1> against <http://other.com/> assert_equals: failure should set href to input expected "http://0xffffffff1" but got "http://0xffffffff1/" -FAIL Parsing: <http://256.256.256.256> against <http://other.com/> assert_equals: failure should set href to input expected "http://256.256.256.256" but got "http://256.256.256.256/" -PASS Parsing: <https://0x.0x.0> against <about:blank> -PASS Parsing: <https://0x100000000/test> against <about:blank> -PASS Parsing: <https://256.0.0.1/test> against <about:blank> -PASS Parsing: <file:///C%3A/> against <about:blank> -PASS Parsing: <file:///C%7C/> against <about:blank> -FAIL Parsing: <file://%43%3A> against <about:blank> assert_equals: failure should set href to input expected "file://%43%3A" but got "file://c:/" -FAIL Parsing: <file://%43%7C> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <file://%43|> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <file://C%7C> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <file://%43%7C/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <https://%43%7C/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <asdf://%43|/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -FAIL Parsing: <asdf://%43%7C/> against <about:blank> assert_equals: host expected "%43%7C" but got "" -PASS Parsing: <pix/submit.gif> against <file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html> -FAIL Parsing: <..> against <file:///C:/> assert_equals: href expected "file:///C:/" but got "file:///" -PASS Parsing: <..> against <file:///> -FAIL Parsing: </> against <file:///C:/a/b> assert_equals: href expected "file:///C:/" but got "file:///" -FAIL Parsing: </> against <file://h/C:/a/b> assert_equals: href expected "file://h/C:/" but got "file://h/" -PASS Parsing: </> against <file://h/a/b> -FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file://d:/" -FAIL Parsing: <//d:/..> against <file:///C:/a/b> assert_equals: href expected "file:///d:/" but got "file://d:/" -PASS Parsing: <..> against <file:///ab:/> -PASS Parsing: <..> against <file:///1:/> -PASS Parsing: <> against <file:///test?test#test> -PASS Parsing: <file:> against <file:///test?test#test> -PASS Parsing: <?x> against <file:///test?test#test> -PASS Parsing: <file:?x> against <file:///test?test#test> -PASS Parsing: <#x> against <file:///test?test#test> -PASS Parsing: <file:#x> against <file:///test?test#test> -FAIL Parsing: <file:\\//> against <about:blank> assert_equals: href expected "file:////" but got "file:///" -FAIL Parsing: <file:\\\\> against <about:blank> assert_equals: href expected "file:////" but got "file:///" -FAIL Parsing: <file:\\\\?fox> against <about:blank> assert_equals: href expected "file:////?fox" but got "file:///?fox" -FAIL Parsing: <file:\\\\#guppy> against <about:blank> assert_equals: href expected "file:////#guppy" but got "file:///#guppy" -PASS Parsing: <file://spider///> against <about:blank> -FAIL Parsing: <file:\\localhost//> against <about:blank> assert_equals: href expected "file:////" but got "file://localhost//" -PASS Parsing: <file:///localhost//cat> against <about:blank> -FAIL Parsing: <file://\/localhost//cat> against <about:blank> assert_equals: href expected "file:////localhost//cat" but got "file:///localhost//cat" -FAIL Parsing: <file://localhost//a//../..//> against <about:blank> assert_equals: href expected "file://///" but got "file://localhost///" -FAIL Parsing: </////mouse> against <file:///elephant> assert_equals: href expected "file://///mouse" but got "file:///mouse" -PASS Parsing: <\//pig> against <file://lion/> -FAIL Parsing: <\/localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig" -FAIL Parsing: <//localhost//pig> against <file://lion/> assert_equals: href expected "file:////pig" but got "file://localhost//pig" -PASS Parsing: </..//localhost//pig> against <file://lion/> -PASS Parsing: <file://> against <file://ape/> -PASS Parsing: </rooibos> against <file://tea/> -PASS Parsing: </?chai> against <file://tea/> -FAIL Parsing: <C|> against <file://host/dir/file> assert_equals: href expected "file://host/C:" but got "file://host/dir/C%7C" -FAIL Parsing: <C|> against <file://host/D:/dir1/dir2/file> assert_equals: href expected "file://host/C:" but got "file://host/D:/dir1/dir2/C%7C" -FAIL Parsing: <C|#> against <file://host/dir/file> assert_equals: href expected "file://host/C:#" but got "file://host/dir/C%7C#" -FAIL Parsing: <C|?> against <file://host/dir/file> assert_equals: href expected "file://host/C:?" but got "file://host/dir/C%7C?" -FAIL Parsing: <C|/> against <file://host/dir/file> assert_equals: href expected "file://host/C:/" but got "file://host/dir/C%7C/" -FAIL Parsing: <C| -/> against <file://host/dir/file> assert_equals: href expected "file://host/C:/" but got "file://host/dir/C%7C/" -FAIL Parsing: <C|\> against <file://host/dir/file> assert_equals: href expected "file://host/C:/" but got "file://host/dir/C%7C/" -PASS Parsing: <C> against <file://host/dir/file> -FAIL Parsing: <C|a> against <file://host/dir/file> assert_equals: href expected "file://host/dir/C|a" but got "file://host/dir/C%7Ca" -PASS Parsing: </c:/foo/bar> against <file:///c:/baz/qux> -FAIL Parsing: </c|/foo/bar> against <file:///c:/baz/qux> assert_equals: href expected "file:///c:/foo/bar" but got "file:///c%7C/foo/bar" -PASS Parsing: <file:\c:\foo\bar> against <file:///c:/baz/qux> -PASS Parsing: </c:/foo/bar> against <file://host/path> -PASS Parsing: <file://example.net/C:/> against <about:blank> -PASS Parsing: <file://1.2.3.4/C:/> against <about:blank> -PASS Parsing: <file://[1::8]/C:/> against <about:blank> -FAIL Parsing: <C|/> against <file://host/> assert_equals: href expected "file://host/C:/" but got "file://host/C%7C/" -PASS Parsing: </C:/> against <file://host/> -PASS Parsing: <file:C:/> against <file://host/> -PASS Parsing: <file:/C:/> against <file://host/> -FAIL Parsing: <//C:/> against <file://host/> assert_equals: href expected "file:///C:/" but got "file://c:/" -FAIL Parsing: <file://C:/> against <file://host/> assert_equals: href expected "file:///C:/" but got "file://c:/" -PASS Parsing: <///C:/> against <file://host/> -PASS Parsing: <file:///C:/> against <file://host/> -FAIL Parsing: <file:/C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file:///C%7C/" -FAIL Parsing: <file://C|/> against <about:blank> assert_equals: href expected "file:///C:/" but got "file://c%7C/" -PASS Parsing: <file:> against <about:blank> -PASS Parsing: <file:?q=v> against <about:blank> -PASS Parsing: <file:#frag> against <about:blank> -PASS Parsing: <file:///Y:> against <about:blank> -PASS Parsing: <file:///Y:/> against <about:blank> -PASS Parsing: <file:///./Y> against <about:blank> -PASS Parsing: <file:///./Y:> against <about:blank> -FAIL Parsing: <\\\.\Y:> against <about:blank> assert_equals: failure should set href to input expected "\\\\\\.\\Y:" but got "" -PASS Parsing: <file:///y:> against <about:blank> -PASS Parsing: <file:///y:/> against <about:blank> -PASS Parsing: <file:///./y> against <about:blank> -PASS Parsing: <file:///./y:> against <about:blank> -FAIL Parsing: <\\\.\y:> against <about:blank> assert_equals: failure should set href to input expected "\\\\\\.\\y:" but got "" -FAIL Parsing: <file://localhost//a//../..//foo> against <about:blank> assert_equals: href expected "file://///foo" but got "file://localhost///foo" -FAIL Parsing: <file://localhost////foo> against <about:blank> assert_equals: href expected "file://////foo" but got "file://localhost////foo" -FAIL Parsing: <file:////foo> against <about:blank> assert_equals: href expected "file:////foo" but got "file:///foo" -PASS Parsing: <file:///one/two> against <file:///> -FAIL Parsing: <file:////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two" -PASS Parsing: <//one/two> against <file:///> -PASS Parsing: <///one/two> against <file:///> -FAIL Parsing: <////one/two> against <file:///> assert_equals: href expected "file:////one/two" but got "file:///one/two" -PASS Parsing: <file:///.//> against <file:////> -PASS Parsing: <file:.//p> against <about:blank> -PASS Parsing: <file:/.//p> against <about:blank> -PASS Parsing: <http://[1:0::]> against <http://example.net/> -FAIL Parsing: <http://[0:1:2:3:4:5:6:7:8]> against <http://example.net/> assert_equals: failure should set href to input expected "http://[0:1:2:3:4:5:6:7:8]" but got "http://[0:1:2:3:4:5:6:7:8]/" -FAIL Parsing: <https://[0::0::0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0::0::0]" but got "https://[0::0::0]/" -FAIL Parsing: <https://[0:.0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:.0]" but got "https://[0:.0]/" -FAIL Parsing: <https://[0:0:]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:0:]" but got "https://[0:0:]/" -FAIL Parsing: <https://[0:1:2:3:4:5:6:7.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1:2:3:4:5:6:7.0.0.0.1]" but got "https://[0:1:2:3:4:5:6:7.0.0.0.1]/" -FAIL Parsing: <https://[0:1.00.0.0.0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1.00.0.0.0]" but got "https://[0:1.00.0.0.0]/" -FAIL Parsing: <https://[0:1.290.0.0.0]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1.290.0.0.0]" but got "https://[0:1.290.0.0.0]/" -FAIL Parsing: <https://[0:1.23.23]> against <about:blank> assert_equals: failure should set href to input expected "https://[0:1.23.23]" but got "https://[0:1.23.23]/" -FAIL Parsing: <http://?> against <about:blank> assert_equals: failure should set href to input expected "http://?" but got "http:/?" -FAIL Parsing: <http://#> against <about:blank> assert_equals: failure should set href to input expected "http://#" but got "http:/#" -PASS Parsing: <http://f:4294967377/c> against <http://example.org/> -PASS Parsing: <http://f:18446744073709551697/c> against <http://example.org/> -PASS Parsing: <http://f:340282366920938463463374607431768211537/c> against <http://example.org/> -FAIL Parsing: <sc://ñ> against <about:blank> assert_equals: host expected "%C3%B1" but got "" -FAIL Parsing: <sc://ñ?x> against <about:blank> assert_equals: host expected "%C3%B1" but got "" -FAIL Parsing: <sc://ñ#x> against <about:blank> assert_equals: host expected "%C3%B1" but got "" -FAIL Parsing: <#x> against <sc://ñ> assert_equals: href expected "sc://%C3%B1#x" but got "sc://%C3%B1" -FAIL Parsing: <?x> against <sc://ñ> assert_equals: href expected "sc://%C3%B1?x" but got "sc://%C3%B1" -FAIL Parsing: <sc://?> against <about:blank> assert_equals: pathname expected "" but got "//" -FAIL Parsing: <sc://#> against <about:blank> assert_equals: pathname expected "" but got "//" -FAIL Parsing: <///> against <sc://x/> assert_equals: href expected "sc:///" but got "sc:" -FAIL Parsing: <////> against <sc://x/> assert_equals: href expected "sc:////" but got "sc:" -FAIL Parsing: <////x/> against <sc://x/> assert_equals: href expected "sc:////x/" but got "sc://x/" -FAIL Parsing: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> assert_equals: host expected "foobar.com" but got "" -FAIL Parsing: <telnet://user:pass@foobar.com:23/> against <about:blank> assert_equals: username expected "user" but got "" -FAIL Parsing: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> assert_equals: host expected "10.10.10.10:7777" but got "" -FAIL Parsing: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> assert_equals: username expected "foo" but got "" -FAIL Parsing: <rsync://foo@host:911/sup> against <about:blank> assert_equals: username expected "foo" but got "" -FAIL Parsing: <git://github.com/foo/bar.git> against <about:blank> assert_equals: host expected "github.com" but got "" -FAIL Parsing: <irc://myserver.com:6999/channel?passwd> against <about:blank> assert_equals: host expected "myserver.com:6999" but got "" -FAIL Parsing: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> assert_equals: host expected "fw.example.org:9999" but got "" -FAIL Parsing: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> assert_equals: host expected "localhost:389" but got "" -FAIL Parsing: <git+https://github.com/foo/bar> against <about:blank> assert_equals: host expected "github.com" but got "" -PASS Parsing: <urn:ietf:rfc:2648> against <about:blank> -PASS Parsing: <tag:joe@example.org,2001:foo/bar> against <about:blank> -FAIL Parsing: <non-spec:/.//> against <about:blank> assert_equals: pathname expected "//" but got "/.//" -FAIL Parsing: <non-spec:/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/..//" -FAIL Parsing: <non-spec:/a/..//> against <about:blank> assert_equals: href expected "non-spec:/.//" but got "non-spec:/a/..//" -FAIL Parsing: <non-spec:/.//path> against <about:blank> assert_equals: pathname expected "//path" but got "/.//path" -FAIL Parsing: <non-spec:/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path" -FAIL Parsing: <non-spec:/a/..//path> against <about:blank> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/a/..//path" -FAIL Parsing: </.//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: </..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: <..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: <a/..//path> against <non-spec:/p> assert_equals: href expected "non-spec:/.//path" but got "non-spec://path" -FAIL Parsing: <> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//p" but got "non-spec:/..//p" -FAIL Parsing: <path> against <non-spec:/..//p> assert_equals: href expected "non-spec:/.//path" but got "non-spec:/..//path" -FAIL Parsing: <../path> against <non-spec:/.//p> assert_equals: href expected "non-spec:/path" but got "non-spec:/./path" -FAIL Parsing: <non-special://%E2%80%A0/> against <about:blank> assert_equals: host expected "%E2%80%A0" but got "" -FAIL Parsing: <non-special://H%4fSt/path> against <about:blank> assert_equals: host expected "H%4fSt" but got "" -FAIL Parsing: <non-special://[1:2:0:0:5:0:0:0]/> against <about:blank> assert_equals: href expected "non-special://[1:2:0:0:5::]/" but got "non-special://[1:2:0:0:5:0:0:0]/" -FAIL Parsing: <non-special://[1:2:0:0:0:0:0:3]/> against <about:blank> assert_equals: href expected "non-special://[1:2::3]/" but got "non-special://[1:2:0:0:0:0:0:3]/" -FAIL Parsing: <non-special://[1:2::3]:80/> against <about:blank> assert_equals: host expected "[1:2::3]:80" but got "" -FAIL Parsing: <non-special://[:80/> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <blob:https://example.com:443/> against <about:blank> -PASS Parsing: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank> -PASS Parsing: <blob:> against <about:blank> -PASS Parsing: <http://0x7f.0.0.0x7g> against <about:blank> -PASS Parsing: <http://0X7F.0.0.0X7G> against <about:blank> -FAIL Parsing: <http://[::127.0.0.0.1]> against <about:blank> assert_equals: failure should set href to input expected "http://[::127.0.0.0.1]" but got "http://[::127.0.0.0.1]/" -PASS Parsing: <http://[0:1:0:1:0:1:0:1]> against <about:blank> -PASS Parsing: <http://[1:0:1:0:1:0:1:0]> against <about:blank> -PASS Parsing: <http://example.org/test?"> against <about:blank> -PASS Parsing: <http://example.org/test?#> against <about:blank> -PASS Parsing: <http://example.org/test?<> against <about:blank> -PASS Parsing: <http://example.org/test?>> against <about:blank> -PASS Parsing: <http://example.org/test?⌣> against <about:blank> -PASS Parsing: <http://example.org/test?%23%23> against <about:blank> -PASS Parsing: <http://example.org/test?%GH> against <about:blank> -PASS Parsing: <http://example.org/test?a#%EF> against <about:blank> -PASS Parsing: <http://example.org/test?a#%GH> against <about:blank> -FAIL Parsing: <a> against <about:blank> assert_equals: failure should set href to input expected "a" but got "" -FAIL Parsing: <a/> against <about:blank> assert_equals: failure should set href to input expected "a/" but got "" -FAIL Parsing: <a//> against <about:blank> assert_equals: failure should set href to input expected "a//" but got "" -FAIL Parsing: <test-a-colon.html> against <a:> assert_equals: failure should set href to input expected "test-a-colon.html" but got "" -FAIL Parsing: <test-a-colon-b.html> against <a:b> assert_equals: failure should set href to input expected "test-a-colon-b.html" but got "" -PASS Parsing: <test-a-colon-slash.html> against <a:/> -FAIL Parsing: <test-a-colon-slash-slash.html> against <a://> assert_equals: href expected "a:///test-a-colon-slash-slash.html" but got "" -PASS Parsing: <test-a-colon-slash-b.html> against <a:/b> -FAIL Parsing: <test-a-colon-slash-slash-b.html> against <a://b> assert_equals: href expected "a://b/test-a-colon-slash-slash-b.html" but got "a://b" -PASS Parsing: <http://example.org/test?a#b\0c> against <about:blank> -FAIL Parsing: <non-spec://example.org/test?a#b\0c> against <about:blank> assert_equals: host expected "example.org" but got "" -PASS Parsing: <non-spec:/test?a#b\0c> against <about:blank> -PASS Parsing: <10.0.0.7:8080/foo.html> against <file:///some/dir/bar.html> -PASS Parsing: <a!@$*=/foo.html> against <file:///some/dir/bar.html> -PASS Parsing: <a1234567890-+.:foo/bar> against <http://example.com/dir/file> -PASS Parsing: <file://ab/p> against <about:blank> -PASS Parsing: <file://a%C2%ADb/p> against <about:blank> -FAIL Parsing: <file:///p> against <about:blank> assert_equals: failure should set href to input expected "file:///p" but got "file://%C2%AD/p" -PASS Parsing: <file://%C2%AD/p> against <about:blank> -FAIL Parsing: <file://xn--/p> against <about:blank> assert_unreached: Expected URL to fail parsing Reached unreachable code -PASS Parsing: <#link> against <https://example.org/##link> -PASS Parsing: <non-special:cannot-be-a-base-url-\0~> against <about:blank> -PASS Parsing: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank> -PASS Parsing: <https://user:pass[@foo/bar> against <http://example.org> -FAIL Parsing: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/" -FAIL Parsing: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://%20!%22$%&%27()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" -FAIL Parsing: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> assert_equals: href expected "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/" but got "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/" -FAIL Parsing: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> assert_equals: href expected "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" but got "wss://joe:%20!%22$%&%27()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/" -FAIL Parsing: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: host expected "!\"$%&'()*+,-.;=_`{}~" but got "" -FAIL Parsing: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: href expected "wss://!\"$&'()*+,-.;=_`{}~/" but got "wss://%21%22%24%26%27%28%29%2A+%2C-.%3B%3D_%60%7B%7D%7E/" -FAIL Parsing: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~" but got "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~" -FAIL Parsing: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> assert_equals: href expected "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~" but got "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]%5E_%60%7B%7C%7D~" -FAIL Parsing: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: href expected "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~" but got "foo://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~" -PASS Parsing: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -FAIL Parsing: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> assert_equals: host expected "host" but got "" -PASS Parsing: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -FAIL Parsing: <abc:rootless> against <abc://host/path> assert_equals: href expected "abc:rootless" but got "abc://host/rootless" -FAIL Parsing: <abc:rootless> against <abc:/path> assert_equals: href expected "abc:rootless" but got "abc:/rootless" -PASS Parsing: <abc:rootless> against <abc:path> -FAIL Parsing: <abc:/rooted> against <abc://host/path> assert_equals: href expected "abc:/rooted" but got "abc://host/rooted" -FAIL Parsing: <http://1.2.3.4.5> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5" but got "http://1.2.3.4.5/" -FAIL Parsing: <http://1.2.3.4.5.> against <http://other.com/> assert_equals: failure should set href to input expected "http://1.2.3.4.5." but got "http://1.2.3.4.5./" -PASS Parsing: <http://0..0x300/> against <about:blank> -PASS Parsing: <http://0..0x300./> against <about:blank> -FAIL Parsing: <http://256.256.256.256.256> against <http://other.com/> assert_equals: failure should set href to input expected "http://256.256.256.256.256" but got "http://256.256.256.256.256/" -FAIL Parsing: <http://256.256.256.256.256.> against <http://other.com/> assert_equals: failure should set href to input expected "http://256.256.256.256.256." but got "http://256.256.256.256.256./" -FAIL Parsing: <http://1.2.3.08> against <about:blank> assert_equals: failure should set href to input expected "http://1.2.3.08" but got "http://1.2.3.08/" -FAIL Parsing: <http://1.2.3.08.> against <about:blank> assert_equals: failure should set href to input expected "http://1.2.3.08." but got "http://1.2.3.08./" -FAIL Parsing: <http://1.2.3.09> against <about:blank> assert_equals: failure should set href to input expected "http://1.2.3.09" but got "http://1.2.3.09/" -FAIL Parsing: <http://09.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://09.2.3.4" but got "http://09.2.3.4/" -FAIL Parsing: <http://09.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://09.2.3.4." but got "http://09.2.3.4./" -FAIL Parsing: <http://01.2.3.4.5> against <about:blank> assert_equals: failure should set href to input expected "http://01.2.3.4.5" but got "http://01.2.3.4.5/" -FAIL Parsing: <http://01.2.3.4.5.> against <about:blank> assert_equals: failure should set href to input expected "http://01.2.3.4.5." but got "http://01.2.3.4.5./" -FAIL Parsing: <http://0x100.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://0x100.2.3.4" but got "http://0x100.2.3.4/" -FAIL Parsing: <http://0x100.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://0x100.2.3.4." but got "http://0x100.2.3.4./" -FAIL Parsing: <http://0x1.2.3.4.5> against <about:blank> assert_equals: failure should set href to input expected "http://0x1.2.3.4.5" but got "http://0x1.2.3.4.5/" -FAIL Parsing: <http://0x1.2.3.4.5.> against <about:blank> assert_equals: failure should set href to input expected "http://0x1.2.3.4.5." but got "http://0x1.2.3.4.5./" -FAIL Parsing: <http://foo.1.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://foo.1.2.3.4" but got "http://foo.1.2.3.4/" -FAIL Parsing: <http://foo.1.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.1.2.3.4." but got "http://foo.1.2.3.4./" -FAIL Parsing: <http://foo.2.3.4> against <about:blank> assert_equals: failure should set href to input expected "http://foo.2.3.4" but got "http://foo.2.3.4/" -FAIL Parsing: <http://foo.2.3.4.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.2.3.4." but got "http://foo.2.3.4./" -FAIL Parsing: <http://foo.09> against <about:blank> assert_equals: failure should set href to input expected "http://foo.09" but got "http://foo.09/" -FAIL Parsing: <http://foo.09.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.09." but got "http://foo.09./" -FAIL Parsing: <http://foo.0x4> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0x4" but got "http://foo.0x4/" -FAIL Parsing: <http://foo.0x4.> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0x4." but got "http://foo.0x4./" -PASS Parsing: <http://foo.09..> against <about:blank> -PASS Parsing: <http://0999999999999999999/> against <about:blank> -FAIL Parsing: <http://foo.0x> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0x" but got "http://foo.0x/" -FAIL Parsing: <http://foo.0XFfFfFfFfFfFfFfFfFfAcE123> against <about:blank> assert_equals: failure should set href to input expected "http://foo.0XFfFfFfFfFfFfFfFfFfAcE123" but got "http://foo.0xfffffffffffffffffface123/" -FAIL Parsing: <http://💩.123/> against <about:blank> assert_equals: failure should set href to input expected "http://💩.123/" but got "http://xn--ls8h.123/" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/url/a-element-origin-expected.txt deleted file mode 100644 index 0353e737..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/url/a-element-origin-expected.txt +++ /dev/null
@@ -1,342 +0,0 @@ -This is a testharness.js-based test. -Found 329 tests; 324 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS Loading data… -PASS Parsing origin: <http://example . -org> against <http://example.org/foo/bar> -PASS Parsing origin: <http://user:pass@foo:21/bar;par?b#c> against <http://example.org/foo/bar> -PASS Parsing origin: <https://test:@test> against <about:blank> -PASS Parsing origin: <https://:@test> against <about:blank> -PASS Parsing origin: <non-special://test:@test/x> against <about:blank> -PASS Parsing origin: <non-special://:@test/x> against <about:blank> -PASS Parsing origin: <http:foo.com> against <http://example.org/foo/bar> -PASS Parsing origin: < :foo.com -> against <http://example.org/foo/bar> -PASS Parsing origin: < foo.com > against <http://example.org/foo/bar> -PASS Parsing origin: <a: foo.com> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:21/ b ? d # e > against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:0/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:00000000000000/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f:00000000000000000000080/c> against <http://example.org/foo/bar> -PASS Parsing origin: <http://f: -/c> against <http://example.org/foo/bar> -PASS Parsing origin: <> against <http://example.org/foo/bar> -PASS Parsing origin: < > against <http://example.org/foo/bar> -PASS Parsing origin: <:foo.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <:foo.com\> against <http://example.org/foo/bar> -PASS Parsing origin: <:> against <http://example.org/foo/bar> -PASS Parsing origin: <:a> against <http://example.org/foo/bar> -PASS Parsing origin: <:/> against <http://example.org/foo/bar> -PASS Parsing origin: <:\> against <http://example.org/foo/bar> -PASS Parsing origin: <:#> against <http://example.org/foo/bar> -PASS Parsing origin: <#> against <http://example.org/foo/bar> -PASS Parsing origin: <#/> against <http://example.org/foo/bar> -PASS Parsing origin: <#\> against <http://example.org/foo/bar> -PASS Parsing origin: <#;?> against <http://example.org/foo/bar> -PASS Parsing origin: <?> against <http://example.org/foo/bar> -PASS Parsing origin: </> against <http://example.org/foo/bar> -PASS Parsing origin: <:23> against <http://example.org/foo/bar> -PASS Parsing origin: </:23> against <http://example.org/foo/bar> -PASS Parsing origin: <\x> against <http://example.org/foo/bar> -PASS Parsing origin: <\\x\hello> against <http://example.org/foo/bar> -PASS Parsing origin: <::> against <http://example.org/foo/bar> -PASS Parsing origin: <::23> against <http://example.org/foo/bar> -PASS Parsing origin: <foo://> against <http://example.org/foo/bar> -PASS Parsing origin: <http://a:b@c:29/d> against <http://example.org/foo/bar> -PASS Parsing origin: <http::@c:29> against <http://example.org/foo/bar> -PASS Parsing origin: <http://&a:foo(b]c@d:2/> against <http://example.org/foo/bar> -PASS Parsing origin: <http://::@c@d:2> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo.com:b@d/> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo.com/\@> against <http://example.org/foo/bar> -PASS Parsing origin: <http:\\foo.com\> against <http://example.org/foo/bar> -PASS Parsing origin: <http:\\a\b:c\d@foo.com\> against <http://example.org/foo/bar> -PASS Parsing origin: <foo:/> against <http://example.org/foo/bar> -PASS Parsing origin: <foo:/bar.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <foo://///////> against <http://example.org/foo/bar> -PASS Parsing origin: <foo://///////bar.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <foo:////://///> against <http://example.org/foo/bar> -PASS Parsing origin: <c:/foo> against <http://example.org/foo/bar> -PASS Parsing origin: <//foo/bar> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo/path;a??e#f#g> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo/abcd?efgh?ijkl> against <http://example.org/foo/bar> -PASS Parsing origin: <http://foo/abcd#foo?bar> against <http://example.org/foo/bar> -PASS Parsing origin: <[61:24:74]:98> against <http://example.org/foo/bar> -PASS Parsing origin: <http:[61:27]/:foo> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[2001::1]> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[::127.0.0.1]> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[0:0:0:0:0:0:13.1.68.3]> against <http://example.org/foo/bar> -PASS Parsing origin: <http://[2001::1]:80> against <http://example.org/foo/bar> -PASS Parsing origin: <http:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftp:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <https:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <madeupscheme:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftps:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <gopher:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ws:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <wss:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <data:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <javascript:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <mailto:/example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <http:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftp:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <https:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <madeupscheme:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ftps:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <gopher:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <ws:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <wss:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <data:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <javascript:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: <mailto:example.com/> against <http://example.org/foo/bar> -PASS Parsing origin: </a/b/c> against <http://example.org/foo/bar> -PASS Parsing origin: </a/ /c> against <http://example.org/foo/bar> -PASS Parsing origin: </a%2fc> against <http://example.org/foo/bar> -PASS Parsing origin: </a/%2f/c> against <http://example.org/foo/bar> -PASS Parsing origin: <#β> against <http://example.org/foo/bar> -PASS Parsing origin: <data:text/html,test#test> against <http://example.org/foo/bar> -PASS Parsing origin: <tel:1234567890> against <http://example.org/foo/bar> -PASS Parsing origin: <ssh://example.com/foo/bar.git> against <http://example.org/> -PASS Parsing origin: <http://example.com/././foo> against <about:blank> -PASS Parsing origin: <http://example.com/./.foo> against <about:blank> -PASS Parsing origin: <http://example.com/foo/.> against <about:blank> -PASS Parsing origin: <http://example.com/foo/./> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/../> against <about:blank> -PASS Parsing origin: <http://example.com/foo/..bar> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/../ton> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar/../ton/../../a> against <about:blank> -PASS Parsing origin: <http://example.com/foo/../../..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/../../../ton> against <about:blank> -PASS Parsing origin: <http://example.com/foo/%2e> against <about:blank> -PASS Parsing origin: <http://example.com/foo/%2e%2> against <about:blank> -PASS Parsing origin: <http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar> against <about:blank> -PASS Parsing origin: <http://example.com////../..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar//../..> against <about:blank> -PASS Parsing origin: <http://example.com/foo/bar//..> against <about:blank> -PASS Parsing origin: <http://example.com/foo> against <about:blank> -PASS Parsing origin: <http://example.com/%20foo> against <about:blank> -PASS Parsing origin: <http://example.com/foo%> against <about:blank> -PASS Parsing origin: <http://example.com/foo%2> against <about:blank> -PASS Parsing origin: <http://example.com/foo%2zbar> against <about:blank> -PASS Parsing origin: <http://example.com/foo%2©zbar> against <about:blank> -PASS Parsing origin: <http://example.com/foo%41%7a> against <about:blank> -PASS Parsing origin: <http://example.com/foo %91> against <about:blank> -FAIL Parsing origin: <http://example.com/foo%00%51> against <about:blank> assert_equals: origin expected "http://example.com" but got "null" -PASS Parsing origin: <http://example.com/(%28:%3A%29)> against <about:blank> -PASS Parsing origin: <http://example.com/%3A%3a%3C%3c> against <about:blank> -PASS Parsing origin: <http://example.com/foo bar> against <about:blank> -PASS Parsing origin: <http://example.com\\foo\\bar> against <about:blank> -PASS Parsing origin: <http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd> against <about:blank> -PASS Parsing origin: <http://example.com/@asdf%40> against <about:blank> -PASS Parsing origin: <http://example.com/你好你好> against <about:blank> -PASS Parsing origin: <http://example.com/‥/foo> against <about:blank> -PASS Parsing origin: <http://example.com//foo> against <about:blank> -PASS Parsing origin: <http://example.com//foo//bar> against <about:blank> -PASS Parsing origin: <http://www.google.com/foo?bar=baz#> against <about:blank> -PASS Parsing origin: <http://www.google.com/foo?bar=baz# »> against <about:blank> -PASS Parsing origin: <data:test# »> against <about:blank> -PASS Parsing origin: <http://www.google.com> against <about:blank> -PASS Parsing origin: <http://192.0x00A80001> against <about:blank> -PASS Parsing origin: <http://www/foo%2Ehtml> against <about:blank> -PASS Parsing origin: <http://www/foo/%2E/html> against <about:blank> -PASS Parsing origin: <http://%25DOMAIN:foobar@foodomain.com/> against <about:blank> -PASS Parsing origin: <http:\\www.google.com\foo> against <about:blank> -PASS Parsing origin: <http://foo:80/> against <about:blank> -PASS Parsing origin: <http://foo:81/> against <about:blank> -PASS Parsing origin: <httpa://foo:80/> against <about:blank> -PASS Parsing origin: <https://foo:443/> against <about:blank> -PASS Parsing origin: <https://foo:80/> against <about:blank> -PASS Parsing origin: <ftp://foo:21/> against <about:blank> -PASS Parsing origin: <ftp://foo:80/> against <about:blank> -PASS Parsing origin: <gopher://foo:70/> against <about:blank> -PASS Parsing origin: <gopher://foo:443/> against <about:blank> -PASS Parsing origin: <ws://foo:80/> against <about:blank> -PASS Parsing origin: <ws://foo:81/> against <about:blank> -PASS Parsing origin: <ws://foo:443/> against <about:blank> -PASS Parsing origin: <ws://foo:815/> against <about:blank> -PASS Parsing origin: <wss://foo:80/> against <about:blank> -PASS Parsing origin: <wss://foo:81/> against <about:blank> -PASS Parsing origin: <wss://foo:443/> against <about:blank> -PASS Parsing origin: <wss://foo:815/> against <about:blank> -PASS Parsing origin: <http:/example.com/> against <about:blank> -PASS Parsing origin: <ftp:/example.com/> against <about:blank> -PASS Parsing origin: <https:/example.com/> against <about:blank> -PASS Parsing origin: <madeupscheme:/example.com/> against <about:blank> -PASS Parsing origin: <ftps:/example.com/> against <about:blank> -PASS Parsing origin: <gopher:/example.com/> against <about:blank> -PASS Parsing origin: <ws:/example.com/> against <about:blank> -PASS Parsing origin: <wss:/example.com/> against <about:blank> -PASS Parsing origin: <data:/example.com/> against <about:blank> -PASS Parsing origin: <javascript:/example.com/> against <about:blank> -PASS Parsing origin: <mailto:/example.com/> against <about:blank> -PASS Parsing origin: <http:example.com/> against <about:blank> -PASS Parsing origin: <ftp:example.com/> against <about:blank> -PASS Parsing origin: <https:example.com/> against <about:blank> -PASS Parsing origin: <madeupscheme:example.com/> against <about:blank> -PASS Parsing origin: <ftps:example.com/> against <about:blank> -PASS Parsing origin: <gopher:example.com/> against <about:blank> -PASS Parsing origin: <ws:example.com/> against <about:blank> -PASS Parsing origin: <wss:example.com/> against <about:blank> -PASS Parsing origin: <data:example.com/> against <about:blank> -PASS Parsing origin: <javascript:example.com/> against <about:blank> -PASS Parsing origin: <mailto:example.com/> against <about:blank> -PASS Parsing origin: <http:@www.example.com> against <about:blank> -PASS Parsing origin: <http:/@www.example.com> against <about:blank> -PASS Parsing origin: <http://@www.example.com> against <about:blank> -PASS Parsing origin: <http:a:b@www.example.com> against <about:blank> -PASS Parsing origin: <http:/a:b@www.example.com> against <about:blank> -PASS Parsing origin: <http://a:b@www.example.com> against <about:blank> -PASS Parsing origin: <http://@pple.com> against <about:blank> -PASS Parsing origin: <http::b@www.example.com> against <about:blank> -PASS Parsing origin: <http:/:b@www.example.com> against <about:blank> -PASS Parsing origin: <http://:b@www.example.com> against <about:blank> -PASS Parsing origin: <http:a:@www.example.com> against <about:blank> -PASS Parsing origin: <http:/a:@www.example.com> against <about:blank> -PASS Parsing origin: <http://a:@www.example.com> against <about:blank> -PASS Parsing origin: <http://www.@pple.com> against <about:blank> -PASS Parsing origin: <http://:@www.example.com> against <about:blank> -PASS Parsing origin: </> against <http://www.example.com/test> -PASS Parsing origin: </test.txt> against <http://www.example.com/test> -PASS Parsing origin: <.> against <http://www.example.com/test> -PASS Parsing origin: <..> against <http://www.example.com/test> -PASS Parsing origin: <test.txt> against <http://www.example.com/test> -PASS Parsing origin: <./test.txt> against <http://www.example.com/test> -PASS Parsing origin: <../test.txt> against <http://www.example.com/test> -PASS Parsing origin: <../aaa/test.txt> against <http://www.example.com/test> -PASS Parsing origin: <../../test.txt> against <http://www.example.com/test> -PASS Parsing origin: <中/test.txt> against <http://www.example.com/test> -PASS Parsing origin: <http://www.example2.com> against <http://www.example.com/test> -PASS Parsing origin: <//www.example2.com> against <http://www.example.com/test> -PASS Parsing origin: <http://ExAmPlE.CoM> against <http://other.com/> -PASS Parsing origin: <http://GOOgoo.com> against <http://other.com/> -PASS Parsing origin: <\0 http://example.com/ \r > against <about:blank> -PASS Parsing origin: <http://www.foo。bar.com> against <http://other.com/> -PASS Parsing origin: <https://x/�?�#�> against <about:blank> -PASS Parsing origin: <http://Go.com> against <http://other.com/> -PASS Parsing origin: <http://你好你好> against <http://other.com/> -FAIL Parsing origin: <https://faß.ExAmPlE/> against <about:blank> assert_equals: origin expected "https://xn--fa-hia.example" but got "https://fass.example" -PASS Parsing origin: <sc://faß.ExAmPlE/> against <about:blank> -PASS Parsing origin: <http://%30%78%63%30%2e%30%32%35%30.01> against <http://other.com/> -PASS Parsing origin: <http://%30%78%63%30%2e%30%32%35%30.01%2e> against <http://other.com/> -PASS Parsing origin: <http://0Xc0.0250.01> against <http://other.com/> -PASS Parsing origin: <http://./> against <about:blank> -PASS Parsing origin: <http://../> against <about:blank> -PASS Parsing origin: <http://foo:💩@example.com/bar> against <http://other.com/> -PASS Parsing origin: <#> against <test:test> -PASS Parsing origin: <#x> against <mailto:x@x.com> -PASS Parsing origin: <#x> against <data:,> -PASS Parsing origin: <#x> against <about:blank> -PASS Parsing origin: <#> against <test:test?test> -PASS Parsing origin: <https://@test@test@example:800/> against <http://doesnotmatter/> -PASS Parsing origin: <https://@@@example> against <http://doesnotmatter/> -PASS Parsing origin: <http://`{}:`{}@h/`{}?`{}> against <http://doesnotmatter/> -PASS Parsing origin: <http://host/?'> against <about:blank> -PASS Parsing origin: <notspecial://host/?'> against <about:blank> -PASS Parsing origin: </some/path> against <http://user@example.org/smth> -PASS Parsing origin: <> against <http://user:pass@example.org:21/smth> -PASS Parsing origin: </some/path> against <http://user:pass@example.org:21/smth> -PASS Parsing origin: <i> against <sc:/pa/pa> -PASS Parsing origin: <i> against <sc://ho/pa> -PASS Parsing origin: <i> against <sc:///pa/pa> -PASS Parsing origin: <../i> against <sc:/pa/pa> -PASS Parsing origin: <../i> against <sc://ho/pa> -PASS Parsing origin: <../i> against <sc:///pa/pa> -PASS Parsing origin: </i> against <sc:/pa/pa> -PASS Parsing origin: </i> against <sc://ho/pa> -PASS Parsing origin: </i> against <sc:///pa/pa> -PASS Parsing origin: <?i> against <sc:/pa/pa> -PASS Parsing origin: <?i> against <sc://ho/pa> -PASS Parsing origin: <?i> against <sc:///pa/pa> -PASS Parsing origin: <#i> against <sc:sd> -PASS Parsing origin: <#i> against <sc:sd/sd> -PASS Parsing origin: <#i> against <sc:/pa/pa> -PASS Parsing origin: <#i> against <sc://ho/pa> -PASS Parsing origin: <#i> against <sc:///pa/pa> -PASS Parsing origin: <about:/../> against <about:blank> -PASS Parsing origin: <data:/../> against <about:blank> -PASS Parsing origin: <javascript:/../> against <about:blank> -PASS Parsing origin: <mailto:/../> against <about:blank> -PASS Parsing origin: <sc://ñ.test/> against <about:blank> -PASS Parsing origin: <x> against <sc://ñ> -PASS Parsing origin: <sc:\../> against <about:blank> -PASS Parsing origin: <sc::a@example.net> against <about:blank> -PASS Parsing origin: <wow:%NBD> against <about:blank> -PASS Parsing origin: <wow:%1G> against <about:blank> -PASS Parsing origin: <wow:> against <about:blank> -FAIL Parsing origin: <http://example.com/U+d800U+dfff﷏ﷰ?U+d800U+dfff﷏ﷰ> against <about:blank> assert_equals: origin expected "http://example.com" but got "null" -FAIL Parsing origin: <http://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: origin expected "http://\x1f!\"$&'()*+,-.;=_`{}~" but got "null" -PASS Parsing origin: <sc://!"$&'()*+,-.;=_`{}~/> against <about:blank> -PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> -PASS Parsing origin: <https://%e2%98%83> against <about:blank> -PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank> -PASS Parsing origin: <http://facebook.com/?foo=%7B%22abc%22> against <about:blank> -PASS Parsing origin: <https://localhost:3000/jqueryui@1.2.3> against <about:blank> -PASS Parsing origin: <h t -t\rp://h o -s\rt:9 0 -0\r0/p a -t\rh?q u -e\rry#f r -a\rg> against <about:blank> -PASS Parsing origin: <?a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing origin: <??a=b&c=d> against <http://example.org/foo/bar> -PASS Parsing origin: <http:> against <http://example.org/foo/bar> -PASS Parsing origin: <sc:> against <https://example.org/foo/bar> -PASS Parsing origin: <http://foo.bar/baz?qux#foobar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo"bar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo<bar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo>bar> against <about:blank> -PASS Parsing origin: <http://foo.bar/baz?qux#foo`bar> against <about:blank> -PASS Parsing origin: <http://1.2.3.4/> against <http://other.com/> -PASS Parsing origin: <http://1.2.3.4./> against <http://other.com/> -PASS Parsing origin: <http://192.168.257> against <http://other.com/> -PASS Parsing origin: <http://192.168.257.> against <http://other.com/> -PASS Parsing origin: <http://192.168.257.com> against <http://other.com/> -PASS Parsing origin: <http://256> against <http://other.com/> -PASS Parsing origin: <http://256.com> against <http://other.com/> -PASS Parsing origin: <http://999999999> against <http://other.com/> -PASS Parsing origin: <http://999999999.> against <http://other.com/> -PASS Parsing origin: <http://999999999.com> against <http://other.com/> -PASS Parsing origin: <http://10000000000.com> against <http://other.com/> -PASS Parsing origin: <http://4294967295> against <http://other.com/> -PASS Parsing origin: <http://0xffffffff> against <http://other.com/> -PASS Parsing origin: <https://0x.0x.0> against <about:blank> -PASS Parsing origin: <asdf://%43%7C/> against <about:blank> -PASS Parsing origin: <http://[1:0::]> against <http://example.net/> -PASS Parsing origin: <sc://ñ> against <about:blank> -PASS Parsing origin: <sc://ñ?x> against <about:blank> -PASS Parsing origin: <sc://ñ#x> against <about:blank> -PASS Parsing origin: <#x> against <sc://ñ> -PASS Parsing origin: <?x> against <sc://ñ> -PASS Parsing origin: <tftp://foobar.com/someconfig;mode=netascii> against <about:blank> -PASS Parsing origin: <telnet://user:pass@foobar.com:23/> against <about:blank> -PASS Parsing origin: <ut2004://10.10.10.10:7777/Index.ut2> against <about:blank> -PASS Parsing origin: <redis://foo:bar@somehost:6379/0?baz=bam&qux=baz> against <about:blank> -PASS Parsing origin: <rsync://foo@host:911/sup> against <about:blank> -PASS Parsing origin: <git://github.com/foo/bar.git> against <about:blank> -PASS Parsing origin: <irc://myserver.com:6999/channel?passwd> against <about:blank> -PASS Parsing origin: <dns://fw.example.org:9999/foo.bar.org?type=TXT> against <about:blank> -PASS Parsing origin: <ldap://localhost:389/ou=People,o=JNDITutorial> against <about:blank> -PASS Parsing origin: <git+https://github.com/foo/bar> against <about:blank> -PASS Parsing origin: <urn:ietf:rfc:2648> against <about:blank> -PASS Parsing origin: <tag:joe@example.org,2001:foo/bar> against <about:blank> -PASS Parsing origin: <blob:https://example.com:443/> against <about:blank> -PASS Parsing origin: <blob:d3958f5c-0777-0845-9dcf-2cb28783acaf> against <about:blank> -PASS Parsing origin: <blob:> against <about:blank> -PASS Parsing origin: <non-special:cannot-be-a-base-url-\0~> against <about:blank> -PASS Parsing origin: <https://www.example.com/path{path.html?query'=query#fragment<fragment> against <about:blank> -PASS Parsing origin: <https://user:pass[@foo/bar> against <http://example.org> -PASS Parsing origin: <foo:// !"$%&'()*+,-.;<=>@[\]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <wss:// !"$%&'()*+,-.;<=>@[]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <foo://joe: !"$%&'()*+,-.:;<=>@[\]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <wss://joe: !"$%&'()*+,-.:;<=>@[]^_`{|}~@host/> against <about:blank> -PASS Parsing origin: <foo://!"$%&'()*+,-.;=_`{}~/> against <about:blank> -FAIL Parsing origin: <wss://!"$&'()*+,-.;=_`{}~/> against <about:blank> assert_equals: origin expected "wss://!\"$&'()*+,-.;=_`{}~" but got "null" -PASS Parsing origin: <foo://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <wss://host/ !"$%&'()*+,-./:;<=>@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <foo://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <wss://host/dir/? !"$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <foo://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -PASS Parsing origin: <wss://host/dir/# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~> against <about:blank> -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt new file mode 100644 index 0000000..aa5c600 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt
@@ -0,0 +1,124 @@ +This is a testharness.js-based test. +Found 120 tests; 112 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +FAIL CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +FAIL CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/css/css-writing-modes/alt-display-vertical-001-manual-expected.png b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/css/css-writing-modes/alt-display-vertical-001-manual-expected.png new file mode 100644 index 0000000..65b2e569 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/css/css-writing-modes/alt-display-vertical-001-manual-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-cancel-and-hold-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-cancel-and-hold-expected.txt new file mode 100644 index 0000000..bb885d8 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webaudio/the-audio-api/the-audioparam-interface/audioparam-cancel-and-hold-expected.txt
@@ -0,0 +1,110 @@ +This is a testharness.js-based test. +Found 106 tests; 103 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS # AUDIT TASK RUNNER STARTED. +PASS Executing "cancelTime" +PASS Executing "linear" +PASS Executing "exponential" +PASS Executing "setTarget" +PASS Executing "setValueCurve" +PASS Executing "setValueCurve after end" +PASS Executing "initial setTarget" +PASS Executing "post cancel: Linear" +PASS Executing "post cancel: Exponential" +PASS Executing "post cancel: ValueCurve" +PASS Executing "post cancel: setTarget" +PASS Executing "post cancel: setValue" +PASS Executing "cancel future setTarget" +PASS Executing "cancel setTarget now" +PASS Executing "cancel future setValueCurve" +PASS Executing "cancel setValueCurve now" +PASS Executing "linear, cancel, linear, cancel, linear" +PASS Audit report +PASS > [cancelTime] Test Invalid Values +PASS cancelAndHoldAtTime(-1) threw RangeError: "Failed to execute 'cancelAndHoldAtTime' on 'AudioParam': Time must be a finite non-negative number: -1". +PASS cancelAndHoldAtTime(NaN) threw TypeError: "Failed to execute 'cancelAndHoldAtTime' on 'AudioParam': The provided double value is non-finite.". +PASS cancelAndHoldAtTime(Infinity) threw TypeError: "Failed to execute 'cancelAndHoldAtTime' on 'AudioParam': The provided double value is non-finite.". +PASS < [cancelTime] All assertions passed. (total 3 assertions) +PASS > [linear] Cancel linearRampToValueAtTime +PASS linearRampToValueAtTime: linearRampToValue(0, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":0.000059605,"relativeThreshold":0}. +PASS Cancelling linearRampToValueAtTime: linearRampToValue(0, 0.5) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling linearRampToValueAtTime: linearRampToValue(0, 0.5) at time 0.25 is 0.5102040767669678 within an error of 0.000083998. +PASS < [linear] All assertions passed. (total 3 assertions) +PASS > [exponential] Cancel exponentialRampAtTime +PASS exponentialRampToValue(0.001, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":5.9605e-8,"relativeThreshold":0}. +PASS Cancelling exponentialRampToValue(0.001, 0.5) at time 0.25 contains only the constant 0.033932220190763474. +PASS Expected value for cancelling exponentialRampToValue(0.001, 0.5) at time 0.25 is 0.033932216465473175 within an error of 0.0000018664. +PASS < [exponential] All assertions passed. (total 3 assertions) +PASS > [setTarget] Cancel setTargetAtTime +PASS setTargetAtTime(0, 0.01, 0.05) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS Cancelling setTargetAtTime(0, 0.01, 0.05) at time 0.25 contains only the constant 0.008229752071201801. +FAIL X Expected value for cancelling setTargetAtTime(0, 0.01, 0.05) at time 0.25 is not close to 0.008229747414588928 within a relative error of 4.5267e-7 (RelErr=5.658269492964734e-7). Got 0.008229752071201801. assert_true: expected true got false +FAIL < [setTarget] 1 out of 3 assertions were failed. assert_true: expected true got false +PASS > [setValueCurve] Cancel setValueCurveAtTime +PASS setValueCurveAtTime([1,0], 0.01, 0.49) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS Cancelling setValueCurveAtTime([1,0], 0.01, 0.49) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling setValueCurveAtTime([1,0], 0.01, 0.49) at time 0.25 is 0.510204081632653 within an error of 9.5368e-9. +PASS < [setValueCurve] All assertions passed. (total 3 assertions) +PASS > [setValueCurve after end] Cancel setValueCurveAtTime after the end +PASS setValueCurveAtTime([1,0], 0.01, 0.11499999999999999) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS Cancelling setValueCurveAtTime([1,0], 0.01, 0.11499999999999999) at time 0.25 contains only the constant 0. +PASS Expected value for cancelling setValueCurveAtTime([1,0], 0.01, 0.11499999999999999) at time 0.25 is 0 within an error of 0. +PASS < [setValueCurve after end] All assertions passed. (total 3 assertions) +PASS > [initial setTarget] Cancel with initial setTargetAtTime +PASS setTargetAtTime(0, 0.01, 0.1) up to time 0.25 equals [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS Cancelling setTargetAtTime(0, 0.01, 0.1) at time 0.25 contains only the constant 0.09071767330169678. +PASS Expected value for cancelling setTargetAtTime(0, 0.01, 0.1) at time 0.25 is 0.09071795642375946 within an error of 0.000003121. +PASS < [initial setTarget] All assertions passed. (total 3 assertions) +PASS > [post cancel: Linear] LinearRamp after cancelling +PASS Post cancellation linearRampToValueAtTime: linearRampToValue(0, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":5.9605e-8,"relativeThreshold":0}. +PASS Cancelling Post cancellation linearRampToValueAtTime: linearRampToValue(0, 0.5) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling Post cancellation linearRampToValueAtTime: linearRampToValue(0, 0.5) at time 0.25 is 0.5102040767669678 within an error of 0.000083998. +PASS Post linearRamp(2, 0.375) equals [0.5102040767669678,0.510452389717102,0.5107007026672363,0.5109489560127258,0.5111972689628601,0.5114455819129944,0.5116938948631287,0.5119421482086182,0.5121904611587524,0.5124387741088867,0.512687087059021,0.5129353404045105,0.5131836533546448,0.513431966304779,0.5136802792549133,0.5139285922050476...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [post cancel: Linear] All assertions passed. (total 4 assertions) +PASS > [post cancel: Exponential] ExponentialRamp after cancelling +PASS Post cancel exponentialRampToValueAtTime: linearRampToValue(0, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":5.9605e-8,"relativeThreshold":0}. +PASS Cancelling Post cancel exponentialRampToValueAtTime: linearRampToValue(0, 0.5) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling Post cancel exponentialRampToValueAtTime: linearRampToValue(0, 0.5) at time 0.25 is 0.5102040767669678 within an error of 0.000083998. +PASS Post exponentialRamp(2, 0.375) equals [0.5102040767669678,0.510320246219635,0.5104364156723022,0.5105526447296143,0.5106688737869263,0.5107851624488831,0.5109014511108398,0.5110177993774414,0.511134147644043,0.5112505555152893,0.5113669633865356,0.511483371257782,0.5115998387336731,0.5117163062095642,0.5118328332901001,0.511949360370636...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [post cancel: Exponential] All assertions passed. (total 4 assertions) +PASS > [post cancel: ValueCurve] +PASS Post cancel setValueCurveAtTime: linearRampToValue(0, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":5.9605e-8,"relativeThreshold":0}. +PASS Cancelling Post cancel setValueCurveAtTime: linearRampToValue(0, 0.5) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling Post cancel setValueCurveAtTime: linearRampToValue(0, 0.5) at time 0.25 is 0.5102040767669678 within an error of 0.000083998. +PASS Post setValueCurve([0.125,2], 0.375, 0.125) equals [0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678,0.5102040767669678...] with an element-wise tolerance of {"absoluteThreshold":0.000083998,"relativeThreshold":0}. +PASS < [post cancel: ValueCurve] All assertions passed. (total 4 assertions) +PASS > [post cancel: setTarget] +PASS Post cancel setTargetAtTime: linearRampToValue(0, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":5.9605e-8,"relativeThreshold":0}. +PASS Cancelling Post cancel setTargetAtTime: linearRampToValue(0, 0.5) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling Post cancel setTargetAtTime: linearRampToValue(0, 0.5) at time 0.25 is 0.5102040767669678 within an error of 0.000083998. +PASS Post setTargetAtTime(0.125, 0.375, 0.1) equals [0.5102040767669678,0.5101238489151001,0.5100436210632324,0.5099633932113647,0.5098832249641418,0.509803056716919,0.509722888469696,0.5096427202224731,0.509562611579895,0.5094825029373169,0.5094023942947388,0.5093223452568054,0.5092422962188721,0.5091622471809387,0.5090821981430054,0.5090022087097168...] with an element-wise tolerance of {"absoluteThreshold":0.000084037,"relativeThreshold":0}. +PASS < [post cancel: setTarget] All assertions passed. (total 4 assertions) +PASS > [post cancel: setValue] +PASS Post cancel setValueAtTime: linearRampToValue(0, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":5.9605e-8,"relativeThreshold":0}. +PASS Cancelling Post cancel setValueAtTime: linearRampToValue(0, 0.5) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling Post cancel setValueAtTime: linearRampToValue(0, 0.5) at time 0.25 is 0.5102040767669678 within an error of 0.000083998. +PASS Post setValueAtTime(0.125, 0.375) equals [0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125,0.125...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [post cancel: setValue] All assertions passed. (total 4 assertions) +PASS > [cancel future setTarget] +PASS After cancelling future setTarget event, output contains only the constant 0.5. +PASS < [cancel future setTarget] All assertions passed. (total 1 assertions) +PASS > [cancel setTarget now] +PASS After cancelling setTarget event starting now, output contains only the constant 0.5. +PASS < [cancel setTarget now] All assertions passed. (total 1 assertions) +PASS > [cancel future setValueCurve] +PASS After cancelling future setValueCurve event, output contains only the constant 0.5. +PASS < [cancel future setValueCurve] All assertions passed. (total 1 assertions) +PASS > [cancel setValueCurve now] +PASS After cancelling current setValueCurve event starting now, output contains only the constant 0.5. +PASS < [cancel setValueCurve now] All assertions passed. (total 1 assertions) +PASS > [linear, cancel, linear, cancel, linear] Schedules 3 linear ramps, cancelling 2 of them, so that we end up with 2 cancel events next to each other +PASS 1st linearRamp: linearRampToValue(0, 0.5) up to time 0.25 equals [0,0.0020833334419876337,0.004166666883975267,0.0062500000931322575,0.008333333767950535,0.010416666977107525,0.012500000186264515,0.014583333395421505,0.01666666753590107,0.01875000074505806,0.02083333395421505,0.02291666716337204,0.02500000037252903,0.02708333358168602,0.02916666679084301,0.03125...] with an element-wise tolerance of {"absoluteThreshold":5.9605e-8,"relativeThreshold":0}. +PASS Cancelling 1st linearRamp: linearRampToValue(0, 0.5) at time 0.25 contains only the constant 0.5102040767669678. +PASS Expected value for cancelling 1st linearRamp: linearRampToValue(0, 0.5) at time 0.25 is 0.5102040767669678 within an error of 0. +PASS 2nd linearRamp(2, 0.5) equals [0.5102040767669678,0.5103282332420349,0.510452389717102,0.5105765461921692,0.5107007026672363,0.5108247995376587,0.5109489560127258,0.511073112487793,0.5111972689628601,0.5113214254379272,0.5114455819129944,0.5115697383880615,0.5116938948631287,0.5118180513381958,0.5119421482086182,0.5120663046836853...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS Cancelling 2nd linearRamp(2, 0.5) at time 0.375 contains only the constant 1.2551020383834839. +PASS Expected value for cancelling 2nd linearRamp(2, 0.5) at time 0.375 is 1.2551020383834839 within an error of 0. +PASS 3rd linearRamp(0, 0.5) equals [1.2551020383834839,1.2548928260803223,1.2546836137771606,1.2544745206832886,1.254265308380127,1.2540560960769653,1.2538468837738037,1.2536377906799316,1.25342857837677,1.2532193660736084,1.2530101537704468,1.2528010606765747,1.252591848373413,1.2523826360702515,1.2521734237670898,1.2519643306732178...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [linear, cancel, linear, cancel, linear] All assertions passed. (total 7 assertions) +FAIL # AUDIT TASK RUNNER FINISHED: 1 out of 17 tasks were failed. assert_true: expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections-expected.txt new file mode 100644 index 0000000..7c30828 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/webaudio/the-audio-api/the-audioparam-interface/k-rate-dynamics-compressor-connections-expected.txt
@@ -0,0 +1,79 @@ +This is a testharness.js-based test. +Found 63 tests; 60 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS # AUDIT TASK RUNNER STARTED. +PASS Executing "attack" +PASS Executing "knee" +PASS Executing "ratio" +PASS Executing "release" +PASS Executing "threshold" +PASS Audit report +PASS > [attack] Dynamics compressor attack +PASS attack: refNode = new DynamicsCompressorNode(context) did not throw an exception. +PASS attack: tstNode = new DynamicsCompressorNode(context, {"attack":0}) did not throw an exception. +PASS attack: refNode[attack].setValueAtTime(refNode[attack].minValue, 0) did not throw an exception. +PASS attack: refNode[attack].linearRampToValueAtTime(refNode[attack].minValue, 0.25) did not throw an exception. +PASS attack: mod = new ConstantSourceNode(context, {offset: 0}) did not throw an exception. +PASS attack: mod.offset.setValueAtTime(0, 0) did not throw an exception. +PASS attack: mod.offset.linearRampToValueAtTime(1, 0.25) did not throw an exception. +PASS attack: mod.connect(tstNode[attack]) did not throw an exception. +PASS k-rate attack AudioParam with input equals [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [attack] All assertions passed. (total 9 assertions) +PASS > [knee] Dynamics compressor knee +PASS knee: refNode = new DynamicsCompressorNode(context) did not throw an exception. +PASS knee: tstNode = new DynamicsCompressorNode(context, {"knee":0}) did not throw an exception. +PASS knee: refNode[knee].setValueAtTime(refNode[knee].minValue, 0) did not throw an exception. +PASS knee: refNode[knee].linearRampToValueAtTime(refNode[knee].minValue, 0.25) did not throw an exception. +PASS knee: mod = new ConstantSourceNode(context, {offset: 0}) did not throw an exception. +PASS knee: mod.offset.setValueAtTime(0, 0) did not throw an exception. +PASS knee: mod.offset.linearRampToValueAtTime(40, 0.25) did not throw an exception. +PASS knee: mod.connect(tstNode[knee]) did not throw an exception. +PASS k-rate knee AudioParam with input equals [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [knee] All assertions passed. (total 9 assertions) +PASS > [ratio] Dynamics compressor ratio +PASS ratio: refNode = new DynamicsCompressorNode(context) did not throw an exception. +PASS ratio: tstNode = new DynamicsCompressorNode(context, {"ratio":1}) did not throw an exception. +PASS ratio: refNode[ratio].setValueAtTime(refNode[ratio].minValue, 0) did not throw an exception. +PASS ratio: refNode[ratio].linearRampToValueAtTime(refNode[ratio].minValue, 0.25) did not throw an exception. +PASS ratio: mod = new ConstantSourceNode(context, {offset: 0}) did not throw an exception. +PASS ratio: mod.offset.setValueAtTime(0, 0) did not throw an exception. +PASS ratio: mod.offset.linearRampToValueAtTime(19, 0.25) did not throw an exception. +PASS ratio: mod.connect(tstNode[ratio]) did not throw an exception. +PASS k-rate ratio AudioParam with input equals [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [ratio] All assertions passed. (total 9 assertions) +PASS > [release] Dynamics compressor release +PASS release: refNode = new DynamicsCompressorNode(context) did not throw an exception. +PASS release: tstNode = new DynamicsCompressorNode(context, {"release":0}) did not throw an exception. +PASS release: refNode[release].setValueAtTime(refNode[release].minValue, 0) did not throw an exception. +PASS release: refNode[release].linearRampToValueAtTime(refNode[release].minValue, 0.25) did not throw an exception. +PASS release: mod = new ConstantSourceNode(context, {offset: 0}) did not throw an exception. +PASS release: mod.offset.setValueAtTime(0, 0) did not throw an exception. +PASS release: mod.offset.linearRampToValueAtTime(1, 0.25) did not throw an exception. +PASS release: mod.connect(tstNode[release]) did not throw an exception. +PASS k-rate release AudioParam with input equals [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. +PASS < [release] All assertions passed. (total 9 assertions) +PASS > [threshold] Dynamics compressor threshold +PASS threshold: refNode = new DynamicsCompressorNode(context) did not throw an exception. +PASS threshold: tstNode = new DynamicsCompressorNode(context, {"threshold":-100}) did not throw an exception. +PASS threshold: refNode[threshold].setValueAtTime(refNode[threshold].minValue, 0) did not throw an exception. +PASS threshold: refNode[threshold].linearRampToValueAtTime(refNode[threshold].minValue, 0.25) did not throw an exception. +PASS threshold: mod = new ConstantSourceNode(context, {offset: 0}) did not throw an exception. +PASS threshold: mod.offset.setValueAtTime(0, 0) did not throw an exception. +PASS threshold: mod.offset.linearRampToValueAtTime(100, 0.25) did not throw an exception. +PASS threshold: mod.connect(tstNode[threshold]) did not throw an exception. +FAIL X k-rate threshold AudioParam with input does not equal [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0...] with an element-wise tolerance of {"absoluteThreshold":0,"relativeThreshold":0}. + Index Actual Expected AbsError RelError Test threshold + [512] 4.0975883603096008e-3 4.0966668166220188e-3 9.2154368758201599e-7 2.2494963072000363e-4 0.0000000000000000e+0 + [513] 4.9103251658380032e-3 4.9092206172645092e-3 1.1045485734939575e-6 2.2499469052369222e-4 0.0000000000000000e+0 + [514] 5.8354442007839680e-3 5.8341315016150475e-3 1.3126991689205170e-6 2.2500335629341333e-4 0.0000000000000000e+0 + [515] 6.1213369481265545e-3 6.1199599876999855e-3 1.3769604265689850e-6 2.2499500476088518e-4 0.0000000000000000e+0 + [516] 7.3028206825256348e-3 7.3011782951653004e-3 1.6423873603343964e-6 2.2494826094329921e-4 0.0000000000000000e+0 + ...and 11483 more errors. + Max AbsError of 3.0715018510818481e-5 at index of 2523. + [2523] 3.1251750886440277e-2 3.1282465904951096e-2 3.0715018510818481e-5 9.8186052864704626e-4 0.0000000000000000e+0 + Max RelError of 1.0166148481892119e-3 at index of 2450. + [2450] -9.4820801168680191e-3 -9.4917295500636101e-3 9.6494331955909729e-6 1.0166148481892119e-3 0.0000000000000000e+0 + assert_true: expected true got false +FAIL < [threshold] 1 out of 9 assertions were failed. assert_true: expected true got false +FAIL # AUDIT TASK RUNNER FINISHED: 1 out of 5 tasks were failed. assert_true: expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/backface-visibility-interop/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/backface-visibility-interop/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt new file mode 100644 index 0000000..aa5c600 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/backface-visibility-interop/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt
@@ -0,0 +1,124 @@ +This is a testharness.js-based test. +Found 120 tests; 112 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +FAIL CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +FAIL CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/composite-relative-keyframes/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/composite-relative-keyframes/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt new file mode 100644 index 0000000..aa5c600 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/composite-relative-keyframes/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt
@@ -0,0 +1,124 @@ +This is a testharness.js-based test. +Found 120 tests; 112 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +FAIL CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +FAIL CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/threaded/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/threaded/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt new file mode 100644 index 0000000..aa5c600 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/threaded/external/wpt/css/css-transforms/animation/perspective-origin-interpolation-expected.txt
@@ -0,0 +1,124 @@ +This is a testharness.js-based test. +Found 120 tests; 112 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (-0.3) should be [7px 33px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0) should be [10px 30px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.3) should be [13px 27px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (0.6) should be [16px 24px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from neutral to [20px 20px] at (1.5) should be [25px 15px] +FAIL CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [initial] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (-0.3) should be [33px 7px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0) should be [30px 10px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.3) should be [27px 13px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (0.6) should be [24px 16px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [inherit] to [20px 20px] at (1.5) should be [15px 25px] +FAIL CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Transitions with transition: all: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS CSS Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +FAIL Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (-0.3) should be [26.5px 26.5px] assert_equals: expected "26.5px 26.5px " but got "26.48px 26.48px " +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0) should be [25px 25px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.3) should be [23.5px 23.5px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (0.6) should be [22px 22px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1) should be [20px 20px] +PASS Web Animations: property <perspective-origin> from [unset] to [20px 20px] at (1.5) should be [17.5px 17.5px] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Transitions with transition: all: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS CSS Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (-0.3) should be [-30% 20%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0) should be [0% 50%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.3) should be [30% 80%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (0.6) should be [60% 110%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1) should be [100% 150%] +PASS Web Animations: property <perspective-origin> from [0% 50%] to [100% 150%] at (1.5) should be [150% 200%] +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/resource-timing/initiator-type/workers-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/resource-timing/initiator-type/workers-expected.txt new file mode 100644 index 0000000..ebaffe2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/resource-timing/initiator-type/workers-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL The initiator type for classic worker must be 'other' promise_test: Unhandled rejection with value: object "Error: observe_entry: timeout" +FAIL The initiator type for module worker must be 'other' promise_test: Unhandled rejection with value: object "Error: observe_entry: timeout" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/web-locks/README.txt b/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/web-locks/README.txt new file mode 100644 index 0000000..2289aa4 --- /dev/null +++ b/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/web-locks/README.txt
@@ -0,0 +1 @@ +This suite runs web-locks tests with ThirdPartyStoragePartitioning enabled.
diff --git a/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/web-locks/partitioned-web-locks.tentative.https-expected.txt b/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/web-locks/partitioned-web-locks.tentative.https-expected.txt new file mode 100644 index 0000000..a19e6d2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/third-party-storage-partitioning/external/wpt/web-locks/partitioned-web-locks.tentative.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +PASS WebLocks of an iframe under a 3rd-party site are partitioned +Harness: the test ran to completion. +
diff --git a/third_party/closure_compiler/externs/accessibility_private.js b/third_party/closure_compiler/externs/accessibility_private.js index 7f8134bf..8240ae8 100644 --- a/third_party/closure_compiler/externs/accessibility_private.js +++ b/third_party/closure_compiler/externs/accessibility_private.js
@@ -340,7 +340,8 @@ * @typedef {{ * visible: boolean, * icon: !chrome.accessibilityPrivate.DictationBubbleIconType, - * text: (string|undefined) + * text: (string|undefined), + * hints: (!Array<string>|undefined) * }} */ chrome.accessibilityPrivate.DictationBubbleProperties;
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 9751c2eb..2cb75d6 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 50531fc68fa220f0ce7f178571493c8660a7688c +Revision: 36ad57186286ac6511ce149fd51e1b52c2d3e2e4 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_ios.cc b/third_party/crashpad/crashpad/client/crashpad_client_ios.cc index 467cc0cf..7c378ba7 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_ios.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_ios.cc
@@ -71,6 +71,13 @@ if (!in_process_handler_.Initialize( database, url, annotations, system_data_) || !InstallMachExceptionHandler() || + // xnu turns hardware faults into Mach exceptions, so the only signal + // left to register is SIGABRT, which never starts off as a hardware + // fault. Installing a handler for other signals would lead to + // recording exceptions twice. As a consequence, Crashpad will not + // generate intermediate dumps for anything manually calling + // raise(SIG*). In practice, this doesn’t actually happen for crash + // signals that originate as hardware faults. !Signals::InstallHandler(SIGABRT, CatchSignal, 0, &old_action_)) { LOG(ERROR) << "Unable to initialize Crashpad."; return false;
diff --git a/third_party/crashpad/crashpad/snapshot/BUILD.gn b/third_party/crashpad/crashpad/snapshot/BUILD.gn index e3ad7f67..1a1d893 100644 --- a/third_party/crashpad/crashpad/snapshot/BUILD.gn +++ b/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -364,6 +364,7 @@ if (crashpad_is_ios) { sources += [ + "ios/memory_snapshot_ios_intermediate_dump_test.cc", "ios/process_snapshot_ios_intermediate_dump_test.cc", "mac/cpu_context_mac_test.cc", ]
diff --git a/third_party/crashpad/crashpad/snapshot/ios/memory_snapshot_ios_intermediate_dump_test.cc b/third_party/crashpad/crashpad/snapshot/ios/memory_snapshot_ios_intermediate_dump_test.cc new file mode 100644 index 0000000..bbe2a88 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/ios/memory_snapshot_ios_intermediate_dump_test.cc
@@ -0,0 +1,161 @@ +// Copyright 2022 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "snapshot/ios/memory_snapshot_ios_intermediate_dump.h" + +#include <string> +#include <vector> + +#include "gtest/gtest.h" + +namespace crashpad { +namespace test { +namespace { + +using internal::MemorySnapshotIOSIntermediateDump; + +const vm_address_t kDefaultAddress = 0x1000; + +class ReadToString : public crashpad::MemorySnapshot::Delegate { + public: + const std::string& result() { return result_; } + + private: + // MemorySnapshot::Delegate: + bool MemorySnapshotDelegateRead(void* data, size_t size) override { + result_ = std::string(reinterpret_cast<const char*>(data), size); + return true; + } + + std::string result_; +}; + +std::unique_ptr<MemorySnapshotIOSIntermediateDump> CreateMemorySnapshot( + vm_address_t address, + std::vector<uint8_t>& data) { + auto memory = std::make_unique<MemorySnapshotIOSIntermediateDump>(); + memory->Initialize( + address, reinterpret_cast<const vm_address_t>(data.data()), data.size()); + return memory; +} + +TEST(MemorySnapshotIOSIntermediateDumpTest, MergeSame) { + std::vector<uint8_t> data(10, 'a'); + auto memory = CreateMemorySnapshot(kDefaultAddress, data); + std::unique_ptr<const MemorySnapshot> merged( + memory->MergeWithOtherSnapshot(memory.get())); + EXPECT_EQ(merged->Address(), kDefaultAddress); + EXPECT_EQ(merged->Size(), data.size()); + ReadToString delegate; + merged->Read(&delegate); + EXPECT_EQ(delegate.result(), "aaaaaaaaaa"); +} + +TEST(MemorySnapshotIOSIntermediateDumpTest, MergeNoOverlap) { + std::vector<uint8_t> data1(10, 'a'); + auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); + + std::vector<uint8_t> data2(10, 'b'); + auto memory2 = CreateMemorySnapshot(kDefaultAddress + 10, data2); + + std::unique_ptr<const MemorySnapshot> merged( + memory1->MergeWithOtherSnapshot(memory2.get())); + EXPECT_EQ(merged->Address(), kDefaultAddress); + EXPECT_EQ(merged->Size(), 20u); + ReadToString delegate; + merged->Read(&delegate); + EXPECT_EQ(delegate.result(), "aaaaaaaaaabbbbbbbbbb"); +} + +TEST(MemorySnapshotIOSIntermediateDumpTest, MergePartial) { + std::vector<uint8_t> data1(10, 'a'); + auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); + + std::vector<uint8_t> data2(10, 'b'); + auto memory2 = CreateMemorySnapshot(kDefaultAddress + 5, data2); + + std::unique_ptr<const MemorySnapshot> merged( + memory1->MergeWithOtherSnapshot(memory2.get())); + EXPECT_EQ(merged->Address(), kDefaultAddress); + EXPECT_EQ(merged->Size(), 15u); + ReadToString delegate; + merged->Read(&delegate); + EXPECT_EQ(delegate.result(), "aaaaabbbbbbbbbb"); +} + +TEST(MemorySnapshotIOSIntermediateDumpTest, NoMerge) { + std::vector<uint8_t> data1(10, 'a'); + auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); + + std::vector<uint8_t> data2(10, 'b'); + auto memory2 = CreateMemorySnapshot(kDefaultAddress + 20, data2); + + std::unique_ptr<const MemorySnapshot> merged( + memory1->MergeWithOtherSnapshot(memory2.get())); + EXPECT_EQ(merged.get(), nullptr); +} + +TEST(MemorySnapshotIOSIntermediateDumpTest, EnvelopeBiggerFirst) { + std::vector<uint8_t> data1(30, 'a'); + auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); + + std::vector<uint8_t> data2(10, 'b'); + auto memory2 = CreateMemorySnapshot(kDefaultAddress + 15, data2); + + std::unique_ptr<const MemorySnapshot> merged( + memory1->MergeWithOtherSnapshot(memory2.get())); + EXPECT_EQ(merged->Address(), kDefaultAddress); + EXPECT_EQ(merged->Size(), data1.size()); + + ReadToString delegate; + merged->Read(&delegate); + EXPECT_EQ(delegate.result(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +} + +TEST(MemorySnapshotIOSIntermediateDumpTest, EnvelopeBiggerSecond) { + std::vector<uint8_t> data1(10, 'a'); + auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); + + std::vector<uint8_t> data2(20, 'b'); + auto memory2 = CreateMemorySnapshot(kDefaultAddress, data2); + + std::unique_ptr<const MemorySnapshot> merged( + memory1->MergeWithOtherSnapshot(memory2.get())); + EXPECT_EQ(merged->Address(), kDefaultAddress); + EXPECT_EQ(merged->Size(), data2.size()); + + ReadToString delegate; + merged->Read(&delegate); + EXPECT_EQ(delegate.result(), "bbbbbbbbbbbbbbbbbbbb"); +} + +TEST(MemorySnapshotIOSIntermediateDumpTest, SmallerAddressSecond) { + std::vector<uint8_t> data1(10, 'a'); + auto memory1 = CreateMemorySnapshot(kDefaultAddress, data1); + + std::vector<uint8_t> data2(20, 'b'); + auto memory2 = CreateMemorySnapshot(kDefaultAddress - 10, data2); + + std::unique_ptr<const MemorySnapshot> merged( + memory1->MergeWithOtherSnapshot(memory2.get())); + EXPECT_EQ(merged->Address(), kDefaultAddress - 10); + EXPECT_EQ(merged->Size(), data2.size()); + ReadToString delegate; + merged->Read(&delegate); + EXPECT_EQ(delegate.result(), "bbbbbbbbbbbbbbbbbbbb"); +} + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm b/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm index 3613e22..1022d29 100644 --- a/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm +++ b/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm
@@ -16,6 +16,7 @@ #include <objc/runtime.h> #import "Service/Sources/EDOClientService.h" +#include "build/build_config.h" #import "test/ios/host/cptest_shared_object.h" #include "util/mach/exception_types.h" #include "util/mach/mach_extensions.h" @@ -33,15 +34,8 @@ @implementation CPTestTestCase + (void)setUp { - // Swizzle away the handleCrashUnderSymbol callback. Without this, any time - // the host app is intentionally crashed, the test is immediately failed. - SEL originalSelector = NSSelectorFromString(@"handleCrashUnderSymbol:"); - SEL swizzledSelector = @selector(handleCrashUnderSymbol:); - Method originalMethod = class_getInstanceMethod( - objc_getClass("XCUIApplicationImpl"), originalSelector); - Method swizzledMethod = - class_getInstanceMethod([self class], swizzledSelector); - method_exchangeImplementations(originalMethod, swizzledMethod); + [CPTestTestCase swizzleHandleCrashUnderSymbol]; + [CPTestTestCase swizleMayTerminateOutOfBandWithoutCrashReport]; // Override EDO default error handler. Without this, the default EDO error // handler will throw an error and fail the test. @@ -50,12 +44,43 @@ }); } +// Swizzle away the -[XCUIApplicationImpl handleCrashUnderSymbol:] callback. +// Without this, any time the host app is intentionally crashed, the test is +// immediately failed. ++ (void)swizzleHandleCrashUnderSymbol { + SEL originalSelector = NSSelectorFromString(@"handleCrashUnderSymbol:"); + SEL swizzledSelector = @selector(handleCrashUnderSymbol:); + Method originalMethod = class_getInstanceMethod( + objc_getClass("XCUIApplicationImpl"), originalSelector); + Method swizzledMethod = + class_getInstanceMethod([self class], swizzledSelector); + method_exchangeImplementations(originalMethod, swizzledMethod); +} + +// Swizzle away the time consuming 'Checking for crash reports corresponding to' +// from -[XCUIApplicationProcess swizleMayTerminateOutOfBandWithoutCrashReport] +// that is unnecessary for these tests. ++ (void)swizleMayTerminateOutOfBandWithoutCrashReport { + SEL originalSelector = + NSSelectorFromString(@"mayTerminateOutOfBandWithoutCrashReport"); + SEL swizzledSelector = @selector(mayTerminateOutOfBandWithoutCrashReport); + Method originalMethod = class_getInstanceMethod( + objc_getClass("XCUIApplicationProcess"), originalSelector); + Method swizzledMethod = + class_getInstanceMethod([self class], swizzledSelector); + method_exchangeImplementations(originalMethod, swizzledMethod); +} + // This gets called after tearDown, so there's no straightforward way to // test that this is called. However, not swizzling this out will cause every // crashing test to fail. - (void)handleCrashUnderSymbol:(id)arg1 { } +- (BOOL)mayTerminateOutOfBandWithoutCrashReport { + return YES; +} + - (void)setUp { app_ = [[XCUIApplication alloc] init]; [app_ launch]; @@ -85,19 +110,6 @@ XCTAssertEqualObjects(result, @"crashpad"); } -- (void)testSegv { - [rootObject_ crashSegv]; -#if defined(NDEBUG) -#if TARGET_OS_SIMULATOR - [self verifyCrashReportException:EXC_BAD_INSTRUCTION]; -#else - [self verifyCrashReportException:EXC_BREAKPOINT]; -#endif -#else - [self verifyCrashReportException:EXC_BAD_ACCESS]; -#endif -} - - (void)testKillAbort { [rootObject_ crashKillAbort]; [self verifyCrashReportException:EXC_SOFT_SIGNAL]; @@ -108,10 +120,12 @@ - (void)testTrap { [rootObject_ crashTrap]; -#if TARGET_OS_SIMULATOR +#if defined(ARCH_CPU_X86_64) [self verifyCrashReportException:EXC_BAD_INSTRUCTION]; -#else +#elif defined(ARCH_CPU_ARM64) [self verifyCrashReportException:EXC_BREAKPOINT]; +#else +#error Port to your CPU architecture #endif } @@ -125,15 +139,7 @@ - (void)testBadAccess { [rootObject_ crashBadAccess]; -#if defined(NDEBUG) -#if TARGET_OS_SIMULATOR - [self verifyCrashReportException:EXC_BAD_INSTRUCTION]; -#else - [self verifyCrashReportException:EXC_BREAKPOINT]; -#endif -#else [self verifyCrashReportException:EXC_BAD_ACCESS]; -#endif } - (void)testException {
diff --git a/third_party/crashpad/crashpad/test/ios/host/cptest_application_delegate.mm b/third_party/crashpad/crashpad/test/ios/host/cptest_application_delegate.mm index 3bf39df..212ab69 100644 --- a/third_party/crashpad/crashpad/test/ios/host/cptest_application_delegate.mm +++ b/third_party/crashpad/crashpad/test/ios/host/cptest_application_delegate.mm
@@ -241,7 +241,9 @@ return [dict passByValue]; } -- (void)crashBadAccess { +// Use [[clang::optnone]] here to get consistent exception codes, otherwise the +// exception can change depending on optimization level. +- (void)crashBadAccess [[clang::optnone]] { strcpy(nullptr, "bla"); } @@ -249,11 +251,6 @@ kill(getpid(), SIGABRT); } -- (void)crashSegv { - long* zero = nullptr; - *zero = 0xc045004d; -} - - (void)crashTrap { __builtin_trap(); }
diff --git a/third_party/crashpad/crashpad/test/ios/host/cptest_shared_object.h b/third_party/crashpad/crashpad/test/ios/host/cptest_shared_object.h index 90e3de8..2fe36c5 100644 --- a/third_party/crashpad/crashpad/test/ios/host/cptest_shared_object.h +++ b/third_party/crashpad/crashpad/test/ios/host/cptest_shared_object.h
@@ -58,9 +58,6 @@ // Triggers a crash with a call to kill(SIGABRT). - (void)crashKillAbort; -// Triggers a segfault crash. -- (void)crashSegv; - // Trigger a crash with a __builtin_trap. - (void)crashTrap;
diff --git a/third_party/rust/third_party.toml b/third_party/rust/third_party.toml index 685b7ee..05c80df 100644 --- a/third_party/rust/third_party.toml +++ b/third_party/rust/third_party.toml
@@ -33,4 +33,4 @@ cxxbridge-cmd = "1" cxx = "1" serde = "1" -serde_jsonrc = "0.1" +serde_jsonrc = { version="0.1", features=["unbounded_depth"] }
diff --git a/tools/binary_size/libsupersize/viewer/caspian/README.md b/tools/binary_size/libsupersize/viewer/caspian/README.md index 194fbceb..4696774 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/README.md +++ b/tools/binary_size/libsupersize/viewer/caspian/README.md
@@ -65,14 +65,24 @@ ## Debugging WASM -Follow this article: https://developer.chrome.com/blog/wasm-debugging-2020/ +Based on this article: https://developer.chrome.com/blog/wasm-debugging-2020/ -Make sure to: +The one-time setup steps are: - * Run Chrome on the same machine you are serving from - * Use Chrome Dev or Canary (`sudo apt-get install google-chrome-unstable`) - * Install the reference extension - * Enabled DWARF debugging in DevTools' experiments panel + * On the same machine as your source code: + * Install Chrome Canary (`sudo apt-get install google-chrome-unstable`) + * Open Chrome Canary + * Install the Chrome extension: https://goo.gle/wasm-debugging-extension + * Enable DWARF debugging in DevTools' experiments panel + * Gears button in top right, then "experiments" on left nav, then filter for "dwarf". + +The every-time steps are: + + * Start server: `tools/binary_size/libsupersize/viewer/upload_html_viewer.py --local` + * Open `viewer.html` and load a file. + * Open DevTools to the "Sources" panel. + * Look for `tree-worker-wasm.js > file://` + * Find the `.cc` files within it and set breakpoints. ## Updating Emscripten Version
diff --git a/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch b/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch index 9ebc274..456cc17 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch +++ b/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch
@@ -108,6 +108,6 @@ + executable_extension = ".js" + link_outputs = [ + "{{output_dir}}/{{target_output_name}}.wasm", -+ "{{output_dir}}/{{target_output_name}}.wasm.map", ++ "{{output_dir}}/{{target_output_name}}.wasm.debug.wasm", + ] +}
diff --git a/tools/binary_size/libsupersize/viewer/static/tree-ui.js b/tools/binary_size/libsupersize/viewer/static/tree-ui.js index 2682ac1c..3e49470 100644 --- a/tools/binary_size/libsupersize/viewer/static/tree-ui.js +++ b/tools/binary_size/libsupersize/viewer/static/tree-ui.js
@@ -416,7 +416,7 @@ // Process response of an initial load / upload. function processLoadTreeResponse(message) { - const {diffMode, beforeBlobUrl, loadBlobUrl, isMultiContainer} = + const {diffMode, beforeBlobUrl, loadBlobUrl, isMultiContainer, root} = message.loadResults; console.log( '%cPro Tip: %cawait supersize.worker.openNode("$FILE_PATH")',
diff --git a/tools/binary_size/libsupersize/viewer/templates/sw.js b/tools/binary_size/libsupersize/viewer/templates/sw.js index b048d4d..6053e42e 100644 --- a/tools/binary_size/libsupersize/viewer/templates/sw.js +++ b/tools/binary_size/libsupersize/viewer/templates/sw.js
@@ -9,7 +9,6 @@ const filesToCache = [ 'auth.js', 'auth-consts.js', - 'caspian_web.wasm.map', 'caspian_web.js', 'caspian_web.wasm', 'favicon.ico',
diff --git a/tools/binary_size/libsupersize/viewer/upload_html_viewer.py b/tools/binary_size/libsupersize/viewer/upload_html_viewer.py index ad187f9..7ff7129 100755 --- a/tools/binary_size/libsupersize/viewer/upload_html_viewer.py +++ b/tools/binary_size/libsupersize/viewer/upload_html_viewer.py
@@ -14,14 +14,17 @@ import urllib.request import uuid -_STATIC_FILES_DIR = (pathlib.Path(__file__).parent / 'static').resolve() +_VIEWER_DIR = pathlib.Path(__file__).parent.resolve() +_STATIC_FILES_DIR = _VIEWER_DIR / 'static' _FIREBASE_PROJECT = 'chrome-supersize' _PROD_URL = 'https://chrome-supersize.firebaseapp.com/' _WASM_FILES = [ 'caspian_web.js', 'caspian_web.wasm', - 'caspian_web.wasm.map', +] +_DEBUG_WASM_FILES = [ + 'caspian_web.wasm.debug.wasm', ] _PROD = 'prod' @@ -44,9 +47,8 @@ def _FirebaseInitProjectDir(project_dir): """Create a firebase.json file that is needed for deployment.""" - static_dir = os.path.join(project_dir, 'public') - with open(os.path.join(project_dir, 'firebase.json'), 'w') as f: - f.write(""" + static_dir = project_dir / 'public' + project_dir.joinpath('firebase.json').write_text("""\ { "hosting": { "public": "public", @@ -91,18 +93,25 @@ for f in _WASM_FILES: print(f'Downloading: {_PROD_URL + f}') with urllib.request.urlopen(_PROD_URL + f) as response: - with open(_STATIC_FILES_DIR / f, 'wb') as output: + with _STATIC_FILES_DIR.joinpath(f).open('wb') as output: shutil.copyfileobj(response, output) def _FillInAndCopyTemplates(project_static_dir): """Generate and copy over the templates/sw.js file.""" - template_file = os.path.join(os.path.dirname(__file__), 'templates', 'sw.js') + src_path = _VIEWER_DIR / 'templates' / 'sw.js' + dst_path = project_static_dir / 'sw.js' cache_hash = uuid.uuid4().hex + dst_path.write_text(src_path.read_text().replace('{{cache_hash}}', + cache_hash)) - with open(template_file, 'r') as in_file: - with open(os.path.join(project_static_dir, 'sw.js'), 'w') as out_file: - out_file.write(in_file.read().replace('{{cache_hash}}', cache_hash)) + +def _CopyStaticFiles(project_static_dir, *, include_debug_wasm): + shutil.copytree(_STATIC_FILES_DIR, project_static_dir) + # Don't upload the debug info since it's machine-dependent and large. + if not include_debug_wasm: + for f in _DEBUG_WASM_FILES: + project_static_dir.joinpath(f).unlink(missing_ok=True) def _Prompt(message): @@ -144,9 +153,12 @@ if options.deploy_mode != _DEV: _FirebaseLogin() with tempfile.TemporaryDirectory(prefix='firebase-') as project_dir: + project_dir = pathlib.Path(project_dir) _MaybeDownloadWasmFiles(options.download_wasm) project_static_dir = _FirebaseInitProjectDir(project_dir) - shutil.copytree(_STATIC_FILES_DIR, project_static_dir) + _CopyStaticFiles(project_static_dir, + include_debug_wasm=options.deploy_mode == _DEV) + _FirebaseLogin() _FillInAndCopyTemplates(project_static_dir) _FirebaseDeploy(project_dir, deploy_mode=options.deploy_mode) else:
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 192002d..dd40d1f5 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -122,7 +122,7 @@ 'android-12-x64-fyi-rel': 'android_release_bot_minimal_symbols_x64_fastbuild_webview_trichrome', 'android-annotator-rel': 'android_release_bot_minimal_symbols_arm64_webview_google', 'android-pie-arm64-wpt-rel-non-cq': 'android_release_bot_minimal_symbols_arm64_webview_monochrome', - 'android-web-platform-pie-x86-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_monochrome', + 'android-chrome-pie-x86-wpt-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_monochrome', 'android-weblayer-pie-x86-wpt-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_monochrome', 'android-weblayer-pie-x86-wpt-smoketest': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_monochrome', 'android-webview-pie-x86-wpt-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_monochrome_webview_shell', @@ -275,11 +275,11 @@ 'chromium.fyi': { 'Afl Upload Linux ASan': 'afl_asan_shared_release_bot', 'CFI Linux CF (reclient shadow)': 'cfi_full_cfi_icall_cfi_diag_recover_release_static_reclient', - 'Comparison Linux': { + 'Comparison Linux (reclient)': { 'goma': 'gpu_tests_release_bot', 'reclient': 'gpu_tests_release_bot_reclient', }, - 'Comparison Windows': { + 'Comparison Windows (reclient)': { 'goma': 'gpu_tests_release_bot_minimal_symbols', 'reclient': 'gpu_tests_release_bot_minimal_symbols_reclient', }, @@ -820,7 +820,7 @@ 'android-pie-arm64-rel-rts': 'android_release_trybot_arm64_webview_monochrome_expectations_fastbuild', 'android-pie-arm64-wpt-rel-non-cq': 'android_release_trybot_arm64_webview_monochrome', 'android-pie-x86-rel': 'android_release_trybot_x86_fastbuild_webview_monochrome', - 'android-web-platform-pie-x86-fyi-rel': 'android_release_trybot_x86_fastbuild_webview_monochrome', + 'android-chrome-pie-x86-wpt-fyi-rel': 'android_release_trybot_x86_fastbuild_webview_monochrome', 'android-weblayer-10-x86-rel-tests': 'android_release_trybot_minimal_symbols_x86_fastbuild_resource_allowlisting_disable_proguard_chrome_google', 'android-weblayer-marshmallow-x86-rel-tests': 'android_release_trybot_minimal_symbols_x86_fastbuild_resource_allowlisting_disable_proguard_chrome_google', 'android-weblayer-pie-x86-rel-tests': 'android_release_trybot_minimal_symbols_x86_fastbuild_disable_proguard_webview_monochrome',
diff --git a/tools/mb/mb_config_expectations/chromium.android.fyi.json b/tools/mb/mb_config_expectations/chromium.android.fyi.json index eaf75e2..55672ed 100644 --- a/tools/mb/mb_config_expectations/chromium.android.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.android.fyi.json
@@ -77,22 +77,7 @@ "use_goma": true } }, - "android-pie-arm64-wpt-rel-non-cq": { - "gn_args": { - "dcheck_always_on": false, - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "strip_debug_info": true, - "symbol_level": 1, - "system_webview_package_name": "com.google.android.apps.chrome", - "target_cpu": "arm64", - "target_os": "android", - "use_goma": true - } - }, - "android-web-platform-pie-x86-fyi-rel": { + "android-chrome-pie-x86-wpt-fyi-rel": { "gn_args": { "dcheck_always_on": false, "disable_android_lint": true, @@ -109,6 +94,21 @@ "use_goma": true } }, + "android-pie-arm64-wpt-rel-non-cq": { + "gn_args": { + "dcheck_always_on": false, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "strip_debug_info": true, + "symbol_level": 1, + "system_webview_package_name": "com.google.android.apps.chrome", + "target_cpu": "arm64", + "target_os": "android", + "use_goma": true + } + }, "android-weblayer-pie-x86-wpt-fyi-rel": { "gn_args": { "dcheck_always_on": false,
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json index a4395ea..5e653402 100644 --- a/tools/mb/mb_config_expectations/chromium.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -30,7 +30,7 @@ "use_thin_lto": true } }, - "Comparison Linux": { + "Comparison Linux (reclient)": { "goma": { "dcheck_always_on": false, "ffmpeg_branding": "Chrome", @@ -49,7 +49,7 @@ "use_remoteexec": true } }, - "Comparison Windows": { + "Comparison Windows (reclient)": { "goma": { "dcheck_always_on": false, "ffmpeg_branding": "Chrome",
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json index a5718eb7..a9cc0be 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -95,6 +95,24 @@ "use_goma": true } }, + "android-chrome-pie-x86-wpt-fyi-rel": { + "gn_args": { + "blink_enable_generated_code_formatting": false, + "dcheck_always_on": true, + "disable_android_lint": true, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "strip_debug_info": true, + "symbol_level": 0, + "system_webview_package_name": "com.google.android.apps.chrome", + "target_cpu": "x86", + "target_os": "android", + "use_errorprone_java_compiler": false, + "use_goma": true + } + }, "android-cronet-arm-dbg": { "gn_args": { "arm_use_neon": false, @@ -779,24 +797,6 @@ "use_goma": true } }, - "android-web-platform-pie-x86-fyi-rel": { - "gn_args": { - "blink_enable_generated_code_formatting": false, - "dcheck_always_on": true, - "disable_android_lint": true, - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "strip_debug_info": true, - "symbol_level": 0, - "system_webview_package_name": "com.google.android.apps.chrome", - "target_cpu": "x86", - "target_os": "android", - "use_errorprone_java_compiler": false, - "use_goma": true - } - }, "android-weblayer-10-x86-rel-tests": { "gn_args": { "blink_enable_generated_code_formatting": false,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index c96b6ea..37d1401 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -12819,6 +12819,16 @@ <int value="2" label="First service disabled"/> </enum> +<enum name="ChromeOSBrowserProcessState"> + <int value="0" label="Running"/> + <int value="1" label="Sleeping"/> + <int value="2" label="Uninterruptible Wait"/> + <int value="3" label="Zombie"/> + <int value="4" label="Traced or Stopped"/> + <int value="5" label="Unknown"/> + <int value="6" label="Error getting state"/> +</enum> + <enum name="ChromeOSCameraClientType"> <int value="0" label="Unknown"/> <int value="1" label="Testing"/> @@ -54808,6 +54818,7 @@ <int value="667643314" label="LitePageServerPreviews:enabled"/> <int value="669097106" label="NtpRealboxMatchOmniboxTheme:disabled"/> <int value="669958310" label="EnableSuggestedLocalFiles:disabled"/> + <int value="671800756" label="TabStripImprovements:enabled"/> <int value="672067370" label="InstallableAmbientBadgeMessage:enabled"/> <int value="673588373" label="OmniboxPedalSuggestions:disabled"/> <int value="674627327" label="MagnifierNewFocusFollowing:enabled"/> @@ -55098,6 +55109,7 @@ <int value="878773995" label="ChromeHomeBottomNavLabels:disabled"/> <int value="879538323" label="ForceMajorVersionInMinorPositionInUserAgent:enabled"/> + <int value="879651295" label="TabStripImprovements:disabled"/> <int value="879699575" label="disable-gesture-tap-highlight"/> <int value="879992337" label="disable-pull-to-refresh-effect"/> <int value="880510010" label="enable-permissions-bubbles"/> @@ -86607,6 +86619,7 @@ <int value="0" label="Success"/> <int value="1" label="Tab hidden before a frame is presented"/> <int value="2" label="Presentation failure"/> + <int value="3" label="Tab shown twice without being hidden"/> </enum> <enum name="TabUnderAction">
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index 6640c2c..201cf61 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -473,18 +473,6 @@ </summary> </histogram> -<histogram name="Blink.Canvas.WillReadFrequently" - enum="BooleanWillReadFrequently" expires_after="2021-01-31"> - <obsolete> - Expired on 2021-01-31. This metric was replaced with - Blink.Canvas.2DLayerBridge.WillReadFrequently - </obsolete> - <owner>fserb@chromium.org</owner> - <summary> - Logs if the canvas is initialized to be read frequently or not. - </summary> -</histogram> - <histogram name="Blink.ColorGamut.Destination" enum="Gamut" expires_after="M85"> <owner>brianosman@chromium.org</owner> <owner>mcasas@google.com</owner> @@ -2875,53 +2863,6 @@ </token> </histogram> -<histogram - name="Blink.{Host}.RenderTaskDuration.{Thread}.{Context}.{Resource}.{Filter}" - units="microseconds" expires_after="2022-05-11"> - <obsolete> - Removed in M93. This metric was replaced with - Blink.{Host}.RenderTaskDuration.{Context}.{Filter} - </obsolete> - <owner>junov@chromium.org</owner> - <owner>fserb@chromium.org</owner> - <owner>aaronhk@chromium.org</owner> - <summary> - Time spent executing a script task that draws content to a {Context} context - of a {Host}. - - Note: This metric drops reports on clients with low-resolution clocks, which - means these reports will be biased against a portion of the population on - Windows. See Windows.HasHighResolutionTimeTicks for the affected sample. - </summary> - <token key="Host"> - <variant name="Canvas"/> - <variant name="OffscreenCanvas"/> - </token> - <token key="Thread"> - <variant name="MainThread"/> - <variant name="Worker"/> - </token> - <token key="Context"> - <variant name="2D"/> - <variant name="ImageBitmap"/> - <variant name="WebGL"/> - <variant name="WebGL2"/> - <variant name="WebGPU"/> - </token> - <token key="Resource"> - <variant name="Bitmap"/> - <variant name="PassThrough"/> - <variant name="SharedBitmap"/> - <variant name="SharedImage"/> - <variant name="SkiaDawnSharedImage"/> - <variant name="SwapChain"/> - </token> - <token key="Filter"> - <variant name="All"/> - <variant name="Animation"/> - </token> -</histogram> - <histogram name="Blink.{Host}.{Heap}.{Context}" units="KB" expires_after="2022-05-11"> <owner>junov@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/bluetooth/histograms.xml b/tools/metrics/histograms/metadata/bluetooth/histograms.xml index 68bf789..2f78d36 100644 --- a/tools/metrics/histograms/metadata/bluetooth/histograms.xml +++ b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
@@ -143,26 +143,6 @@ <token key="BluetoothPairedStates" variants="BluetoothPairedStates"/> </histogram> -<histogram name="Bluetooth.ChromeOS.Disconnect.Result{BluetoothTransportTypes}" - enum="DisconnectResult" expires_after="2022-07-21"> - <obsolete> - Removed 2022-01-25. Removed in favor of - Bluetooth.ChromeOS.UserInitiatedDisconnect.Result, because this actually - recorded only user initiated disconnect results, and a more general - Bluetooth.ChromeOS.DeviceDisconnect was introduced to record all device - disconnections. check http://b/215601529 for details. - </obsolete> - <owner>khorimoto@chromium.org</owner> - <owner>cros-connectivity@google.com</owner> - <summary> - Emitted each time a bluetooth device disconnect attempt completes. - {BluetoothTransportTypes} - </summary> - <token key="BluetoothTransportTypes" variants="BluetoothTransportTypes"> - <variant name=""/> - </token> -</histogram> - <histogram name="Bluetooth.ChromeOS.FastPair.AccountKey.Failure.{FastPairPairingProtocol}" enum="FastPairAccountKeyFailure" expires_after="2022-09-20">
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml index c730730..f187d4d 100644 --- a/tools/metrics/histograms/metadata/chromeos/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -759,6 +759,24 @@ <token key="FeatureName" variants="FeaturesLoggingUsageEvents"/> </histogram> +<histogram name="ChromeOS.FirmwareUpdateUi.{Source}.DeviceCount" + units="devices" expires_after="2023-01-01"> + <owner>jimmyxgong@chromium.org</owner> + <owner>zentaro@chromium.org</owner> + <owner>cros-peripherals@google.com</owner> + <summary> + Records the total number of devices found. OnStartup is recorded when a user + first logs in and OnRefresh is recorded for any subsequent request. The + cases in which a subsequent request will be made are when the Firmware + Update SWA is launched, when an install is completed, and when we detect + that a device has been added or removed. + </summary> + <token key="Source"> + <variant name="OnRefresh"/> + <variant name="OnStartup"/> + </token> +</histogram> + <histogram name="ChromeOS.Gaia.Message.{GaiaAuthFlow}.{MessageName}" enum="BooleanReceived" expires_after="2022-06-01"> <owner>rsorokin@chromium.org</owner> @@ -1011,6 +1029,22 @@ </summary> </histogram> +<histogram name="ChromeOS.Liveness.BrowserStateAtTimeout" + enum="ChromeOSBrowserProcessState" expires_after="2023-01-30"> + <owner>iby@google.com</owner> + <owner>xiyuan@google.com</owner> + <owner>kaznacheev@google.com</owner> + <summary> + Records the state of the Chrome browser process at the moment + session_manager's LivenessChecker ping times out. This is the moment when + LivenessChecker will send an abort signal, if sending an abort signal is + enabled, but this metric is recorded regardless of whether or not aborting + from LivenessChecker is enabled. Exactly one sample of this metric is + recorded when the timeout occurs. If aborting is enabled, this should mean + one sample per abort. + </summary> +</histogram> + <histogram name="ChromeOS.Liveness.PingResponseTime" units="ms" expires_after="2022-08-05"> <owner>rtinkoff@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml index b44b064..2030bcce 100644 --- a/tools/metrics/histograms/metadata/content/histograms.xml +++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -654,19 +654,6 @@ </summary> </histogram> -<histogram name="ContentSuggestions.Feed.LoadTime" units="ms" - expires_after="M89"> - <obsolete> - Removed along with FeedV1 in M89 - </obsolete> - <owner>carlosk@chromium.org</owner> - <owner>harringtond@chromium.org</owner> - <owner>feed@chromium.org</owner> - <summary> - The time it takes for the Feed to load entries from the storage. - </summary> -</histogram> - <histogram name="ContentSuggestions.Feed.Network.CompressedResponseSizeKB{NetworkRequestType}" units="KB" expires_after="2023-03-01"> @@ -747,19 +734,6 @@ <token key="Type" variants="FeedNetworkRequestType"/> </histogram> -<histogram name="ContentSuggestions.Feed.Network.TokenDuration" units="ms" - expires_after="M89"> - <obsolete> - Removed along with FeedV1 in M89 - </obsolete> - <owner>carlosk@chromium.org</owner> - <owner>harringtond@chromium.org</owner> - <owner>feed@chromium.org</owner> - <summary> - The amount of time it takes to get an access token for signed in users. - </summary> -</histogram> - <histogram name="ContentSuggestions.Feed.Network.TokenFetchStatus" enum="GoogleServiceAuthError" expires_after="2023-03-01"> <owner>carlosk@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml index ceb4b88..bc6bb89 100644 --- a/tools/metrics/histograms/metadata/enterprise/histograms.xml +++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -1871,21 +1871,6 @@ <summary>Result of a single attempt to upload system logs.</summary> </histogram> -<histogram name="Enterprise.UploadJobSuccess" enum="EnterpriseUploadJobSuccess" - expires_after="M87"> - <obsolete> - Removed 2022/01 - </obsolete> - <owner>bmalcolm@chromium.org</owner> - <owner>managed-devices@google.com</owner> - <summary> - Number of retries the client did to execute an UploadJob. It's recorded - after the request has been completed, either successfully after 0 or more - retries, with a failure because of too many retries or if the UploadJob is - interrupted (destroyed before it could succeed or fail). - </summary> -</histogram> - <histogram name="Enterprise.UserPolicyChromeOS.ChildUser.OAuthTokenError" enum="GoogleServiceAuthError" expires_after="2022-06-26"> <owner>agawronska@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index d846780..e1569ad 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -41,13 +41,6 @@ <variants name="KeySystemWithRobustness"> <variant name="ClearKey" summary="Clear Key key system"/> <variant name="Unknown" summary="Unknown key system"/> - <variant name="Widevine" summary="Widevine key system"> - <obsolete> - Deprecated as of 11/2021, when we split some Media.EME.Widevine UMAs into - Media.EME.Widevine.HardwareSecure and Media.EME.Widevine.SoftwareSecure - ones. - </obsolete> - </variant> <variant name="Widevine.HardwareSecure" summary="Hardware secure Widevine key system"/> <variant name="Widevine.SoftwareSecure" @@ -940,15 +933,6 @@ </summary> </histogram> -<histogram name="Media.Audio.Render.OutputStreamDuration" units="ms" - expires_after="2022-01-30"> - <obsolete> - Removed Mar 2020. Use Media.Audio.Render.OutputStreamDuration2 instead. - </obsolete> - <owner>olka@chromium.org</owner> - <owner>henrika@chromium.org</owner> -</histogram> - <histogram name="Media.Audio.Render.OutputStreamDuration2" units="ms" expires_after="2023-01-21"> <owner>olka@chromium.org</owner> @@ -3061,33 +3045,6 @@ </summary> </histogram> -<histogram name="Media.MojoVideoDecoderServiceTiming.{Impl}.{Method}" - units="ms" expires_after="M95"> - <obsolete> - Removed Aug 2021. - </obsolete> - <owner>dalecurtis@chromium.org</owner> - <owner>media-dev@chromium.org</owner> - <summary> - The duration of MojoVideoDecoderService method calls. Recorded every call. - </summary> - <token key="Impl"> - <variant name="Alternate" - summary="Timing for the kAlternate media::VideoDecoderImplementation."> - <obsolete> - Removed when D3D11/DXVA VideoDecoder implementations became mutually - exclusive in M93. - </obsolete> - </variant> - <variant name="Default" - summary="Timing for the kDefault media::VideoDecoderImplementation."/> - </token> - <token key="Method"> - <variant name="Construct" summary="The time taken for Construct()."/> - <variant name="Destruct" summary="Time time taken for destruction."/> - </token> -</histogram> - <histogram name="Media.MSE.AudioCodec" enum="MSECodec" expires_after="never"> <!-- expires-never: Codec support planning metric. -->
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml index 3d704ace..720030f 100644 --- a/tools/metrics/histograms/metadata/optimization/histograms.xml +++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -562,6 +562,18 @@ </histogram> <histogram + name="OptimizationGuide.PageContentAnnotations.AnnotateVisitResultCached" + enum="BooleanCacheHit" expires_after="M106"> + <owner>mcrouse@chromium.org</owner> + <owner>chrome-intelligence-core@google.com</owner> + <summary> + Records whether the requested annotation for a visit was provided by the + in-memory cache or required them to be determined by executing the models. + Recorded once for every requested visit annotation. + </summary> +</histogram> + +<histogram name="OptimizationGuide.PageContentAnnotations.BatchRequestedSize.{AnnotationType}" units="counts" expires_after="M106"> <owner>robertogden@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index cf24c94..c0ed65d2 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -2670,6 +2670,54 @@ </metric> </event> +<event name="Blink.FedCm"> + <owner>yigu@chromium.org</owner> + <owner>webid-core@google.com</owner> + <summary> + Records performance metrics for FedCM(Federated Credential Management) API. + </summary> + <metric name="Status.RequestIdToken" enum="FedCmRequestIdTokenStatus"> + <summary> + Records the status of a request id token call to the FedCM API. + </summary> + </metric> + <metric name="Status.Revoke" enum="FedCmRevokeStatus"> + <summary> + Records the status of a revoke call to the FedCM API. + </summary> + </metric> + <metric name="Timing.CancelOnDialog"> + <summary> + Records the time (in milliseconds) from when the accounts dialog is shown + to when the user closes the dialog without selecting any account. + </summary> + </metric> + <metric name="Timing.ContinueOnDialog"> + <summary> + Records the time (in milliseconds) from when the accounts dialog is shown + to when the user presses the Continue button. + </summary> + </metric> + <metric name="Timing.IdTokenResponse"> + <summary> + Records the time (in milliseconds) from when the user presses the Continue + button to when the id token response is received. + </summary> + </metric> + <metric name="Timing.ShowAccountsDialog"> + <summary> + Records the time (in milliseconds) from when a call to the API was made to + when the accounts dialog is shown. + </summary> + </metric> + <metric name="Timing.TurnaroundTime"> + <summary> + Records the overall time (in milliseconds) from when the API is called to + when the id token response is received. + </summary> + </metric> +</event> + <event name="Blink.FindInPage" singular="True"> <owner>vmpstr@chromium.org</owner> <owner>chrishtr@chromium.org</owner>
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py index 829cd7d9..30cd48d 100644 --- a/tools/perf/core/bot_platforms.py +++ b/tools/perf/core/bot_platforms.py
@@ -650,7 +650,7 @@ ANDROID_PIXEL4A_POWER = PerfPlatform('android-pixel4a_power-perf', 'Android QD4A.200102.001.A1', _ANDROID_PIXEL4A_POWER_BENCHMARK_CONFIGS, - 10, 'android') + 12, 'android') # Cros/Lacros LACROS_EVE_PERF = PerfPlatform('lacros-eve-perf', '',
diff --git a/tools/perf/core/perf_benchmark.py b/tools/perf/core/perf_benchmark.py index d6298aa8..1759f276 100644 --- a/tools/perf/core/perf_benchmark.py +++ b/tools/perf/core/perf_benchmark.py
@@ -130,6 +130,8 @@ return 'linux' if target_os == 'cros': return 'chromeos' + if target_os == 'lacros': + return 'chromeos_lacros' return target_os def _GetVariationsBrowserArgs(self,
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 12a9dc2..4b7bca4 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "9a67df2e38d08a8179971d986d915479b5e0fb47", - "remote_path": "perfetto_binaries/trace_processor_shell/win/383df8c3092e183e0335ba3f1c502cc660c523dc/trace_processor_shell.exe" + "hash": "38e96510b19d13b09e7a75ff74663f45c795598a", + "remote_path": "perfetto_binaries/trace_processor_shell/win/33928bc89438655f0ab59f4fb8c56ae4a6aa2afa/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "7270d5dd8c35977685779103677c14d9b2839ddc", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/383df8c3092e183e0335ba3f1c502cc660c523dc/trace_processor_shell" + "hash": "45900341c5c8a8e38b7b56a3150f441ad9c3a65a", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/448ab50107d2f6382e413564e51e8130e92c4e09/trace_processor_shell" }, "mac_arm64": { "hash": "c0397e87456ad6c6a7aa0133e5b81c97adbab4ab", "remote_path": "perfetto_binaries/trace_processor_shell/mac_arm64/cefb3e0ec3a0580c996f801e854fe02963c03d5c/trace_processor_shell" }, "linux": { - "hash": "ee50898c0a4577b4a7ab121c958522c13dc0ab0c", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/383df8c3092e183e0335ba3f1c502cc660c523dc/trace_processor_shell" + "hash": "b7042c0b9d667bdb81d120c7c1f5b847ec05229e", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/33928bc89438655f0ab59f4fb8c56ae4a6aa2afa/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/core/shard_maps/android-pixel4a_power-perf_map.json b/tools/perf/core/shard_maps/android-pixel4a_power-perf_map.json index 1a158320..fe3b3ed 100644 --- a/tools/perf/core/shard_maps/android-pixel4a_power-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel4a_power-perf_map.json
@@ -3,9 +3,6 @@ "benchmarks": { "power.mobile": { "abridged": false - }, - "system_health.scroll_jank_mobile": { - "abridged": false } } }, @@ -72,6 +69,22 @@ } } }, + "10": { + "benchmarks": { + "system_health.scroll_jank_mobile": { + "end": 5, + "abridged": false + } + } + }, + "11": { + "benchmarks": { + "system_health.scroll_jank_mobile": { + "begin": 5, + "abridged": false + } + } + }, "extra_infos": { "num_stories": 5, "predicted_min_shard_time": 318.0,
diff --git a/ui/accessibility/extensions/colorenhancer/src/background.js b/ui/accessibility/extensions/colorenhancer/src/background.js index 01b8fbc..5da2674 100644 --- a/ui/accessibility/extensions/colorenhancer/src/background.js +++ b/ui/accessibility/extensions/colorenhancer/src/background.js
@@ -4,92 +4,104 @@ importScripts('./common.js', './storage.js'); -const storage = new Storage(); +class Background { + constructor() { + /** @private {Storage} */ + this.storage_ = new Storage(); -function forEachTab(tabCallback) { - chrome.windows.getAll({'populate': true}, windows => { - for (const w of windows) { - for (const tab of w.tabs) { - if (isDisallowedUrl(tab.url)) { - continue; + this.init_(); + } + + /** + * @param {function(chrome.tabs.Tab)} tabCallback A function that performs + * an action on each tab + * @private + */ + forEachTab_(tabCallback) { + chrome.windows.getAll({'populate': true}, windows => { + for (const w of windows) { + for (const tab of w.tabs) { + if (isDisallowedUrl(tab.url)) { + continue; + } + tabCallback(tab); } - tabCallback(tab); } + }); + } + + /** + * Adds filter script and css to all existing tabs. + * + * TODO(wnwen): Verify content scripts are not being injected multiple times. + * @private + */ + injectContentScripts_() { + this.forEachTab_(tab => chrome.scripting.executeScript({ + target: {tabId: tab.id}, + files: ['src/common.js', 'src/cvd.js'], + })); + } + + /** + * Updates all existing tabs with config values. + * @private + */ + updateTabs_() { + this.forEachTab_(async (tab) => { + const msg = { + 'delta': await this.storage_.getSiteDelta(siteFromUrl(tab.url)), + 'severity': await this.storage_.getDefaultSeverity(), + 'type': await this.storage_.getDefaultType(), + 'simulate': await this.storage_.getDefaultSimulate(), + 'enable': await this.storage_.getDefaultEnable() + }; + debugPrint('updateTabs: sending ' + JSON.stringify(msg) + ' to ' + + siteFromUrl(tab.url)); + chrome.tabs.sendMessage(tab.id, msg); + }); + } + + /** @private */ + async onInitReceived_(sender) { + let delta; + if (sender.tab) { + delta = await this.storage_.getSiteDelta(siteFromUrl(sender.tab.url)); + } else { + delta = await this.storage_.getDefaultDelta(); } - }); -} -/** - * Adds filter script and css to all existing tabs. - * - * TODO(wnwen): Verify content scripts are not being injected multiple times. - */ -function injectContentScripts() { - forEachTab(tab => chrome.scripting.executeScript({ - target: {tabId: tab.id}, - files: ['src/common.js', 'src/cvd.js'], - })); -} - -/** - * Updates all existing tabs with config values. - */ -function updateTabs() { - forEachTab(async function(tab) { - const msg = { - 'delta': await storage.getSiteDelta(siteFromUrl(tab.url)), - 'severity': await storage.getDefaultSeverity(), - 'type': await storage.getDefaultType(), - 'simulate': await storage.getDefaultSimulate(), - 'enable': await storage.getDefaultEnable() + return { + 'delta': delta, + 'severity': await this.storage_.getDefaultSeverity(), + 'type': await this.storage_.getDefaultType(), + 'simulate': await this.storage_.getDefaultSimulate(), + 'enable': await this.storage_.getDefaultEnable() }; - debugPrint('updateTabs: sending ' + JSON.stringify(msg) + ' to ' + - siteFromUrl(tab.url)); - chrome.tabs.sendMessage(tab.id, msg); - }); -} - -async function onInitReceived(sender) { - let delta; - if (sender.tab) { - delta = await storage.getSiteDelta(siteFromUrl(sender.tab.url)); - } else { - delta = await storage.getDefaultDelta(); } - return { - 'delta': delta, - 'severity': await storage.getDefaultSeverity(), - 'type': await storage.getDefaultType(), - 'simulate': await storage.getDefaultSimulate(), - 'enable': await storage.getDefaultEnable() - }; + /** + * Initial extension loading. + * @private + */ + init_() { + this.injectContentScripts_(); + this.updateTabs_(); + + chrome.runtime.onMessage.addListener( + (message, sender, sendResponse) => { + if (message === 'init') { + this.onInitReceived_(sender).then(sendResponse); + return true; // Keep message context open for async response. + } else if (message === 'updateTabs') { + this.updateTabs_(); + } + }); + chrome.storage.onChanged.addListener(this.updateTabs_.bind(this)); + + //TODO(mustaq): Handle uninstall + + } } -/** - * Initial extension loading. - */ -(function initialize() { - injectContentScripts(); - updateTabs(); - - chrome.runtime.onMessage.addListener( - function(message, sender, sendResponse) { - if (message === 'init') { - onInitReceived(sender).then(sendResponse); - return true; // Keep message context open for async response. - } - }); - - //TODO(mustaq): Handle uninstall - - chrome.storage.onChanged.addListener(function() { - updateTabs(); - }); -})(); - -chrome.runtime.onMessage.addListener(message => { - if (message === 'updateTabs') { - updateTabs(); - } -}); +const background = new Background();
diff --git a/ui/accessibility/extensions/colorenhancer/src/cvd.js b/ui/accessibility/extensions/colorenhancer/src/cvd.js index cc9de65..bed924b 100644 --- a/ui/accessibility/extensions/colorenhancer/src/cvd.js +++ b/ui/accessibility/extensions/colorenhancer/src/cvd.js
@@ -56,80 +56,89 @@ [0, 0, 1] ]; + /** @enum {number} */ + const Index = { + ZERO: 0, + ONE: 1, + TWO: 2, + }; + + /** @typedef {!Array<!Array<number>>} */ + let Matrix; /** - * Adds two matrices. - * @param {!object} m1 A 3x3 matrix. - * @param {!object} m2 A 3x3 matrix. - * @return {!object} The 3x3 matrix m1 + m2. + * Creates a matrix with elements specified by the elementCalculator function. + * @param {!function(!Index, !Index): number} elementCalculator Given the i + * and j indices of the element, calculates the value for the new matrix. + * @return {!Matrix} */ - function add3x3(m1, m2) { + function matrixMaker3x3(elementCalculator) { const result = []; - for (let i = 0; i < 3; i++) { + for (const i of Object.values(Index)) { result[i] = []; - for (let j = 0; j < 3; j++) { - result[i].push(m1[i][j] + m2[i][j]); + for (const j of Object.values(Index)) { + result[i][j] = elementCalculator(i, j); } } return result; } + /** + * Adds two matrices. + * @param {!Matrix} m1 A 3x3 matrix. + * @param {!Matrix} m2 A 3x3 matrix. + * @return {!Matrix} The 3x3 matrix m1 + m2. + */ + function add3x3(m1, m2) { + /** @type {!function(!Index, !Index): number} */ + const adder = (i, j) => m1[i][j] + m2[i][j]; + return matrixMaker3x3(adder); + } + /** * Subtracts one matrix from another. - * @param {!object} m1 A 3x3 matrix. - * @param {!object} m2 A 3x3 matrix. - * @return {!object} The 3x3 matrix m1 - m2. + * @param {!Matrix} m1 A 3x3 matrix. + * @param {!Matrix} m2 A 3x3 matrix. + * @return {!Matrix} The 3x3 matrix m1 - m2. */ function sub3x3(m1, m2) { - const result = []; - for (let i = 0; i < 3; i++) { - result[i] = []; - for (let j = 0; j < 3; j++) { - result[i].push(m1[i][j] - m2[i][j]); - } - } - return result; + /** @type {!function(!Index, !Index): number} */ + const subtracter = (i, j) => m1[i][j] - m2[i][j]; + return matrixMaker3x3(subtracter); } /** * Multiplies one matrix with another. - * @param {!object} m1 A 3x3 matrix. - * @param {!object} m2 A 3x3 matrix. - * @return {!object} The 3x3 matrix m1 * m2. + * @param {!Matrix} m1 A 3x3 matrix. + * @param {!Matrix} m2 A 3x3 matrix. + * @return {!Matrix} The 3x3 matrix m1 * m2. */ function mul3x3(m1, m2) { - const result = []; - for (let i = 0; i < 3; i++) { - result[i] = []; - for (let j = 0; j < 3; j++) { - let sum = 0; - for (let k = 0; k < 3; k++) { - sum += m1[i][k] * m2[k][j]; - } - result[i].push(sum); + /** @type {!function(!Index, !Index): number} */ + const multiplier = (i, j) => { + let sum = 0; + for (const k of Object.values(Index)) { + sum += m1[i][k] * m2[k][j]; } + return sum; } - return result; + + return matrixMaker3x3(multiplier); } /** * Multiplies a matrix with a number. - * @param {!object} m A 3x3 matrix. + * @param {!Matrix} m A 3x3 matrix. * @param {!number} k A scalar multiplier. - * @return {!object} The 3x3 matrix m * k. + * @return {!Matrix} The 3x3 matrix m * k. */ function mul3x3Scalar(m, k) { - const result = []; - for (let i = 0; i < 3; i++) { - result[i] = []; - for (let j = 0; j < 3; j++) { - result[i].push(k * m[i][j]); - } - } - return result; + /** @type {!function(!Index, !Index): number} */ + const scaler = (i, j) => k * m[i][j]; + return matrixMaker3x3(scaler); } @@ -137,7 +146,7 @@ /** * Makes the SVG matrix string (of 20 values) for a given matrix. - * @param {!object} m A 3x3 matrix. + * @param {!Matrix} m A 3x3 matrix. * @return {!string} The SVG matrix string for m. */ function svgMatrixStringFrom3x3(m) { @@ -153,7 +162,7 @@ /** * Makes a human readable string for a given matrix. - * @param {!object} m A 3x3 matrix. + * @param {!Matrix} m A 3x3 matrix. * @return {!string} A human-readable string for m. */ function humanReadbleStringFrom3x3(m) { @@ -265,23 +274,19 @@ * @param {string} cvdType Type of CVD, either "PROTANOMALY" or * "DEUTERANOMALY" or "TRITANOMALY". * @param {number} severity A real number in [0,1] denoting severity. + * @return {!Matrix} */ function getCvdSimulationMatrix(cvdType, severity) { const cvdSimulationParam = cvdSimulationParams[cvdType]; const severity_squared = severity * severity; - const matrix = []; - for (let i = 0; i < 3; i++) { - const row = []; - for (let j = 0; j < 3; j++) { - const paramRow = i*3+j; - const val = cvdSimulationParam[paramRow][0] * severity_squared - + cvdSimulationParam[paramRow][1] * severity - + cvdSimulationParam[paramRow][2]; - row.push(val); - } - matrix.push(row); + + const calculateElementValue = (i, j) => { + const paramRow = i*3+j; + return cvdSimulationParam[paramRow][0] * severity_squared + + cvdSimulationParam[paramRow][1] * severity + + cvdSimulationParam[paramRow][2]; } - return matrix; + return matrixMaker3x3(calculateElementValue); } @@ -291,6 +296,7 @@ * @param {string} cvdType Type of CVD, either "PROTANOMALY" or * "DEUTERANOMALY" or "TRITANOMALY". * @param {number} delta A real number in [0,1] denoting color adjustment. + * @return {!Matrix} */ function getCvdCorrectionMatrix(cvdType, delta) { cvdCorrectionParam = cvdCorrectionParams[cvdType]; @@ -308,6 +314,7 @@ * @param {number} delta A real number in [0,1] denoting color adjustment. * @param {boolean} simulate Whether to simulate the CVD type. * @param {boolean} enable Whether to enable color filtering. + * @return {!Matrix} */ function getEffectiveCvdMatrix(cvdType, severity, delta, simulate, enable) { if (!enable) { @@ -340,7 +347,6 @@ function addElements() { let style = document.getElementById(STYLE_ID); if (!style) { - const baseUrl = window.location.href.replace(window.location.hash, ''); style = document.createElement('style'); style.id = STYLE_ID; style.setAttribute('type', 'text/css'); @@ -490,7 +496,7 @@ /** * Adds support for a color enhancement filter. - * @param {!Object} matrix 3x3 RGB transformation matrix. + * @param {!Matrix} matrix 3x3 RGB transformation matrix. */ exports.injectColorEnhancementFilter = function(matrix) { setFilter(matrix);
diff --git a/ui/accessibility/extensions/colorenhancer/src/storage.js b/ui/accessibility/extensions/colorenhancer/src/storage.js index e9ef887..a4299a85 100644 --- a/ui/accessibility/extensions/colorenhancer/src/storage.js +++ b/ui/accessibility/extensions/colorenhancer/src/storage.js
@@ -3,8 +3,116 @@ // found in the LICENSE file. // TODO(wnwen): Wrap calls. +// TODO(anastasi): Change interface to remove unneeded promises. + +/** @typedef {string|number|boolean} */ +let StoredValue; +/** @typedef {{newValue: StoredValue, oldValue: StoredValue}} */ +let Change; class Storage { + constructor() { + /** @private {number} */ + this.defaultDelta_ = Storage.DEFAULT_DELTA; + + /** @private {!Object<string, number>} */ + this.siteDeltas_ = {}; + + /** @private {number} */ + this.defaultSeverity_ = Storage.DEFAULT_SEVERITY; + + /** @private {string} */ + this.defaultType_ = Storage.INVALID_TYPE_PLACEHOLDER; + + /** @private {boolean} */ + this.defaultSimulate_ = Storage.DEFAULT_SIMULATE; + + /** @private {boolean} */ + this.defaultEnable_ = Storage.DEFAULT_ENABLE; + + this.init_(); + } + + /** @private */ + init_() { + chrome.storage.onChanged.addListener( + this.onStorageChanged_.bind(this, (change) => change.newValue)); + chrome.storage.local.get( + null /** all items */, + this.onStorageChanged_.bind(this, (newVal) => newVal)); + } + + /** + * Updates the cached values. + * @param {(function(Change): StoredValue) | + * (function(StoredValue): StoredValue)} getValueFromAPIResult Gets the + * new value from the result indexed at a key. When called by + * storage.local.get(), this returns exactly what it is given. When + * called by storage.onChanged, this extracts newValue (instead of + * oldValue). + * @param {Object<string, Change>|Object<string, StoredValue>} changes The + * updates from the chrome.storage API. + * @private + */ + onStorageChanged_(getValueFromAPIResult, changes) { + if (changes[Storage.DELTA_TAG]) { + const newVal = getValueFromAPIResult(changes[Storage.DELTA_TAG]); + if (this.validDelta_(newVal)) { + this.defaultDelta_ = newVal; + } else { + this.defaultDelta_ = Storage.DEFAULT_DELTA; + } + } + + if (changes[Storage.PER_SITE_DELTA_TAG]) { + const newVal = getValueFromAPIResult(changes[Storage.PER_SITE_DELTA_TAG]); + if (typeof (newVal) === 'object') { + for (const site of Object.keys(newVal)) { + if (!this.validDelta_(newVal[site])) { + newVal[site] = this.defaultDelta_; + } + } + this.siteDeltas_ = newVal; + } else { + this.siteDeltas_ = {}; + } + } + + if (changes[Storage.SEVERITY_TAG]) { + const newVal = getValueFromAPIResult(changes[Storage.SEVERITY_TAG]); + if (this.validSeverity_(newVal)) { + this.defaultSeverity_ = newVal; + } else { + this.defaultSeverity_ = Storage.DEFAULT_SEVERITY; + } + } + + if (changes[Storage.TYPE_TAG]) { + const newVal = getValueFromAPIResult(changes[Storage.TYPE_TAG]); + if (this.validType_(newVal)) { + this.defaultType_ = newVal; + } + } + + if (changes[Storage.SIMULATE_TAG]) { + const newVal = getValueFromAPIResult(changes[Storage.SIMULATE_TAG]); + if (this.validBoolean_(newVal)) { + this.defaultSimulate_ = newVal; + } else { + this.defaultSimulate_ = Storage.DEFAULT_SIMULATE; + } + } + + if (changes[Storage.ENABLE_TAG]) { + const newVal = getValueFromAPIResult(changes[Storage.ENABLE_TAG]); + if (this.validBoolean_(newVal)) { + this.defaultEnable_ = newVal; + } else { + this.defaultEnable_ = Storage.DEFAULT_ENABLE; + } + } + } + // ======= Delta setting ======= /** @@ -19,15 +127,7 @@ /** @return {Promise<number>} */ getDefaultDelta() { return new Promise(resolve => { - chrome.storage.local.get([Storage.DELTA_TAG], (result) => { - let delta = result[Storage.DELTA_TAG]; - if (this.validDelta_(delta)) { - resolve(delta); - return; - } - delta = Storage.DEFAULT_DELTA; - this.store_(Storage.DELTA_TAG, delta, () => resolve(delta)); - }); + resolve(this.defaultDelta_); }); } @@ -39,6 +139,7 @@ if (!this.validDelta_(delta)) { delta = Storage.DEFAULT_DELTA; } + this.defaultDelta_ = delta; return new Promise( resolve => this.store_(Storage.DELTA_TAG, delta, resolve)); } @@ -49,15 +150,13 @@ */ getSiteDelta(site) { return new Promise(resolve => { - chrome.storage.local.get([Storage.PER_SITE_DELTA_TAG], (result) => { - const siteDeltas = result [Storage.PER_SITE_DELTA_TAG] || {}; - const delta = siteDeltas[site]; - if (!this.validDelta_(delta)) { - this.getDefaultDelta().then(resolve); - return; - } - resolve(delta); - }); + const delta = this.siteDeltas_[site]; + if (!this.validDelta_(delta)) { + this.setSiteDelta(site, this.defaultDelta_); + resolve(this.defaultDelta_); + return; + } + resolve(delta); }); } @@ -67,20 +166,18 @@ * @return {Promise} */ setSiteDelta(site, delta) { - return new Promise(async resolve => { + return new Promise(resolve => { if (!this.validDelta_(delta)) { - delta = await this.getDefaultDelta(); + delta = this.defaultDelta_; } - chrome.storage.local.get([Storage.PER_SITE_DELTA_TAG], (result) => { - const siteDeltas = result[Storage.PER_SITE_DELTA_TAG] || {}; - siteDeltas[site] = delta; - this.store_(Storage.PER_SITE_DELTA_TAG, siteDeltas, resolve); - }); + this.siteDeltas_[site] = delta; + this.store_(Storage.PER_SITE_DELTA_TAG, this.siteDeltas_, resolve); }); } /** @return {Promise} */ resetSiteDeltas() { + this.siteDeltas_ = {}; return new Promise( resolve => this.store_(Storage.PER_SITE_DELTA_TAG, {}, resolve)); } @@ -99,15 +196,7 @@ /** @return {Promise<number>} */ getDefaultSeverity() { return new Promise(resolve => { - chrome.storage.local.get([Storage.SEVERITY_TAG], (result) => { - let severity = result[Storage.SEVERITY_TAG]; - if (this.validSeverity_(severity)) { - resolve(severity); - return; - } - severity = Storage.DEFAULT_SEVERITY; - this.store_(Storage.SEVERITY_TAG, severity, () => resolve(severity)); - }); + resolve(this.defaultSeverity_); }); } @@ -119,6 +208,7 @@ if (!this.validSeverity_(severity)) { severity = Storage.DEFAULT_SEVERITY; } + this.defaultSeverity_ = severity; return new Promise( resolve => this.store_(Storage.SEVERITY_TAG, severity, resolve)); } @@ -138,15 +228,7 @@ /** @return {Promise<string>} */ getDefaultType() { return new Promise(resolve => { - chrome.storage.local.get([Storage.TYPE_TAG], (result) => { - const type = result[Storage.TYPE_TAG]; - if (this.validType_(type)) { - resolve(type); - } else { - // TODO(anastasi): add appropriate error handling - resolve(Storage.INVALID_TYPE_PLACEHOLDER); - } - }); + resolve(this.defaultType_); }); } @@ -158,6 +240,7 @@ if (!this.validType_(type)) { type = Storage.INVALID_TYPE_PLACEHOLDER; } + this.defaultType_ = type; return new Promise(resolve => this.store_(Storage.TYPE_TAG, type, resolve)); } @@ -166,16 +249,7 @@ /** @return {Promise<boolean>} */ getDefaultSimulate() { return new Promise(resolve => { - chrome.storage.local.get([Storage.SIMULATE_TAG], (result) => { - let simulate = result[Storage.SIMULATE_TAG]; - - if (this.validBoolean_(simulate)) { - resolve(simulate); - return; - } - simulate = Storage.DEFAULT_SIMULATE; - this.store_(Storage.SIMULATE_TAG, simulate, () => resolve(simulate)); - }); + resolve(this.defaultSimulate_); }); } @@ -187,6 +261,7 @@ if (!this.validBoolean_(simulate)) { simulate = Storage.DEFAULT_SIMULATE; } + this.defaultSimulate_ = simulate; return new Promise( resolve => this.store_(Storage.SIMULATE_TAG, simulate, resolve)); } @@ -196,16 +271,7 @@ /** @return {Promise<boolean>} */ getDefaultEnable() { return new Promise(resolve => { - chrome.storage.local.get([Storage.ENABLE_TAG], (result) => { - let enable = result[Storage.ENABLE_TAG]; - - if (this.validBoolean_(enable)) { - resolve(enable); - return; - } - enable = Storage.DEFAULT_ENABLE; - this.store_(Storage.ENABLE_TAG, enable, () => resolve(enable)); - }); + resolve(this.defaultEnable_); }); } @@ -217,6 +283,7 @@ if (!this.validBoolean_(enable)) { enable = Storage.DEFAULT_ENABLE; } + this.defaultEnable_ = enable; return new Promise( resolve => this.store_(Storage.ENABLE_TAG, enable, resolve)); }
diff --git a/ui/android/java/res/values/attrs.xml b/ui/android/java/res/values/attrs.xml index 7e8b195f..0e85ac7 100644 --- a/ui/android/java/res/values/attrs.xml +++ b/ui/android/java/res/values/attrs.xml
@@ -8,21 +8,6 @@ <!-- The top or bottom inset of a drawable. --> <attr name="verticalInset" format="reference|dimension"/> - <!-- Used in SwitchMaterial tint lists because the color roles are different in light and dark - themes. --> - <attr name="colorSwitchTrackNormal" format="color"/> - <attr name="colorSwitchThumbDisabled" format="color"/> - <!-- Splintered SwitchMaterial roles to roll back dynamic colors. --> - <attr name="colorPrimaryNonDynamic" format="color"/> - <attr name="colorPrimaryContainerNonDynamic" format="color"/> - <attr name="colorSwitchThumbNormalNonDynamic" format="color"/> - <attr name="colorSwitchThumbDisabledNonDynamic" format="color"/> - <attr name="colorSwitchTrackNormalNonDynamic" format="color"/> - - <!-- Fixed colors that won't work with dynamic colors. --> - <!-- Used in SwitchMaterial thumb tint list for the disabled state. --> - <attr name="colorFixedOnSurfaceAlpha38OverSurface" format="color"/> - <!-- Splintered semantic names that support dynamic colors. --> <attr name="default_bg_color_dynamic" format="color"/> <attr name="divider_line_bg_color_dynamic" format="color"/>
diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java index de432b6..b390299 100644 --- a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java +++ b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
@@ -27,6 +27,7 @@ import org.chromium.base.ContentUriUtils; import org.chromium.base.ContextUtils; +import org.chromium.base.FileUtils; import org.chromium.base.Log; import org.chromium.base.StrictModeContext; import org.chromium.base.ThreadUtils; @@ -641,7 +642,6 @@ private static boolean isUnderAppDir(String path, Context context) { File file = new File(path); File dataDir = ContextCompat.getDataDir(context); - try { String pathCanonical = file.getCanonicalPath(); String dataDirCanonical = dataDir.getCanonicalPath(); @@ -912,7 +912,9 @@ @Override public Boolean doInBackground() { - return !isUnderAppDir(mFilePath, mContext); + // Don't allow invalid file path or files under app dir to be uploaded. + return !isUnderAppDir(mFilePath, mContext) + && !FileUtils.getAbsoluteFilePath(mFilePath).isEmpty(); } @Override
diff --git a/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java b/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java index c078628..e4557c7 100644 --- a/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java +++ b/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
@@ -7,19 +7,26 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; import android.net.Uri; import android.webkit.MimeTypeMap; import androidx.core.content.ContextCompat; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowMimeTypeMap; import org.chromium.base.ContextUtils; +import org.chromium.base.FileUtils; +import org.chromium.base.FileUtilsJni; import org.chromium.base.test.BaseRobolectricTestRunner; import java.io.File; @@ -35,6 +42,14 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class SelectFileDialogTest { + @Mock + FileUtils.Natives mFileUtilsMocks; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + /** * Returns the determined scope for the accepted |fileTypes|. */ @@ -164,6 +179,11 @@ private void testFilePath( String path, SelectFileDialog selectFileDialog, boolean expectedPass) { + testFilePath(path, selectFileDialog, expectedPass, expectedPass); + } + + private void testFilePath(String path, SelectFileDialog selectFileDialog, + boolean expectedFileSelectionResult, boolean expectedGetDisplayNameResult) { Uri[] uris = new Uri[1]; uris[0] = Uri.fromFile(new File(path)); @@ -172,12 +192,15 @@ SelectFileDialog.GetDisplayNameTask task2 = selectFileDialog.new GetDisplayNameTask(ContextUtils.getApplicationContext(), /* isMultiple = */ false, uris); - assertEquals(expectedPass, task.doInBackground()); - assertEquals(expectedPass, null != task2.doInBackground()); + assertEquals(expectedFileSelectionResult, task.doInBackground()); + assertEquals(expectedGetDisplayNameResult, null != task2.doInBackground()); } @Test public void testFilePathTasks() throws IOException { + FileUtilsJni.TEST_HOOKS.setInstanceForTesting(mFileUtilsMocks); + doReturn("/tmp/xyz.jpn").when(mFileUtilsMocks).getAbsoluteFilePath(any()); + SelectFileDialog selectFileDialog = new SelectFileDialog(0); // Obtain the data directory for RoboElectric. It should look something like: @@ -207,6 +230,11 @@ // Make sure that dataDir/../dataDir is treated the same as dataDir (and fail the request). testFilePath(dataDir + "/../" + lastComponent + "/xyz.jpg", selectFileDialog, /* expectedPass= */ false); + + // Tests invalid file path should fail file selection. + doReturn(new String()).when(mFileUtilsMocks).getAbsoluteFilePath(any()); + testFilePath("\\/tmp/xyz.jpg", selectFileDialog, + /* expectedFileSelectionResult= */ false, /* expectedGetDisplayNameResult= */ true); } @Test
diff --git a/ui/base/models/tree_node_model.h b/ui/base/models/tree_node_model.h index f1c14be..1737bae 100644 --- a/ui/base/models/tree_node_model.h +++ b/ui/base/models/tree_node_model.h
@@ -9,6 +9,7 @@ #include <algorithm> #include <memory> +#include <set> #include <string> #include <vector> @@ -17,10 +18,6 @@ #include "base/observer_list.h" #include "ui/base/models/tree_model.h" -namespace bookmarks { -class BookmarkModel; -} - namespace ui { // TreeNodeModel and TreeNodes provide an implementation of TreeModel around @@ -161,10 +158,33 @@ return parent_ ? parent_->HasAncestor(ancestor) : false; } - private: - // TODO(https://crbug.com/956314): Remove this. - friend class bookmarks::BookmarkModel; + // Reorders children according to a new arbitrary order. |new_order| must + // contain one entry per child node, and the value of the entry at position + // |i| represents the new position, which must be unique and in the range + // between 0 (inclusive) and the number of children (exclusive). + void ReorderChildren(const std::vector<size_t>& new_order) { + const size_t children_count = children_.size(); + DCHECK_EQ(children_count, new_order.size()); + DCHECK_EQ(children_count, + std::set(new_order.begin(), new_order.end()).size()); + TreeNodes new_children(children_count); + for (size_t old_index = 0; old_index < children_count; ++old_index) { + const size_t new_index = new_order[old_index]; + DCHECK_LT(new_index, children_count); + DCHECK(children_[old_index]); + DCHECK(!new_children[new_index]); + new_children[new_index] = std::move(children_[old_index]); + } + children_ = std::move(new_children); + } + // Sorts children according to a comparator. + template <typename Compare> + void SortChildren(Compare comp) { + std::stable_sort(children_.begin(), children_.end(), comp); + } + + private: // Title displayed in the tree. std::u16string title_;
diff --git a/ui/base/models/tree_node_model_unittest.cc b/ui/base/models/tree_node_model_unittest.cc index 7afb9e68..f090989 100644 --- a/ui/base/models/tree_node_model_unittest.cc +++ b/ui/base/models/tree_node_model_unittest.cc
@@ -285,4 +285,53 @@ EXPECT_FALSE(child1->is_root()); } +TEST_F(TreeNodeModelTest, ReorderChildren) { + TestNode root; + + TestNode* child0 = root.Add(std::make_unique<TestNode>(), 0); + TestNode* child1 = root.Add(std::make_unique<TestNode>(), 1); + TestNode* child2 = root.Add(std::make_unique<TestNode>(), 2); + TestNode* child3 = root.Add(std::make_unique<TestNode>(), 3); + + ASSERT_EQ(4u, root.children().size()); + ASSERT_EQ(child0, root.children()[0].get()); + ASSERT_EQ(child1, root.children()[1].get()); + ASSERT_EQ(child2, root.children()[2].get()); + ASSERT_EQ(child3, root.children()[3].get()); + + root.ReorderChildren({3, 1, 2, 0}); + + ASSERT_EQ(4u, root.children().size()); + EXPECT_EQ(child3, root.children()[0].get()); + EXPECT_EQ(child1, root.children()[1].get()); + EXPECT_EQ(child2, root.children()[2].get()); + EXPECT_EQ(child0, root.children()[3].get()); +} + +TEST_F(TreeNodeModelTest, SortChildren) { + TestNode root; + + TestNode* child3 = root.Add(std::make_unique<TestNode>(3), 0); + TestNode* child1 = root.Add(std::make_unique<TestNode>(1), 1); + TestNode* child2 = root.Add(std::make_unique<TestNode>(2), 2); + TestNode* child0 = root.Add(std::make_unique<TestNode>(0), 3); + + ASSERT_EQ(4u, root.children().size()); + ASSERT_EQ(child3, root.children()[0].get()); + ASSERT_EQ(child1, root.children()[1].get()); + ASSERT_EQ(child2, root.children()[2].get()); + ASSERT_EQ(child0, root.children()[3].get()); + + root.SortChildren([](const std::unique_ptr<TestNode>& lhs, + const std::unique_ptr<TestNode>& rhs) { + return lhs->value < rhs->value; + }); + + ASSERT_EQ(4u, root.children().size()); + EXPECT_EQ(child0, root.children()[0].get()); + EXPECT_EQ(child1, root.children()[1].get()); + EXPECT_EQ(child2, root.children()[2].get()); + EXPECT_EQ(child3, root.children()[3].get()); +} + } // namespace ui
diff --git a/ui/color/color_id.h b/ui/color/color_id.h index 8386184..4db2fbf 100644 --- a/ui/color/color_id.h +++ b/ui/color/color_id.h
@@ -54,8 +54,7 @@ E_CPONLY(kColorButtonForeground) \ E_CPONLY(kColorButtonForegroundChecked) \ E_CPONLY(kColorButtonForegroundDisabled) \ - E(kColorButtonForegroundProminent, \ - NativeTheme::kColorId_TextOnProminentButtonColor) \ + E_CPONLY(kColorButtonForegroundProminent) \ E_CPONLY(kColorButtonForegroundUnchecked) \ E_CPONLY(kColorDialogBackground) \ E_CPONLY(kColorDialogForeground) \ @@ -69,7 +68,7 @@ E_CPONLY(kColorFrameInactive) \ E_CPONLY(kColorHelpIconActive) \ E_CPONLY(kColorHelpIconInactive) \ - E(kColorIcon, NativeTheme::kColorId_DefaultIconColor) \ + E_CPONLY(kColorIcon) \ E_CPONLY(kColorIconDisabled) \ E_CPONLY(kColorIconSecondary) \ E_CPONLY(kColorLabelForeground) \ @@ -80,22 +79,21 @@ E_CPONLY(kColorLinkForeground) \ E_CPONLY(kColorLinkForegroundDisabled) \ E_CPONLY(kColorLinkForegroundPressed) \ - E(kColorMenuBackground, NativeTheme::kColorId_MenuBackgroundColor) \ - E(kColorTouchableMenuBackground, NativeTheme::kColorId_MenuBackgroundColor) \ + E_CPONLY(kColorMenuBackground) \ + E_CPONLY(kColorTouchableMenuBackground) \ E_CPONLY(kColorMenuBorder) \ E_CPONLY(kColorMenuDropmarker) \ - E(kColorMenuIcon, NativeTheme::kColorId_MenuIconColor) \ + E_CPONLY(kColorMenuIcon) \ E_CPONLY(kColorMenuItemBackgroundAlertedInitial) \ E_CPONLY(kColorMenuItemBackgroundAlertedTarget) \ E_CPONLY(kColorMenuItemBackgroundHighlighted) \ - E(kColorMenuItemBackgroundSelected, \ - NativeTheme::kColorId_FocusedMenuItemBackgroundColor) \ + E_CPONLY(kColorMenuItemBackgroundSelected) \ E_CPONLY(kColorMenuItemForeground) \ E_CPONLY(kColorMenuItemForegroundDisabled) \ E_CPONLY(kColorMenuItemForegroundHighlighted) \ E_CPONLY(kColorMenuItemForegroundSecondary) \ E_CPONLY(kColorMenuItemForegroundSelected) \ - E(kColorMenuSeparator, NativeTheme::kColorId_MenuSeparatorColor) \ + E_CPONLY(kColorMenuSeparator) \ E_CPONLY(kColorNotificationActionsBackground) \ E_CPONLY(kColorNotificationBackgroundActive) \ E_CPONLY(kColorNotificationBackgroundInactive) \ @@ -180,8 +178,7 @@ E(kColorWindowBackground, NativeTheme::kColorId_WindowBackground) #if BUILDFLAG(IS_CHROMEOS) -#define CHROMEOS_COLOR_IDS \ - /* ChromeOS native colors */ \ +#define PLATFORM_SPECIFIC_COLOR_IDS \ E_CPONLY(kColorNativeColor1) \ E_CPONLY(kColorNativeColor1Shade1) \ E_CPONLY(kColorNativeColor1Shade2) \ @@ -192,11 +189,8 @@ E_CPONLY(kColorNativeColor6) \ E_CPONLY(kColorNativeBaseColor) \ E_CPONLY(kColorNativeSecondaryColor) -#endif - -#if BUILDFLAG(IS_WIN) -#define WIN_COLOR_IDS \ - /* Windows native colors */ \ +#elif BUILDFLAG(IS_WIN) +#define PLATFORM_SPECIFIC_COLOR_IDS \ E(kColorNative3dDkShadow, COLOR_3DDKSHADOW) \ E(kColorNative3dLight, COLOR_3DLIGHT) \ E(kColorNativeActiveBorder, COLOR_ACTIVEBORDER) \ @@ -227,19 +221,13 @@ E(kColorNativeWindow, COLOR_WINDOW) \ E(kColorNativeWindowFrame, COLOR_WINDOWFRAME) \ E(kColorNativeWindowText, COLOR_WINDOWTEXT) +#else +#define PLATFORM_SPECIFIC_COLOR_IDS #endif -#if BUILDFLAG(IS_WIN) #define COLOR_IDS \ CROSS_PLATFORM_COLOR_IDS \ - WIN_COLOR_IDS -#elif BUILDFLAG(IS_CHROMEOS) -#define COLOR_IDS \ - CROSS_PLATFORM_COLOR_IDS \ - CHROMEOS_COLOR_IDS -#else -#define COLOR_IDS CROSS_PLATFORM_COLOR_IDS -#endif + PLATFORM_SPECIFIC_COLOR_IDS // clang-format on namespace ui {
diff --git a/ui/color/win/native_color_mixers_win.cc b/ui/color/win/native_color_mixers_win.cc index 828d786..32c2741 100644 --- a/ui/color/win/native_color_mixers_win.cc +++ b/ui/color/win/native_color_mixers_win.cc
@@ -45,7 +45,7 @@ return; #define E(chrome, native) {chrome, color_utils::GetSysSkColor(native)}, - mixer.AddSet({kColorSetNative, {WIN_COLOR_IDS}}); + mixer.AddSet({kColorSetNative, {PLATFORM_SPECIFIC_COLOR_IDS}}); #undef E // Window Background
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc index 3c58e65d..7df5959 100644 --- a/ui/gtk/gtk_ui.cc +++ b/ui/gtk/gtk_ui.cc
@@ -953,11 +953,6 @@ active_selection_fg_color_ = color_provider->GetColor(ui::kColorTextfieldSelectionForeground); - colors_[ThemeProperties::COLOR_TAB_THROBBER_SPINNING] = - color_provider->GetColor(ui::kColorThrobber); - colors_[ThemeProperties::COLOR_TAB_THROBBER_WAITING] = - color_provider->GetColor(ui::kColorThrobberPreconnect); - // Generate colors that depend on whether or not a custom window frame is // used. These colors belong in |color_map| below, not |colors_|. for (bool custom_frame : {false, true}) {
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc index e798a31..4657731 100644 --- a/ui/native_theme/common_theme.cc +++ b/ui/native_theme/common_theme.cc
@@ -31,9 +31,6 @@ NativeTheme::ColorId color_id, NativeTheme::ColorScheme color_scheme) { switch (color_id) { - case NativeTheme::kColorId_MenuSeparatorColor: - return color_scheme == NativeTheme::ColorScheme::kDark ? SK_ColorWHITE - : SK_ColorBLACK; case NativeTheme::kColorId_FocusedBorderColor: case NativeTheme::kColorId_ProminentButtonColor: return color_scheme == NativeTheme::ColorScheme::kDark @@ -47,12 +44,8 @@ absl::optional<SkColor> GetDarkSchemeColor(NativeTheme::ColorId color_id, const NativeTheme* base_theme) { switch (color_id) { - case NativeTheme::kColorId_DefaultIconColor: - return gfx::kGoogleGrey500; case NativeTheme::kColorId_FocusedBorderColor: return gfx::kGoogleBlue400; - case NativeTheme::kColorId_MenuSeparatorColor: - return gfx::kGoogleGrey800; case NativeTheme::kColorId_ProminentButtonColor: return gfx::kGoogleBlue300; case NativeTheme::kColorId_WindowBackground: @@ -71,33 +64,9 @@ return gfx::kGoogleBlue500; // Button - case NativeTheme::kColorId_TextOnProminentButtonColor: - return color_utils::GetColorWithMaxContrast( - base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_ProminentButtonColor, color_scheme)); case NativeTheme::kColorId_ProminentButtonColor: return gfx::kGoogleBlue600; - // Icon - case NativeTheme::kColorId_DefaultIconColor: - return gfx::kGoogleGrey700; - - // Menu - case NativeTheme::kColorId_MenuBackgroundColor: - return base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - case NativeTheme::kColorId_MenuSeparatorColor: - return gfx::kGoogleGrey300; - case NativeTheme::kColorId_FocusedMenuItemBackgroundColor: { - const SkColor bg = base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_WindowBackground, color_scheme); - const SkColor fg = color_utils::GetColorWithMaxContrast(bg); - return color_utils::AlphaBlend(fg, bg, gfx::kGoogleGreyAlpha200); - } - case NativeTheme::kColorId_MenuIconColor: - return base_theme->GetUnprocessedSystemColor( - NativeTheme::kColorId_DefaultIconColor, color_scheme); - // Throbber case NativeTheme::kColorId_ThrobberWaitingColor: { const SkColor bg = base_theme->GetUnprocessedSystemColor(
diff --git a/ui/native_theme/native_theme_color_id.h b/ui/native_theme/native_theme_color_id.h index e53194c..92787e1f 100644 --- a/ui/native_theme/native_theme_color_id.h +++ b/ui/native_theme/native_theme_color_id.h
@@ -8,14 +8,8 @@ // Clang format mangles lists like the below badly. // clang-format off #define NATIVE_THEME_CROSS_PLATFORM_COLOR_IDS \ - OP(kColorId_DefaultIconColor), \ OP(kColorId_FocusedBorderColor), \ - OP(kColorId_FocusedMenuItemBackgroundColor), \ - OP(kColorId_MenuBackgroundColor), \ - OP(kColorId_MenuIconColor), \ - OP(kColorId_MenuSeparatorColor), \ OP(kColorId_ProminentButtonColor), \ - OP(kColorId_TextOnProminentButtonColor), \ OP(kColorId_ThrobberSpinningColor), \ OP(kColorId_ThrobberWaitingColor), \ OP(kColorId_WindowBackground)
diff --git a/ui/native_theme/native_theme_mac.mm b/ui/native_theme/native_theme_mac.mm index a766a9c8..8ecee23a 100644 --- a/ui/native_theme/native_theme_mac.mm +++ b/ui/native_theme/native_theme_mac.mm
@@ -147,16 +147,6 @@ SkColor NativeThemeMac::GetSystemColorDeprecated(ColorId color_id, ColorScheme color_scheme, bool apply_processing) const { - if (GetPreferredContrast() == PreferredContrast::kMore) { - switch (color_id) { - case kColorId_FocusedMenuItemBackgroundColor: - return color_scheme == ColorScheme::kDark ? SK_ColorLTGRAY - : SK_ColorDKGRAY; - default: - break; - } - } - absl::optional<SkColor> os_color = GetOSColor(color_id, color_scheme); if (os_color.has_value()) return os_color.value(); @@ -176,11 +166,6 @@ // Even with --secondary-ui-md, menus use the platform colors and styling, and // Mac has a couple of specific color overrides, documented below. switch (color_id) { - case kColorId_MenuSeparatorColor: - return color_scheme == ColorScheme::kDark - ? SkColorSetA(gfx::kGoogleGrey800, 0xCC) - : SkColorSetA(SK_ColorBLACK, 0x26); - case kColorId_FocusedBorderColor: return SkColorSetA( skia::NSSystemColorToSkColor([NSColor keyboardFocusIndicatorColor]),
diff --git a/ui/native_theme/native_theme_utils.cc b/ui/native_theme/native_theme_utils.cc index 31e321a..a5667e0 100644 --- a/ui/native_theme/native_theme_utils.cc +++ b/ui/native_theme/native_theme_utils.cc
@@ -45,17 +45,9 @@ using NTCID = NativeTheme::ColorId; static constexpr const auto map = base::MakeFixedFlatMap<NativeTheme::ColorId, ColorId>({ - {NTCID::kColorId_DefaultIconColor, kColorIcon}, {NTCID::kColorId_FocusedBorderColor, kColorFocusableBorderFocused}, - {NTCID::kColorId_FocusedMenuItemBackgroundColor, - kColorMenuItemBackgroundSelected}, - {NTCID::kColorId_MenuBackgroundColor, kColorMenuBackground}, - {NTCID::kColorId_MenuIconColor, kColorMenuIcon}, - {NTCID::kColorId_MenuSeparatorColor, kColorMenuSeparator}, {NTCID::kColorId_ProminentButtonColor, kColorButtonBackgroundProminent}, - {NTCID::kColorId_TextOnProminentButtonColor, - kColorButtonForegroundProminent}, {NTCID::kColorId_ThrobberSpinningColor, kColorThrobber}, {NTCID::kColorId_ThrobberWaitingColor, kColorThrobberPreconnect}, {NTCID::kColorId_WindowBackground, kColorWindowBackground},
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc index e30e7a2..0f2d9333 100644 --- a/ui/native_theme/native_theme_win.cc +++ b/ui/native_theme/native_theme_win.cc
@@ -619,28 +619,18 @@ case kColorId_WindowBackground: return system_colors_[SystemThemeColor::kWindow]; - case kColorId_MenuIconColor: case kColorId_ThrobberSpinningColor: - case kColorId_DefaultIconColor: return system_colors_[SystemThemeColor::kWindowText]; case kColorId_ThrobberWaitingColor: return system_colors_[SystemThemeColor::kGrayText]; - case kColorId_MenuBackgroundColor: - return system_colors_[SystemThemeColor::kButtonFace]; - - case kColorId_MenuSeparatorColor: case kColorId_FocusedBorderColor: return system_colors_[SystemThemeColor::kButtonText]; case kColorId_ProminentButtonColor: - case kColorId_FocusedMenuItemBackgroundColor: return system_colors_[SystemThemeColor::kHighlight]; - case kColorId_TextOnProminentButtonColor: - return system_colors_[SystemThemeColor::kHighlightText]; - default: return absl::nullopt; }
diff --git a/ui/ozone/common/features.cc b/ui/ozone/common/features.cc index 8f12b54..3b5015f 100644 --- a/ui/ozone/common/features.cc +++ b/ui/ozone/common/features.cc
@@ -16,9 +16,13 @@ // to properly composite the buffers. This mode is used to support fractional // scale factor. const base::Feature kWaylandSurfaceSubmissionInPixelCoordinates{ - "WaylandSurfaceSubmissionInPixelCoordinates", - base::FEATURE_DISABLED_BY_DEFAULT}; - + "WaylandSurfaceSubmissionInPixelCoordinates", +#if BUILDFLAG(IS_CHROMEOS_LACROS) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +}; bool IsWaylandSurfaceSubmissionInPixelCoordinatesEnabled() { return base::FeatureList::IsEnabled(
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js index 47f7810a..42f7dd1e 100644 --- a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_pairing_ui.js
@@ -241,6 +241,14 @@ } } + disconnectedCallback() { + super.disconnectedCallback(); + + if (this.bluetoothDiscoveryDelegateReceiver_) { + this.bluetoothDiscoveryDelegateReceiver_.$.close(); + } + } + /** @override */ onPropertiesUpdated(properties) { const wasBluetoothEnabled = this.isBluetoothEnabled_;