diff --git a/DEPS b/DEPS index d838752..e23d339 100644 --- a/DEPS +++ b/DEPS
@@ -245,15 +245,15 @@ # 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': '3f95fd2ed8c4d12315a2f73484e297f69aa37d2e', + 'skia_revision': '44a83926207668ad8de5eae74d68a54812ca55ad', # 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': 'ceb9223e1ab1df795d5f3e69f9fae92bb8328e92', + 'v8_revision': 'f5e412a1cd82fb606b79a587f1c4bda7f9445701', # 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': 'e7413adff5a3f91d34bbf3f2bb0b3be848091cd7', + 'angle_revision': '543f5750f70e014dc9c2217fb2fcf1c6b63badd5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -312,7 +312,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '8f3d60691b27c6868c3b719b63d76667eef36366', + 'catapult_revision': 'd6ef4a8af654ca24f8adca2a892f6f7857d57d2f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -360,7 +360,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'a2241d402e05dac272c0b3b7d26fd8a2cbd90ae7', + 'dawn_revision': '3649af2486cd1c805f364a54cdf127179330024a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -408,7 +408,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libunwind_revision': 'd81cd6236cd771e78d7e1a1807404ef3f1d21820', + 'libunwind_revision': '4ead61094cab5ac7a90198fbe182596c4775183e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -427,7 +427,7 @@ 'libcxx_revision': '79a2e924d96e2fc1e4b937c42efd08898fa472d7', # GN CIPD package version. - 'gn_version': 'git_revision:2e56c317bd8e2bf152cfa2ead6ac5fa476fe28b4', + 'gn_version': 'git_revision:18df6af86191edab1e47c84d56e608da414d446b', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -1427,7 +1427,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '9c674c8ed6844fb88b545a8df9282a9405f8a072', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'cefb3e0ec3a0580c996f801e854fe02963c03d5c', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1648,7 +1648,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'c843f8d63c8c17acfbb7d48e09059a581ba779b9', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '9754a43403e0b955546aff0e7d07d6f70def4043', + Var('webrtc_git') + '/src.git' + '@' + '977234879de72cb9df9b191adc9c7520c5c51c35', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1691,6 +1691,8 @@ 'dep_type': 'cipd', 'condition': 'checkout_win', }, + # TODO(crbug.com/1280002): Remove this entry once the autoroller has been + # updated to roll the mac_amd64 version. 'src/tools/skia_goldctl/mac': { 'packages': [ { @@ -1702,11 +1704,33 @@ 'condition': 'checkout_mac', }, + 'src/tools/skia_goldctl/mac_amd64': { + 'packages': [ + { + 'package': 'skia/tools/goldctl/mac-amd64', + 'version': 'zLP4FDegN-yg3uvzWUdf4zNRVHDwHd0VLm86FkZCP_MC', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_mac', + }, + + 'src/tools/skia_goldctl/mac_arm64': { + 'packages': [ + { + 'package': 'skia/tools/goldctl/mac-arm64', + 'version': 'FOo-HR3_OFTL0pn9TIm0H93TmtXgEfjSazYb3xAtx68C', + }, + ], + 'dep_type': 'cipd', + 'condition': 'checkout_mac', + }, + 'src/v8': Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3f843f82c4b67159e309b74ba45690d27f3eac5c', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6b2cb689b53fd43f282594b87295a1ebcf675b0b', 'condition': 'checkout_src_internal', }, @@ -3396,7 +3420,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib', - 'version': 'version:2@1.6.0.cr0', + 'version': 'version:2@1.6.10.cr0', }, ], 'condition': 'checkout_android', @@ -3407,7 +3431,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common', - 'version': 'version:2@1.6.0.cr0', + 'version': 'version:2@1.6.10.cr0', }, ], 'condition': 'checkout_android',
diff --git a/WATCHLISTS b/WATCHLISTS index 7758604..d5e3604f 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1485,8 +1485,9 @@ 'ui/gl/gl_.*egl.*|'\ 'ui/gl/gl_.*ozone.*' }, - 'ozone_scenic': { - 'filepath': 'ui/ozone/platform/scenic', + 'ozone_fuchsia': { + 'filepath': 'ui/ozone/platform/flatland/|'\ + 'ui/ozone/platform/scenic/' }, 'page_info' : { 'filepath': 'chrome/browser/ui/page_info/'\ @@ -2670,10 +2671,11 @@ 'origin_trials': ['chasej+watch@chromium.org', 'iclelland+watch@chromium.org'], 'ozone': ['ozone-reviews@chromium.org'], - 'ozone_scenic': ['dworsham@google.com', - 'fuchsia-reviews@chromium.org', - 'rjkroege@chromium.org', - 'spang+watch@chromium.org'], + 'ozone_fuchsia': ['dworsham@google.com', + 'emircan@google.com', + 'fuchsia-reviews@chromium.org', + 'rjkroege@chromium.org', + 'spang+watch@chromium.org'], 'page_info' : ['permissions-reviews@chromium.org', 'olesiamarukhno+watch@google.com'], 'page_load_metrics' : ['bmcquade+watch@chromium.org',
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java index 87a96f4..aa21f9d 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
@@ -7,6 +7,7 @@ import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.os.Build; import android.os.Looper; import android.os.Process; @@ -54,6 +55,7 @@ import org.chromium.build.BuildConfig; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.net.NetworkChangeNotifier; +import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.base.ResourceBundle; /** @@ -194,6 +196,28 @@ // NOTE: Finished writing Java resources. From this point on, it's safe to use them. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && mIsPostedFromBackgroundThread) { + // Try to work around the problem we're seeing with resources on Android 12. When + // WebView is being initialized from a background thread, it's possible that the + // asset path updated by WebViewFactory is no longer present by the time we get + // here due to something on the UI thread having caused a resource update in the + // app in the meantime, because WebViewFactory does not add the path persistently. + // So, we can try to add them again using the "better" method in WebViewDelegate. + + // However, we only want to try this if the resources are actually missing, because + // in the past we've seen this cause apps that were working to *start* crashing. + // The first resource that gets accessed in startup happens during the + // AwBrowserProcess.start() call when trying to determine if the device is a tablet, + // and that's the most common place for us to crash. So, try calling that same + // method and see if it throws - if so then we're unlikely to make the situation + // any worse by trying to fix the path. + try { + DeviceFormFactor.isTablet(); + } catch (Resources.NotFoundException e) { + mFactory.addWebViewAssetPath(context); + } + } + AwBrowserProcess.configureChildProcessLauncher(); // finishVariationsInitLocked() must precede native initialization so the seed is
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 64481a5..eab3df6 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -541,6 +541,8 @@ "ime/mode_indicator_observer.h", "in_session_auth/auth_dialog_contents_view.cc", "in_session_auth/auth_dialog_contents_view.h", + "in_session_auth/authentication_dialog.cc", + "in_session_auth/authentication_dialog.h", "in_session_auth/in_session_auth_dialog.cc", "in_session_auth/in_session_auth_dialog.h", "in_session_auth/in_session_auth_dialog_controller_impl.cc", @@ -2354,6 +2356,7 @@ "highlighter/highlighter_gesture_util_unittest.cc", "host/ash_window_tree_host_platform_unittest.cc", "ime/ime_controller_impl_unittest.cc", + "in_session_auth/authentication_dialog_unittest.cc", "in_session_auth/in_session_auth_dialog_controller_impl_unittest.cc", "in_session_auth/mock_in_session_auth_dialog_client.cc", "in_session_auth/mock_in_session_auth_dialog_client.h",
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 8719724..a013d75 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -859,8 +859,12 @@ } void AppListControllerImpl::OnWallpaperColorsChanged() { - if (IsVisible(last_visible_display_id_)) - fullscreen_presenter_->GetView()->OnWallpaperColorsChanged(); + // Clamshell ProductivityLauncher doesn't use wallpaper prominent color. + if (IsVisible(last_visible_display_id_) && !ShouldShowAppListBubble()) { + AppListView* app_list_view = fullscreen_presenter_->GetView(); + DCHECK(app_list_view); + app_list_view->OnWallpaperColorsChanged(); + } } void AppListControllerImpl::OnWallpaperPreviewStarted() {
diff --git a/ash/app_list/app_list_controller_impl_unittest.cc b/ash/app_list/app_list_controller_impl_unittest.cc index 057bde9..5cecc6a3 100644 --- a/ash/app_list/app_list_controller_impl_unittest.cc +++ b/ash/app_list/app_list_controller_impl_unittest.cc
@@ -1281,6 +1281,15 @@ EXPECT_FALSE(controller->bubble_presenter_for_test()->IsShowing()); } +TEST_F(AppListControllerImplAppListBubbleTest, + WallpaperColorChangeDoesNotCrash) { + auto* controller = Shell::Get()->app_list_controller(); + controller->ShowAppList(); + // Simulate synced wallpaper update while bubble is open. + controller->OnWallpaperColorsChanged(); + // No crash. +} + class AppListControllerWithAssistantTest : public AppListControllerImplTest { public: AppListControllerWithAssistantTest()
diff --git a/ash/app_list/views/apps_container_view.cc b/ash/app_list/views/apps_container_view.cc index 305f29d..790b567 100644 --- a/ash/app_list/views/apps_container_view.cc +++ b/ash/app_list/views/apps_container_view.cc
@@ -135,8 +135,10 @@ // The vertical spacing between recent apps and continue section view. constexpr int kRecentAppsTopMargin = 16; -// The vertical spacing above and below the separator. -constexpr int kSeparatorVerticalInset = 16; +// The vertical spacing above and below the separator when using kRegular/kDense +// AppListConfigType. +constexpr int kRegularSeparatorVerticalInset = 16; +constexpr int kDenseSeparatorVerticalInset = 8; // The width of the separator. constexpr int kSeparatorWidth = 240; @@ -285,8 +287,10 @@ ColorProvider::ContentLayerType::kSeparatorColor)); separator_->SetPreferredSize( gfx::Size(kSeparatorWidth, views::Separator::kThickness)); + // Initially set the vertical inset to kRegularSeparatorVerticalInset. The + // value will be updated in `AppsContainerView::UpdateAppListConfig()` separator_->SetProperty(views::kMarginsKey, - gfx::Insets(kSeparatorVerticalInset, 0)); + gfx::Insets(kRegularSeparatorVerticalInset, 0)); separator_->SetPaintToLayer(); separator_->layer()->SetFillsBoundsOpaquely(false); separator_->SetProperty(views::kCrossAxisAlignmentKey, @@ -315,6 +319,18 @@ return recent_apps_ && recent_apps_->GetVisible(); } + void UpdateAppListConfig(AppListConfig* config) { + if (recent_apps_) + recent_apps_->UpdateAppListConfig(config); + + const int separator_vertical_inset = + config->type() == AppListConfigType::kRegular + ? kRegularSeparatorVerticalInset + : kDenseSeparatorVerticalInset; + separator_->SetProperty(views::kMarginsKey, + gfx::Insets(separator_vertical_inset, 0)); + } + ContinueSectionView* continue_section() { return continue_section_; } RecentAppsView* recent_apps() { return recent_apps_; } views::View* separator() { return separator_; } @@ -494,8 +510,8 @@ apps_grid_view()->UpdateAppListConfig(app_list_config_.get()); app_list_folder_view()->UpdateAppListConfig(app_list_config_.get()); - if (GetRecentApps()) - GetRecentApps()->UpdateAppListConfig(app_list_config_.get()); + if (continue_container_) + continue_container_->UpdateAppListConfig(app_list_config_.get()); } void AppsContainerView::OnActiveAppListModelsChanged(
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 582ad69..f5f1ef2 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -2938,9 +2938,12 @@ <message name="IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_PIN_OR_PASSWORD_REQUIRED" desc="Text shown when fingerprint has been disabled because it has been too long since the user last used the device"> PIN or password required for more security </message> - <message name="IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS" desc="Text shown in the user pod to tell user that fingerprint unlock has reached maximum attempt"> + <message name="IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS_OLD" desc="Text shown in the user pod to tell user that fingerprint unlock has reached maximum attempt"> Too many attempts </message> + <message name="IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS" desc="Label for the Fingerprint icon on user's lock screen after too many failed attempts to authenticate a fingerprint."> + Too many fingerprint attempts + </message> <message name="IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_SUCCESS" desc="Accessibility text read by chromevox when the user successfully authenticated with fingerprint on the lock screen"> Unlocking with fingerprint </message> @@ -4342,14 +4345,9 @@ <message name="IDS_AUTH_FACTOR_LABEL_CLICK_TO_ENTER" desc="Label on user's lock screen when a user is successfully authenticated and may click on arrow icon to unlock/use the Chromebook."> Tap or click to enter </message> - - <!-- Fingerprint strings shown on the lock screen --> <message name="IDS_AUTH_FACTOR_LABEL_UNLOCKED" desc="Label on user's lock screen when a Chromebook is successfully unlocked."> Unlocked </message> - <message name="IDS_FINGERPRINT_LABEL_NOT_AUTHENTICATED" desc="Label for the Fingerprint icon on user's lock screen after too many failed attempts to authenticate a fingerprint."> - Too many fingerprint attempts - </message> <!-- Launcher: Continue Section --> <message name="IDS_ASH_LAUNCHER_CONTINUE_SECTION_LABEL" desc="Label for the continue section of the launcher, which shows recent files and apps that the user can continue using.">
diff --git a/ash/ash_strings_grd/IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS.png.sha1 b/ash/ash_strings_grd/IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS.png.sha1 new file mode 100644 index 0000000..07167116 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS.png.sha1
@@ -0,0 +1 @@ +834ab29efa299cbc263dc04d6de461c3e4ff384c \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS_OLD.png.sha1 b/ash/ash_strings_grd/IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS_OLD.png.sha1 new file mode 100644 index 0000000..4558338e --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS_OLD.png.sha1
@@ -0,0 +1 @@ +8d9e7b62efed878aaea4d62b0f9f04992f861dca \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_FINGERPRINT_LABEL_NOT_AUTHENTICATED.png.sha1 b/ash/ash_strings_grd/IDS_FINGERPRINT_LABEL_NOT_AUTHENTICATED.png.sha1 deleted file mode 100644 index f8c7178..0000000 --- a/ash/ash_strings_grd/IDS_FINGERPRINT_LABEL_NOT_AUTHENTICATED.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -10d180a982c5f66ec725a9efff9a98a7367f933a \ No newline at end of file
diff --git a/ash/components/fwupd/firmware_update_manager.cc b/ash/components/fwupd/firmware_update_manager.cc index d22f33f3..b56e3b9 100644 --- a/ash/components/fwupd/firmware_update_manager.cc +++ b/ash/components/fwupd/firmware_update_manager.cc
@@ -346,6 +346,12 @@ void FirmwareUpdateManager::BindInterface( mojo::PendingReceiver<firmware_update::mojom::UpdateProvider> pending_receiver) { + // Clear any bound receiver, since this service is a singleton and is bound + // to the firmware updater UI it's possible that the app can be closed and + // reopened multiple times resulting in multiple attempts to bind to this + // receiver. + receiver_.reset(); + receiver_.Bind(std::move(pending_receiver)); }
diff --git a/ash/in_session_auth/authentication_dialog.cc b/ash/in_session_auth/authentication_dialog.cc new file mode 100644 index 0000000..2de13c86 --- /dev/null +++ b/ash/in_session_auth/authentication_dialog.cc
@@ -0,0 +1,142 @@ +// 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/in_session_auth/authentication_dialog.h" +#include <memory> +#include "ash/public/cpp/shelf_config.h" +#include "ash/strings/grit/ash_strings.h" +#include "base/bind.h" +#include "base/time/time.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/ui_base_types.h" +#include "ui/display/screen.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/geometry/insets.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/layout/flex_layout.h" +#include "ui/views/layout/layout_provider.h" +#include "ui/views/layout/layout_types.h" +#include "ui/views/view_class_properties.h" +#include "ui/views/widget/widget.h" + +namespace ash { + +namespace { + +void AddMargins(views::View* view) { + const auto* layout_provider = views::LayoutProvider::Get(); + const int horizontal_spacing = layout_provider->GetDistanceMetric( + views::DISTANCE_RELATED_CONTROL_HORIZONTAL); + const int vertical_spacing = layout_provider->GetDistanceMetric( + views::DISTANCE_RELATED_CONTROL_VERTICAL); + + view->SetProperty(views::kMarginsKey, + gfx::Insets(vertical_spacing, horizontal_spacing)); +} + +void ConfigurePasswordField(views::Textfield* password_field) { + const auto password_field_name = + l10n_util::GetStringUTF16(IDS_ASH_LOGIN_POD_PASSWORD_PLACEHOLDER); + password_field->SetAccessibleName(password_field_name); + password_field->SetReadOnly(false); + password_field->SetTextInputType(ui::TextInputType::TEXT_INPUT_TYPE_PASSWORD); + password_field->SetPlaceholderText(password_field_name); + AddMargins(password_field); +} + +void ConfigureInvalidPasswordLabel(views::Label* invalid_password_label) { + invalid_password_label->SetProperty(views::kCrossAxisAlignmentKey, + views::LayoutAlignment::kStart); + invalid_password_label->SetEnabledColor(SK_ColorRED); + AddMargins(invalid_password_label); +} + +void CenterWidgetOnPrimaryDisplay(views::Widget* widget) { + auto bounds = display::Screen::GetScreen()->GetPrimaryDisplay().work_area(); + bounds.ClampToCenteredSize(widget->GetContentsView()->GetPreferredSize()); + widget->SetBounds(bounds); +} + +} // namespace + +// static +AuthenticationDialog* AuthenticationDialog::Show( + OnSubmitCallback submit_callback) { + auto* authentication_dialog = + new AuthenticationDialog(std::move(submit_callback)); + auto* widget = DialogDelegateView::CreateDialogWidget(authentication_dialog, + /*context=*/nullptr, + /*parent=*/nullptr); + CenterWidgetOnPrimaryDisplay(widget); + widget->Show(); + authentication_dialog->Init(); + return authentication_dialog; +} + +AuthenticationDialog::~AuthenticationDialog() = default; + +void AuthenticationDialog::Init() { + ConfigureOkButton(); + password_field_->RequestFocus(); +} + +void AuthenticationDialog::NotifyResult(Result result, + const std::u16string& token, + base::TimeDelta timeout) { + std::move(on_submit_).Run(result, token, timeout); +} + +void AuthenticationDialog::CancelAuthAttempt() { + NotifyResult(Result::kAborted, u"", base::Seconds(0)); +} + +void AuthenticationDialog::OnSubmit() { + // TODO(crbug.com/1271551): Call appropriate backends to get token + // and notify interested parties with |AuthenticationDialog::NotifyResult| + // For now, we always assume the given password is invalid + password_field_->SetInvalid(true); + password_field_->SelectAll(false); + invalid_password_label_->SetText( + l10n_util::GetStringUTF16(IDS_ASH_LOGIN_ERROR_AUTHENTICATING)); +} + +void AuthenticationDialog::ConfigureChildViews() { + ConfigurePasswordField(password_field_); + ConfigureInvalidPasswordLabel(invalid_password_label_); +} + +void AuthenticationDialog::ConfigureOkButton() { + views::LabelButton* ok_button = GetOkButton(); + ok_button->SetText( + l10n_util::GetStringUTF16(IDS_ASH_LOGIN_SUBMIT_BUTTON_ACCESSIBLE_NAME)); + ok_button->SetCallback(base::BindRepeating(&AuthenticationDialog::OnSubmit, + base::Unretained(this))); +} + +AuthenticationDialog::AuthenticationDialog(OnSubmitCallback submit_callback) + : password_field_(AddChildView(std::make_unique<views::Textfield>())), + invalid_password_label_(AddChildView(std::make_unique<views::Label>())), + on_submit_(std::move(submit_callback)) { + // Dialog setup + set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( + views::DistanceMetric::DISTANCE_BUBBLE_PREFERRED_WIDTH)); + SetTitle(l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_TITLE)); + SetModalType(ui::MODAL_TYPE_SYSTEM); + + // Callback setup + SetCancelCallback(base::BindOnce(&AuthenticationDialog::CancelAuthAttempt, + base::Unretained(this))); + SetCloseCallback(base::BindOnce(&AuthenticationDialog::CancelAuthAttempt, + base::Unretained(this))); + + SetLayoutManager(std::make_unique<views::FlexLayout>()) + ->SetOrientation(views::LayoutOrientation::kVertical) + .SetCollapseMargins(true); + + ConfigureChildViews(); +} + +} // namespace ash
diff --git a/ash/in_session_auth/authentication_dialog.h b/ash/in_session_auth/authentication_dialog.h new file mode 100644 index 0000000..44d8ac03 --- /dev/null +++ b/ash/in_session_auth/authentication_dialog.h
@@ -0,0 +1,68 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_IN_SESSION_AUTH_AUTHENTICATION_DIALOG_H_ +#define ASH_IN_SESSION_AUTH_AUTHENTICATION_DIALOG_H_ + +#include "ash/ash_export.h" +#include "base/time/time.h" +#include "ui/views/controls/label.h" +#include "ui/views/window/dialog_delegate.h" + +namespace views { +class Textfield; +} + +namespace ash { + +// To be used for in-session authentication. Currently, only password +// is supported, however, there are plans to enrich this dialog to eventually +// support all configured forms of authentication on the system. +class ASH_EXPORT AuthenticationDialog : public views::DialogDelegateView { + public: + enum class Result { kSuccess, kAborted }; + + // Callback used to notify invokers of the dialog of success/failure. + // |timeout| here is the length of time the token retrieved from + // backends is valid for + using OnSubmitCallback = base::OnceCallback<void(Result result, + const std::u16string& token, + base::TimeDelta timeout)>; + + // Creates and displays a new instance of a widget that hosts the + // AuthenticationDialog, returning a pointer to it. + // |submit_callback| is called whenever the "Submit" button is clicked + static AuthenticationDialog* Show(OnSubmitCallback submit_callback); + + ~AuthenticationDialog() override; + + // Called post widget initialization. For now, this configures the Ok button + // with custom behavior needed to handle retry of password entry. Also focuses + // the text input field. + void Init(); + + private: + explicit AuthenticationDialog(OnSubmitCallback submit_callback); + + void NotifyResult(Result result, + const std::u16string& token, + base::TimeDelta timeout); + + void ConfigureOkButton(); + + void CancelAuthAttempt(); + + void OnSubmit(); + + void ConfigureChildViews(); + + views::Textfield* password_field_; + views::Label* invalid_password_label_; + + OnSubmitCallback on_submit_; +}; + +} // namespace ash + +#endif // ASH_IN_SESSION_AUTH_AUTHENTICATION_DIALOG_H_
diff --git a/ash/in_session_auth/authentication_dialog_unittest.cc b/ash/in_session_auth/authentication_dialog_unittest.cc new file mode 100644 index 0000000..ea523f6 --- /dev/null +++ b/ash/in_session_auth/authentication_dialog_unittest.cc
@@ -0,0 +1,45 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/in_session_auth/authentication_dialog.h" + +#include "ash/test/ash_test_base.h" +#include "base/test/bind.h" +#include "ui/views/controls/textfield/textfield.h" + +namespace ash { +namespace { + +class AuthenticationDialogTest : public AshTestBase { + public: + void SetUp() override { + AshTestBase::SetUp(); + dialog_ = AuthenticationDialog::Show(base::BindLambdaForTesting( + [&](AuthenticationDialog::Result result, const std::u16string& token, + base::TimeDelta timeout) { + result_ = result; + called_ = true; + })); + } + + protected: + bool called_ = false; + AuthenticationDialog::Result result_; + AuthenticationDialog* dialog_; +}; + +TEST_F(AuthenticationDialogTest, CallbackCalledOnCancel) { + dialog_->Cancel(); + EXPECT_TRUE(called_); + EXPECT_EQ(result_, AuthenticationDialog::Result::kAborted); +} + +TEST_F(AuthenticationDialogTest, CallbackCalledOnClose) { + dialog_->Close(); + EXPECT_TRUE(called_); + EXPECT_EQ(result_, AuthenticationDialog::Result::kAborted); +} + +} // namespace +} // namespace ash \ No newline at end of file
diff --git a/ash/login/ui/fingerprint_auth_factor_model.cc b/ash/login/ui/fingerprint_auth_factor_model.cc index b31ecb85..43add99 100644 --- a/ash/login/ui/fingerprint_auth_factor_model.cc +++ b/ash/login/ui/fingerprint_auth_factor_model.cc
@@ -93,7 +93,7 @@ case FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING: return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_TOUCH_SENSOR; case FingerprintState::DISABLED_FROM_ATTEMPTS: - return IDS_FINGERPRINT_LABEL_NOT_AUTHENTICATED; + return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS; case FingerprintState::DISABLED_FROM_TIMEOUT: return can_use_pin_ ? IDS_AUTH_FACTOR_LABEL_PASSWORD_OR_PIN_REQUIRED : IDS_AUTH_FACTOR_LABEL_PASSWORD_REQUIRED;
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index 60f5eed..a0c57d9 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -259,7 +259,7 @@ case FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING: return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_TOUCH_SENSOR; case FingerprintState::DISABLED_FROM_ATTEMPTS: - return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS; + return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS_OLD; case FingerprintState::DISABLED_FROM_TIMEOUT: if (can_use_pin) return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_PIN_OR_PASSWORD_REQUIRED;
diff --git a/ash/policy/policy_recommendation_restorer_unittest.cc b/ash/policy/policy_recommendation_restorer_unittest.cc index 52c0bd6..cb7074d 100644 --- a/ash/policy/policy_recommendation_restorer_unittest.cc +++ b/ash/policy/policy_recommendation_restorer_unittest.cc
@@ -32,6 +32,7 @@ /*managed_prefs=*/new TestingPrefStore, /*supervised_user_prefs=*/new TestingPrefStore, /*extension_prefs=*/new TestingPrefStore, + /*standalone_browser_prefs=*/new TestingPrefStore, /*user_prefs=*/new TestingPrefStore, recommended_prefs_, new user_prefs::PrefRegistrySyncable,
diff --git a/ash/shelf/drag_window_from_shelf_controller_unittest.cc b/ash/shelf/drag_window_from_shelf_controller_unittest.cc index 8f67a464..fe64b2d 100644 --- a/ash/shelf/drag_window_from_shelf_controller_unittest.cc +++ b/ash/shelf/drag_window_from_shelf_controller_unittest.cc
@@ -36,6 +36,7 @@ #include "ui/aura/client/window_parenting_client.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/compositor/test/test_utils.h" #include "ui/gfx/geometry/point_f.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/transient_window_manager.h" @@ -107,17 +108,17 @@ void CancelDrag() { window_drag_controller_->CancelDrag(); } void WaitForHomeLauncherAnimationToFinish() { // Wait until home launcher animation finishes. - while (GetAppListTestHelper() - ->GetAppListView() - ->GetWidget() - ->GetLayer() - ->GetAnimator() - ->is_animating()) { - base::RunLoop run_loop; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(200)); - run_loop.Run(); - } + ui::Layer* layer = + GetAppListTestHelper()->GetAppListView()->GetWidget()->GetLayer(); + ui::Compositor* compositor = layer->GetCompositor(); + + while (layer->GetAnimator()->is_animating()) + EXPECT_TRUE(ui::WaitForNextFrameToBePresented(compositor)); + + // Ensure there is one more frame presented after animation finishes + // to allow animation throughput data is passed from cc to ui. + ignore_result( + ui::WaitForNextFrameToBePresented(compositor, base::Milliseconds(200))); } SplitViewController* split_view_controller() { @@ -1393,4 +1394,4 @@ EXPECT_FALSE(transient_child_win1->IsVisible()); EXPECT_FALSE(transient_child_win2->IsVisible()); } -} // namespace ash \ No newline at end of file +} // namespace ash
diff --git a/ash/system/power/power_prefs_unittest.cc b/ash/system/power/power_prefs_unittest.cc index 6f65319..5081c2e 100644 --- a/ash/system/power/power_prefs_unittest.cc +++ b/ash/system/power/power_prefs_unittest.cc
@@ -220,6 +220,7 @@ auto pref_value_store = std::make_unique<PrefValueStore>( managed_pref_store_.get() /* managed_prefs */, nullptr /* supervised_user_prefs */, nullptr /* extension_prefs */, + nullptr /* standalone_browser_prefs */, nullptr /* command_line_prefs */, user_pref_store_.get(), nullptr /* recommended_prefs */, pref_registry_->defaults().get(), pref_notifier.get());
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc index 3683768..6c6a4e3 100644 --- a/ash/wallpaper/wallpaper_controller_impl.cc +++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -2623,7 +2623,8 @@ for (size_t i = 0; i < variants.size(); i++) { ImageDownloader::Get()->Download( - GURL(variants.at(i).url), NO_TRAFFIC_ANNOTATION_YET, + GURL(variants.at(i).url.spec() + GetBackdropWallpaperSuffix()), + NO_TRAFFIC_ANNOTATION_YET, base::BindOnce( &WallpaperControllerImpl::OnOnlineWallpaperVariantDownloaded, set_wallpaper_weak_factory_.GetWeakPtr(), params, on_done,
diff --git a/ash/webui/diagnostics_ui/backend/BUILD.gn b/ash/webui/diagnostics_ui/backend/BUILD.gn index 0de4aa0..99abf73 100644 --- a/ash/webui/diagnostics_ui/backend/BUILD.gn +++ b/ash/webui/diagnostics_ui/backend/BUILD.gn
@@ -47,6 +47,7 @@ ] deps = [ + "//ash", "//ash/constants:constants", "//ash/public/cpp", "//ash/webui/diagnostics_ui/mojom", @@ -65,6 +66,8 @@ "//services/device/public/mojom", "//ui/base", "//ui/base/ime/ash", + "//ui/chromeos/events", + "//ui/events/devices", "//ui/events/ozone", "//ui/events/ozone/evdev:event_device_info", "//ui/events/ozone/layout", @@ -118,9 +121,11 @@ "//components/sync_preferences:test_support", "//content/test:test_support", "//dbus", + "//device/udev_linux:test_support", "//services/data_decoder/public/cpp:test_support", "//services/device/public/cpp:test_support", "//testing/gtest", + "//ui/chromeos/events", "//ui/events/ozone", "//ui/events/ozone/evdev:event_device_info_test_utils", "//ui/gfx",
diff --git a/ash/webui/diagnostics_ui/backend/DEPS b/ash/webui/diagnostics_ui/backend/DEPS new file mode 100644 index 0000000..bb33d0a --- /dev/null +++ b/ash/webui/diagnostics_ui/backend/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "input_data_provider_unittest\.cc": [ + "+device/udev_linux/fake_udev_loader.h", + ] +}
diff --git a/ash/webui/diagnostics_ui/backend/input_data_provider.cc b/ash/webui/diagnostics_ui/backend/input_data_provider.cc index 3e93f9b..04f2b76 100644 --- a/ash/webui/diagnostics_ui/backend/input_data_provider.cc +++ b/ash/webui/diagnostics_ui/backend/input_data_provider.cc
@@ -20,6 +20,8 @@ #include "base/strings/string_util.h" #include "chromeos/system/statistics_provider.h" #include "ui/base/ime/ash/input_method_manager.h" +#include "ui/events/devices/device_util_linux.h" +#include "ui/events/devices/input_device.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/ozone/evdev/event_device_info.h" @@ -33,27 +35,27 @@ const std::string base_name_prefix = "event"; std::string base_name = path.BaseName().value(); - DCHECK(base::StartsWith(base_name, base_name_prefix)); + if (!base::StartsWith(base_name, base_name_prefix)) + return false; base_name.erase(0, base_name_prefix.length()); return base::StringToInt(base_name, id); } -mojom::ConnectionType ConnectionTypeFromInputDeviceType( - ui::InputDeviceType type) { - switch (type) { - case ui::InputDeviceType::INPUT_DEVICE_INTERNAL: - return mojom::ConnectionType::kInternal; - case ui::InputDeviceType::INPUT_DEVICE_USB: - return mojom::ConnectionType::kUsb; - case ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH: - return mojom::ConnectionType::kBluetooth; - case ui::InputDeviceType::INPUT_DEVICE_UNKNOWN: - return mojom::ConnectionType::kUnknown; - } +// Determine if this particular evdev provides touchpad or touchscreen input; +// we do not want stylus devices, which also claim to be touchscreens. +bool IsTouchInputDevice(InputDeviceInformation* device_info) { + return (device_info->event_device_info.HasTouchpad() || + (device_info->event_device_info.HasTouchscreen() && + !device_info->event_device_info.HasStylus())); } + } // namespace -std::unique_ptr<ui::EventDeviceInfo> InputDeviceInfoHelper::GetDeviceInfo( +// All blockings calls for identifying hardware need to go here: both +// EventDeviceInfo::Initialize and ui::GetInputPathInSys can block in +// base::MakeAbsoluteFilePath. +std::unique_ptr<InputDeviceInformation> InputDeviceInfoHelper::GetDeviceInfo( + int id, base::FilePath path) { base::ScopedFD fd(open(path.value().c_str(), O_RDWR | O_NONBLOCK)); if (fd.get() < 0) { @@ -61,12 +63,26 @@ return nullptr; } - auto device_info = std::make_unique<ui::EventDeviceInfo>(); - if (!device_info->Initialize(fd.get(), path)) { + auto info = std::make_unique<InputDeviceInformation>(); + + if (!info->event_device_info.Initialize(fd.get(), path)) { LOG(ERROR) << "Failed to get device info for " << path; return nullptr; } - return device_info; + + const base::FilePath sys_path = ui::GetInputPathInSys(path); + + info->path = path; + info->evdev_id = id; + info->connection_type = InputDataProvider::ConnectionTypeFromInputDeviceType( + info->event_device_info.device_type()); + info->input_device = ui::InputDevice( + id, info->event_device_info.device_type(), info->event_device_info.name(), + info->event_device_info.phys(), sys_path, + info->event_device_info.vendor_id(), info->event_device_info.product_id(), + info->event_device_info.version()); + + return info; } InputDataProvider::InputDataProvider() @@ -84,6 +100,21 @@ device_manager_->RemoveObserver(this); } +// static +mojom::ConnectionType InputDataProvider::ConnectionTypeFromInputDeviceType( + ui::InputDeviceType type) { + switch (type) { + case ui::InputDeviceType::INPUT_DEVICE_INTERNAL: + return mojom::ConnectionType::kInternal; + case ui::InputDeviceType::INPUT_DEVICE_USB: + return mojom::ConnectionType::kUsb; + case ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH: + return mojom::ConnectionType::kBluetooth; + case ui::InputDeviceType::INPUT_DEVICE_UNKNOWN: + return mojom::ConnectionType::kUnknown; + } +} + void InputDataProvider::Initialize() { device_manager_->AddObserver(this); device_manager_->ScanDevices(this); @@ -104,6 +135,7 @@ void InputDataProvider::OnBoundInterfaceDisconnect() { receiver_.reset(); } + void InputDataProvider::GetConnectedDevices( GetConnectedDevicesCallback callback) { std::vector<mojom::KeyboardInfoPtr> keyboard_vector; @@ -158,10 +190,12 @@ if (event.action_type() == ui::DeviceEvent::ActionType::ADD) { info_helper_.AsyncCall(&InputDeviceInfoHelper::GetDeviceInfo) - .WithArgs(event.path()) + .WithArgs(id, event.path()) .Then(base::BindOnce(&InputDataProvider::ProcessDeviceInfo, - weak_factory_.GetWeakPtr(), id)); + weak_factory_.GetWeakPtr())); + } else { + DCHECK(event.action_type() == ui::DeviceEvent::ActionType::REMOVE); if (keyboards_.contains(id)) { keyboards_.erase(id); for (auto& observer : connected_devices_observers_) { @@ -176,40 +210,39 @@ } } +InputDeviceInformation::InputDeviceInformation() = default; +InputDeviceInformation::~InputDeviceInformation() = default; + void InputDataProvider::ProcessDeviceInfo( - int id, - std::unique_ptr<ui::EventDeviceInfo> device_info) { + std::unique_ptr<InputDeviceInformation> device_info) { if (device_info == nullptr) { return; } - if (device_info->HasTouchpad() || - (device_info->HasTouchscreen() && !device_info->HasStylus())) { - AddTouchDevice(id, device_info.get()); - } else if (device_info->HasKeyboard()) { - AddKeyboard(id, device_info.get()); + if (IsTouchInputDevice(device_info.get())) { + AddTouchDevice(device_info.get()); + } else if (device_info->event_device_info.HasKeyboard()) { + AddKeyboard(device_info.get()); } } -void InputDataProvider::AddTouchDevice(int id, - const ui::EventDeviceInfo* device_info) { - touch_devices_[id] = touch_helper_.ConstructTouchDevice( - id, device_info, - ConnectionTypeFromInputDeviceType(device_info->device_type())); +void InputDataProvider::AddTouchDevice( + const InputDeviceInformation* device_info) { + touch_devices_[device_info->evdev_id] = + touch_helper_.ConstructTouchDevice(device_info); for (auto& observer : connected_devices_observers_) { - observer->OnTouchDeviceConnected(touch_devices_[id]->Clone()); + observer->OnTouchDeviceConnected( + touch_devices_[device_info->evdev_id]->Clone()); } } -void InputDataProvider::AddKeyboard(int id, - const ui::EventDeviceInfo* device_info) { - keyboards_[id] = keyboard_helper_.ConstructKeyboard( - id, device_info, - ConnectionTypeFromInputDeviceType(device_info->device_type())); +void InputDataProvider::AddKeyboard(const InputDeviceInformation* device_info) { + keyboards_[device_info->evdev_id] = + keyboard_helper_.ConstructKeyboard(device_info); for (auto& observer : connected_devices_observers_) { - observer->OnKeyboardConnected(keyboards_[id]->Clone()); + observer->OnKeyboardConnected(keyboards_[device_info->evdev_id]->Clone()); } }
diff --git a/ash/webui/diagnostics_ui/backend/input_data_provider.h b/ash/webui/diagnostics_ui/backend/input_data_provider.h index 699e974e..cf86582 100644 --- a/ash/webui/diagnostics_ui/backend/input_data_provider.h +++ b/ash/webui/diagnostics_ui/backend/input_data_provider.h
@@ -18,6 +18,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote_set.h" +#include "ui/chromeos/events/event_rewriter_chromeos.h" #include "ui/events/ozone/device/device_event.h" #include "ui/events/ozone/device/device_event_observer.h" #include "ui/events/ozone/device/device_manager.h" @@ -26,14 +27,37 @@ namespace ash { namespace diagnostics { +// Wrapper for tracking several pieces of information about an evdev-backed +// device. +class InputDeviceInformation { + public: + InputDeviceInformation(); + InputDeviceInformation(const InputDeviceInformation& other) = delete; + InputDeviceInformation& operator=(const InputDeviceInformation& other) = + delete; + ~InputDeviceInformation(); + + int evdev_id; + ui::EventDeviceInfo event_device_info; + ui::InputDevice input_device; + mojom::ConnectionType connection_type; + base::FilePath path; +}; + +// Class for running GetDeviceInfo in its own sequence that can block. class InputDeviceInfoHelper { public: + InputDeviceInfoHelper() {} virtual ~InputDeviceInfoHelper() {} - virtual std::unique_ptr<ui::EventDeviceInfo> GetDeviceInfo( + virtual std::unique_ptr<InputDeviceInformation> GetDeviceInfo( + int evdev_id, base::FilePath path); }; +// Provides information about input devices connected to the system. Implemented +// in the browser process and called by the Diagnostics SWA (a renderer +// process). class InputDataProvider : public mojom::InputDataProvider, public ui::DeviceEventObserver { public: @@ -48,6 +72,8 @@ // Handler for when remote attached to |receiver_| disconnects. void OnBoundInterfaceDisconnect(); bool ReceiverIsBound(); + static mojom::ConnectionType ConnectionTypeFromInputDeviceType( + ui::InputDeviceType type); // mojom::InputDataProvider: void GetConnectedDevices(GetConnectedDevicesCallback callback) override; @@ -69,15 +95,15 @@ private: void Initialize(); - void ProcessDeviceInfo(int id, - std::unique_ptr<ui::EventDeviceInfo> device_info); + void ProcessDeviceInfo(std::unique_ptr<InputDeviceInformation> device_info); - void AddTouchDevice(int id, const ui::EventDeviceInfo* device_info); - void AddKeyboard(int id, const ui::EventDeviceInfo* device_info); + void AddTouchDevice(const InputDeviceInformation* device_info); + void AddKeyboard(const InputDeviceInformation* device_info); InputDataProviderKeyboard keyboard_helper_; InputDataProviderTouch touch_helper_; + // Map by evdev ids to information blocks base::flat_map<int, mojom::KeyboardInfoPtr> keyboards_; base::flat_map<int, mojom::TouchDeviceInfoPtr> touch_devices_;
diff --git a/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.cc b/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.cc index 568bad7..aab7065 100644 --- a/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.cc +++ b/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.cc
@@ -4,10 +4,17 @@ #include "ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.h" +#include <fcntl.h> +#include <linux/input.h> #include <vector> #include "ash/constants/ash_switches.h" +#include "ash/display/privacy_screen_controller.h" +#include "ash/shell.h" +#include "ash/webui/diagnostics_ui/backend/input_data_provider.h" #include "base/command_line.h" +#include "base/containers/fixed_flat_map.h" +#include "base/files/scoped_file.h" #include "base/logging.h" #include "base/run_loop.h" #include "base/strings/strcat.h" @@ -16,6 +23,9 @@ #include "base/strings/string_util.h" #include "chromeos/system/statistics_provider.h" #include "ui/base/ime/ash/input_method_manager.h" +#include "ui/chromeos/events/event_rewriter_chromeos.h" +#include "ui/events/devices/device_util_linux.h" +#include "ui/events/devices/input_device.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/dom/keycode_converter.h" #include "ui/events/ozone/evdev/event_device_info.h" @@ -25,6 +35,135 @@ namespace { +enum { + kFKey1 = 0, + kFKey2, + kFKey3, + kFKey4, + kFKey5, + kFKey6, + kFKey7, + kFKey8, + kFKey9, + kFKey10, + kFKey11, + kFKey12, + kFKey13, + kFKey14, + kFKey15 +}; + +// Mapping from keyboard scancodes to TopRowKeys (must be in scancode-sorted +// order). This replicates and should be identical to the mapping behaviour +// of ChromeOS: changes will be needed if new AT scancodes or HID mappings +// are used in a top-row key, likely added in +// ui/events/keycodes/dom/dom_code_data.inc +// +// Note that there are no dedicated scancodes for kScreenMirror. +constexpr auto kScancodeMapping = + base::MakeFixedFlatMap<uint32_t, mojom::TopRowKey>({ + // Vivaldi extended Set-1 AT-style scancodes + {0x90, mojom::TopRowKey::kPreviousTrack}, + {0x91, mojom::TopRowKey::kFullscreen}, + {0x92, mojom::TopRowKey::kOverview}, + {0x93, mojom::TopRowKey::kScreenshot}, + {0x94, mojom::TopRowKey::kScreenBrightnessDown}, + {0x95, mojom::TopRowKey::kScreenBrightnessUp}, + {0x96, mojom::TopRowKey::kPrivacyScreenToggle}, + {0x97, mojom::TopRowKey::kKeyboardBacklightDown}, + {0x98, mojom::TopRowKey::kKeyboardBacklightUp}, + {0x99, mojom::TopRowKey::kNextTrack}, + {0x9A, mojom::TopRowKey::kPlayPause}, + {0xA0, mojom::TopRowKey::kVolumeMute}, + {0xAE, mojom::TopRowKey::kVolumeDown}, + {0xB0, mojom::TopRowKey::kVolumeUp}, + {0xD3, mojom::TopRowKey::kDelete}, // Only relevant for Drallion. + {0xE9, mojom::TopRowKey::kForward}, + {0xEA, mojom::TopRowKey::kBack}, + {0xE7, mojom::TopRowKey::kRefresh}, + + // HID 32-bit usage codes + {0x070046, mojom::TopRowKey::kScreenshot}, + {0x0C00E2, mojom::TopRowKey::kVolumeMute}, + {0x0C00E9, mojom::TopRowKey::kVolumeUp}, + {0x0C00EA, mojom::TopRowKey::kVolumeDown}, + {0x0C006F, mojom::TopRowKey::kScreenBrightnessUp}, + {0x0C0070, mojom::TopRowKey::kScreenBrightnessDown}, + {0x0C0079, mojom::TopRowKey::kKeyboardBacklightUp}, + {0x0C007A, mojom::TopRowKey::kKeyboardBacklightDown}, + {0x0C00B5, mojom::TopRowKey::kNextTrack}, + {0x0C00B6, mojom::TopRowKey::kPreviousTrack}, + {0x0C00CD, mojom::TopRowKey::kPlayPause}, + {0x0C0224, mojom::TopRowKey::kBack}, + {0x0C0225, mojom::TopRowKey::kForward}, + {0x0C0227, mojom::TopRowKey::kRefresh}, + {0x0C0232, mojom::TopRowKey::kFullscreen}, + {0x0C029F, mojom::TopRowKey::kOverview}, + {0x0C02D0, mojom::TopRowKey::kPrivacyScreenToggle}, + }); + +// Hard-coded top-row key mappings. These are intended to match the behaviour of +// EventRewriterChromeOS::RewriteFunctionKeys for historical keyboards. No +// updates should be needed, as all new keyboards are expected to be using +// customizable top row keys (vivaldi). + +constexpr mojom::TopRowKey kSystemKeys1[] = { + mojom::TopRowKey::kBack, + mojom::TopRowKey::kForward, + mojom::TopRowKey::kRefresh, + mojom::TopRowKey::kFullscreen, + mojom::TopRowKey::kOverview, + mojom::TopRowKey::kScreenBrightnessDown, + mojom::TopRowKey::kScreenBrightnessUp, + mojom::TopRowKey::kVolumeMute, + mojom::TopRowKey::kVolumeDown, + mojom::TopRowKey::kVolumeUp}; + +constexpr mojom::TopRowKey kSystemKeys2[] = { + mojom::TopRowKey::kBack, + mojom::TopRowKey::kRefresh, + mojom::TopRowKey::kFullscreen, + mojom::TopRowKey::kOverview, + mojom::TopRowKey::kScreenBrightnessDown, + mojom::TopRowKey::kScreenBrightnessUp, + mojom::TopRowKey::kPlayPause, + mojom::TopRowKey::kVolumeMute, + mojom::TopRowKey::kVolumeDown, + mojom::TopRowKey::kVolumeUp}; + +constexpr mojom::TopRowKey kSystemKeysWilco[] = { + mojom::TopRowKey::kBack, + mojom::TopRowKey::kRefresh, + mojom::TopRowKey::kFullscreen, + mojom::TopRowKey::kOverview, + mojom::TopRowKey::kScreenBrightnessDown, + mojom::TopRowKey::kScreenBrightnessUp, + mojom::TopRowKey::kVolumeMute, + mojom::TopRowKey::kVolumeDown, + mojom::TopRowKey::kVolumeUp, + mojom::TopRowKey::kNone, // F10 + mojom::TopRowKey::kNone, // F11 + mojom::TopRowKey::kScreenMirror, // F12 + mojom::TopRowKey::kDelete // Just a normal Delete key, but in the top row. +}; + +constexpr mojom::TopRowKey kSystemKeysDrallion[] = { + mojom::TopRowKey::kBack, + mojom::TopRowKey::kRefresh, + mojom::TopRowKey::kFullscreen, + mojom::TopRowKey::kOverview, + mojom::TopRowKey::kScreenBrightnessDown, + mojom::TopRowKey::kScreenBrightnessUp, + mojom::TopRowKey::kVolumeMute, + mojom::TopRowKey::kVolumeDown, + mojom::TopRowKey::kVolumeUp, + mojom::TopRowKey::kNone, // F10 + mojom::TopRowKey::kNone, // F11 + mojom::TopRowKey::kNone, // F12 - May be Privacy Screen on some models. + mojom::TopRowKey::kScreenMirror, + mojom::TopRowKey::kDelete // Just a normal Delete key, but in the top row. +}; + mojom::MechanicalLayout GetSystemMechanicalLayout() { chromeos::system::StatisticsProvider* stats_provider = chromeos::system::StatisticsProvider::GetInstance(); @@ -151,17 +290,96 @@ return glyph_set; } +void InputDataProviderKeyboard::ProcessKeyboardTopRowLayout( + const InputDeviceInformation* device_info, + ui::EventRewriterChromeOS::KeyboardTopRowLayout* out_top_row_layout, + std::vector<mojom::TopRowKey>* out_top_row_keys) { + ui::InputDevice input_device = device_info->input_device; + ui::EventRewriterChromeOS::DeviceType device_type; + ui::EventRewriterChromeOS::KeyboardTopRowLayout top_row_layout; + base::flat_map<uint32_t, ui::EventRewriterChromeOS::MutableKeyState> + scan_code_map; + ui::EventRewriterChromeOS::IdentifyKeyboard(input_device, &device_type, + &top_row_layout, &scan_code_map); + + // Simple array in physical order from left to right + std::vector<mojom::TopRowKey> top_row_keys = {}; + + switch (top_row_layout) { + case ui::EventRewriterChromeOS::kKbdTopRowLayoutWilco: + top_row_keys.assign(std::begin(kSystemKeysWilco), + std::end(kSystemKeysWilco)); + break; + + case ui::EventRewriterChromeOS::kKbdTopRowLayoutDrallion: + top_row_keys.assign(std::begin(kSystemKeysDrallion), + std::end(kSystemKeysDrallion)); + + // On some Drallion devices, the F12 key is used for the Privacy Screen. + + // This should be the same logic as in + // EventRewriterControllerImpl::Initialize. This is a historic device, and + // this logic should not need to be updated, as newer devices will use + // custom top row layouts (vivaldi). + if (Shell::Get()->privacy_screen_controller() && + Shell::Get()->privacy_screen_controller()->IsSupported()) { + top_row_keys[kFKey12] = mojom::TopRowKey::kPrivacyScreenToggle; + } + + break; + + case ui::EventRewriterChromeOS::kKbdTopRowLayoutCustom: + + // Process scan-code map generated from custom top-row key layout: it maps + // from physical scan codes to several things, including VKEY key-codes, + // which we will use to produce indexes. + + for (auto iter = scan_code_map.begin(); iter != scan_code_map.end(); + iter++) { + size_t fn_key_number = iter->second.key_code - ui::VKEY_F1; + uint32_t scancode = iter->first; + + if (top_row_keys.size() < fn_key_number + 1) + top_row_keys.resize(fn_key_number + 1, mojom::TopRowKey::kNone); + + if (kScancodeMapping.contains(scancode)) + top_row_keys[fn_key_number] = kScancodeMapping.at(scancode); + else + top_row_keys[fn_key_number] = mojom::TopRowKey::kUnknown; + } + break; + + case ui::EventRewriterChromeOS::kKbdTopRowLayout2: + top_row_keys.assign(std::begin(kSystemKeys2), std::end(kSystemKeys2)); + break; + + case ui::EventRewriterChromeOS::kKbdTopRowLayout1: + default: + top_row_keys.assign(std::begin(kSystemKeys1), std::end(kSystemKeys1)); + } + + *out_top_row_layout = std::move(top_row_layout); + *out_top_row_keys = std::move(top_row_keys); +} + mojom::KeyboardInfoPtr InputDataProviderKeyboard::ConstructKeyboard( - int id, - const ui::EventDeviceInfo* device_info, - mojom::ConnectionType connection_type) { + const InputDeviceInformation* device_info) { mojom::KeyboardInfoPtr result = mojom::KeyboardInfo::New(); - result->id = id; - result->connection_type = connection_type; - result->name = device_info->name(); + + result->id = device_info->evdev_id; + result->connection_type = device_info->connection_type; + result->name = device_info->event_device_info.name(); + + // TODO(crbug.com/1207678): review support for WWCB keyboards, Chromebase + // keyboards, and Dell KM713 Chrome keyboard. + + ui::EventRewriterChromeOS::KeyboardTopRowLayout top_row_layout_type; + + ProcessKeyboardTopRowLayout(device_info, &top_row_layout_type, + &result->top_row_keys); if (result->connection_type == mojom::ConnectionType::kInternal) { - if (device_info->HasKeyEvent(KEY_KBD_LAYOUT_NEXT)) { + if (device_info->event_device_info.HasKeyEvent(KEY_KBD_LAYOUT_NEXT)) { // Only Dell Enterprise devices have this key, marked by a globe icon. result->physical_layout = mojom::PhysicalLayout::kChromeOSDellEnterprise; } else { @@ -176,14 +394,36 @@ chromeos::switches::kHasNumberPad) ? mojom::NumberPadPresence::kPresent : mojom::NumberPadPresence::kNotPresent; + + // Log if there is contradictory information. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kHasNumberPad) && + !device_info->event_device_info.HasNumberpad()) + LOG(ERROR) << "OS believes internal numberpad is implemented, but " + "evdev disagrees."; } else { result->physical_layout = mojom::PhysicalLayout::kUnknown; - result->number_pad_present = mojom::NumberPadPresence::kUnknown; - // TODO(crbug.com/1207678): support WWCB keyboards, Chromebase keyboards, - // and Dell KM713 Chrome keyboard. + + if (top_row_layout_type == ui::EventRewriterChromeOS::KeyboardTopRowLayout:: + kKbdTopRowLayoutCustom) { + // If keyboard has WWCB top row custom layout (vivaldi) then we can trust + // the HID descriptor to be accurate about presence of keys. + result->number_pad_present = + !device_info->event_device_info.HasNumberpad() + ? mojom::NumberPadPresence::kNotPresent + : mojom::NumberPadPresence::kPresent; + } else { + // Without WWCB information, absence of KP keycodes means it definitely + // doesn't have a numberpad, but the presence isn't a reliable indicator. + result->number_pad_present = + !device_info->event_device_info.HasNumberpad() + ? mojom::NumberPadPresence::kNotPresent + : mojom::NumberPadPresence::kUnknown; + } } - result->has_assistant_key = device_info->HasKeyEvent(KEY_ASSISTANT); + result->has_assistant_key = + device_info->event_device_info.HasKeyEvent(KEY_ASSISTANT); return result; }
diff --git a/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.h b/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.h index 14776d1..ea6f9481 100644 --- a/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.h +++ b/ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.h
@@ -7,6 +7,7 @@ #include "ash/webui/diagnostics_ui/mojom/input_data_provider.mojom.h" #include "base/memory/weak_ptr.h" +#include "ui/chromeos/events/event_rewriter_chromeos.h" #include "ui/events/ozone/evdev/event_device_info.h" #include "ui/events/ozone/layout/xkb/xkb_evdev_codes.h" #include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h" @@ -14,6 +15,8 @@ namespace ash { namespace diagnostics { +class InputDeviceInformation; + // Helper to provide InputDataProvider diagnostic interface with // keyboard-specific logic. class InputDataProviderKeyboard { @@ -29,15 +32,18 @@ mojom::InputDataProvider::GetKeyboardVisualLayoutCallback callback); mojom::KeyboardInfoPtr ConstructKeyboard( - int id, - const ui::EventDeviceInfo* device_info, - mojom::ConnectionType connection_type); + const InputDeviceInformation* device_info); private: void ProcessXkbLayout( mojom::InputDataProvider::GetKeyboardVisualLayoutCallback callback); mojom::KeyGlyphSetPtr LookupGlyphSet(uint32_t evdev_code); + void ProcessKeyboardTopRowLayout( + const InputDeviceInformation* device_info, + ui::EventRewriterChromeOS::KeyboardTopRowLayout* out_top_row_layout, + std::vector<mojom::TopRowKey>* out_top_row_keys); + ui::XkbEvdevCodes xkb_evdev_codes_; ui::XkbKeyboardLayoutEngine xkb_layout_engine_;
diff --git a/ash/webui/diagnostics_ui/backend/input_data_provider_touch.cc b/ash/webui/diagnostics_ui/backend/input_data_provider_touch.cc index 29335cc..48b05e87 100644 --- a/ash/webui/diagnostics_ui/backend/input_data_provider_touch.cc +++ b/ash/webui/diagnostics_ui/backend/input_data_provider_touch.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "ash/webui/diagnostics_ui/backend/input_data_provider_touch.h" +#include "ash/webui/diagnostics_ui/backend/input_data_provider.h" +#include "base/logging.h" #include "ui/events/ozone/evdev/event_device_info.h" namespace ash { @@ -12,15 +14,17 @@ InputDataProviderTouch::~InputDataProviderTouch() {} mojom::TouchDeviceInfoPtr InputDataProviderTouch::ConstructTouchDevice( - int id, - const ui::EventDeviceInfo* device_info, - mojom::ConnectionType connection_type) { + const InputDeviceInformation* device_info) { mojom::TouchDeviceInfoPtr result = mojom::TouchDeviceInfo::New(); - result->id = id; - result->connection_type = connection_type; - result->type = device_info->HasTouchpad() ? mojom::TouchDeviceType::kPointer - : mojom::TouchDeviceType::kDirect; - result->name = device_info->name(); + + result->id = device_info->evdev_id; + result->connection_type = device_info->connection_type; + + // TODO(crbug.com/1207678): double-check logic + result->type = device_info->event_device_info.HasTouchpad() + ? mojom::TouchDeviceType::kPointer + : mojom::TouchDeviceType::kDirect; + result->name = device_info->event_device_info.name(); return result; }
diff --git a/ash/webui/diagnostics_ui/backend/input_data_provider_touch.h b/ash/webui/diagnostics_ui/backend/input_data_provider_touch.h index 93aaa565..5fe7db2 100644 --- a/ash/webui/diagnostics_ui/backend/input_data_provider_touch.h +++ b/ash/webui/diagnostics_ui/backend/input_data_provider_touch.h
@@ -11,6 +11,8 @@ namespace ash { namespace diagnostics { +class InputDeviceInformation; + // Helper to provide InputDataProvider diagnostic interface with touch-specific // logic. class InputDataProviderTouch { @@ -21,9 +23,7 @@ ~InputDataProviderTouch(); mojom::TouchDeviceInfoPtr ConstructTouchDevice( - int id, - const ui::EventDeviceInfo* device_info, - mojom::ConnectionType connection_type); + const InputDeviceInformation* device_info); }; } // namespace diagnostics
diff --git a/ash/webui/diagnostics_ui/backend/input_data_provider_unittest.cc b/ash/webui/diagnostics_ui/backend/input_data_provider_unittest.cc index a09db7b9..e07bf86f 100644 --- a/ash/webui/diagnostics_ui/backend/input_data_provider_unittest.cc +++ b/ash/webui/diagnostics_ui/backend/input_data_provider_unittest.cc
@@ -8,10 +8,13 @@ #include "base/command_line.h" #include "base/run_loop.h" +#include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "base/test/task_environment.h" +#include "base/test/test_future.h" #include "chromeos/system/fake_statistics_provider.h" #include "chromeos/system/statistics_provider.h" +#include "device/udev_linux/fake_udev_loader.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/ozone/device/device_event_observer.h" #include "ui/events/ozone/device/device_manager.h" @@ -20,6 +23,77 @@ namespace ash { namespace diagnostics { +namespace { + +constexpr mojom::TopRowKey kClassicTopRowKeys[] = { + mojom::TopRowKey::kBack, + mojom::TopRowKey::kForward, + mojom::TopRowKey::kRefresh, + mojom::TopRowKey::kFullscreen, + mojom::TopRowKey::kOverview, + mojom::TopRowKey::kScreenBrightnessDown, + mojom::TopRowKey::kScreenBrightnessUp, + mojom::TopRowKey::kVolumeMute, + mojom::TopRowKey::kVolumeDown, + mojom::TopRowKey::kVolumeUp}; + +constexpr mojom::TopRowKey kInternalJinlonTopRowKeys[] = { + mojom::TopRowKey::kBack, + mojom::TopRowKey::kRefresh, + mojom::TopRowKey::kFullscreen, + mojom::TopRowKey::kOverview, + mojom::TopRowKey::kScreenshot, + mojom::TopRowKey::kScreenBrightnessDown, + mojom::TopRowKey::kScreenBrightnessUp, + mojom::TopRowKey::kPrivacyScreenToggle, + mojom::TopRowKey::kKeyboardBacklightDown, + mojom::TopRowKey::kKeyboardBacklightUp, + mojom::TopRowKey::kVolumeMute, + mojom::TopRowKey::kVolumeDown, + mojom::TopRowKey::kVolumeUp}; + +// One possible variant of a Dell configuration +constexpr mojom::TopRowKey kInternalDellTopRowKeys[] = { + mojom::TopRowKey::kBack, + mojom::TopRowKey::kRefresh, + mojom::TopRowKey::kFullscreen, + mojom::TopRowKey::kOverview, + mojom::TopRowKey::kScreenBrightnessDown, + mojom::TopRowKey::kScreenBrightnessUp, + mojom::TopRowKey::kVolumeMute, + mojom::TopRowKey::kVolumeDown, + mojom::TopRowKey::kVolumeUp, + mojom::TopRowKey::kNone, + mojom::TopRowKey::kNone, + mojom::TopRowKey::kScreenMirror, + mojom::TopRowKey::kDelete}; + +constexpr char kKbdTopRowPropertyName[] = "CROS_KEYBOARD_TOP_ROW_LAYOUT"; +constexpr char kKbdTopRowLayoutAttributeName[] = "function_row_physmap"; + +constexpr char kSillyDeviceName[] = "eventWithoutANumber"; + +constexpr char kInvalidMechnicalLayout[] = "Not ANSI, JIS, or ISO"; + +// NOTE: This is only creates a simple ui::InputDevice based on a device +// capabilities report; it is not suitable for subclasses of ui::InputDevice. +ui::InputDevice InputDeviceFromCapabilities( + int device_id, + const ui::DeviceCapabilities& capabilities) { + ui::EventDeviceInfo device_info = {}; + ui::CapabilitiesToDeviceInfo(capabilities, &device_info); + + const std::string sys_path = + base::StringPrintf("/dev/input/event%d-%s", device_id, capabilities.path); + + return ui::InputDevice(device_id, device_info.device_type(), + device_info.name(), device_info.phys(), + base::FilePath(sys_path), device_info.vendor_id(), + device_info.product_id(), device_info.version()); +} + +} // namespace + class FakeDeviceManager : public ui::DeviceManager { public: FakeDeviceManager() {} @@ -60,34 +134,71 @@ class FakeInputDeviceInfoHelper : public InputDeviceInfoHelper { public: - std::unique_ptr<ui::EventDeviceInfo> GetDeviceInfo( + FakeInputDeviceInfoHelper() {} + + ~FakeInputDeviceInfoHelper() override {} + + std::unique_ptr<InputDeviceInformation> GetDeviceInfo( + int id, base::FilePath path) override { - std::unique_ptr<ui::EventDeviceInfo> dev_info = - std::make_unique<ui::EventDeviceInfo>(); ui::DeviceCapabilities device_caps; - std::string base_name = path.BaseName().value(); + const std::string base_name = path.BaseName().value(); + if (base_name == "event0") { device_caps = ui::kLinkKeyboard; + EXPECT_EQ(0, id); } else if (base_name == "event1") { device_caps = ui::kLinkTouchpad; + EXPECT_EQ(1, id); } else if (base_name == "event2") { device_caps = ui::kKohakuTouchscreen; + EXPECT_EQ(2, id); } else if (base_name == "event3") { device_caps = ui::kKohakuStylus; + EXPECT_EQ(3, id); } else if (base_name == "event4") { device_caps = ui::kHpUsbKeyboard; + EXPECT_EQ(4, id); } else if (base_name == "event5") { - device_caps = ui::kSarienKeyboard; + device_caps = ui::kSarienKeyboard; // Wilco + EXPECT_EQ(5, id); } else if (base_name == "event6") { device_caps = ui::kEveKeyboard; + EXPECT_EQ(6, id); } else if (base_name == "event7") { + device_caps = ui::kJinlonKeyboard; + EXPECT_EQ(7, id); + } else if (base_name == "event8") { + device_caps = ui::kMicrosoftBluetoothNumberPad; + EXPECT_EQ(8, id); + } else if (base_name == "event9") { + device_caps = ui::kLogitechTouchKeyboardK400; + EXPECT_EQ(9, id); + } else if (base_name == kSillyDeviceName) { + // Simulate a device that is properly described, but has a malformed + // device name. + EXPECT_EQ(98, id); + device_caps = ui::kLinkKeyboard; + } else if (base_name == "event99") { + EXPECT_EQ(99, id); // Simulate a device that couldn't be opened or have its info determined // for whatever reason. return nullptr; } - EXPECT_TRUE(ui::CapabilitiesToDeviceInfo(device_caps, dev_info.get())); - return dev_info; + auto info = std::make_unique<InputDeviceInformation>(); + + EXPECT_TRUE( + ui::CapabilitiesToDeviceInfo(device_caps, &info->event_device_info)); + info->evdev_id = id; + info->path = path; + info->input_device = + InputDeviceFromCapabilities(info->evdev_id, device_caps); + info->connection_type = + InputDataProvider::ConnectionTypeFromInputDeviceType( + info->event_device_info.device_type()); + + return info; } }; @@ -112,7 +223,46 @@ auto manager = std::make_unique<FakeDeviceManager>(); manager_ = manager.get(); + fake_udev_ = std::make_unique<testing::FakeUdevLoader>(); provider_ = std::make_unique<TestInputDataProvider>(std::move(manager)); + + // Apply these early; delaying until + // FakeInputDeviceInfoHelper::GetDeviceInfo() is not appropriate, as + // fake_udev is not thread safe. (If multiple devices are constructed in a + // row, then GetDeviceInfo() invocation can overlap with + // ProcessInputDataProvider::ProcessDeviceInfo() which reads from udev). + UdevAddFakeDeviceCapabilities("/dev/input/event5", ui::kSarienKeyboard); + UdevAddFakeDeviceCapabilities("/dev/input/event6", ui::kEveKeyboard); + UdevAddFakeDeviceCapabilities("/dev/input/event7", ui::kJinlonKeyboard); + } + + void UdevAddFakeDeviceCapabilities( + const std::string& device_name, + const ui::DeviceCapabilities& device_caps) { + std::map<std::string, std::string> + sysfs_properties; // Old style numeric tags + std::map<std::string, std::string> + sysfs_attributes; // New style vivaldi scancode layouts + + if (device_caps.kbd_function_row_physmap && + strlen(device_caps.kbd_function_row_physmap) > 0) { + sysfs_attributes[kKbdTopRowLayoutAttributeName] = + device_caps.kbd_function_row_physmap; + } + + if (device_caps.kbd_top_row_layout && + strlen(device_caps.kbd_top_row_layout) > 0) { + sysfs_properties[kKbdTopRowPropertyName] = device_caps.kbd_top_row_layout; + } + + // Each device needs a unique sys path + const std::string sys_path = device_name + "-" + device_caps.path; + + fake_udev_->AddFakeDevice(device_caps.name, sys_path.c_str(), + /*subsystem=*/"input", /*devnode=*/absl::nullopt, + /*devtype=*/absl::nullopt, + std::move(sysfs_attributes), + std::move(sysfs_properties)); } ~InputDataProviderTest() override { @@ -123,12 +273,12 @@ protected: base::test::TaskEnvironment task_environment_; FakeDeviceManager* manager_; + std::unique_ptr<testing::FakeUdevLoader> fake_udev_; chromeos::system::FakeStatisticsProvider statistics_provider_; std::unique_ptr<InputDataProvider> provider_; }; TEST_F(InputDataProviderTest, GetConnectedDevices_DeviceInfoMapping) { - base::RunLoop run_loop; ui::DeviceEvent event0(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::ADD, base::FilePath("/dev/input/event0")); @@ -147,44 +297,48 @@ provider_->OnDeviceEvent(event3); task_environment_.RunUntilIdle(); - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - ASSERT_EQ(1ul, keyboards.size()); - // The stylus device should be filtered out, hence only 2 touch devices. - ASSERT_EQ(2ul, touch_devices.size()); + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); - mojom::KeyboardInfoPtr keyboard = keyboards[0].Clone(); - EXPECT_EQ(0u, keyboard->id); - EXPECT_EQ(mojom::ConnectionType::kInternal, keyboard->connection_type); - EXPECT_EQ("AT Translated Set 2 keyboard", keyboard->name); + const auto& keyboards = future.Get<0>(); + const auto& touch_devices = future.Get<1>(); - mojom::TouchDeviceInfoPtr touchpad = touch_devices[0].Clone(); - EXPECT_EQ(1u, touchpad->id); - EXPECT_EQ(mojom::ConnectionType::kInternal, touchpad->connection_type); - EXPECT_EQ(mojom::TouchDeviceType::kPointer, touchpad->type); - EXPECT_EQ("Atmel maXTouch Touchpad", touchpad->name); + ASSERT_EQ(1ul, keyboards.size()); + // The stylus device should be filtered out, hence only 2 touch devices. + ASSERT_EQ(2ul, touch_devices.size()); - mojom::TouchDeviceInfoPtr touchscreen = touch_devices[1].Clone(); - EXPECT_EQ(2u, touchscreen->id); - EXPECT_EQ(mojom::ConnectionType::kInternal, - touchscreen->connection_type); - EXPECT_EQ(mojom::TouchDeviceType::kDirect, touchscreen->type); - EXPECT_EQ("Atmel maXTouch Touchscreen", touchscreen->name); + const mojom::KeyboardInfoPtr& keyboard = keyboards[0]; + EXPECT_EQ(0u, keyboard->id); + EXPECT_EQ(mojom::ConnectionType::kInternal, keyboard->connection_type); + EXPECT_EQ("AT Translated Set 2 keyboard", keyboard->name); - run_loop.Quit(); - })); - run_loop.Run(); + const mojom::TouchDeviceInfoPtr& touchpad = touch_devices[0]; + EXPECT_EQ(1u, touchpad->id); + EXPECT_EQ(mojom::ConnectionType::kInternal, touchpad->connection_type); + EXPECT_EQ(mojom::TouchDeviceType::kPointer, touchpad->type); + EXPECT_EQ("Atmel maXTouch Touchpad", touchpad->name); + + const mojom::TouchDeviceInfoPtr& touchscreen = touch_devices[1]; + EXPECT_EQ(2u, touchscreen->id); + EXPECT_EQ(mojom::ConnectionType::kInternal, touchscreen->connection_type); + EXPECT_EQ(mojom::TouchDeviceType::kDirect, touchscreen->type); + EXPECT_EQ("Atmel maXTouch Touchscreen", touchscreen->name); } TEST_F(InputDataProviderTest, GetConnectedDevices_AddEventAfterFirstCall) { - base::RunLoop run_loop; - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - ASSERT_EQ(0ul, keyboards.size()); - ASSERT_EQ(0ul, touch_devices.size()); - })); + { + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); + + const auto& keyboards = future.Get<0>(); + const auto& touch_devices = future.Get<1>(); + ASSERT_EQ(0ul, keyboards.size()); + ASSERT_EQ(0ul, touch_devices.size()); + } ui::DeviceEvent event(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::ADD, @@ -192,25 +346,60 @@ provider_->OnDeviceEvent(event); task_environment_.RunUntilIdle(); - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - ASSERT_EQ(1ul, keyboards.size()); - mojom::KeyboardInfoPtr keyboard = keyboards[0].Clone(); - EXPECT_EQ(4u, keyboard->id); - EXPECT_EQ(mojom::ConnectionType::kUsb, keyboard->connection_type); - EXPECT_EQ("Chicony HP Elite USB Keyboard", keyboard->name); + { + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); - EXPECT_EQ(0ul, touch_devices.size()); + const auto& keyboards = future.Get<0>(); + const auto& touch_devices = future.Get<1>(); - run_loop.Quit(); - })); + ASSERT_EQ(1ul, keyboards.size()); + const mojom::KeyboardInfoPtr& keyboard = keyboards[0]; + EXPECT_EQ(4u, keyboard->id); + EXPECT_EQ(mojom::ConnectionType::kUsb, keyboard->connection_type); + EXPECT_EQ("Chicony HP Elite USB Keyboard", keyboard->name); - run_loop.Run(); + EXPECT_EQ(0ul, touch_devices.size()); + } +} + +TEST_F(InputDataProviderTest, GetConnectedDevices_AddUnusualDevices) { + ui::DeviceEvent event0(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::ADD, + base::FilePath("/dev/input/event8")); + ui::DeviceEvent event1(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::ADD, + base::FilePath("/dev/input/event9")); + provider_->OnDeviceEvent(event0); + provider_->OnDeviceEvent(event1); + task_environment_.RunUntilIdle(); + + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); + + const auto& keyboards = future.Get<0>(); + const auto& touch_devices = future.Get<1>(); + + ASSERT_EQ(2ul, keyboards.size()); + // The stylus device should be filtered out, hence only 2 touch devices. + ASSERT_EQ(0ul, touch_devices.size()); + + const mojom::KeyboardInfoPtr& keyboard1 = keyboards[0]; + EXPECT_EQ(8u, keyboard1->id); + EXPECT_EQ(mojom::ConnectionType::kBluetooth, keyboard1->connection_type); + EXPECT_EQ(ui::kMicrosoftBluetoothNumberPad.name, keyboard1->name); + + const mojom::KeyboardInfoPtr& keyboard2 = keyboards[1]; + EXPECT_EQ(9u, keyboard2->id); + EXPECT_EQ(mojom::ConnectionType::kUnknown, keyboard2->connection_type); + EXPECT_EQ(ui::kLogitechTouchKeyboardK400.name, keyboard2->name); } TEST_F(InputDataProviderTest, GetConnectedDevices_Remove) { - base::RunLoop run_loop; ui::DeviceEvent add_touch_event(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::ADD, base::FilePath("/dev/input/event1")); @@ -221,15 +410,21 @@ provider_->OnDeviceEvent(add_kbd_event); task_environment_.RunUntilIdle(); - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - ASSERT_EQ(1ul, keyboards.size()); - EXPECT_EQ(4u, keyboards[0]->id); + { + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); - ASSERT_EQ(1ul, touch_devices.size()); - EXPECT_EQ(1u, touch_devices[0]->id); - })); + const auto& keyboards = future.Get<0>(); + const auto& touch_devices = future.Get<1>(); + + ASSERT_EQ(1ul, keyboards.size()); + EXPECT_EQ(4u, keyboards[0]->id); + + ASSERT_EQ(1ul, touch_devices.size()); + EXPECT_EQ(1u, touch_devices[0]->id); + } ui::DeviceEvent remove_touch_event(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::REMOVE, @@ -241,20 +436,21 @@ provider_->OnDeviceEvent(remove_kbd_event); task_environment_.RunUntilIdle(); - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - EXPECT_EQ(0ul, keyboards.size()); - EXPECT_EQ(0ul, touch_devices.size()); + { + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); - run_loop.Quit(); - })); + const auto& keyboards = future.Get<0>(); + const auto& touch_devices = future.Get<1>(); - run_loop.Run(); + EXPECT_EQ(0ul, keyboards.size()); + EXPECT_EQ(0ul, touch_devices.size()); + } } TEST_F(InputDataProviderTest, KeyboardPhysicalLayoutDetection) { - base::RunLoop run_loop; statistics_provider_.SetMachineStatistic( chromeos::system::kKeyboardMechanicalLayoutKey, "ISO"); @@ -267,50 +463,77 @@ ui::DeviceEvent event2(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::ADD, base::FilePath("/dev/input/event5")); + ui::DeviceEvent event3(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::ADD, + base::FilePath("/dev/input/event7")); provider_->OnDeviceEvent(event0); provider_->OnDeviceEvent(event1); provider_->OnDeviceEvent(event2); + provider_->OnDeviceEvent(event3); task_environment_.RunUntilIdle(); - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - ASSERT_EQ(3ul, keyboards.size()); + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); - mojom::KeyboardInfoPtr builtin_keyboard = keyboards[0].Clone(); - EXPECT_EQ(0u, builtin_keyboard->id); - EXPECT_EQ(mojom::PhysicalLayout::kChromeOS, - builtin_keyboard->physical_layout); - EXPECT_EQ(mojom::MechanicalLayout::kIso, - builtin_keyboard->mechanical_layout); - EXPECT_EQ(mojom::NumberPadPresence::kNotPresent, - builtin_keyboard->number_pad_present); + const auto& keyboards = future.Get<0>(); - mojom::KeyboardInfoPtr external_keyboard = keyboards[1].Clone(); - EXPECT_EQ(4u, external_keyboard->id); - EXPECT_EQ(mojom::PhysicalLayout::kUnknown, - external_keyboard->physical_layout); - EXPECT_EQ(mojom::MechanicalLayout::kUnknown, - external_keyboard->mechanical_layout); - EXPECT_EQ(mojom::NumberPadPresence::kUnknown, - external_keyboard->number_pad_present); + ASSERT_EQ(4ul, keyboards.size()); - mojom::KeyboardInfoPtr dell_internal_keyboard = keyboards[2].Clone(); - EXPECT_EQ(5u, dell_internal_keyboard->id); - EXPECT_EQ(mojom::PhysicalLayout::kChromeOSDellEnterprise, - dell_internal_keyboard->physical_layout); - EXPECT_EQ(mojom::MechanicalLayout::kIso, - dell_internal_keyboard->mechanical_layout); - EXPECT_EQ(mojom::NumberPadPresence::kNotPresent, - dell_internal_keyboard->number_pad_present); + const mojom::KeyboardInfoPtr& builtin_keyboard = keyboards[0]; + EXPECT_EQ(0u, builtin_keyboard->id); + EXPECT_EQ(mojom::PhysicalLayout::kChromeOS, + builtin_keyboard->physical_layout); + EXPECT_EQ(mojom::MechanicalLayout::kIso, builtin_keyboard->mechanical_layout); + EXPECT_EQ(mojom::NumberPadPresence::kNotPresent, + builtin_keyboard->number_pad_present); + EXPECT_EQ( + std::vector(std::begin(kClassicTopRowKeys), std::end(kClassicTopRowKeys)), + builtin_keyboard->top_row_keys); - run_loop.Quit(); - })); - run_loop.Run(); + const mojom::KeyboardInfoPtr& external_keyboard = keyboards[1]; + EXPECT_EQ(4u, external_keyboard->id); + EXPECT_EQ(mojom::PhysicalLayout::kUnknown, + external_keyboard->physical_layout); + EXPECT_EQ(mojom::MechanicalLayout::kUnknown, + external_keyboard->mechanical_layout); + EXPECT_EQ(mojom::NumberPadPresence::kUnknown, + external_keyboard->number_pad_present); + EXPECT_EQ( + std::vector(std::begin(kClassicTopRowKeys), std::end(kClassicTopRowKeys)), + external_keyboard->top_row_keys); + + const mojom::KeyboardInfoPtr& dell_internal_keyboard = keyboards[2]; + EXPECT_EQ(5u, dell_internal_keyboard->id); + EXPECT_EQ(mojom::PhysicalLayout::kChromeOSDellEnterprise, + dell_internal_keyboard->physical_layout); + EXPECT_EQ(mojom::MechanicalLayout::kIso, + dell_internal_keyboard->mechanical_layout); + EXPECT_EQ(mojom::NumberPadPresence::kNotPresent, + dell_internal_keyboard->number_pad_present); + EXPECT_EQ(std::vector(std::begin(kInternalDellTopRowKeys), + std::end(kInternalDellTopRowKeys)), + dell_internal_keyboard->top_row_keys); + + const mojom::KeyboardInfoPtr& jinlon_internal_keyboard = keyboards[3]; + EXPECT_EQ(7u, jinlon_internal_keyboard->id); + EXPECT_EQ(mojom::PhysicalLayout::kChromeOS, + jinlon_internal_keyboard->physical_layout); + EXPECT_EQ(mojom::MechanicalLayout::kIso, + jinlon_internal_keyboard->mechanical_layout); + EXPECT_EQ(mojom::NumberPadPresence::kNotPresent, + jinlon_internal_keyboard->number_pad_present); + EXPECT_EQ(std::vector(std::begin(kInternalJinlonTopRowKeys), + std::end(kInternalJinlonTopRowKeys)), + jinlon_internal_keyboard->top_row_keys); + + // TODO(b/208729519): We should check a Drallion keyboard, however that + // invokes a check through the global Shell that does not operate in + // this test. } TEST_F(InputDataProviderTest, KeyboardAssistantKeyDetection) { - base::RunLoop run_loop; ui::DeviceEvent link_event(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::ADD, base::FilePath("/dev/input/event0")); @@ -321,43 +544,46 @@ provider_->OnDeviceEvent(eve_event); task_environment_.RunUntilIdle(); - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - ASSERT_EQ(2ul, keyboards.size()); + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); + const auto& keyboards = future.Get<0>(); - mojom::KeyboardInfoPtr link_keyboard = keyboards[0].Clone(); - EXPECT_EQ(0u, link_keyboard->id); - EXPECT_FALSE(link_keyboard->has_assistant_key); - mojom::KeyboardInfoPtr eve_keyboard = keyboards[1].Clone(); - EXPECT_EQ(6u, eve_keyboard->id); - EXPECT_TRUE(eve_keyboard->has_assistant_key); - })); + ASSERT_EQ(2ul, keyboards.size()); + + const mojom::KeyboardInfoPtr& link_keyboard = keyboards[0]; + EXPECT_EQ(0u, link_keyboard->id); + EXPECT_FALSE(link_keyboard->has_assistant_key); + const mojom::KeyboardInfoPtr& eve_keyboard = keyboards[1]; + EXPECT_EQ(6u, eve_keyboard->id); + EXPECT_TRUE(eve_keyboard->has_assistant_key); } -TEST_F(InputDataProviderTest, KeyboardNumberPadDetection) { +TEST_F(InputDataProviderTest, KeyboardNumberPadDetectionInternal) { + // Detection of internal number pad depends on command-line + // argument, and is not a property of the keyboard device. + base::CommandLine::ForCurrentProcess()->InitFromArgv( {"", "--has-number-pad"}); - base::RunLoop run_loop; ui::DeviceEvent link_event(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::ADD, base::FilePath("/dev/input/event0")); provider_->OnDeviceEvent(link_event); task_environment_.RunUntilIdle(); - provider_->GetConnectedDevices(base::BindLambdaForTesting( - [&](std::vector<mojom::KeyboardInfoPtr> keyboards, - std::vector<mojom::TouchDeviceInfoPtr> touch_devices) { - ASSERT_EQ(1ul, keyboards.size()); + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); + const auto& keyboards = future.Get<0>(); - mojom::KeyboardInfoPtr builtin_keyboard = keyboards[0].Clone(); - EXPECT_EQ(0u, builtin_keyboard->id); - EXPECT_EQ(mojom::NumberPadPresence::kPresent, - builtin_keyboard->number_pad_present); + ASSERT_EQ(1ul, keyboards.size()); - run_loop.Quit(); - })); - run_loop.Run(); + const mojom::KeyboardInfoPtr& builtin_keyboard = keyboards[0]; + EXPECT_EQ(0u, builtin_keyboard->id); + EXPECT_EQ(mojom::NumberPadPresence::kPresent, + builtin_keyboard->number_pad_present); } TEST_F(InputDataProviderTest, ObserveConnectedDevices_Keyboards) { @@ -404,14 +630,37 @@ EXPECT_EQ(1u, fake_observer.touch_devices_disconnected[0]); } -TEST_F(InputDataProviderTest, BadDeviceDoesntCrash) { +TEST_F(InputDataProviderTest, ChangeDeviceDoesNotCrash) { + ui::DeviceEvent add_device_event(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::ADD, + base::FilePath("/dev/input/event1")); + ui::DeviceEvent change_device_event(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::CHANGE, + base::FilePath("/dev/input/event1")); + provider_->OnDeviceEvent(add_device_event); + task_environment_.RunUntilIdle(); + provider_->OnDeviceEvent(change_device_event); + task_environment_.RunUntilIdle(); +} + +TEST_F(InputDataProviderTest, BadDeviceDoesNotCrash) { + // Try a device that specifically fails to be processed ui::DeviceEvent add_bad_device_event(ui::DeviceEvent::DeviceType::INPUT, ui::DeviceEvent::ActionType::ADD, - base::FilePath("/dev/input/event7")); + base::FilePath("/dev/input/event99")); provider_->OnDeviceEvent(add_bad_device_event); task_environment_.RunUntilIdle(); } +TEST_F(InputDataProviderTest, SillyDeviceDoesNotCrash) { + // Try a device that has data, but has a non-parseable name. + ui::DeviceEvent add_silly_device_event(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::ADD, + base::FilePath(kSillyDeviceName)); + provider_->OnDeviceEvent(add_silly_device_event); + task_environment_.RunUntilIdle(); +} + TEST_F(InputDataProviderTest, GetKeyboardVisualLayout_AmericanEnglish) { statistics_provider_.SetMachineStatistic(chromeos::system::kKeyboardLayoutKey, "xkb:us::eng,m17n:ar,t13n:ar"); @@ -422,28 +671,25 @@ provider_->OnDeviceEvent(add_keyboard_event); task_environment_.RunUntilIdle(); - base::RunLoop run_loop; - provider_->GetKeyboardVisualLayout( - 6, base::BindLambdaForTesting( - [&](base::flat_map<uint32_t, mojom::KeyGlyphSetPtr> layout) { - ASSERT_FALSE(layout[KEY_Q].is_null()); - EXPECT_EQ("q", layout[KEY_Q]->main_glyph); - EXPECT_FALSE(layout[KEY_Q]->shift_glyph.has_value()); + base::test::TestFuture<base::flat_map<uint32_t, mojom::KeyGlyphSetPtr>> + future; + provider_->GetKeyboardVisualLayout(6, future.GetCallback()); + const auto& layout = future.Get<0>(); - ASSERT_FALSE(layout[KEY_3].is_null()); - EXPECT_EQ("3", layout[KEY_3]->main_glyph); - EXPECT_EQ("#", layout[KEY_3]->shift_glyph); + ASSERT_FALSE(layout.at(KEY_Q).is_null()); + EXPECT_EQ("q", layout.at(KEY_Q)->main_glyph); + EXPECT_FALSE(layout.at(KEY_Q)->shift_glyph.has_value()); - // Check all of the essential keys (at least on US QWERTY) have - // glyphs. - for (auto const& entry : layout) { - EXPECT_FALSE(entry.second.is_null()) - << "No glyphs for evdev code " << entry.first; - } + ASSERT_FALSE(layout.at(KEY_3).is_null()); + EXPECT_EQ("3", layout.at(KEY_3)->main_glyph); + EXPECT_EQ("#", layout.at(KEY_3)->shift_glyph); - run_loop.Quit(); - })); - run_loop.Run(); + // Check all of the essential keys (at least on US QWERTY) have + // glyphs. + for (auto const& entry : layout) { + EXPECT_FALSE(entry.second.is_null()) + << "No glyphs for evdev code " << entry.first; + } } TEST_F(InputDataProviderTest, GetKeyboardVisualLayout_FrenchFrench) { @@ -456,27 +702,85 @@ provider_->OnDeviceEvent(add_keyboard_event); task_environment_.RunUntilIdle(); - base::RunLoop run_loop; - provider_->GetKeyboardVisualLayout( - 6, base::BindLambdaForTesting( - [&](base::flat_map<uint32_t, mojom::KeyGlyphSetPtr> layout) { - ASSERT_FALSE(layout[KEY_Q].is_null()); - EXPECT_EQ("a", layout[KEY_Q]->main_glyph); - EXPECT_FALSE(layout[KEY_Q]->shift_glyph.has_value()); + base::test::TestFuture<base::flat_map<uint32_t, mojom::KeyGlyphSetPtr>> + future; + provider_->GetKeyboardVisualLayout(6, future.GetCallback()); + const auto& layout = future.Get<0>(); - ASSERT_FALSE(layout[KEY_3].is_null()); - EXPECT_EQ("\"", layout[KEY_3]->main_glyph); - EXPECT_EQ("3", layout[KEY_3]->shift_glyph); + ASSERT_FALSE(layout.at(KEY_Q).is_null()); + EXPECT_EQ("a", layout.at(KEY_Q)->main_glyph); + EXPECT_FALSE(layout.at(KEY_Q)->shift_glyph.has_value()); - // Check all of the essential keys have glyphs. - for (auto const& entry : layout) { - EXPECT_FALSE(entry.second.is_null()) - << "No glyphs for evdev code " << entry.first; - } + ASSERT_FALSE(layout.at(KEY_3).is_null()); + EXPECT_EQ("\"", layout.at(KEY_3)->main_glyph); + EXPECT_EQ("3", layout.at(KEY_3)->shift_glyph); - run_loop.Quit(); - })); - run_loop.Run(); + // Check all of the essential keys have glyphs. + for (auto const& entry : layout) { + EXPECT_FALSE(entry.second.is_null()) + << "No glyphs for evdev code " << entry.first; + } +} + +TEST_F(InputDataProviderTest, GetKeyboardMechanicalLayout_Unknown1) { + statistics_provider_.ClearMachineStatistic( + chromeos::system::kKeyboardMechanicalLayoutKey); + + ui::DeviceEvent add_keyboard_event(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::ADD, + base::FilePath("/dev/input/event6")); + provider_->OnDeviceEvent(add_keyboard_event); + task_environment_.RunUntilIdle(); + + { + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); + + const auto& keyboards = future.Get<0>(); + + ASSERT_EQ(1ul, keyboards.size()); + + const mojom::KeyboardInfoPtr& builtin_keyboard = keyboards[0]; + EXPECT_EQ(6u, builtin_keyboard->id); + EXPECT_EQ(mojom::PhysicalLayout::kChromeOS, + builtin_keyboard->physical_layout); + EXPECT_EQ(mojom::MechanicalLayout::kUnknown, + builtin_keyboard->mechanical_layout); + EXPECT_EQ(mojom::NumberPadPresence::kNotPresent, + builtin_keyboard->number_pad_present); + } +} + +TEST_F(InputDataProviderTest, GetKeyboardMechanicalLayout_Unknown2) { + statistics_provider_.SetMachineStatistic( + chromeos::system::kKeyboardMechanicalLayoutKey, kInvalidMechnicalLayout); + ui::DeviceEvent add_keyboard_event(ui::DeviceEvent::DeviceType::INPUT, + ui::DeviceEvent::ActionType::ADD, + base::FilePath("/dev/input/event6")); + provider_->OnDeviceEvent(add_keyboard_event); + task_environment_.RunUntilIdle(); + + { + base::test::TestFuture<std::vector<mojom::KeyboardInfoPtr>, + std::vector<mojom::TouchDeviceInfoPtr>> + future; + provider_->GetConnectedDevices(future.GetCallback()); + + const auto& keyboards = future.Get<0>(); + + ASSERT_EQ(1ul, keyboards.size()); + + const mojom::KeyboardInfoPtr& builtin_keyboard = keyboards[0]; + EXPECT_EQ(6u, builtin_keyboard->id); + EXPECT_EQ(mojom::PhysicalLayout::kChromeOS, + builtin_keyboard->physical_layout); + EXPECT_EQ(mojom::MechanicalLayout::kUnknown, + builtin_keyboard->mechanical_layout); + EXPECT_EQ(mojom::NumberPadPresence::kNotPresent, + builtin_keyboard->number_pad_present); + } } TEST_F(InputDataProviderTest, ResetReceiverOnDisconnect) {
diff --git a/ash/webui/diagnostics_ui/mojom/input_data_provider.mojom b/ash/webui/diagnostics_ui/mojom/input_data_provider.mojom index 22cc37a..e3a07bd 100644 --- a/ash/webui/diagnostics_ui/mojom/input_data_provider.mojom +++ b/ash/webui/diagnostics_ui/mojom/input_data_provider.mojom
@@ -5,13 +5,15 @@ module ash.diagnostics.mojom; enum ConnectionType { - kInternal, // Includes internal USB devices. + // Includes devices connected over USB that are on fully internal busses, as + // well as the keyboards/touchpads for detachables. + kInternal, kUsb, kBluetooth, + // An unknown device is most likely to be internal. kUnknown, }; -// The physical style of a keyboard. enum PhysicalLayout { kUnknown, // A typical Chrome OS keyboard with action keys on the top row, reduced @@ -31,11 +33,40 @@ }; enum NumberPadPresence { + // Unknown indicates there is no reliable evidence whether a numberpad is + // present. This is common for external keyboards. kUnknown, kPresent, kNotPresent, }; +// Note that this enumeration will need to be extended if new keys are added. +enum TopRowKey { + // Either no key at all, or no special action key at this position. + kNone, + // Marker for keys which cannot be decoded, but have some action. + kUnknown, + kBack, + kForward, + kRefresh, + kFullscreen, + kOverview, + kScreenshot, + kScreenBrightnessDown, + kScreenBrightnessUp, + kPrivacyScreenToggle, + kVolumeMute, + kVolumeDown, + kVolumeUp, + kKeyboardBacklightDown, + kKeyboardBacklightUp, + kNextTrack, + kPreviousTrack, + kPlayPause, + kScreenMirror, + kDelete, +}; + // Describes a connected keyboard. struct KeyboardInfo { // The number of the keyboard's /dev/input/event* node. @@ -44,8 +75,11 @@ string name; PhysicalLayout physical_layout; MechanicalLayout mechanical_layout; - bool has_assistant_key; NumberPadPresence number_pad_present; + // Excludes left-most Escape key, and right-most key (usually Power/Lock). + array<TopRowKey> top_row_keys; + // Only applicable to CrOS keyboards. + bool has_assistant_key; }; // Describes the glyphs that appear on a single key.
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_types.js b/ash/webui/diagnostics_ui/resources/diagnostics_types.js index e79f6d9..4b0e379 100644 --- a/ash/webui/diagnostics_ui/resources/diagnostics_types.js +++ b/ash/webui/diagnostics_ui/resources/diagnostics_types.js
@@ -465,6 +465,12 @@ export const NumberPadPresence = ash.diagnostics.mojom.NumberPadPresence; /** + * Type alias for TopRowKey. + * @typedef {ash.diagnostics.mojom.TopRowKey} + */ +export const TopRowKey = ash.diagnostics.mojom.TopRowKey; + +/** * Type alias for KeyboardInfo. * @typedef {ash.diagnostics.mojom.KeyboardInfo} */
diff --git a/ash/webui/diagnostics_ui/resources/fake_data.js b/ash/webui/diagnostics_ui/resources/fake_data.js index e98de2d..1facc4a 100644 --- a/ash/webui/diagnostics_ui/resources/fake_data.js +++ b/ash/webui/diagnostics_ui/resources/fake_data.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {AuthenticationType, BatteryChargeStatus, BatteryHealth, BatteryInfo, BatteryState, ConnectionType, CpuUsage, ExternalPowerSource, KeyboardInfo, LockType, MechanicalLayout, MemoryUsage, Network, NetworkGuidInfo, NetworkState, NetworkType, NumberPadPresence, PhysicalLayout, PowerRoutineResult, RoamingState, RoutineType, SecurityType, StandardRoutineResult, SystemInfo, TouchDeviceInfo, TouchDeviceType, WiFiStateProperties} from './diagnostics_types.js'; +import {AuthenticationType, BatteryChargeStatus, BatteryHealth, BatteryInfo, BatteryState, ConnectionType, CpuUsage, ExternalPowerSource, KeyboardInfo, LockType, MechanicalLayout, MemoryUsage, Network, NetworkGuidInfo, NetworkState, NetworkType, NumberPadPresence, PhysicalLayout, PowerRoutineResult, RoamingState, RoutineType, SecurityType, StandardRoutineResult, SystemInfo, TopRowKey, TouchDeviceInfo, TouchDeviceType, WiFiStateProperties} from './diagnostics_types.js'; import {stringToMojoString16} from './mojo_utils.js'; /** @type {!Array<!BatteryChargeStatus>} */ @@ -629,6 +629,12 @@ physicalLayout: PhysicalLayout.kChromeOS, mechanicalLayout: MechanicalLayout.kAnsi, hasAssistantKey: true, + topRowKeys: [ + TopRowKey.kBack, TopRowKey.kForward, TopRowKey.kRefresh, + TopRowKey.kFullscreen, TopRowKey.kOverview, + TopRowKey.kScreenBrightnessDown, TopRowKey.kScreenBrightnessUp, + TopRowKey.kVolumeMute, TopRowKey.kVolumeDown, TopRowKey.kVolumeUp + ], numberPadPresent: NumberPadPresence.kPresent, }, ];
diff --git a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html index 4506111..7ffa8e1 100644 --- a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html +++ b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.html
@@ -3,15 +3,27 @@ height: 200px; width: 300px; } + + paper-spinner-lite { + height: 300px; + width: 300px; + } </style> <base-page orientation="column"> <div slot="header"> <h1>[[i18n('provisioningPageTitleText')]]</h1> <div id="provisioningDeviceStatus">[[statusString_]]</div> + <div> + <cr-button id="retryProvisioningButton" class="cancel-button" + on-click="onRetryProvsioningButtonClicked_" + hidden$="[[!shouldShowRetryButton_]]"> + [[i18n('provisioningPageFailedRetryButtonLabel')]] + </cr-button> + </div> </div> <div slot="body"> - <!-- TODO(joonbug): Replace with spinner --> - <iron-icon icon="shimless:shimless-placeholder"></iron-icon> + <paper-spinner-lite hidden$="[[!shouldShowSpinner_]]" active> + </paper-spinner-lite> </div> </base-page>
diff --git a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js b/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js index ef94348..abc9cf2 100644 --- a/ash/webui/shimless_rma/resources/reimaging_provisioning_page.js +++ b/ash/webui/shimless_rma/resources/reimaging_provisioning_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 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/icons.m.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import './shimless_rma_shared_css.js'; @@ -67,6 +68,18 @@ type: String, computed: 'getStatusString_(status_, progress_)', }, + + /** @protected {boolean} */ + shouldShowSpinner_: { + type: Boolean, + value: false, + }, + + /** @protected {boolean} */ + shouldShowRetryButton_: { + type: Boolean, + value: false, + }, }; } @@ -119,6 +132,10 @@ 'disable-next-button', {bubbles: true, composed: true, detail: disabled}, )); + this.shouldShowSpinner_ = this.status_ === ProvisioningStatus.kInProgress; + this.shouldShowRetryButton_ = + this.status_ === ProvisioningStatus.kFailedBlocking || + this.status_ === ProvisioningStatus.kFailedNonBlocking; } /** @return {!Promise<!StateResult>} */ @@ -130,6 +147,26 @@ return Promise.reject(new Error('Provisioning is not complete.')); } } + + /** @private */ + onRetryProvsioningButtonClicked_() { + if (this.status_ !== ProvisioningStatus.kFailedBlocking && + this.status_ !== ProvisioningStatus.kFailedNonBlocking) { + console.error('Provisioning has not failed.'); + return; + } + + this.dispatchEvent(new CustomEvent( + 'transition-state', + { + bubbles: true, + composed: true, + detail: (() => { + return this.shimlessRmaService_.retryProvisioning(); + }) + }, + )); + } } customElements.define(ReimagingProvisioningPage.is, ReimagingProvisioningPage);
diff --git a/ash/webui/shimless_rma/shimless_rma.cc b/ash/webui/shimless_rma/shimless_rma.cc index 2ac3c051..7a19f41 100644 --- a/ash/webui/shimless_rma/shimless_rma.cc +++ b/ash/webui/shimless_rma/shimless_rma.cc
@@ -186,6 +186,8 @@ IDS_SHIMLESS_RMA_PROVISIONING_FAILED_BLOCKING}, {"provisioningPageFailedNonBlockingText", IDS_SHIMLESS_RMA_PROVISIONING_FAILED_NON_BLOCKING}, + {"provisioningPageFailedRetryButtonLabel", + IDS_SHIMLESS_RMA_PROVISIONING_FAILED_RETRY_BUTTON_LABEL}, // Repair complete page {"repairCompletedTitleText", IDS_SHIMLESS_RMA_REPAIR_COMPLETED}, {"repairCompletedDescriptionText",
diff --git a/base/logging.cc b/base/logging.cc index f4888b0..174785c 100644 --- a/base/logging.cc +++ b/base/logging.cc
@@ -804,9 +804,12 @@ #endif #elif defined(OS_FUCHSIA) // LogMessage() will silently drop the message if the logger is not valid. - GetScopedFxLogger().LogMessage( - file_, line_, base::StringPiece(str_newline).substr(message_start_), - LogSeverityToFuchsiaLogSeverity(severity_)); + // Skip the final character of |str_newline|, since LogMessage() will add + // a newline. + const auto message = base::StringPiece(str_newline).substr(message_start_); + GetScopedFxLogger().LogMessage(file_, line_, + message.substr(0, message.size() - 1), + LogSeverityToFuchsiaLogSeverity(severity_)); #endif // OS_FUCHSIA }
diff --git a/build/skia_gold_common/skia_gold_session.py b/build/skia_gold_common/skia_gold_session.py index 7e69a23..5683b772 100644 --- a/build/skia_gold_common/skia_gold_session.py +++ b/build/skia_gold_common/skia_gold_session.py
@@ -5,6 +5,7 @@ import logging import os +import platform import shutil import sys import tempfile @@ -17,7 +18,11 @@ if sys.platform == 'win32': GOLDCTL_BINARY = os.path.join(GOLDCTL_BINARY, 'win', 'goldctl') + '.exe' elif sys.platform == 'darwin': - GOLDCTL_BINARY = os.path.join(GOLDCTL_BINARY, 'mac', 'goldctl') + machine = platform.machine().lower() + if any(machine.startswith(m) for m in ('arm64', 'aarch64')): + GOLDCTL_BINARY = os.path.join(GOLDCTL_BINARY, 'mac_arm64', 'goldctl') + else: + GOLDCTL_BINARY = os.path.join(GOLDCTL_BINARY, 'mac_amd64', 'goldctl') else: GOLDCTL_BINARY = os.path.join(GOLDCTL_BINARY, 'linux', 'goldctl')
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc index a3ba577b..f3eeb68 100644 --- a/cc/trees/proxy_main.cc +++ b/cc/trees/proxy_main.cc
@@ -405,6 +405,8 @@ layer_tree_host_->RecordEndOfFrameMetrics( begin_main_frame_start_time, begin_main_frame_state->active_sequence_trackers); + if (blocking) + commit_trace_.reset(); } void ProxyMain::DidCompleteCommit(CommitTimestamps commit_timestamps) {
diff --git a/chrome/android/features/vr/OWNERS b/chrome/android/features/vr/OWNERS index 7461f332..b84a4e5 100644 --- a/chrome/android/features/vr/OWNERS +++ b/chrome/android/features/vr/OWNERS
@@ -1,3 +1,2 @@ -alcooper@chromium.org -bialpio@chromium.org +file://components/webxr/OWNERS mthiesse@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/DividerLineMenuItemViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/DividerLineMenuItemViewBinder.java index 68dbb5c..3eedce5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/DividerLineMenuItemViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/DividerLineMenuItemViewBinder.java
@@ -48,6 +48,7 @@ int id = model.get(AppMenuItemProperties.MENU_ITEM_ID); assert id == R.id.divider_line_id; view.setId(id); + view.setEnabled(false); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java index 216f9621..7c13333 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProvider.java
@@ -89,7 +89,12 @@ RemoteViews getRemoteViews(@NonNull Context context, @NonNull SearchActivityPreferences prefs, @NonNull AppWidgetManager manager, int widgetId) { - return getDelegate().createDinoWidgetRemoteViews(context, prefs); + Bundle options = manager.getAppWidgetOptions(widgetId); + return getDelegate().createDinoWidgetRemoteViews(context, prefs, + getPortraitModeTargetAreaWidth(options), + getPortraitModeTargetAreaHeight(options), + getLandscapeModeTargetAreaWidth(options), + getLandscapeModeTargetAreaHeight(options)); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java index b65a8a5..a52e845 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -730,8 +730,12 @@ if (shareDirectly) { RecordUserAction.record("MobileMenuDirectShare"); + new UkmRecorder.Bridge().recordEventWithBooleanMetric( + tab.getWebContents(), "MobileMenu.DirectShare", "HasOccurred"); } else { RecordUserAction.record("MobileMenuShare"); + new UkmRecorder.Bridge().recordEventWithBooleanMetric( + tab.getWebContents(), "MobileMenu.Share", "HasOccurred"); } shareDelegate.share(tab, shareDirectly, ShareOrigin.OVERFLOW_MENU); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS index c07db33..b84a4e5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS
@@ -1,2 +1,2 @@ -bialpio@chromium.org +file://components/webxr/OWNERS mthiesse@chromium.org
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/OWNERS index 9d0ccab2..d89d1987 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/OWNERS +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/OWNERS
@@ -1,2 +1 @@ file://chrome/android/java/src/org/chromium/chrome/browser/vr/VR_JAVA_OWNERS -bsheedy@chromium.org
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 748a5b1..09f541f 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6499,6 +6499,12 @@ <message name="IDS_ACCNAME_TAB_SEARCH" desc="The accessible name for the Tab Search bubble."> Search tabs </message> + <message name="IDS_ACCNAME_TAB_SCROLL_LEADING" desc="The accessible name for the TabStrip leading scroll button."> + Scroll towards the first tab + </message> + <message name="IDS_ACCNAME_TAB_SCROLL_TRAILING" desc="The accessible name for the TabStrip trailing scroll button."> + Scroll towards the last tab + </message> <!-- Clipboard permission --> <message name="IDS_ALLOWED_CLIPBOARD_TITLE" desc="Title of the info bubble shown when a site has been allowed access to read the contents of the system clipboard.">
diff --git a/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SCROLL_LEADING.png.sha1 b/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SCROLL_LEADING.png.sha1 new file mode 100644 index 0000000..0fd4b26 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SCROLL_LEADING.png.sha1
@@ -0,0 +1 @@ +ba7dce18cc93123490aaa6ed96d5ac16d56e0679 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SCROLL_TRAILING.png.sha1 b/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SCROLL_TRAILING.png.sha1 new file mode 100644 index 0000000..0fd4b26 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_ACCNAME_TAB_SCROLL_TRAILING.png.sha1
@@ -0,0 +1 @@ +ba7dce18cc93123490aaa6ed96d5ac16d56e0679 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 08c30085..d12c537 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1989,7 +1989,6 @@ "//chrome/browser/touch_to_fill", "//chrome/browser/ui", "//chrome/browser/ui/color:mixers", - "//chrome/browser/ui/webui/app_management:mojo_bindings", "//chrome/browser/ui/webui/app_service_internals:mojo_bindings", "//chrome/browser/ui/webui/bluetooth_internals", "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings", @@ -2415,6 +2414,7 @@ "//ui/surface", "//ui/web_dialogs", "//ui/webui", + "//ui/webui/resources/cr_components/app_management:mojo_bindings", "//ui/webui/resources/cr_components/color_change_listener:mojom", "//ui/webui/resources/cr_components/customize_themes:mojom", "//ui/webui/resources/cr_components/most_visited:mojom", @@ -7390,7 +7390,6 @@ "//chrome/browser/resources/chromeos/smb_shares:web_components", "//chrome/browser/resources/chromeos/vm:web_components", "//chrome/browser/supervised_user:supervised_user_unscaled_resources", - "//chrome/browser/ui/webui/app_management:mojo_bindings_js", "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings_js", "//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings_js", "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings_js", @@ -7398,6 +7397,7 @@ "//chrome/browser/ui/webui/chromeos/vm:mojo_bindings_webui_js", "//chrome/browser/ui/webui/settings/chromeos:mojom_js", "//chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom:mojom_js", + "//ui/webui/resources/cr_components/app_management:mojo_bindings_js", ] }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index db900fd..8fb19e9 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1209,19 +1209,43 @@ constexpr FeatureEntry::FeatureParam kOmniboxZeroSuggestCacheDuration15Secs[] = {{"ZeroSuggestCacheDurationSec", "15"}}; +constexpr FeatureEntry::FeatureParam + kOmniboxZeroSuggestCacheDuration15SecsCounterfactual[] = { + {"ZeroSuggestCacheDurationSec", "15"}, + {"ZeroSuggestCacheCounterfactual", "true"}}; constexpr FeatureEntry::FeatureParam kOmniboxZeroSuggestCacheDuration30Secs[] = {{"ZeroSuggestCacheDurationSec", "30"}}; +constexpr FeatureEntry::FeatureParam + kOmniboxZeroSuggestCacheDuration30SecsCounterfactual[] = { + {"ZeroSuggestCacheDurationSec", "30"}, + {"ZeroSuggestCacheCounterfactual", "true"}}; constexpr FeatureEntry::FeatureParam kOmniboxZeroSuggestCacheDuration60Secs[] = {{"ZeroSuggestCacheDurationSec", "60"}}; +constexpr FeatureEntry::FeatureParam + kOmniboxZeroSuggestCacheDuration60SecsCounterfactual[] = { + {"ZeroSuggestCacheDurationSec", "60"}, + {"ZeroSuggestCacheCounterfactual", "true"}}; constexpr FeatureEntry::FeatureVariation kOmniboxZeroSuggestPrefetchingVariations[] = { {"15 seconds", kOmniboxZeroSuggestCacheDuration15Secs, base::size(kOmniboxZeroSuggestCacheDuration15Secs), nullptr}, + {"15 seconds (counterfactual)", + kOmniboxZeroSuggestCacheDuration15SecsCounterfactual, + base::size(kOmniboxZeroSuggestCacheDuration15SecsCounterfactual), + nullptr}, {"30 seconds", kOmniboxZeroSuggestCacheDuration30Secs, base::size(kOmniboxZeroSuggestCacheDuration30Secs), nullptr}, + {"30 seconds (counterfactual)", + kOmniboxZeroSuggestCacheDuration30SecsCounterfactual, + base::size(kOmniboxZeroSuggestCacheDuration30SecsCounterfactual), + nullptr}, {"60 seconds", kOmniboxZeroSuggestCacheDuration60Secs, - base::size(kOmniboxZeroSuggestCacheDuration60Secs), nullptr}}; + base::size(kOmniboxZeroSuggestCacheDuration60Secs), nullptr}, + {"60 seconds (counterfactual)", + kOmniboxZeroSuggestCacheDuration60SecsCounterfactual, + base::size(kOmniboxZeroSuggestCacheDuration60SecsCounterfactual), + nullptr}}; const FeatureEntry::FeatureParam kOmniboxUIMaxAutocompleteMatches3[] = { {OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam, "3"}};
diff --git a/chrome/browser/android/vr/OWNERS b/chrome/browser/android/vr/OWNERS index 6a8c7d0..b84a4e5 100644 --- a/chrome/browser/android/vr/OWNERS +++ b/chrome/browser/android/vr/OWNERS
@@ -1,6 +1,2 @@ -alcooper@chromium.org -bialpio@chromium.org +file://components/webxr/OWNERS mthiesse@chromium.org - -# WebXR-related, including GvrSchedulerDelegate. -klausw@chromium.org
diff --git a/chrome/browser/android/vr/arcore_device/OWNERS b/chrome/browser/android/vr/arcore_device/OWNERS deleted file mode 100644 index 8f984dc5..0000000 --- a/chrome/browser/android/vr/arcore_device/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -bialpio@chromium.org -klausw@chromium.org
diff --git a/chrome/browser/ash/crosapi/url_handler_ash.cc b/chrome/browser/ash/crosapi/url_handler_ash.cc index 7d48990..bb91c59 100644 --- a/chrome/browser/ash/crosapi/url_handler_ash.cc +++ b/chrome/browser/ash/crosapi/url_handler_ash.cc
@@ -64,6 +64,10 @@ } void UrlHandlerAsh::OpenUrl(const GURL& url) { + OpenUrlInternal(url); +} + +bool UrlHandlerAsh::OpenUrlInternal(const GURL& url) { GURL target_url = crosapi::gurl_os_handler_utils::SanitizeAshURL(url); // Settings will be handled. if (target_url == GURL(chrome::kChromeUIOSSettingsURL)) { @@ -72,7 +76,7 @@ settings_window_manager->ShowChromePageForProfile( ProfileManager::GetPrimaryUserProfile(), target_url, display::kInvalidDisplayId); - return; + return true; } web_app::SystemAppType app_id; @@ -104,10 +108,11 @@ } } else { LOG(ERROR) << "Invalid URL passed to UrlHandlerAsh::OpenUrl:" << url; - return; + return false; } ShowOsAppForProfile(ProfileManager::GetPrimaryUserProfile(), target_url, app_id); + return true; } } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/url_handler_ash.h b/chrome/browser/ash/crosapi/url_handler_ash.h index 5e46526c..401f955 100644 --- a/chrome/browser/ash/crosapi/url_handler_ash.h +++ b/chrome/browser/ash/crosapi/url_handler_ash.h
@@ -24,6 +24,10 @@ // crosapi::mojom::UrlHandler: void OpenUrl(const GURL& url) override; + // Returns |false| when the URL was invalid and will not get processed and + // |true| when the URL will get processed (synchronous or asynchronously). + bool OpenUrlInternal(const GURL& url); + private: mojo::ReceiverSet<mojom::UrlHandler> receivers_; };
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 de3f6651..1cb29c1 100644 --- a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.cc +++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.cc
@@ -148,37 +148,7 @@ OnDlpRestrictionCheckedCallback callback) { ConfidentialContentsInfo info = GetScreenShareConfidentialContentsInfo(media_id); - MaybeReportEvent(info.restriction_info, - DlpRulesManager::Restriction::kScreenShare); - DlpBooleanHistogram(dlp::kScreenShareBlockedUMA, - IsBlocked(info.restriction_info)); - if (IsBlocked(info.restriction_info)) { - ShowDlpScreenShareDisabledNotification(application_title); - std::move(callback).Run(false); - 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. - std::move(callback).Run(true); - return; - } - // 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::OnDlpWarnDialogReply, - base::Unretained(this), info.confidential_contents, - DlpRulesManager::Restriction::kScreenShare, - std::move(callback)), - info.confidential_contents, application_title); - return; - } - // No restrictions apply. - std::move(callback).Run(true); + ProcessScreenShareRestriction(application_title, info, std::move(callback)); } void DlpContentManagerAsh::OnVideoCaptureStarted(const ScreenshotArea& area) { @@ -640,21 +610,8 @@ return GetConfidentialContentsOnScreen(DlpContentRestriction::kScreenShare); } if (media_id.type == content::DesktopMediaID::Type::TYPE_WEB_CONTENTS) { - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost( - content::RenderFrameHost::FromID( - media_id.web_contents_id.render_process_id, - media_id.web_contents_id.main_render_frame_id)); - ConfidentialContentsInfo info; - if (web_contents && !web_contents->IsBeingDestroyed()) { - info.restriction_info = - GetConfidentialRestrictions(web_contents) - .GetRestrictionLevelAndUrl(DlpContentRestriction::kScreenShare); - info.confidential_contents.Add(web_contents); - } else { - NOTREACHED(); - } - return info; + return GetScreenShareConfidentialContentsInfoForWebContents( + media_id.web_contents_id); } DCHECK_EQ(media_id.type, content::DesktopMediaID::Type::TYPE_WINDOW); ConfidentialContentsInfo info;
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 bf9cd92..0f4b8824 100644 --- a/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h +++ b/chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h
@@ -90,11 +90,10 @@ // application |application_name| is restricted or not advised. Depending on // the result, calls |callback| and passes an indicator whether to proceed or // not. - // Virtual to allow tests to override. - virtual void CheckScreenShareRestriction( + void CheckScreenShareRestriction( const content::DesktopMediaID& media_id, const std::u16string& application_title, - OnDlpRestrictionCheckedCallback callback); + OnDlpRestrictionCheckedCallback callback) override; // Called when video capturing for |area| is started. void OnVideoCaptureStarted(const ScreenshotArea& area);
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc index ed18d27..59033e6 100644 --- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc +++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.cc
@@ -64,9 +64,9 @@ void HandleBusResult(MetricCallback callback, CrosHealthdMetricSampler::MetricType metric_type, + MetricData metric_data, cros_healthd::TelemetryInfoPtr result) { bool anything_reported = false; - MetricData metric_data; const auto& bus_result = result->bus_result; if (!bus_result.is_null()) { @@ -99,15 +99,15 @@ } if (anything_reported) { - std::move(callback).Run(metric_data); + std::move(callback).Run(std::move(metric_data)); } } void HandleCpuResult(MetricCallback callback, CrosHealthdMetricSampler::MetricType metric_type, + MetricData metric_data, cros_healthd::TelemetryInfoPtr result) { bool anything_reported = false; - MetricData metric_data; const auto& cpu_result = result->cpu_result; if (!cpu_result.is_null()) { @@ -148,15 +148,15 @@ } if (anything_reported) { - std::move(callback).Run(metric_data); + std::move(callback).Run(std::move(metric_data)); } } void HandleAudioResult(MetricCallback callback, CrosHealthdMetricSampler::MetricType metric_type, + MetricData metric_data, chromeos::cros_healthd::mojom::TelemetryInfoPtr result) { bool anything_reported = false; - MetricData metric_data; auto* const audio_info_out = metric_data.mutable_telemetry_data()->mutable_audio_telemetry(); const auto& audio_result = result->audio_result; @@ -192,15 +192,15 @@ } if (anything_reported) { - std::move(callback).Run(metric_data); + std::move(callback).Run(std::move(metric_data)); } } void HandleMemoryResult(MetricCallback callback, CrosHealthdMetricSampler::MetricType metric_type, + MetricData metric_data, cros_healthd::TelemetryInfoPtr result) { bool anything_reported = false; - MetricData metric_data; const auto& memory_result = result->memory_result; if (!memory_result.is_null()) { @@ -251,13 +251,14 @@ } if (anything_reported) { - std::move(callback).Run(metric_data); + std::move(callback).Run(std::move(metric_data)); } } void OnHealthdInfoReceived(MetricCallback callback, cros_healthd::ProbeCategoryEnum probe_category, CrosHealthdMetricSampler::MetricType metric_type, + MetricData metric_data, cros_healthd::TelemetryInfoPtr result) { if (!result) { DVLOG(1) << "cros_healthd: null telemetry result"; @@ -266,19 +267,23 @@ switch (probe_category) { case cros_healthd::ProbeCategoryEnum::kAudio: { - HandleAudioResult(std::move(callback), metric_type, std::move(result)); + HandleAudioResult(std::move(callback), metric_type, + std::move(metric_data), std::move(result)); break; } case cros_healthd::ProbeCategoryEnum::kBus: { - HandleBusResult(std::move(callback), metric_type, std::move(result)); + HandleBusResult(std::move(callback), metric_type, std::move(metric_data), + std::move(result)); break; } case cros_healthd::ProbeCategoryEnum::kCpu: { - HandleCpuResult(std::move(callback), metric_type, std::move(result)); + HandleCpuResult(std::move(callback), metric_type, std::move(metric_data), + std::move(result)); break; } case cros_healthd::ProbeCategoryEnum::kMemory: { - HandleMemoryResult(std::move(callback), metric_type, std::move(result)); + HandleMemoryResult(std::move(callback), metric_type, + std::move(metric_data), std::move(result)); break; } default: { @@ -299,9 +304,14 @@ void CrosHealthdMetricSampler::Collect(MetricCallback callback) { auto healthd_callback = base::BindOnce(OnHealthdInfoReceived, std::move(callback), - probe_category_, metric_type_); + probe_category_, metric_type_, std::move(metric_data_)); + metric_data_.Clear(); chromeos::cros_healthd::ServiceConnection::GetInstance()->ProbeTelemetryInfo( std::vector<cros_healthd::ProbeCategoryEnum>{probe_category_}, std::move(healthd_callback)); } + +void CrosHealthdMetricSampler::SetMetricData(MetricData metric_data) { + metric_data_ = std::move(metric_data); +} } // namespace reporting
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h index 1a4291d..ecf533c 100644 --- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h +++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler.h
@@ -30,7 +30,17 @@ // Collect is called to invoke the healthd probing process. void Collect(MetricCallback callback) override; + // Set the metric data that the sampler will collect on. This can be used if + // part of the info or telemetry collected for the probe category is set + // without the the healthd metric sampler. After one call to Collect(), this + // metric data is cleared. + void SetMetricData(MetricData metric_data); + private: + // The metric data to populate when calling Collect(). This can be set using + // SetMetricData and is cleared after every call to Collect() + MetricData metric_data_; + // probe_category is the category to probe from the health daemon. const chromeos::cros_healthd::mojom::ProbeCategoryEnum probe_category_;
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc index b418e2b..4cd6cd5 100644 --- a/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc +++ b/chrome/browser/ash/policy/reporting/metrics_reporting/cros_healthd_metric_sampler_unittest.cc
@@ -119,11 +119,12 @@ MetricData CollectData(cros_healthd::TelemetryInfoPtr telemetry_info, cros_healthd::ProbeCategoryEnum probe_category, - CrosHealthdMetricSampler::MetricType metric_type) { - MetricData data; + CrosHealthdMetricSampler::MetricType metric_type, + MetricData metric_data) { chromeos::cros_healthd::FakeCrosHealthdClient::Get() ->SetProbeTelemetryInfoResponseForTesting(telemetry_info); CrosHealthdMetricSampler sampler(probe_category, metric_type); + sampler.SetMetricData(metric_data); test::TestEvent<MetricData> metric_collect_event; sampler.Collect(metric_collect_event.cb()); @@ -177,7 +178,7 @@ test_case.healthd_encryption_state, test_case.max_keys, test_case.key_length, test_case.healthd_encryption_algorithm)), cros_healthd::ProbeCategoryEnum::kMemory, - CrosHealthdMetricSampler::MetricType::kInfo); + CrosHealthdMetricSampler::MetricType::kInfo, MetricData{}); ASSERT_TRUE(result.has_info_data()); ASSERT_TRUE(result.info_data().has_memory_info()); @@ -196,7 +197,7 @@ MetricData result = CollectData(CreateBusResult(test_case.healthd_security_level), cros_healthd::ProbeCategoryEnum::kBus, - CrosHealthdMetricSampler::MetricType::kInfo); + CrosHealthdMetricSampler::MetricType::kInfo, MetricData{}); ASSERT_TRUE(result.has_info_data()); ASSERT_TRUE(result.info_data().has_bus_device_info()); ASSERT_TRUE(result.info_data().bus_device_info().has_thunderbolt_info()); @@ -205,10 +206,34 @@ test_case.reporting_security_level); } +TEST_F(CrosHealthdMetricSamplerTest, SetMetricData) { + MetricData metric_data; + auto* const memory_encryption_info_out = metric_data.mutable_info_data() + ->mutable_memory_info() + ->mutable_tme_info(); + memory_encryption_info_out->set_key_length(1); + // Pass a null memory result so that only encryption state is set. + MetricData result = CollectData( + CreateMemoryResult(nullptr), cros_healthd::ProbeCategoryEnum::kMemory, + CrosHealthdMetricSampler::MetricType::kInfo, metric_data); + + ASSERT_TRUE(result.has_info_data()); + ASSERT_TRUE(result.info_data().has_memory_info()); + ASSERT_TRUE(result.info_data().memory_info().has_tme_info()); + + // Since only encryption state should be set by the sampler, we can verify + // that the keylength field set above propagated to the metric data. + const auto& tme_info = result.info_data().memory_info().tme_info(); + EXPECT_EQ(tme_info.key_length(), 1); + EXPECT_EQ(tme_info.encryption_state(), + ::reporting::MEMORY_ENCRYPTION_STATE_DISABLED); +} + TEST_F(CrosHealthdMetricSamplerTest, TestKeylockerConfigured) { - MetricData result = CollectData(CreateCpuResult(CreateKeylockerInfo(true)), - cros_healthd::ProbeCategoryEnum::kCpu, - CrosHealthdMetricSampler::MetricType::kInfo); + MetricData result = + CollectData(CreateCpuResult(CreateKeylockerInfo(true)), + cros_healthd::ProbeCategoryEnum::kCpu, + CrosHealthdMetricSampler::MetricType::kInfo, MetricData{}); ASSERT_TRUE(result.has_info_data()); ASSERT_TRUE(result.info_data().has_cpu_info()); @@ -218,9 +243,10 @@ } TEST_F(CrosHealthdMetricSamplerTest, TestKeylockerUnconfigured) { - MetricData result = CollectData(CreateCpuResult(CreateKeylockerInfo(false)), - cros_healthd::ProbeCategoryEnum::kCpu, - CrosHealthdMetricSampler::MetricType::kInfo); + MetricData result = + CollectData(CreateCpuResult(CreateKeylockerInfo(false)), + cros_healthd::ProbeCategoryEnum::kCpu, + CrosHealthdMetricSampler::MetricType::kInfo, MetricData{}); ASSERT_TRUE(result.has_info_data()); ASSERT_TRUE(result.info_data().has_cpu_info()); @@ -230,9 +256,9 @@ } TEST_F(CrosHealthdMetricSamplerTest, TestKeylockerUnsupported) { - MetricData result = CollectData(CreateCpuResult(nullptr), - cros_healthd::ProbeCategoryEnum::kCpu, - CrosHealthdMetricSampler::MetricType::kInfo); + MetricData result = CollectData( + CreateCpuResult(nullptr), cros_healthd::ProbeCategoryEnum::kCpu, + CrosHealthdMetricSampler::MetricType::kInfo, MetricData{}); ASSERT_TRUE(result.has_info_data()); ASSERT_TRUE(result.info_data().has_cpu_info()); @@ -280,7 +306,7 @@ /*input_gain=*/50, /*input_device_name=*/"airpods", /*underruns=*/2, /*severe_underruns=*/2)), cros_healthd::ProbeCategoryEnum::kAudio, - CrosHealthdMetricSampler::MetricType::kTelemetry); + CrosHealthdMetricSampler::MetricType::kTelemetry, MetricData{}); ASSERT_TRUE(result.has_telemetry_data()); ASSERT_TRUE(result.telemetry_data().has_audio_telemetry()); @@ -298,7 +324,7 @@ /*input_gain=*/0, /*input_device_name=*/"", /*underruns=*/0, /*severe_underruns=*/0)), cros_healthd::ProbeCategoryEnum::kAudio, - CrosHealthdMetricSampler::MetricType::kTelemetry); + CrosHealthdMetricSampler::MetricType::kTelemetry, MetricData{}); ASSERT_TRUE(result.has_telemetry_data()); ASSERT_TRUE(result.telemetry_data().has_audio_telemetry());
diff --git a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc index 46f60bb..54ef592 100644 --- a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc +++ b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc
@@ -20,6 +20,8 @@ namespace { +bool g_enable_delegate_for_testing = false; + SkColor GetBgColor(bool use_dark_mode) { return cros_styles::ResolveColor( cros_styles::ColorName::kBgColor, use_dark_mode, @@ -70,7 +72,8 @@ } bool OsUrlHandlerSystemWebAppDelegate::IsAppEnabled() const { - return crosapi::browser_util::IsLacrosEnabled(); + return g_enable_delegate_for_testing || + crosapi::browser_util::IsLacrosEnabled(); } bool OsUrlHandlerSystemWebAppDelegate::ShouldShowInLauncher() const { @@ -108,3 +111,7 @@ crosapi::gurl_os_handler_utils::GetSystemUrlFromChromeUrl(target_url); return ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(target_url); } + +void OsUrlHandlerSystemWebAppDelegate::EnableDelegateForTesting(bool enable) { + g_enable_delegate_for_testing = enable; +}
diff --git a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h index fd76aa9..a313bbc0 100644 --- a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h +++ b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h
@@ -33,6 +33,9 @@ bool ShouldShowInSearch() const override; bool ShouldReuseExistingWindow() const override; bool IsUrlInSystemAppScope(const GURL& url) const override; + + // Can be called by a test to enforce the app to be enabled. + static void EnableDelegateForTesting(bool enable); }; #endif // CHROME_BROWSER_ASH_WEB_APPLICATIONS_OS_URL_HANDLER_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index b7105dc..6a21319 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -209,7 +209,6 @@ #include "chrome/browser/apps/digital_goods/digital_goods_factory_impl.h" #include "chrome/browser/nearby_sharing/common/nearby_share_features.h" #include "chrome/browser/speech/cros_speech_recognition_service_factory.h" -#include "chrome/browser/ui/webui/app_management/app_management.mojom.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h" #include "chrome/browser/ui/webui/chromeos/audio/audio.mojom.h" @@ -252,6 +251,7 @@ #include "chromeos/services/network_health/public/mojom/network_health.mojom.h" // nogncheck #include "media/capture/video/chromeos/mojom/camera_app.mojom.h" #include "third_party/blink/public/mojom/digital_goods/digital_goods.mojom.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC) || \
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 5ebad974f..6125095 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -6163,10 +6163,8 @@ void ChromeContentBrowserClient::OnKeepaliveRequestStarted( content::BrowserContext* context) { #if !defined(OS_ANDROID) - // TODO(crbug.com/1161996): Remove this entry once the investigation is - // done. - VLOG(1) << "OnKeepaliveRequestStarted: " << num_keepalive_requests_ << " ==> " - << num_keepalive_requests_ + 1; + DVLOG(1) << "OnKeepaliveRequestStarted: " << num_keepalive_requests_ + << " ==> " << num_keepalive_requests_ + 1; ++num_keepalive_requests_; DCHECK_GT(num_keepalive_requests_, 0u); @@ -6180,10 +6178,8 @@ const auto timeout = GetKeepaliveTimerTimeout(context); keepalive_deadline_ = std::max(keepalive_deadline_, now + timeout); if (keepalive_deadline_ > now && !keepalive_timer_.IsRunning()) { - // TODO(crbug.com/1161996): Remove this entry once the investigation is - // done. - VLOG(1) << "Starting a keepalive timer(" << timeout.InSecondsF() - << " seconds)"; + DVLOG(1) << "Starting a keepalive timer(" << timeout.InSecondsF() + << " seconds)"; keepalive_timer_.Start( FROM_HERE, keepalive_deadline_ - now, base::BindOnce( @@ -6198,15 +6194,11 @@ void ChromeContentBrowserClient::OnKeepaliveRequestFinished() { #if !defined(OS_ANDROID) DCHECK_GT(num_keepalive_requests_, 0u); - // TODO(crbug.com/1161996): Remove this entry once the investigation is - // done. - VLOG(1) << "OnKeepaliveRequestFinished: " << num_keepalive_requests_ - << " ==> " << num_keepalive_requests_ - 1; + DVLOG(1) << "OnKeepaliveRequestFinished: " << num_keepalive_requests_ + << " ==> " << num_keepalive_requests_ - 1; --num_keepalive_requests_; if (num_keepalive_requests_ == 0) { - // TODO(crbug.com/1161996): Remove this entry once the investigation is - // done. - VLOG(1) << "Stopping the keepalive timer"; + DVLOG(1) << "Stopping the keepalive timer"; keepalive_timer_.Stop(); // This deletes the keep alive handle attached to the timer function and // unblock the shutdown sequence. @@ -6313,14 +6305,9 @@ void ChromeContentBrowserClient::OnKeepaliveTimerFired( std::unique_ptr<ScopedKeepAlive> keep_alive_handle) { - // TODO(crbug.com/1161996): Remove this entry once the investigation is done. - VLOG(1) << "OnKeepaliveTimerFired"; const auto now = base::TimeTicks::Now(); const auto then = keepalive_deadline_; if (now < then) { - // TODO(crbug.com/1161996): Remove this entry once the investigation is - // done. - VLOG(1) << "Extending keepalive timer"; keepalive_timer_.Start( FROM_HERE, then - now, base::BindOnce(&ChromeContentBrowserClient::OnKeepaliveTimerFired,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index fa6248bc..4bcceea 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -4635,6 +4635,8 @@ "policy/dlp/dlp_rules_manager_impl_unittest.cc", "policy/dlp/dlp_rules_manager_test_utils.cc", "policy/dlp/dlp_rules_manager_test_utils.h", + "policy/dlp/mock_dlp_content_manager.cc", + "policy/dlp/mock_dlp_content_manager.h", "policy/dlp/mock_dlp_content_observer.cc", "policy/dlp/mock_dlp_content_observer.h", "policy/dlp/mock_dlp_rules_manager.cc",
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc index a901f45..f395aa3 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.cc
@@ -195,6 +195,63 @@ .GetRestrictionLevelAndUrl(DlpContentRestriction::kPrint); } +DlpContentManager::ConfidentialContentsInfo +DlpContentManager::GetScreenShareConfidentialContentsInfoForWebContents( + const content::WebContentsMediaCaptureId& web_contents_id) const { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost( + content::RenderFrameHost::FromID( + web_contents_id.render_process_id, + web_contents_id.main_render_frame_id)); + ConfidentialContentsInfo info; + if (web_contents && !web_contents->IsBeingDestroyed()) { + info.restriction_info = + GetConfidentialRestrictions(web_contents) + .GetRestrictionLevelAndUrl(DlpContentRestriction::kScreenShare); + info.confidential_contents.Add(web_contents); + } else { + NOTREACHED(); + } + return info; +} + +void DlpContentManager::ProcessScreenShareRestriction( + const std::u16string& application_title, + ConfidentialContentsInfo info, + OnDlpRestrictionCheckedCallback callback) { + MaybeReportEvent(info.restriction_info, + DlpRulesManager::Restriction::kScreenShare); + DlpBooleanHistogram(dlp::kScreenShareBlockedUMA, + IsBlocked(info.restriction_info)); + if (IsBlocked(info.restriction_info)) { + ShowDlpScreenShareDisabledNotification(application_title); + std::move(callback).Run(false); + return; + } + if (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. + std::move(callback).Run(true); + return; + } + // 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::OnDlpWarnDialogReply, + base::Unretained(this), info.confidential_contents, + DlpRulesManager::Restriction::kScreenShare, + std::move(callback)), + info.confidential_contents, application_title); + return; + } + // No restrictions apply. + std::move(callback).Run(true); +} + 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 1c2545c..5d6f237 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager.h
@@ -19,6 +19,8 @@ #include "url/gurl.h" namespace content { +struct DesktopMediaID; +struct WebContentsMediaCaptureId; class WebContents; } // namespace content @@ -52,6 +54,15 @@ void CheckPrintingRestriction(content::WebContents* web_contents, OnDlpRestrictionCheckedCallback callback); + // 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. + virtual void CheckScreenShareRestriction( + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + OnDlpRestrictionCheckedCallback callback) = 0; + protected: // Structure that relates a list of confidential contents to the // corresponding restriction level. @@ -80,6 +91,17 @@ RestrictionLevelAndUrl GetPrintingRestrictionInfo( content::WebContents* web_contents) const; + // Returns confidential info for screen share of a single WebContents with + // |web_contents_id|. + ConfidentialContentsInfo GetScreenShareConfidentialContentsInfoForWebContents( + const content::WebContentsMediaCaptureId& web_contents_id) const; + + // Applies retrieved restrictions in |info| to screens share attempt from + // app |application_title| and calls the |callback| with a result. + void ProcessScreenShareRestriction(const std::u16string& application_title, + ConfidentialContentsInfo info, + OnDlpRestrictionCheckedCallback callback); + // 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
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 cc47c83d..f8d0e1c7 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.cc
@@ -69,6 +69,23 @@ return g_dlp_content_manager; } +void DlpContentManagerLacros::CheckScreenShareRestriction( + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + OnDlpRestrictionCheckedCallback callback) { + if (media_id.type == content::DesktopMediaID::Type::TYPE_WEB_CONTENTS) { + ProcessScreenShareRestriction( + application_title, + 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. + std::move(callback).Run(true); + } +} + DlpContentManagerLacros::DlpContentManagerLacros() = default; DlpContentManagerLacros::~DlpContentManagerLacros() = default;
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 da6d4483..6236b1e 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_content_manager_lacros.h
@@ -9,6 +9,7 @@ #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 "content/public/browser/desktop_media_id.h" #include "ui/aura/window_observer.h" namespace aura { @@ -30,6 +31,15 @@ // 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. + void CheckScreenShareRestriction( + const content::DesktopMediaID& media_id, + const std::u16string& application_title, + OnDlpRestrictionCheckedCallback callback) override; + private: DlpContentManagerLacros(); ~DlpContentManagerLacros() override;
diff --git a/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.cc b/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.cc new file mode 100644 index 0000000..e7ab8ae --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.cc
@@ -0,0 +1,13 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h" + +namespace policy { + +MockDlpContentManager::MockDlpContentManager() = default; + +MockDlpContentManager::~MockDlpContentManager() = default; + +} // 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 new file mode 100644 index 0000000..e773f8a --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h
@@ -0,0 +1,37 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DLP_MOCK_DLP_CONTENT_MANAGER_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_DLP_MOCK_DLP_CONTENT_MANAGER_H_ + +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace policy { + +class MockDlpContentManager : public DlpContentManager { + public: + MockDlpContentManager(); + ~MockDlpContentManager() override; + + MOCK_METHOD(void, + OnConfidentialityChanged, + (content::WebContents*, const DlpContentRestrictionSet&), + (override)); + MOCK_METHOD(void, + OnWebContentsDestroyed, + (content::WebContents*), + (override)); + MOCK_METHOD(void, OnVisibilityChanged, (content::WebContents*), (override)); + MOCK_METHOD(void, + CheckScreenShareRestriction, + (const content::DesktopMediaID& media_id, + const std::u16string& application_title, + OnDlpRestrictionCheckedCallback callback), + (override)); +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_DLP_MOCK_DLP_CONTENT_MANAGER_H_
diff --git a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc index 771400e..ad3eb6b 100644 --- a/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -44,6 +44,7 @@ #include "third_party/blink/public/common/features.h" #include "third_party/boringssl/src/include/openssl/nid.h" #include "third_party/boringssl/src/include/openssl/ssl.h" +#include "url/origin.h" using DevToolsProtocolTest = DevToolsProtocolTestBase; using testing::AllOf; @@ -207,6 +208,68 @@ EXPECT_EQ(nullptr, DevToolsWindow::FindDevToolsWindow(agent_host_.get())); } +IN_PROC_BROWSER_TEST_F( + DevToolsProtocolTest, + NoPendingUrlShownWhenAttachedToBrowserInitiatedFailedNavigation) { + GURL url("invalid.scheme:for-sure"); + ui_test_utils::AllBrowserTabAddedWaiter tab_added_waiter; + + content::WebContents* web_contents = + browser()->OpenURL(content::OpenURLParams( + url, content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_TYPED, false)); + tab_added_waiter.Wait(); + content::NavigationController& navigation_controller = + web_contents->GetController(); + content::NavigationEntry* pending_entry = + navigation_controller.GetPendingEntry(); + ASSERT_NE(nullptr, pending_entry); + EXPECT_EQ(url, pending_entry->GetURL()); + + EXPECT_EQ(pending_entry, navigation_controller.GetVisibleEntry()); + agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(web_contents); + agent_host_->AttachClient(this); + SendCommandSync("Page.enable"); + + // Ensure that a failed pending entry is cleared when the DevTools protocol + // attaches, so that any modified page content is not attributed to the failed + // URL. (crbug/1192417) + EXPECT_EQ(nullptr, navigation_controller.GetPendingEntry()); + EXPECT_EQ(GURL(""), navigation_controller.GetVisibleEntry()->GetURL()); +} + +IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, + NoPendingUrlShownForPageNavigateFromChromeExtension) { + GURL url("https://example.com"); + // DevTools protocol use cases that have an initiator origin (e.g., for + // extensions) should use renderer-initiated navigations and be subject to URL + // spoof defenses. + navigation_initiator_origin_ = + url::Origin::Create(GURL("chrome-extension://abc123/")); + + // Attach DevTools and start a navigation but don't wait for it to finish. + Attach(); + SendCommandSync("Page.enable"); + base::DictionaryValue params; + params.SetStringKey("url", url.spec()); + SendCommand("Page.navigate", std::move(params), false); + content::NavigationController& navigation_controller = + web_contents()->GetController(); + content::NavigationEntry* pending_entry = + navigation_controller.GetPendingEntry(); + ASSERT_NE(nullptr, pending_entry); + EXPECT_EQ(url, pending_entry->GetURL()); + + // Attaching the DevTools protocol to the initial empty document of a new tab + // should prevent the pending URL from being visible, since the protocol + // allows modifying the initial empty document in a way that could be useful + // for URL spoofs. + EXPECT_NE(pending_entry, navigation_controller.GetVisibleEntry()); + EXPECT_NE(nullptr, navigation_controller.GetPendingEntry()); + EXPECT_EQ(GURL("about:blank"), + navigation_controller.GetVisibleEntry()->GetURL()); +} + class DevToolsProtocolTest_AppId : public DevToolsProtocolTest { public: DevToolsProtocolTest_AppId() {
diff --git a/chrome/browser/devtools/protocol/devtools_protocol_test_support.cc b/chrome/browser/devtools/protocol/devtools_protocol_test_support.cc index 2c9b449..670128f 100644 --- a/chrome/browser/devtools/protocol/devtools_protocol_test_support.cc +++ b/chrome/browser/devtools/protocol/devtools_protocol_test_support.cc
@@ -146,6 +146,10 @@ bool DevToolsProtocolTestBase::AllowUnsafeOperations() { return allow_unsafe_operations_; } +absl::optional<url::Origin> +DevToolsProtocolTestBase::GetNavigationInitiatorOrigin() { + return navigation_initiator_origin_; +} bool DevToolsProtocolTestBase::MaySendInputEventsToBrowser() { return may_send_input_event_to_browser_;
diff --git a/chrome/browser/devtools/protocol/devtools_protocol_test_support.h b/chrome/browser/devtools/protocol/devtools_protocol_test_support.h index 3cfba04..45dc805d 100644 --- a/chrome/browser/devtools/protocol/devtools_protocol_test_support.h +++ b/chrome/browser/devtools/protocol/devtools_protocol_test_support.h
@@ -15,6 +15,8 @@ #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host_client.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "url/origin.h" class DevToolsProtocolTestBase : public InProcessBrowserTest, public content::DevToolsAgentHostClient { @@ -26,6 +28,8 @@ allow_unsafe_operations_ = allow; } + absl::optional<url::Origin> GetNavigationInitiatorOrigin() override; + protected: using NotificationMatcher = base::RepeatingCallback<bool(const base::Value&)>; @@ -82,6 +86,7 @@ base::Value waiting_for_notification_params_; bool allow_unsafe_operations_ = true; bool may_send_input_event_to_browser_ = true; + absl::optional<url::Origin> navigation_initiator_origin_; }; #endif // CHROME_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_TEST_SUPPORT_H_
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc index 73e19fb18..83c0bbe 100644 --- a/chrome/browser/extensions/api/debugger/debugger_api.cc +++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -58,6 +58,7 @@ #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/switches.h" +#include "url/origin.h" using content::DevToolsAgentHost; using content::RenderProcessHost; @@ -208,6 +209,7 @@ bool MayAttachToBrowser() override; bool MayReadLocalFiles() override; bool MayWriteLocalFiles() override; + absl::optional<url::Origin> GetNavigationInitiatorOrigin() override; private: using PendingRequests = @@ -440,6 +442,14 @@ return false; } +absl::optional<url::Origin> +ExtensionDevToolsClientHost::GetNavigationInitiatorOrigin() { + // Ensure that navigations started by debugger API are treated as + // renderer-initiated by this extension, so that URL spoof defenses are in + // effect. + return extension_->origin(); +} + // DebuggerFunction ----------------------------------------------------------- DebuggerFunction::DebuggerFunction() : client_host_(nullptr) {}
diff --git a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc index 10b3348..5cdbc3c 100644 --- a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc +++ b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl_unittest.cc
@@ -74,6 +74,14 @@ OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT; std::move(callback).Run(result); } + segmentation_platform::SegmentSelectionResult GetCachedSegmentResult( + const std::string& segmentation_key) override { + segmentation_platform::SegmentSelectionResult result; + result.is_ready = true; + result.segment = optimization_guide::proto::OptimizationTarget:: + OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT; + return result; + } void EnableMetrics(bool signal_collection_allowed) override {} segmentation_platform::ServiceProxy* GetServiceProxy() override { return nullptr;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 6e733cdb..8a925641 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -827,7 +827,7 @@ { "name": "context-menu-google-lens-chip", "owners": [ "yusuyoutube@google.com", "benwgold@google.com", "lens-chrome@google.com" ], - "expiry_milestone": 96 + "expiry_milestone": 100 }, { "name":"context-menu-phase2", "owners":["gambard", "bling-flags@google.com"], @@ -846,17 +846,17 @@ { "name": "context-menu-search-with-google-lens", "owners": [ "benwgold@google.com", "lens-chrome@google.com" ], - "expiry_milestone": 96 + "expiry_milestone": 100 }, { "name": "context-menu-shop-with-google-lens", "owners": [ "yusuyoutube@google.com", "benwgold@google.com", "lens-chrome@google.com" ], - "expiry_milestone": 96 + "expiry_milestone": 100 }, { "name": "context-menu-translate-with-google-lens", "owners": [ "juanmojica@google.com", "hakop@google.com", "benwgold@google.com", "lens-chrome@google.com" ], - "expiry_milestone": 96 + "expiry_milestone": 100 }, { "name": "contextual-nudges", @@ -2213,7 +2213,7 @@ { "name": "enable-lens-region-search", "owners": [ "stanfield@google.com", "benwgold@google.com", "juanmojica@google.com" ], - "expiry_milestone": 98 + "expiry_milestone": 100 }, { "name": "enable-libinput-to-handle-touchpad", @@ -2519,12 +2519,12 @@ { "name": "enable-quick-action-search-widget-android", "owners": [ "maxtauro@google.com", "ender@google.com" ], - "expiry_milestone": 98 + "expiry_milestone": 105 }, { "name": "enable-quick-action-search-widget-android-dino-variant", "owners": [ "maxtauro@google.com", "ender@google.com" ], - "expiry_milestone": 98 + "expiry_milestone": 105 }, { "name": "enable-raw-draw", @@ -3342,7 +3342,7 @@ { "name": "google-lens-sdk-intent", "owners": [ "juanmojica@google.com", "benwgold@google.com", "lens-chrome@google.com" ], - "expiry_milestone": 96 + "expiry_milestone": 100 }, { "name": "google-mobile-services-passwords",
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java index ec4d2e7..354661e 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java
@@ -12,8 +12,10 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; import org.chromium.base.FeatureList; +import org.chromium.base.task.test.ShadowPostTask; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.flags.CachedFlagsSafeMode.Behavior; @@ -28,9 +30,10 @@ * {@link CachedFlagsSafeMode}. */ @RunWith(BaseRobolectricTestRunner.class) +@Config(shadows = {ShadowPostTask.class}) public class CachedFeatureFlagsSafeModeUnitTest { - private static final String CRASHY_FEATURE = "FeatureA"; - private static final String OK_FEATURE = "FeatureB"; + private static final String CRASHY_FEATURE = "CrashyFeature"; + private static final String OK_FEATURE = "OkFeature"; Map<String, Boolean> mDefaultsSwapped; @@ -324,7 +327,12 @@ private void endCleanRun(boolean crashyFeatureValue, boolean okFeatureValue) { FeatureList.setTestFeatures(makeFeatureMap(crashyFeatureValue, okFeatureValue)); CachedFeatureFlags.cacheNativeFlags(Arrays.asList(CRASHY_FEATURE, OK_FEATURE)); + CachedFeatureFlags.onEndCheckpoint(); + // Async task writing values should have run synchronously because of ShadowPostTask. + assertTrue(CachedFlagsSafeMode.getSafeValuePreferences().contains( + "Chrome.Flags.CachedFlag.CrashyFeature")); + CachedFeatureFlags.resetFlagsForTesting(); }
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java index ce4452cc..d2b2d79 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java
@@ -16,6 +16,7 @@ import org.chromium.base.Log; import org.chromium.base.TraceEvent; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.AsyncTask; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.components.version_info.VersionInfo; @@ -129,9 +130,25 @@ void onEndCheckpoint(ValuesReturned safeValuesReturned) { SharedPreferencesManager.getInstance().writeInt( ChromePreferenceKeys.FLAGS_CRASH_STREAK_BEFORE_CACHE, 0); - writeSafeValues(safeValuesReturned); - RecordHistogram.recordEnumeratedHistogram( - "Variations.SafeModeCachedFlags.Cached", mBehavior.get(), Behavior.NUM_ENTRIES); + + new AsyncTask<Void>() { + @Override + protected Void doInBackground() { + try { + writeSafeValues(safeValuesReturned); + } catch (Exception e) { + Log.e(TAG, "Exception writing safe values.", e); + cancel(true); + } + return null; + } + + @Override + protected void onPostExecute(Void unused) { + RecordHistogram.recordEnumeratedHistogram("Variations.SafeModeCachedFlags.Cached", + mBehavior.get(), Behavior.NUM_ENTRIES); + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } private void engageSafeModeInNative() {
diff --git a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensIntentParams.java b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensIntentParams.java index 9fc22b12..46d3813 100644 --- a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensIntentParams.java +++ b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensIntentParams.java
@@ -40,8 +40,6 @@ public Builder() {} - // TODO(b/180967190): remove the with* methods for the required params once - // downstream references are updated. // lensEntryPoint and isIncognito are required params when creating the // LensIntentParams. public Builder(@LensEntryPoint int lensEntryPoint, boolean isIncognito) { @@ -51,16 +49,6 @@ } /** - * Sets the Lens entry point. - * - * @param lensEntryPoint The entry point to set as a parameter - */ - public Builder withLensEntryPoint(@LensEntryPoint int lensEntryPoint) { - this.mLensEntryPoint = lensEntryPoint; - return this; - } - - /** * Sets the image URI. * * @param imageUri The image URI to set as a parameter @@ -101,16 +89,6 @@ } /** - * Sets whether the client is incognito. - * - * @param isIncognito Whether the client is incognito as a boolean parameter - */ - public Builder withIsIncognito(boolean isIncognito) { - this.mIsIncognito = isIncognito; - return this; - } - - /** * Sets whether the client requires account confirmation. * * @param requiresConfirmation Whether the client requires account confirmation as a boolean
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.cc b/chrome/browser/media/webrtc/display_media_access_handler.cc index 6625771d..2c971c7b 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler.cc +++ b/chrome/browser/media/webrtc/display_media_access_handler.cc
@@ -14,7 +14,6 @@ #include "base/containers/cxx20_erase.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "chrome/browser/bad_message.h" #include "chrome/browser/media/webrtc/desktop_capture_devices_util.h" #include "chrome/browser/media/webrtc/desktop_media_picker_factory_impl.h" @@ -36,9 +35,9 @@ #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h" +#endif // defined(OS_CHROMEOS) #if defined(OS_MAC) #include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h" @@ -438,16 +437,16 @@ } #endif // defined(OS_MAC) -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_CHROMEOS) // Check Data Leak Prevention restrictions on Chrome. - policy::DlpContentManagerAsh::Get()->CheckScreenShareRestriction( + policy::DlpContentManager::Get()->CheckScreenShareRestriction( media_id, GetApplicationTitle(web_contents), base::BindOnce(&DisplayMediaAccessHandler::OnDlpRestrictionChecked, base::Unretained(this), web_contents, media_id)); -#else // BUILDFLAG(IS_CHROMEOS_ASH) +#else // defined(OS_CHROMEOS) FinalizeResult(web_contents, media_id, blink::mojom::MediaStreamRequestResult::OK); -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) +#endif // !defined(OS_CHROMEOS) } void DisplayMediaAccessHandler::WebContentsDestroyed( @@ -457,7 +456,7 @@ pending_requests_.erase(web_contents); } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_CHROMEOS) void DisplayMediaAccessHandler::OnDlpRestrictionChecked( content::WebContents* web_contents, const content::DesktopMediaID& media_id, @@ -468,7 +467,7 @@ : blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED; FinalizeResult(web_contents, media_id, result); } -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // defined(OS_CHROMEOS) void DisplayMediaAccessHandler::DeletePendingAccessRequest( int render_process_id,
diff --git a/chrome/browser/media/webrtc/display_media_access_handler.h b/chrome/browser/media/webrtc/display_media_access_handler.h index 97e6e4b1..99f7c75 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler.h +++ b/chrome/browser/media/webrtc/display_media_access_handler.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/containers/flat_map.h" -#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/capture_policy_utils.h" @@ -95,12 +94,12 @@ void OnDisplaySurfaceSelected(content::WebContents* web_contents, content::DesktopMediaID media_id); -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_CHROMEOS) // Called back after checking Data Leak Prevention (DLP) restrictions. void OnDlpRestrictionChecked(content::WebContents* web_contents, const content::DesktopMediaID& media_id, bool is_dlp_allowed); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif // defined(OS_CHROMEOS) void DeletePendingAccessRequest(int render_process_id, int render_frame_id,
diff --git a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc index 6c7962a..277ea6f 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc
@@ -13,7 +13,6 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.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/pref_names.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" @@ -30,8 +29,8 @@ #include "base/mac/mac_util.h" #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/ash/policy/dlp/mock_dlp_content_manager_ash.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/policy/dlp/mock_dlp_content_manager.h" #endif class DisplayMediaAccessHandlerTest : public ChromeRenderViewHostTestHarness { @@ -252,14 +251,14 @@ EXPECT_EQ(0u, devices.size()); } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_CHROMEOS) TEST_F(DisplayMediaAccessHandlerTest, DlpRestricted) { const content::DesktopMediaID media_id(content::DesktopMediaID::TYPE_SCREEN, content::DesktopMediaID::kFakeId); // 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_observer( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .WillOnce([](const content::DesktopMediaID& media_id, @@ -506,15 +505,15 @@ /*expected_number_of_devices=*/2u); } -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_CHROMEOS) TEST_F(DisplayMediaAccessHandlerTest, ChangeSourceDlpRestricted) { const content::DesktopMediaID media_id( content::DesktopMediaID::TYPE_WEB_CONTENTS, content::DesktopMediaID::kNullId, GetWebContentsMediaCaptureId()); // 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_observer( &mock_dlp_content_manager); EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction) .WillOnce([](const content::DesktopMediaID& media_id,
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc index d53fb10..99da00a 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -539,7 +539,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::unique_ptr<StoreUpdateData> prediction_model_update_data = StoreUpdateData::CreatePredictionModelStoreUpdateData( - clock_->Now() + features::StoredModelsInactiveDuration()); + clock_->Now() + features::StoredModelsValidDuration()); bool has_models_to_update = false; std::string debug_msg; for (const auto& model : prediction_models) { @@ -621,7 +621,7 @@ // Store the received model in the store. std::unique_ptr<StoreUpdateData> prediction_model_update_data = StoreUpdateData::CreatePredictionModelStoreUpdateData( - clock_->Now() + features::StoredModelsInactiveDuration()); + clock_->Now() + features::StoredModelsValidDuration()); prediction_model_update_data->CopyPredictionModelIntoUpdateData(model); model_and_features_store_->UpdatePredictionModels( std::move(prediction_model_update_data),
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc index 43e1f8ed..22e37f3 100644 --- a/chrome/browser/prefs/chrome_pref_service_factory.cc +++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -48,6 +48,7 @@ #include "components/prefs/pref_service.h" #include "components/prefs/pref_store.h" #include "components/prefs/pref_value_store.h" +#include "components/prefs/standalone_browser_pref_store.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/search_engines/default_search_manager.h" #include "components/search_engines/search_engines_pref_names.h" @@ -313,6 +314,12 @@ } #endif +#if BUILDFLAG(IS_CHROMEOS_ASH) + scoped_refptr<PrefStore> standalone_browser_prefs = + base::MakeRefCounted<StandaloneBrowserPrefStore>(); + factory->set_standalone_browser_prefs(standalone_browser_prefs); +#endif + factory->set_async(async); factory->set_extension_prefs(std::move(extension_prefs)); factory->set_command_line_prefs(
diff --git a/chrome/browser/resources/download_shelf/app.ts b/chrome/browser/resources/download_shelf/app.ts index 1680034..c370d49 100644 --- a/chrome/browser/resources/download_shelf/app.ts +++ b/chrome/browser/resources/download_shelf/app.ts
@@ -24,25 +24,22 @@ constructor() { super(); - /** @private {!DownloadShelfApiProxy} */ this.apiProxy_ = DownloadShelfApiProxyImpl.getInstance(); - const showAllButton = this.$('#show-all-button') as HTMLElement; + const showAllButton = this.$<HTMLElement>('#show-all-button')!; showAllButton.innerText = loadTimeData.getString('showAll'); showAllButton.addEventListener('click', () => this.onShowAll_()); - const closeButton = this.$('#close-button'); + const closeButton = this.$('#close-button')!; closeButton.setAttribute('aria-label', loadTimeData.getString('close')); closeButton.addEventListener('click', () => this.onClose_()); } - /** @private */ - onShowAll_() { + private onShowAll_() { this.apiProxy_.doShowAll(); } - /** @private */ - onClose_() { + private onClose_() { this.apiProxy_.doClose(); } }
diff --git a/chrome/browser/resources/download_shelf/download_item.ts b/chrome/browser/resources/download_shelf/download_item.ts index d19f678..30037957 100644 --- a/chrome/browser/resources/download_shelf/download_item.ts +++ b/chrome/browser/resources/download_shelf/download_item.ts
@@ -44,20 +44,20 @@ this.opened = false; this.apiProxy_ = DownloadShelfApiProxyImpl.getInstance(); - this.$('#shadow-mask') - .addEventListener('click', () => this.onOpenButtonClick_()); - this.$('#dropdown-button') - .addEventListener('click', e => this.onDropdownButtonClick_(e)); + this.$('#shadow-mask')!.addEventListener( + 'click', () => this.onOpenButtonClick_()); + this.$('#dropdown-button')!.addEventListener( + 'click', e => this.onDropdownButtonClick_(e)); const discardButton = this.$('#discard-button') as HTMLElement; discardButton.innerText = loadTimeData.getString('discardButtonText'); discardButton.addEventListener('click', () => this.onDiscardButtonClick_()); - this.$('#keep-button') - .addEventListener('click', () => this.onKeepButtonClick_()); + this.$('#keep-button')!.addEventListener( + 'click', () => this.onKeepButtonClick_()); this.addEventListener('contextmenu', e => this.onContextMenu_(e)); - this.$('.progress-indicator').addEventListener('animationend', () => { - this.$('.progress-indicator') - .classList.remove('download-complete-animation'); + this.$('.progress-indicator')!.addEventListener('animationend', () => { + this.$('.progress-indicator')!.classList.remove( + 'download-complete-animation'); }); } @@ -132,8 +132,8 @@ this.progress = 1; // Only start animation if it's called from OnDownloadUpdated. if (this.downloadUpdated_) { - this.$('.progress-indicator') - .classList.add('download-complete-animation'); + this.$('.progress-indicator')!.classList.add( + 'download-complete-animation'); } break; case DownloadState.kInterrupted:
diff --git a/chrome/browser/resources/download_shelf/download_list.ts b/chrome/browser/resources/download_shelf/download_list.ts index 740ceea..16266ac 100644 --- a/chrome/browser/resources/download_shelf/download_list.ts +++ b/chrome/browser/resources/download_shelf/download_list.ts
@@ -31,7 +31,7 @@ super(); this.apiProxy_ = DownloadShelfApiProxyImpl.getInstance(); - this.listElement_ = this.$('#download-list') as HTMLElement; + this.listElement_ = this.$<HTMLElement>('#download-list')!; this.resizeObserver_ = new ResizeObserver(() => this.updateElements_()); this.resizeObserver_.observe(this.listElement_); @@ -123,7 +123,7 @@ private clear_() { while (this.listenerIds_.length) { this.apiProxy_.getCallbackRouter().removeListener( - this.listenerIds_.shift()); + this.listenerIds_.shift()!); } while (this.listElement_.firstChild) {
diff --git a/chrome/browser/resources/download_shelf/tsconfig_base.json b/chrome/browser/resources/download_shelf/tsconfig_base.json index 895f374..3e71f763 100644 --- a/chrome/browser/resources/download_shelf/tsconfig_base.json +++ b/chrome/browser/resources/download_shelf/tsconfig_base.json
@@ -4,7 +4,6 @@ "allowJs": true, "noUncheckedIndexedAccess": false, "noUnusedLocals": false, - "strictNullChecks": false, "strictPropertyInitialization": false } }
diff --git a/chrome/browser/resources/segmentation_internals/segmentation_internals.html b/chrome/browser/resources/segmentation_internals/segmentation_internals.html index 3a89402..a52ebb8 100644 --- a/chrome/browser/resources/segmentation_internals/segmentation_internals.html +++ b/chrome/browser/resources/segmentation_internals/segmentation_internals.html
@@ -1,6 +1,12 @@ <!doctype html> <html lang="en" dir="ltr"> <head> + <style> + .segment { + border: 1px outset black; + margin: 2px 2px 2px 2px; + } + </style> <meta charset="utf-8"> <title>Segmentation Internals</title> <meta name="viewport" content="width=device-width"> @@ -12,19 +18,9 @@ <div> Initialized: <span id="initialized">false</span>, Service status: <span id="service-status">0</span> </div> - <h4>Get segment</h4> - <div> - <Label for="segment-key">Segment key:</Label> - <input type="text" id="segment-key"> - <button id="get-segment">Get segment result</button> + <h4>Segment information</h4> + <div id="segment-container"> </div> - <h4>Segment result</h4> - <div> - Is ready: <span id="is-ready"></span> - </div> - <div> - Optimization target: <span id="optimization-target"></span> - </div> <script type="module" src="segmentation_internals.js"></script> </body> </html>
diff --git a/chrome/browser/resources/segmentation_internals/segmentation_internals.ts b/chrome/browser/resources/segmentation_internals/segmentation_internals.ts index f88c479..1fd81a71 100644 --- a/chrome/browser/resources/segmentation_internals/segmentation_internals.ts +++ b/chrome/browser/resources/segmentation_internals/segmentation_internals.ts
@@ -4,20 +4,31 @@ import {$} from 'chrome://resources/js/util.m.js'; +import {SegmentInfo} from './segmentation_internals.mojom-webui.js'; import {SegmentationInternalsBrowserProxy} from './segmentation_internals_browser_proxy.js'; function getProxy(): SegmentationInternalsBrowserProxy { return SegmentationInternalsBrowserProxy.getInstance(); } -function initialize() { - $('get-segment').onclick = async function() { - const {result} = await getProxy().getSegment( - ($('segment-key') as HTMLInputElement).value); - $('is-ready').textContent = String(result.isReady); - $('optimization-target').textContent = String(result.optimizationTarget); - }; +function addChildDivToParent(parent: HTMLElement, info: SegmentInfo) { + const div = document.createElement('div'); + div.className = 'segment'; + div.textContent = String(info.optimizationTarget); + div.setAttribute('simple', ''); + div.addEventListener('click', () => { + if (div.hasAttribute('simple')) { + div.textContent = String(info.segmentData); + div.removeAttribute('simple'); + } else { + div.textContent = String(info.optimizationTarget); + div.setAttribute('simple', ''); + } + }); + parent.appendChild(div); +} +function initialize() { getProxy().getCallbackRouter().onServiceStatusChanged.addListener( (initialized: boolean, status: number) => { $('initialized').textContent = String(initialized); @@ -25,8 +36,16 @@ }); getProxy().getCallbackRouter().onSegmentInfoAvailable.addListener( - () => { - // TODO(qinmin): display the segment info on internal page. + (segmentInfos: Array<SegmentInfo>) => { + const parent = $('segment-container'); + // Remove all current children. + while (parent.firstChild) { + parent.removeChild(parent.firstChild); + } + // Append new children. + for (let i = 0; i < segmentInfos.length; ++i) { + addChildDivToParent(parent, segmentInfos[i]!); + } }); getProxy().getServiceStatus();
diff --git a/chrome/browser/resources/segmentation_internals/segmentation_internals_browser_proxy.ts b/chrome/browser/resources/segmentation_internals/segmentation_internals_browser_proxy.ts index d9b5e018..88e5f30 100644 --- a/chrome/browser/resources/segmentation_internals/segmentation_internals_browser_proxy.ts +++ b/chrome/browser/resources/segmentation_internals/segmentation_internals_browser_proxy.ts
@@ -17,10 +17,6 @@ this.handler.$.bindNewPipeAndPassReceiver()); } - getSegment(key: string) { - return this.handler.getSegment(key); - } - getServiceStatus() { return this.handler.getServiceStatus(); }
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index bb43b3b9..96623b07 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -60,6 +60,11 @@ "chrome://resources/cr_components/chromeos/bluetooth/cros_bluetooth_config.js", "chrome://resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.m.js", "chrome://resources/cr_components/chromeos/network/mojo_interface_provider.m.js", + "chrome://resources/cr_components/app_management/app_management.mojom-lite.js", + "chrome://resources/cr_components/app_management/file_path.mojom-lite.js", + "chrome://resources/cr_components/app_management/image.mojom-lite.js", + "chrome://resources/cr_components/app_management/safe_base_name.mojom-lite.js", + "chrome://resources/cr_components/app_management/types.mojom-lite.js", "chrome://resources/js/cr.m.js", "chrome://resources/chromeos/colors/cros_styles.css", "chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js", @@ -104,11 +109,11 @@ # Mojo files generated by non-OS-settings targets, not bundled. preprocess_if_expr("preprocess_external_mojo") { deps = [ - "//chrome/browser/ui/webui/app_management:mojo_bindings_js", "//chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom:mojom_js", "//components/services/app_service/public/mojom:mojom_js", "//mojo/public/mojom/base", "//ui/gfx/image/mojom:mojom_js", + "//ui/webui/resources/cr_components/app_management:mojo_bindings_js", ] in_folder = "$root_gen_dir" @@ -121,7 +126,7 @@ "mojo/public/mojom/base/file_path.mojom-lite.js", "mojo/public/mojom/base/safe_base_name.mojom-lite.js", "ui/gfx/image/mojom/image.mojom-lite.js", - "chrome/browser/ui/webui/app_management/app_management.mojom-lite.js", + "ui/webui/resources/cr_components/app_management/app_management.mojom-lite.js", "chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/app_notification_handler.mojom-lite.js", "components/services/app_service/public/mojom/types.mojom-lite.js", ] @@ -188,7 +193,7 @@ "mojo/public/mojom/base/file_path.mojom-lite.js|app-management/file_path.mojom-lite.js", "mojo/public/mojom/base/safe_base_name.mojom-lite.js|app-management/safe_base_name.mojom-lite.js", "ui/gfx/image/mojom/image.mojom-lite.js|app-management/image.mojom-lite.js", - "chrome/browser/ui/webui/app_management/app_management.mojom-lite.js|app-management/app_management.mojom-lite.js", + "ui/webui/resources/cr_components/app_management/app_management.mojom-lite.js|app-management/app_management.mojom-lite.js", "chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/app_notification_handler.mojom-lite.js|os_apps_page/app_notification_handler.mojom-lite.js", "components/services/app_service/public/mojom/types.mojom-lite.js|app-management/types.mojom-lite.js", "../../nearby_share/shared/nearby_share_progress_bar_dark.json|nearby_share_progress_bar_dark.json", @@ -256,17 +261,13 @@ "chromeos/os_apps_page/app_management_page/actions.js", "chromeos/os_apps_page/app_management_page/api_listener.js", "chromeos/os_apps_page/app_management_page/browser_proxy.js", - "chromeos/os_apps_page/app_management_page/constants.js", "chromeos/os_apps_page/app_management_page/fake_page_handler.js", "chromeos/os_apps_page/app_management_page/reducers.js", "chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_browser_proxy.js", "chromeos/os_apps_page/app_management_page/store.js", "chromeos/os_apps_page/app_management_page/store_client.js", - "chromeos/os_apps_page/app_management_page/types.js", "chromeos/os_apps_page/app_management_page/util.js", "chromeos/os_apps_page/app_notifications_page/mojo_interface_provider.js", - "chromeos/os_apps_page/permission_constants.js", - "chromeos/os_apps_page/permission_util.js", "chromeos/os_languages_page/input_method_settings.js", "chromeos/os_languages_page/languages_browser_proxy.js", "chromeos/os_languages_page/languages.js", @@ -492,17 +493,13 @@ "chromeos/os_apps_page/app_management_page/icons.js", "chromeos/os_apps_page/app_management_page/main_view.js", "chromeos/os_apps_page/app_management_page/more_permissions_item.js", - "chromeos/os_apps_page/app_management_page/permission_item.js", "chromeos/os_apps_page/app_management_page/pin_to_shelf_item.js", "chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js", "chromeos/os_apps_page/app_management_page/pwa_detail_view.js", "chromeos/os_apps_page/app_management_page/resize_lock_item.js", - "chromeos/os_apps_page/app_management_page/shared_style.js", - "chromeos/os_apps_page/app_management_page/shared_vars.js", "chromeos/os_apps_page/app_management_page/supported_links_overlapping_apps_dialog.js", "chromeos/os_apps_page/app_management_page/supported_links_dialog.js", "chromeos/os_apps_page/app_management_page/supported_links_item.js", - "chromeos/os_apps_page/app_management_page/toggle_row.js", "chromeos/os_apps_page/app_management_page/uninstall_button.js", "chromeos/os_apps_page/os_apps_page.js", "chromeos/os_files_page/os_files_page.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn index aeb1ba9..5286361 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn
@@ -13,8 +13,6 @@ ":android_apps_browser_proxy", ":android_apps_subpage", ":os_apps_page", - ":permission_constants", - ":permission_util", ] } @@ -45,10 +43,10 @@ "..:os_route.m", "..:prefs_behavior", "../../:router", - "./app_management_page:constants", "./app_management_page:store_client", "./app_notifications_page:mojo_interface_provider", "//chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/cr_components/app_management:constants", "//ui/webui/resources/cr_components/chromeos/localized_link:localized_link", "//ui/webui/resources/cr_components/chromeos/localized_link:localized_link", "//ui/webui/resources/js:cr.m", @@ -60,17 +58,6 @@ ] } -js_library("permission_util") { - deps = [ - ":permission_constants", - "//ui/webui/resources/js:assert.m", - ] -} - -js_library("permission_constants") { - deps = [ "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile" ] -} - html_to_js("web_components") { js_files = [ "android_apps_subpage.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn index 56065b9..a79af07 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
@@ -18,26 +18,20 @@ ":arc_detail_view", ":browser_proxy", ":chrome_app_detail_view", - ":constants", ":dom_switch", ":fake_page_handler", ":icons", ":main_view", ":more_permissions_item", - ":permission_item", ":pin_to_shelf_item", ":pwa_detail_view", ":reducers", ":resize_lock_item", - ":shared_style", - ":shared_vars", ":store", ":store_client", ":supported_links_dialog", ":supported_links_item", ":supported_links_overlapping_apps_dialog", - ":toggle_row", - ":types", ":uninstall_button", ":util", ] @@ -45,7 +39,7 @@ js_library("actions") { deps = [ - "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile", + "//ui/webui/resources/cr_components/app_management:mojo_bindings_js_library_for_compile", "//ui/webui/resources/js:cr.m", ] } @@ -96,21 +90,21 @@ js_library("arc_detail_view") { deps = [ - ":constants", ":fake_page_handler", ":more_permissions_item", - ":permission_item", ":pin_to_shelf_item", ":store_client", ":supported_links_item", ":util", + "//ui/webui/resources/cr_components/app_management:constants", + "//ui/webui/resources/cr_components/app_management:permission_item", ] } js_library("browser_proxy") { deps = [ ":fake_page_handler", - "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile", + "//ui/webui/resources/cr_components/app_management:mojo_bindings_js_library_for_compile", ] } @@ -125,10 +119,6 @@ ] } -js_library("constants") { - deps = [ "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile" ] -} - js_library("dom_switch") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -139,7 +129,7 @@ js_library("fake_page_handler") { deps = [ - "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile", + "//ui/webui/resources/cr_components/app_management:mojo_bindings_js_library_for_compile", "//ui/webui/resources/js:promise_resolver.m", ] } @@ -152,12 +142,12 @@ deps = [ ":app_item", ":browser_proxy", - ":constants", ":store_client", ":util", "../..:os_route.m", "../..:route_observer_behavior", "../../..:router", + "//ui/webui/resources/cr_components/app_management:constants", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", ] @@ -167,46 +157,35 @@ deps = [ "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m" ] } -js_library("permission_item") { - deps = [ - ":browser_proxy", - ":fake_page_handler", - ":store_client", - ":toggle_row", - ":util", - "../..:metrics_recorder.m", - ] -} - js_library("pin_to_shelf_item") { deps = [ ":browser_proxy", - ":constants", - ":toggle_row", - ":types", ":util", "../..:metrics_recorder.m", + "//ui/webui/resources/cr_components/app_management:constants", + "//ui/webui/resources/cr_components/app_management:toggle_row", + "//ui/webui/resources/cr_components/app_management:types", "//ui/webui/resources/js:assert.m", ] } js_library("pwa_detail_view") { deps = [ - ":constants", ":fake_page_handler", ":more_permissions_item", - ":permission_item", ":pin_to_shelf_item", ":store_client", ":supported_links_item", ":util", + "//ui/webui/resources/cr_components/app_management:constants", + "//ui/webui/resources/cr_components/app_management:permission_item", ] } js_library("reducers") { deps = [ - ":types", ":util", + "//ui/webui/resources/cr_components/app_management:types", "//ui/webui/resources/js:cr.m", ] } @@ -214,22 +193,14 @@ js_library("resize_lock_item") { deps = [ ":browser_proxy", - ":constants", - ":toggle_row", - ":types", ":util", + "//ui/webui/resources/cr_components/app_management:constants", + "//ui/webui/resources/cr_components/app_management:toggle_row", + "//ui/webui/resources/cr_components/app_management:types", "//ui/webui/resources/js:assert.m", ] } -js_library("shared_style") { - deps = [] -} - -js_library("shared_vars") { - deps = [] -} - js_library("store") { deps = [ "//ui/webui/resources/js:cr.m", @@ -240,7 +211,7 @@ js_library("store_client") { deps = [ ":store", - ":types", + "//ui/webui/resources/cr_components/app_management:types", "//ui/webui/resources/js:cr.m", "//ui/webui/resources/js/cr/ui:store", "//ui/webui/resources/js/cr/ui:store_client", @@ -268,13 +239,12 @@ js_library("supported_links_item") { deps = [ ":browser_proxy", - ":constants", ":store_client", ":supported_links_dialog", ":supported_links_overlapping_apps_dialog", - ":types", ":util", "../..:metrics_recorder.m", + "//ui/webui/resources/cr_components/app_management:constants", "//ui/webui/resources/cr_components/chromeos/localized_link:localized_link", "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m", "//ui/webui/resources/cr_elements/cr_radio_group:cr_radio_group.m", @@ -282,20 +252,6 @@ ] } -js_library("toggle_row") { - deps = [ - ":browser_proxy", - ":store_client", - ":types", - "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle.m", - "//ui/webui/resources/cr_elements/policy:cr_policy_indicator.m", - ] -} - -js_library("types") { - deps = [ "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile" ] -} - js_library("uninstall_button") { deps = [ ":store_client", @@ -309,7 +265,6 @@ js_library("util") { deps = [ - "../:permission_constants", "../..:os_route.m", "../../..:router", ] @@ -326,16 +281,12 @@ "icons.js", "main_view.js", "more_permissions_item.js", - "permission_item.js", "pin_to_shelf_item.js", "pwa_detail_view.js", "resize_lock_item.js", - "shared_style.js", - "shared_vars.js", "supported_links_overlapping_apps_dialog.js", "supported_links_dialog.js", "supported_links_item.js", - "toggle_row.js", "uninstall_button.js", ] }
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/api_listener.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/api_listener.js index eac8266..8aed5e4 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/api_listener.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/api_listener.js
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {createInitialState} from '//resources/cr_components/app_management/util.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {Action} from 'chrome://resources/js/cr/ui/store.js'; import {addApp, changeApp, removeApp} from './actions.js'; import {BrowserProxy} from './browser_proxy.js'; import {AppManagementStore} from './store.js'; -import {createInitialState} from './util.js'; let initialized = false;
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js index 590e42f3..5919592 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_detail_view.js
@@ -10,6 +10,8 @@ import './borealis_page/borealis_detail_view.js'; import '../../../settings_shared_css.js'; +import {AppManagementUserAction, AppType} from '//resources/cr_components/app_management/constants.js'; +import {getSelectedApp, recordAppManagementUserAction} from '//resources/cr_components/app_management/util.js'; import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -18,9 +20,8 @@ import {RouteObserverBehavior} from '../../route_observer_behavior.js'; import {updateSelectedAppId} from './actions.js'; -import {AppManagementUserAction, AppType} from './constants.js'; import {AppManagementStoreClient} from './store_client.js'; -import {getSelectedApp, openMainPage, recordAppManagementUserAction} from './util.js'; +import {openMainPage} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.js index d903c74..bd5f8ec 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.js
@@ -1,17 +1,18 @@ // Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import './shared_style.js'; -import './shared_vars.js'; +import '//resources/cr_components/app_management/shared_style.js'; +import '//resources/cr_components/app_management/shared_vars.js'; import '//resources/cr_elements/cr_icons_css.m.js'; +import {AppManagementEntryPoint, AppManagementEntryPointsHistogramName, AppType} from '//resources/cr_components/app_management/constants.js'; +import {getAppIcon} from '//resources/cr_components/app_management/util.js'; import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {updateSelectedAppId} from './actions.js'; -import {AppManagementEntryPoint, AppManagementEntryPointsHistogramName, AppType} from './constants.js'; import {AppManagementStoreClient} from './store_client.js'; -import {getAppIcon, openAppDetailPage} from './util.js'; +import {openAppDetailPage} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.html index c03a73e..386b7de9 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.html
@@ -11,6 +11,7 @@ </app-management-pin-to-shelf-item> <app-management-permission-item id="notifications-card" class="permission-card-row separated-row" + app_="[[app_]]" permission-label="$i18n{appManagementNotificationsLabel}" permission-type="kNotifications"> </app-management-permission-item> @@ -23,26 +24,31 @@ <div id="subpermission-list" class="permission-list indented-permission-block"> <app-management-permission-item class="subpermission-row" + app_="[[app_]]" icon="app-management:location" permission-label="$i18n{appManagementLocationPermissionLabel}" permission-type="kLocation"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" + app_="[[app_]]" icon="app-management:camera" permission-label="$i18n{appManagementCameraPermissionLabel}" permission-type="kCamera"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" + app_="[[app_]]" icon="app-management:microphone" permission-label="$i18n{appManagementMicrophonePermissionLabel}" permission-type="kMicrophone"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" + app_="[[app_]]" icon="app-management:contacts" permission-label="$i18n{appManagementContactsPermissionLabel}" permission-type="kContacts"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" + app_="[[app_]]" icon="app-management:storage" permission-label="$i18n{appManagementStoragePermissionLabel}" permission-type="kStorage">
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.js index fb816bb2..00f14d9 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_detail_view.js
@@ -3,18 +3,18 @@ // found in the LICENSE file. import './icons.js'; import './more_permissions_item.js'; -import './permission_item.js'; import './pin_to_shelf_item.js'; import './resize_lock_item.js'; -import './shared_style.js'; import './supported_links_item.js'; +import '//resources/cr_components/app_management/shared_style.js'; +import '//resources/cr_components/app_management/permission_item.js'; import '//resources/cr_elements/icons.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getAppIcon, getPermission, getSelectedApp} from 'chrome://resources/cr_components/app_management/util.js'; import {BrowserProxy} from './browser_proxy.js'; import {AppManagementStoreClient} from './store_client.js'; -import {getAppIcon, getPermission, getSelectedApp} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/BUILD.gn index c9541da..1124ca5 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/BUILD.gn
@@ -14,12 +14,12 @@ js_library("borealis_detail_view") { deps = [ - "../:permission_item", "../:pin_to_shelf_item", "../:store_client", "../:util", "../../..:os_route.m", "../../../..:router", + "//ui/webui/resources/cr_components/app_management:permission_item", ] }
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html index 14534897..5011fcda 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html
@@ -45,6 +45,7 @@ </div> <app-management-permission-item id="microphone-permission" + app_="[[app_]]" class="subpermission-row" icon="app-management:microphone" permission-label="$i18n{appManagementMicrophonePermissionLabel}" permission-type="kMicrophone">
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.js index 416af212..5713205 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.js
@@ -7,13 +7,13 @@ import {Polymer, html} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import '../icons.js'; -import '../permission_item.js'; import '../pin_to_shelf_item.js'; -import '../shared_style.js'; +import '//resources/cr_components/app_management/shared_style.js'; +import '//resources/cr_components/app_management/permission_item.js'; import '//resources/cr_elements/icons.m.js'; import {AppManagementStoreClient} from '../store_client.js'; -import {getSelectedApp} from '../util.js'; +import {getSelectedApp} from 'chrome://resources/cr_components/app_management/util.js'; import {routes} from '../../../os_route.m.js'; import {Router} from '../../../../router.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js index 79d9b0d4..79b4d77 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/browser_proxy.js
@@ -12,12 +12,12 @@ import '/app-management/types.mojom-lite.js'; import '/app-management/app_management.mojom-lite.js'; +import {BrowserProxy as ComponentBrowserProxy} from '//resources/cr_components/app_management/browser_proxy.js'; +import {AppType, InstallReason} from '//resources/cr_components/app_management/constants.js'; +import {PermissionType, TriState} from '//resources/cr_components/app_management/permission_constants.js'; import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {PermissionType, TriState} from '../permission_constants.js'; - -import {AppType, InstallReason} from './constants.js'; import {FakePageHandler} from './fake_page_handler.js'; export class BrowserProxy {
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js index 74228c2..8024342a 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/chrome_app_detail_view.js
@@ -3,13 +3,13 @@ // found in the LICENSE file. import './more_permissions_item.js'; import './pin_to_shelf_item.js'; -import './shared_style.js'; +import '//resources/cr_components/app_management/shared_style.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getSelectedApp} from 'chrome://resources/cr_components/app_management/util.js'; import {BrowserProxy} from './browser_proxy.js'; import {AppManagementStoreClient} from './store_client.js'; -import {getSelectedApp} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js index ae98192..cfb5bbf 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {AppType, OptionalBool} from '//resources/cr_components/app_management/constants.js'; +import {PermissionType, PermissionValue, TriState} from '//resources/cr_components/app_management/permission_constants.js'; +import {createBoolPermission, createTriStatePermission, getTriStatePermissionValue} from '//resources/cr_components/app_management/permission_util.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; -import {PermissionType, PermissionValue, TriState} from '../permission_constants.js'; -import {createBoolPermission, createTriStatePermission, getTriStatePermissionValue} from '../permission_util.js'; - -import {AppType, OptionalBool} from './constants.js'; import {AppManagementStore} from './store.js'; /**
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js index 0a22ee1..4940c7ec 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js
@@ -3,13 +3,14 @@ // found in the LICENSE file. import './app_item.js'; -import './shared_style.js'; +import '//resources/cr_components/app_management/shared_style.js'; import '//resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; import '//resources/cr_elements/shared_style_css.m.js'; import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {focusWithoutInk} from '//resources/js/cr/ui/focus_without_ink.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {alphabeticalSort} from 'chrome://resources/cr_components/app_management/util.js'; import {Route, Router} from '../../../router.js'; import {routes} from '../../os_route.m.js'; @@ -17,7 +18,6 @@ import {AppManagementStore} from './store.js'; import {AppManagementStoreClient} from './store_client.js'; -import {alphabeticalSort} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/more_permissions_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/more_permissions_item.js index 9051707..991544b4 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/more_permissions_item.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/more_permissions_item.js
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import './shared_style.js'; +import '//resources/cr_components/app_management/shared_style.js'; import '//resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; +import {AppManagementUserAction} from '//resources/cr_components/app_management/constants.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {recordAppManagementUserAction} from 'chrome://resources/cr_components/app_management/util.js'; import {BrowserProxy} from './browser_proxy.js'; -import {AppManagementUserAction} from './constants.js'; -import {recordAppManagementUserAction} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pin_to_shelf_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pin_to_shelf_item.js index 1fcbb6af..5dea01fd 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pin_to_shelf_item.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pin_to_shelf_item.js
@@ -1,16 +1,16 @@ // 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 './toggle_row.js'; +import '//resources/cr_components/app_management/toggle_row.js'; +import {AppManagementUserAction, OptionalBool} from '//resources/cr_components/app_management/constants.js'; import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {convertOptionalBoolToBool, recordAppManagementUserAction, toggleOptionalBool} from 'chrome://resources/cr_components/app_management/util.js'; import {recordClick, recordNavigation, recordPageBlur, recordPageFocus, recordSearch, recordSettingChange, setUserActionRecorderForTesting} from '../../metrics_recorder.m.js'; import {BrowserProxy} from './browser_proxy.js'; -import {AppManagementUserAction, OptionalBool} from './constants.js'; -import {convertOptionalBoolToBool, recordAppManagementUserAction, toggleOptionalBool} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn index be8d913..4b517b6 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/BUILD.gn
@@ -22,12 +22,12 @@ js_library("plugin_vm_detail_view") { deps = [ ":plugin_vm_browser_proxy", - "../:constants", - "../:permission_item", "../:store_client", "../:util", "../../..:os_route.m", "../../../..:router", + "//ui/webui/resources/cr_components/app_management:constants", + "//ui/webui/resources/cr_components/app_management:permission_item", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:load_time_data.m", "//ui/webui/resources/js:web_ui_listener_behavior.m",
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html index fb39c37..4993af8 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
@@ -10,18 +10,21 @@ </div> <div class="permission-list indented-permission-block"> <app-management-permission-item id="camera-permission" + app_="[[app_]]" class="subpermission-row" icon="app-management:camera" sync-permission-manually permission-label="$i18n{appManagementCameraPermissionLabel}" permission-type="kCamera" on-change="onPermissionChanged_"> </app-management-permission-item> <app-management-permission-item id="microphone-permission" + app_="[[app_]]" class="subpermission-row" icon="app-management:microphone" sync-permission-manually permission-label="$i18n{appManagementMicrophonePermissionLabel}" permission-type="kMicrophone" on-change="onPermissionChanged_"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" icon="cr:print" + app_="[[app_]]" permission-label="$i18n{appManagementPrintingPermissionLabel}" permission-type="kPrinting"> </app-management-permission-item> @@ -64,4 +67,4 @@ </cr-button> </div> </cr-dialog> -</template> \ No newline at end of file +</template>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js index c5414cd3..3ea51cd3 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js
@@ -3,9 +3,9 @@ // found in the LICENSE file. import '../icons.js'; -import '../permission_item.js'; import '../pin_to_shelf_item.js'; -import '../shared_style.js'; +import '//resources/cr_components/app_management/permission_item.js'; +import '//resources/cr_components/app_management/shared_style.js'; import '//resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; import '//resources/cr_elements/icons.m.js'; @@ -13,11 +13,11 @@ import {loadTimeData} from '//resources/js/load_time_data.m.js'; import {WebUIListenerBehavior} from '//resources/js/web_ui_listener_behavior.m.js'; import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getSelectedApp} from 'chrome://resources/cr_components/app_management/util.js'; import {Router} from '../../../../router.js'; import {routes} from '../../../os_route.m.js'; import {AppManagementStoreClient} from '../store_client.js'; -import {getSelectedApp} from '../util.js'; import {PluginVmBrowserProxyImpl} from './plugin_vm_browser_proxy.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.html index 3fa5ee8..57bbb0d 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.html
@@ -8,6 +8,7 @@ </app-management-pin-to-shelf-item> <app-management-permission-item id="notifications-card" class="permission-card-row separated-row" + app_="[[app_]]" permission-label="$i18n{appManagementNotificationsLabel}" permission-type="kNotifications"> </app-management-permission-item> @@ -18,16 +19,19 @@ <div class="permission-list indented-permission-block"> <app-management-permission-item id="location" class="subpermission-row" icon="app-management:location" + app_="[[app_]]" permission-label="$i18n{appManagementLocationPermissionLabel}" permission-type="kLocation"> </app-management-permission-item> <app-management-permission-item id="camera" class="subpermission-row" icon="app-management:camera" + app_="[[app_]]" permission-label="$i18n{appManagementCameraPermissionLabel}" permission-type="kCamera"> </app-management-permission-item> <app-management-permission-item id="microphone" class="subpermission-row" icon="app-management:microphone" + app_="[[app_]]" permission-label="$i18n{appManagementMicrophonePermissionLabel}" permission-type="kMicrophone"> </app-management-permission-item>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.js index fb81312c..6ba3ce7 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_detail_view.js
@@ -3,17 +3,17 @@ // found in the LICENSE file. import './icons.js'; import './more_permissions_item.js'; -import './permission_item.js'; import './pin_to_shelf_item.js'; -import './shared_style.js'; import './supported_links_item.js'; +import '//resources/cr_components/app_management/shared_style.js'; +import '//resources/cr_components/app_management/permission_item.js'; import '//resources/cr_elements/icons.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getAppIcon, getSelectedApp} from 'chrome://resources/cr_components/app_management/util.js'; import {BrowserProxy} from './browser_proxy.js'; import {AppManagementStoreClient} from './store_client.js'; -import {getAppIcon, getSelectedApp} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/resize_lock_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/resize_lock_item.js index dd704f863..5cd6a88 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/resize_lock_item.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/resize_lock_item.js
@@ -1,16 +1,16 @@ // 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. -import './toggle_row.js'; +import '//resources/cr_components/app_management/toggle_row.js'; +import {AppManagementUserAction} from '//resources/cr_components/app_management/constants.js'; import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {recordAppManagementUserAction} from 'chrome://resources/cr_components/app_management/util.js'; import {recordClick, recordNavigation, recordPageBlur, recordPageFocus, recordSearch, recordSettingChange, setUserActionRecorderForTesting} from '../../metrics_recorder.m.js'; import {BrowserProxy} from './browser_proxy.js'; -import {AppManagementUserAction} from './constants.js'; -import {recordAppManagementUserAction} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js index 0a862359a..544102e7 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/store.js
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {createEmptyState} from 'chrome://resources/cr_components/app_management/util.js'; import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; import {Store} from 'chrome://resources/js/cr/ui/store.js'; import {reduceAction} from './reducers.js'; -import {createEmptyState} from './util.js'; /** * @fileoverview A singleton datastore for the App Management page. Page state
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js index 64e3d22e..bcd15c5 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js
@@ -8,18 +8,18 @@ import '//resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; import '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; +import {AppManagementUserAction, AppType} from '//resources/cr_components/app_management/constants.js'; import {assert} from '//resources/js/assert.m.js'; import {focusWithoutInk} from '//resources/js/cr/ui/focus_without_ink.m.js'; import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {recordAppManagementUserAction} from 'chrome://resources/cr_components/app_management/util.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {recordSettingChange} from '../../metrics_recorder.m.js'; import {BrowserProxy} from './browser_proxy.js'; -import {AppManagementUserAction, AppType} from './constants.js'; import {AppManagementStoreClient} from './store_client.js'; -import {recordAppManagementUserAction} from './util.js'; const PREFERRED_APP_PREF = 'preferred';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/uninstall_button.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/uninstall_button.js index e279bbf..9215794 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/uninstall_button.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/uninstall_button.js
@@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import './shared_style.js'; +import '//resources/cr_components/app_management/shared_style.js'; import '//resources/cr_elements/cr_button/cr_button.m.js'; import '//resources/cr_elements/policy/cr_tooltip_icon.m.js'; +import {AppManagementUserAction, InstallReason} from '//resources/cr_components/app_management/constants.js'; import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getSelectedApp, recordAppManagementUserAction} from 'chrome://resources/cr_components/app_management/util.js'; import {recordClick, recordNavigation, recordPageBlur, recordPageFocus, recordSearch, recordSettingChange, setUserActionRecorderForTesting} from '../../metrics_recorder.m.js'; import {BrowserProxy} from './browser_proxy.js'; -import {AppManagementUserAction, InstallReason} from './constants.js'; import {AppManagementStoreClient} from './store_client.js'; -import {getSelectedApp, recordAppManagementUserAction} from './util.js'; Polymer({ _template: html`{__html_template__}`,
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js index 428591b..d6f7c1d 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js
@@ -2,159 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertNotReached} from 'chrome://resources/js/assert.m.js'; -import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; - import {Route, Router} from '../../../router.js'; import {routes} from '../../os_route.m.js'; -import {PermissionType, PermissionValue, TriState} from '../permission_constants.js'; -import {getBoolPermissionValue, getTriStatePermissionValue, isPermissionEnabled} from '../permission_util.js'; - -import {AppManagementUserAction, AppType, OptionalBool, WindowMode} from './constants.js'; - - -/** - * @fileoverview Utility functions for the App Management page. - */ - -/** - * @return {!AppManagementPageState} - */ -export function createEmptyState() { - return { - apps: {}, - selectedAppId: null, - }; -} - -/** - * @param {!Array<App>} apps - * @return {!AppManagementPageState} - */ -export function createInitialState(apps) { - const initialState = createEmptyState(); - - for (const app of apps) { - initialState.apps[app.id] = app; - } - - return initialState; -} - -/** - * @param {App} app - * @return {string} - */ -export function getAppIcon(app) { - return `chrome://app-icon/${app.id}/64`; -} - -/** - * If the given value is not in the set, returns a new set with the value - * added, otherwise returns the old set. - * @template T - * @param {!Set<T>} set - * @param {T} value - * @return {!Set<T>} - */ -export function addIfNeeded(set, value) { - if (!set.has(value)) { - set = new Set(set); - set.add(value); - } - return set; -} - -/** - * If the given value is in the set, returns a new set without the value, - * otherwise returns the old set. - * @template T - * @param {!Set<T>} set - * @param {T} value - * @return {!Set<T>} - */ -export function removeIfNeeded(set, value) { - if (set.has(value)) { - set = new Set(set); - set.delete(value); - } - return set; -} - -/** - * @param {App} app - * @param {string} permissionType - * @return {boolean} - */ -export function getPermissionValueBool(app, permissionType) { - const permission = getPermission(app, permissionType); - assert(permission); - - return isPermissionEnabled(permission.value); -} - -/** - * Undefined is returned when the app does not request a permission. - * - * @param {App} app - * @param {string} permissionType - * @return {Permission|undefined} - */ -export function getPermission(app, permissionType) { - return app.permissions[PermissionType[permissionType]]; -} - -/** - * @param {AppManagementPageState} state - * @return {?App} - */ -export function getSelectedApp(state) { - const selectedAppId = state.selectedAppId; - return selectedAppId ? state.apps[selectedAppId] : null; -} - -/** - * A comparator function to sort strings alphabetically. - * - * @param {string} a - * @param {string} b - */ -export function alphabeticalSort(a, b) { - return a.localeCompare(b); -} - -/** - * Toggles an OptionalBool - * - * @param {OptionalBool} bool - * @return {OptionalBool} - */ -export function toggleOptionalBool(bool) { - switch (bool) { - case OptionalBool.kFalse: - return OptionalBool.kTrue; - case OptionalBool.kTrue: - return OptionalBool.kFalse; - default: - assertNotReached(); - } -} - -/** - * @param {OptionalBool} optionalBool - * @returns {boolean} - */ -export function convertOptionalBoolToBool(optionalBool) { - switch (optionalBool) { - case OptionalBool.kTrue: - return true; - case OptionalBool.kFalse: - return false; - default: - assertNotReached(); - } -} /** * Navigates to the App Detail page. @@ -173,40 +22,3 @@ export function openMainPage() { Router.getInstance().navigateTo(routes.APP_MANAGEMENT); } - -/** - * @param {AppType} appType - * @return {string} - * @private - */ -export function getUserActionHistogramNameForAppType_(appType) { - switch (appType) { - case AppType.kArc: - return 'AppManagement.AppDetailViews.ArcApp'; - case AppType.kChromeApp: - case AppType.kStandaloneBrowser: - case AppType.kStandaloneBrowserChromeApp: - // TODO(https://crbug.com/1225848): Figure out appropriate behavior for - // Lacros-hosted chrome-apps. - return 'AppManagement.AppDetailViews.ChromeApp'; - case AppType.kWeb: - return 'AppManagement.AppDetailViews.WebApp'; - case AppType.kPluginVm: - return 'AppManagement.AppDetailViews.PluginVmApp'; - case AppType.kBorealis: - return 'AppManagement.AppDetailViews.BorealisApp'; - default: - assertNotReached(); - } -} - -/** - * @param {AppType} appType - * @param {AppManagementUserAction} userAction - */ -export function recordAppManagementUserAction(appType, userAction) { - const histogram = getUserActionHistogramNameForAppType_(appType); - const enumLength = Object.keys(AppManagementUserAction).length; - chrome.metricsPrivate.recordEnumerationValue( - histogram, userAction, enumLength); -}
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/BUILD.gn index 3e27d53d..8c5df21 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/BUILD.gn
@@ -40,10 +40,10 @@ js_library("app_notification_row") { deps = [ - "../:permission_constants", - "../:permission_util", "../..:metrics_recorder.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_components/app_management:permission_constants", + "//ui/webui/resources/cr_components/app_management:permission_util", ] externs_list = [ "$externs_path/metrics_private.js" ] }
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notification_row.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notification_row.js index 9e65c43..10af3c6 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notification_row.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notification_row.js
@@ -12,10 +12,10 @@ import '/app-management/types.mojom-lite.js'; import '/os_apps_page/app_notification_handler.mojom-lite.js'; +import {createBoolPermissionValue, createTriStatePermissionValue, isBoolValue, isPermissionEnabled, isTriStateValue} from '//resources/cr_components/app_management/permission_util.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {recordSettingChange} from '../../metrics_recorder.m.js'; -import {createBoolPermissionValue, createTriStatePermissionValue, isBoolValue, isPermissionEnabled, isTriStateValue} from '../permission_util.js'; import {getAppNotificationProvider} from './mojo_interface_provider.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js index a65019b..caecdefa 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/os_apps_page.js
@@ -25,6 +25,8 @@ import './app_management_page/uninstall_button.js'; import '../../controls/settings_dropdown_menu.js'; +import {AppManagementEntryPoint, AppManagementEntryPointsHistogramName} from '//resources/cr_components/app_management/constants.js'; +import {getAppIcon, getSelectedApp} from '//resources/cr_components/app_management/util.js'; import {I18nBehavior} from '//resources/js/i18n_behavior.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; @@ -37,9 +39,7 @@ import {RouteObserverBehavior} from '../route_observer_behavior.js'; import {AndroidAppsBrowserProxyImpl, AndroidAppsInfo} from './android_apps_browser_proxy.js'; -import {AppManagementEntryPoint, AppManagementEntryPointsHistogramName} from './app_management_page/constants.js'; import {AppManagementStoreClient} from './app_management_page/store_client.js'; -import {getAppIcon, getSelectedApp} from './app_management_page/util.js'; import {getAppNotificationProvider} from './app_notifications_page/mojo_interface_provider.js'; /**
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js index 92743b9..ed985af 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.js +++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -56,16 +56,15 @@ import './os_apps_page/app_management_page/dom_switch.js'; import './os_apps_page/app_management_page/icons.js'; import './os_apps_page/app_management_page/main_view.js'; -import './os_apps_page/app_management_page/permission_item.js'; import './os_apps_page/app_management_page/pin_to_shelf_item.js'; import './os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js'; import './os_apps_page/app_management_page/pwa_detail_view.js'; -import './os_apps_page/app_management_page/shared_style.js'; -import './os_apps_page/app_management_page/shared_vars.js'; +import '//resources/cr_components/app_management/shared_style.js'; +import '//resources/cr_components/app_management/shared_vars.js'; import './os_apps_page/app_management_page/supported_links_overlapping_apps_dialog.js'; import './os_apps_page/app_management_page/supported_links_dialog.js'; import './os_apps_page/app_management_page/supported_links_item.js'; -import './os_apps_page/app_management_page/toggle_row.js'; +import '//resources/cr_components/app_management/toggle_row.js'; import './os_apps_page/app_management_page/uninstall_button.js'; import './os_apps_page/app_notifications_page/mojo_interface_provider.js'; import './os_apps_page/os_apps_page.js'; @@ -94,6 +93,11 @@ import './parental_controls_page/parental_controls_page.js'; import './settings_scheduler_slider/settings_scheduler_slider.js'; +export {BrowserProxy as AppManagementComponentBrowserProxy} from '//resources/cr_components/app_management/browser_proxy.js'; +export {PageType, WindowMode} from '//resources/cr_components/app_management/constants.js'; +export {PermissionType, TriState} from '//resources/cr_components/app_management/permission_constants.js'; +export {createBoolPermission, createTriStatePermission, getBoolPermissionValue, isBoolValue} from '//resources/cr_components/app_management/permission_util.js'; +export {convertOptionalBoolToBool, createEmptyState, createInitialState, getPermissionValueBool} from '//resources/cr_components/app_management/util.js'; export {LifetimeBrowserProxyImpl} from '../lifetime_browser_proxy.js'; export {ProfileInfoBrowserProxyImpl} from '../people_page/profile_info_browser_proxy.js'; export {PageStatus, StatusAction, SyncBrowserProxyImpl} from '../people_page/sync_browser_proxy.js'; @@ -129,16 +133,12 @@ export {AndroidAppsBrowserProxyImpl} from './os_apps_page/android_apps_browser_proxy.js'; export {addApp, changeApp, removeApp, updateSelectedAppId} from './os_apps_page/app_management_page/actions.js'; export {BrowserProxy} from './os_apps_page/app_management_page/browser_proxy.js'; -export {PageType, WindowMode} from './os_apps_page/app_management_page/constants.js'; export {FakePageHandler} from './os_apps_page/app_management_page/fake_page_handler.js'; export {PluginVmBrowserProxyImpl} from './os_apps_page/app_management_page/plugin_vm_page/plugin_vm_browser_proxy.js'; export {AppState, reduceAction} from './os_apps_page/app_management_page/reducers.js'; export {AppManagementStore} from './os_apps_page/app_management_page/store.js'; export {AppManagementStoreClientImpl} from './os_apps_page/app_management_page/store_client.js'; -export {convertOptionalBoolToBool, createEmptyState, createInitialState, getPermissionValueBool} from './os_apps_page/app_management_page/util.js'; export {setAppNotificationProviderForTesting} from './os_apps_page/app_notifications_page/mojo_interface_provider.js'; -export {PermissionType, TriState} from './os_apps_page/permission_constants.js'; -export {createBoolPermission, createTriStatePermission, getBoolPermissionValue, isBoolValue} from './os_apps_page/permission_util.js'; export {osPageVisibility} from './os_page_visibility.m.js'; export {AccountManagerBrowserProxy, AccountManagerBrowserProxyImpl} from './os_people_page/account_manager_browser_proxy.js'; export {FingerprintBrowserProxyImpl, FingerprintResultType} from './os_people_page/fingerprint_browser_proxy.m.js';
diff --git a/chrome/browser/resources/tab_strip/alert_indicators.ts b/chrome/browser/resources/tab_strip/alert_indicators.ts index 5df1ad3..e930c00 100644 --- a/chrome/browser/resources/tab_strip/alert_indicators.ts +++ b/chrome/browser/resources/tab_strip/alert_indicators.ts
@@ -20,7 +20,7 @@ constructor() { super(); - this.containerEl_ = this.$('#container') as HTMLElement; + this.containerEl_ = this.$<HTMLElement>('#container')!; const audioIndicator = new AlertIndicatorElement(); const recordingIndicator = new AlertIndicatorElement();
diff --git a/chrome/browser/resources/tab_strip/tab.ts b/chrome/browser/resources/tab_strip/tab.ts index 7c6f7bd..ffeb672 100644 --- a/chrome/browser/resources/tab_strip/tab.ts +++ b/chrome/browser/resources/tab_strip/tab.ts
@@ -61,29 +61,29 @@ super(); this.alertIndicatorsEl_ = - this.$('tabstrip-alert-indicators') as AlertIndicatorsElement; - // Normally, custom elements will get upgraded automatically once added to - // the DOM, but TabElement may need to update properties on + this.$<AlertIndicatorsElement>('tabstrip-alert-indicators')!; + // Normally, custom elements will get upgraded automatically once added + // to the DOM, but TabElement may need to update properties on // AlertIndicatorElement before this happens, so upgrade it manually. customElements.upgrade(this.alertIndicatorsEl_); - this.closeButtonEl_ = this.$('#close') as HTMLElement; + this.closeButtonEl_ = this.$<HTMLElement>('#close')!; this.closeButtonEl_.setAttribute( 'aria-label', loadTimeData.getString('closeTab')); - this.dragImageEl_ = this.$('#dragImage') as HTMLElement; + this.dragImageEl_ = this.$<HTMLElement>('#dragImage')!; - this.tabEl_ = this.$('#tab') as HTMLElement; + this.tabEl_ = this.$<HTMLElement>('#tab')!; - this.faviconEl_ = this.$('#favicon') as HTMLElement; + this.faviconEl_ = this.$<HTMLElement>('#favicon')!; - this.thumbnailContainer_ = this.$('#thumbnail') as HTMLElement; + this.thumbnailContainer_ = this.$<HTMLElement>('#thumbnail')!; - this.thumbnail_ = this.$('#thumbnailImg') as HTMLImageElement; + this.thumbnail_ = this.$<HTMLImageElement>('#thumbnailImg')!; this.tabsApi_ = TabsApiProxyImpl.getInstance(); - this.titleTextEl_ = this.$('#titleText') as HTMLElement; + this.titleTextEl_ = this.$<HTMLElement>('#titleText')!; /** * Flag indicating if this TabElement can accept dragover events. This
diff --git a/chrome/browser/resources/tab_strip/tab_group.ts b/chrome/browser/resources/tab_strip/tab_group.ts index bb0be405..c2a93140 100644 --- a/chrome/browser/resources/tab_strip/tab_group.ts +++ b/chrome/browser/resources/tab_strip/tab_group.ts
@@ -22,7 +22,7 @@ this.tabsApi_ = TabsApiProxyImpl.getInstance(); - this.chip_ = this.$('#chip') as HTMLElement; + this.chip_ = this.$<HTMLElement>('#chip')!; this.chip_.addEventListener('click', () => this.onClickChip_()); this.chip_.addEventListener( 'keydown', e => this.onKeydownChip_(/** @type {!KeyboardEvent} */ (e))); @@ -43,13 +43,13 @@ } getDragImage(): HTMLElement { - return this.$('#dragImage') as HTMLElement; + return this.$<HTMLElement>('#dragImage')!; } getDragImageCenter(): HTMLElement { // Since the drag handle is #dragHandle, the drag image should be // centered relatively to it. - return this.$('#dragHandle') as HTMLElement; + return this.$<HTMLElement>('#dragHandle')!; } private onClickChip_() { @@ -96,7 +96,7 @@ } updateVisuals(visualData: TabGroupVisualData) { - (this.$('#title') as HTMLElement).innerText = visualData.title; + this.$<HTMLElement>('#title')!.innerText = visualData.title; this.style.setProperty('--tabstrip-tab-group-color-rgb', visualData.color); this.style.setProperty( '--tabstrip-tab-group-text-color-rgb', visualData.textColor);
diff --git a/chrome/browser/resources/tab_strip/tab_list.ts b/chrome/browser/resources/tab_strip/tab_list.ts index 5dee171..8487eb9 100644 --- a/chrome/browser/resources/tab_strip/tab_list.ts +++ b/chrome/browser/resources/tab_strip/tab_list.ts
@@ -388,13 +388,12 @@ } private findTabElement_(tabId: number): TabElement|null { - return this.$(`tabstrip-tab[data-tab-id="${tabId}"]`) as TabElement | null; + return this.$<TabElement>(`tabstrip-tab[data-tab-id="${tabId}"]`); } private findTabGroupElement_(groupId: string): TabGroupElement|null { - return this.$(`tabstrip-tab-group[data-group-id="${groupId}"]`) as - TabGroupElement | - null; + return this.$<TabGroupElement>( + `tabstrip-tab-group[data-group-id="${groupId}"]`); } private fetchAndUpdateColors_() { @@ -403,8 +402,7 @@ } private fetchAndUpdateGroupData_() { - const tabGroupElements = - this.$all('tabstrip-tab-group') as NodeListOf<TabGroupElement>; + const tabGroupElements = this.$all<TabGroupElement>('tabstrip-tab-group'); this.tabsApi_.getGroupVisualData().then(({data}) => { tabGroupElements.forEach(tabGroupElement => { tabGroupElement.updateVisuals( @@ -420,7 +418,7 @@ } private getActiveTab_(): TabElement|null { - return this.$('tabstrip-tab[active]') as TabElement | null; + return this.$<TabElement>('tabstrip-tab[active]'); } getIndexOfTab(tabElement: TabElement): number { @@ -473,7 +471,7 @@ // document. When the tab strip first gains keyboard focus, no such event // exists yet, so the outline needs to be explicitly set to visible. this.focusOutlineManager_.visible = true; - (this.$('tabstrip-tab') as HTMLElement).focus(); + this.$<TabElement>('tabstrip-tab')!.focus(); } private onTabActivated_(tabId: number) { @@ -488,7 +486,7 @@ // have updated a Tab to have an active state. For example, if a // tab is created with an already active state, there may be 2 active // TabElements: the newly created tab and the previously active tab. - (this.$all('tabstrip-tab[active]') as NodeListOf<TabElement>) + this.$all<TabElement>('tabstrip-tab[active]') .forEach((previouslyActiveTab) => { if (previouslyActiveTab.tab.id !== tabId) { previouslyActiveTab.tab = /** @type {!Tab} */ ( @@ -705,7 +703,7 @@ index++; } - let elementAtIndex = this.$all('tabstrip-tab')[index]; + let elementAtIndex = this.$all('tabstrip-tab')[index]!; if (elementAtIndex && elementAtIndex.parentElement && isTabGroupElement(elementAtIndex.parentElement)) { elementAtIndex = elementAtIndex.parentElement; @@ -796,7 +794,8 @@ element, this.pinnedTabsElement_.childNodes[index]!); } else { let elementToInsert: TabElement|TabGroupElement = element; - let elementAtIndex = this.$all('tabstrip-tab').item(index); + let elementAtIndex: TabElement|TabGroupElement = + this.$all<TabElement>('tabstrip-tab').item(index); let parentElement = this.unpinnedTabsElement_; if (groupId) { @@ -824,7 +823,7 @@ // TabElement is being sandwiched between two TabElements in a group, it // can be assumed that the tab will eventually be inserted into the // group as well. - elementAtIndex = elementAtIndex.parentElement; + elementAtIndex = elementAtIndex.parentElement as TabGroupElement; } if (elementAtIndex && elementAtIndex.parentElement === parentElement) {
diff --git a/chrome/browser/resources/tools/rollup_plugin.js b/chrome/browser/resources/tools/rollup_plugin.js index 1717bb4..345d743 100644 --- a/chrome/browser/resources/tools/rollup_plugin.js +++ b/chrome/browser/resources/tools/rollup_plugin.js
@@ -62,6 +62,7 @@ } const fullUrl = new URL(pathFromUrl, urlPrefix); + console.log(fullUrl.href); if (excludes.includes(fullUrl.href)) { return fullUrl.href; }
diff --git a/chrome/browser/resources/vr/OWNERS b/chrome/browser/resources/vr/OWNERS index 3bdb0484..da26124 100644 --- a/chrome/browser/resources/vr/OWNERS +++ b/chrome/browser/resources/vr/OWNERS
@@ -1,3 +1,2 @@ -alcooper@chromium.org -bialpio@chromium.org +file://components/webxr/OWNERS tiborg@chromium.org
diff --git a/chrome/browser/segmentation_platform/segmentation_platform_profile_observer_unittest.cc b/chrome/browser/segmentation_platform/segmentation_platform_profile_observer_unittest.cc index 42529cf..7f5c039 100644 --- a/chrome/browser/segmentation_platform/segmentation_platform_profile_observer_unittest.cc +++ b/chrome/browser/segmentation_platform/segmentation_platform_profile_observer_unittest.cc
@@ -8,6 +8,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" +#include "components/segmentation_platform/public/segment_selection_result.h" #include "components/segmentation_platform/public/segmentation_platform_service.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" @@ -29,6 +30,9 @@ MOCK_METHOD(void, GetSelectedSegment, (const std::string&, SegmentSelectionCallback)); + MOCK_METHOD(SegmentSelectionResult, + GetCachedSegmentResult, + (const std::string&)); MOCK_METHOD(void, EnableMetrics, (bool)); MOCK_METHOD(void, GetServiceStatus, ()); };
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 47d5810..ea8b348 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -4099,15 +4099,7 @@ // --ignore-certificate-errors-spki-list. The connection should be established // without interstitial page showing. #if !BUILDFLAG(IS_CHROMEOS_ASH) // Chrome OS does not support the flag. -// TODO(crbug.com/1176880): Disabled on macOS because the WSS SpawnedTestServer -// does not support modern TLS on the macOS bots. -#if defined(OS_MAC) -#define MAYBE_TestWSSExpired DISABLED_TestWSSExpired -#else -#define MAYBE_TestWSSExpired TestWSSExpired -#endif -IN_PROC_BROWSER_TEST_F(SSLUITestIgnoreCertErrorsBySPKIWSS, - MAYBE_TestWSSExpired) { +IN_PROC_BROWSER_TEST_F(SSLUITestIgnoreCertErrorsBySPKIWSS, TestWSSExpired) { ASSERT_TRUE(wss_server_expired_.Start()); // Setup page title observer.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e621e553..1247896 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1705,7 +1705,6 @@ "//chrome/browser/ui/color:color_headers", "//chrome/browser/ui/commander:fuzzy_finder", "//chrome/browser/ui/webui/access_code_cast:mojo_bindings", - "//chrome/browser/ui/webui/app_management:mojo_bindings", "//chrome/browser/ui/webui/app_service_internals:mojo_bindings", "//chrome/browser/ui/webui/image_editor:mojo_bindings", "//chrome/browser/ui/webui/internals/user_education:mojo_bindings", @@ -1752,6 +1751,7 @@ "//ui/base/dragdrop:types", "//ui/base/dragdrop/mojom", "//ui/events", + "//ui/webui/resources/cr_components/app_management:mojo_bindings", "//ui/webui/resources/js/browser_command:mojo_bindings", ] public_deps += [ @@ -2967,7 +2967,6 @@ "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_predictor_proto", "//chrome/browser/ui/app_list/search/search_result_ranker:recurrence_ranker_proto", "//chrome/browser/ui/app_list/search/util:proto", - "//chrome/browser/ui/webui/app_management:mojo_bindings", "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings", "//chrome/browser/ui/webui/chromeos/audio:mojo_bindings", "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings", @@ -3083,6 +3082,7 @@ "//ui/events/ozone/layout:layout", "//ui/file_manager:file_manager", "//ui/ozone", + "//ui/webui/resources/cr_components/app_management:mojo_bindings", ] public_deps += [ "//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java index 854e45f..4b7a5558 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
@@ -20,6 +20,7 @@ import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; +import android.widget.EditText; import android.widget.LinearLayout; import org.junit.Before; @@ -74,6 +75,67 @@ private ShadowAccessibilityManager mShadowAccessibilityManager; private boolean mIsShown; + /** + * A flag to tweak test expectations to deal with an OS bug. + * + * <p>{@code EditableInputConnection}, which {@link AutocompleteEditText} internally rely on, + * has had <a href="https://issuetracker.google.com/issues/209958658">a bug</a> that it still + * returns {@code true} from {@link InputConnection#endBatchEdit()} when its internal batch edit + * count becomes {@code 0} as a result of invocation, which clearly conflicted with the spec. + * There are several tests in this file that are unfortunately affected by this bug. In order + * to abstract out such an OS issue from the actual test expectations, we will dynamically test + * if the bug still exists or not in the test execution environment or not, and set {@code true} + * to this flag if it is still there.</p> + * + * <p>Until a new version of Android OS with + * <a href="https://android-review.googlesource.com/c/platform/frameworks/base/+/1923058">the + * fix</a> and a corresponding version of Robolectric become available in Chromium, this flag is + * expected to be always {@code true}. Once they become available, you can either remove this + * flag with assuming it's always {@code false} or test two different OS behaviors at the same + * time by <a href="http://robolectric.org/configuring/">specifying multiple SDK versions</a> to + * the test runner</a>.</p> + * + * @see #testEditableInputConnectionEndBatchEditBug(Context) + * @see #assertLastBatchEdit(boolean) + */ + private boolean mHasEditableInputConnectionEndBatchEditBug; + + /** + * Test if {@code EditableInputConnection} has a bug that it still returns {@code true} from + * {@link InputConnection#endBatchEdit()} when its internal batch edit count becomes {@code 0} + * as a result of invocation. + * + * <p>See https://issuetracker.google.com/issues/209958658 for details.</p> + * + * @param context The {@link Context} to be used to initialize {@link EditText}. + * @return {@code true} if the bug still exists. {@code false} otherwise. + */ + private static boolean testEditableInputConnectionEndBatchEditBug(Context context) { + EditText editText = new EditText(context); + EditorInfo editorInfo = new EditorInfo(); + InputConnection editableInputConnection = editText.onCreateInputConnection(editorInfo); + editableInputConnection.beginBatchEdit(); + // If this returns true, yes, the bug is still there! + return editableInputConnection.endBatchEdit(); + } + + /** + * A convenient helper method to assert the return value of + * {@link InputConnection#endBatchEdit()} when its internal batch edit count becomes {@code 0}. + * + * @param result The return value of {@link InputConnection#endBatchEdit()}. + * + * @see #mHasEditableInputConnectionEndBatchEditBug + * @see #testEditableInputConnectionEndBatchEditBug(Context) + */ + private void assertLastBatchEdit(boolean result) { + if (mHasEditableInputConnectionEndBatchEditBug) { + assertTrue(result); + } else { + assertFalse(result); + } + } + // Limits the target of InOrder#verify. private static class Verifier { public void onAutocompleteTextStateChanged(boolean updateDisplay) { @@ -176,6 +238,9 @@ MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; + mHasEditableInputConnectionEndBatchEditBug = + testEditableInputConnectionEndBatchEditBug(mContext); + mVerifier = spy(new Verifier()); mAutocomplete = new TestAutocompleteEditText(mContext, null); mFocusPlaceHolder = new LinearLayout(mContext); @@ -388,7 +453,7 @@ assertVerifierCallCounts(0, 2); } mInOrder.verifyNoMoreInteractions(); - assertTrue(mInputConnection.endBatchEdit()); + assertLastBatchEdit(mInputConnection.endBatchEdit()); // Autocomplete text gets redrawn. assertTexts("hello ", "world"); @@ -533,7 +598,7 @@ } mInOrder.verifyNoMoreInteractions(); - assertTrue(mInputConnection.endBatchEdit()); + assertLastBatchEdit(mInputConnection.endBatchEdit()); if (isUsingSpannableModel()) { mInOrder.verify(mVerifier).onUpdateSelection(6, 6); @@ -905,7 +970,7 @@ mInOrder.verifyNoMoreInteractions(); assertVerifierCallCounts(0, 0); - assertTrue(mInputConnection.endBatchEdit()); + assertLastBatchEdit(mInputConnection.endBatchEdit()); mInOrder.verify(mVerifier).onUpdateSelection(4, 4); mInOrder.verify(mVerifier).onUpdateSelection(5, 5); verifyOnPopulateAccessibilityEvent(
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/res/layout/quick_action_search_widget_dino_layout.xml b/chrome/browser/ui/android/quickactionsearchwidget/java/res/layout/quick_action_search_widget_dino_layout.xml index f62165f5..27575c0 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/res/layout/quick_action_search_widget_dino_layout.xml +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/res/layout/quick_action_search_widget_dino_layout.xml
@@ -3,29 +3,49 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/dino_quick_action_button" - android:layout_width="@dimen/quick_action_search_widget_dino_size" - android:layout_height="@dimen/quick_action_search_widget_dino_size" - android:background="@drawable/quick_action_search_widget_dino_background" - android:orientation="vertical"> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/dino_quick_action_area" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:ignore="UselessParent"> - <ImageView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/quick_action_search_widget_dino_margin_start" - android:layout_marginTop="@dimen/quick_action_search_widget_dino_margin_top" - android:layout_marginBottom="@dimen/quick_action_search_widget_dino_margin_text" - android:importantForAccessibility="no" - android:src="@drawable/quick_action_search_widget_dino_content" /> + <!-- Note that the parent layout is not "useless". We use it to enforce a particular + aspect ratio of the Dino widget. There are very few layouts that are permitted to be + used with RemoteViews, ConstraintLayout and is sadly not one of them. + Please check the QuickActionSearchWidgetProviderDelegate to see how the sizes are + enforced for this widget. --> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/quick_action_search_widget_dino_margin_start" - android:maxLines="1" - android:textAppearance="@style/TextAppearance.TextLarge.Primary.Baseline" - android:textAlignment="viewStart" - android:text="@string/dino_widget_text" /> + <LinearLayout + android:id="@+id/dino_quick_action_button" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/quick_action_search_widget_dino_background" + android:paddingTop="@dimen/quick_action_search_widget_dino_padding_vertical" + android:paddingBottom="@dimen/quick_action_search_widget_dino_padding_vertical" + android:paddingStart="@dimen/quick_action_search_widget_dino_padding_start" + android:gravity="fill" + android:orientation="vertical"> -</LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:importantForAccessibility="no" + android:scaleType="fitCenter" + android:adjustViewBounds="true" + android:src="@drawable/quick_action_search_widget_dino_content" /> + + <TextView + android:id="@+id/dino_quick_action_text" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:maxLines="1" + android:textAppearance="@style/TextAppearance.TextLarge.Primary.Baseline" + android:textAlignment="viewStart" + android:gravity="bottom" + android:text="@string/dino_widget_text" /> + + </LinearLayout> +</FrameLayout>
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/res/values/dimens.xml b/chrome/browser/ui/android/quickactionsearchwidget/java/res/values/dimens.xml index dd9e6b9..c4522f0 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/res/values/dimens.xml +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/res/values/dimens.xml
@@ -73,10 +73,10 @@ <dimen name="quick_action_search_widget_xsmall_search_bar_text_size">11sp</dimen> <!-- Dino Widget Dimensions --> - <dimen name="quick_action_search_widget_dino_min_size">136dp</dimen> + <dimen name="quick_action_search_widget_dino_min_size">110dp</dimen> <dimen name="quick_action_search_widget_dino_size">136dp</dimen> + <dimen name="quick_action_search_widget_dino_text_size">13.5dp</dimen> <dimen name="quick_action_search_widget_dino_corner_radius">20dp</dimen> - <dimen name="quick_action_search_widget_dino_margin_start">12dp</dimen> - <dimen name="quick_action_search_widget_dino_margin_top">6dp</dimen> - <dimen name="quick_action_search_widget_dino_margin_text">10dp</dimen> + <dimen name="quick_action_search_widget_dino_padding_start">12dp</dimen> + <dimen name="quick_action_search_widget_dino_padding_vertical">18dp</dimen> </resources>
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java index bcd8d7b..e8120ce7 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java
@@ -9,6 +9,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.util.Size; import android.view.View; import android.widget.RemoteViews; @@ -66,9 +67,9 @@ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) static int getElementSizeInDP( Resources res, @DimenRes int mainDimenRes, @DimenRes int marginDimenRes) { - float density = res.getDisplayMetrics().density; - assert mainDimenRes != 0; + if (mainDimenRes == 0) return 0; + float density = res.getDisplayMetrics().density; float size = res.getDimension(mainDimenRes); if (marginDimenRes != 0) { size += 2 * res.getDimension(marginDimenRes); @@ -177,6 +178,8 @@ private final @NonNull WidgetVariant mSmallWidgetVariant; /** Widget variant describing the Extra Small widget. */ private final @NonNull WidgetVariant mExtraSmallWidgetVariant; + /** Widget variant describing the Dino widget. */ + private final @NonNull WidgetVariant mDinoWidgetVariant; /** * @param context Context that can be used to pre-compute values. Do not cache. @@ -213,6 +216,10 @@ R.dimen.quick_action_search_widget_xsmall_height, R.dimen.quick_action_search_widget_xsmall_button_width, R.dimen.quick_action_search_widget_xsmall_button_horizontal_margin); + mDinoWidgetVariant = + new WidgetVariant(context, R.layout.quick_action_search_widget_dino_layout, + R.dimen.quick_action_search_widget_dino_size, + R.dimen.quick_action_search_widget_dino_size, 0, 0); } /** @@ -253,15 +260,132 @@ } /** + * Given the width and height of the widget cell area (expressed in distance points) and the + * screen density, compute vertical and horizontal paddings that have to be applied to make + * the widget retain the square aspect ratio (1:1). + * The returned size is expressed in pixels. + * + * @param cellAreaWidthDp Width of the cell area, expressed in distance points. + * @param cellAreaHeightDp Height of the cell area, expressed in distance points. + * @param density Screen density. + * @return Size object, describing required horizontal and vertical padding, expressed in + * pixels. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + Size computeWidgetAreaPaddingForDinoWidgetPx( + int cellAreaWidthDp, int cellAreaHeightDp, float density) { + int edgeLengthDp = Math.min(cellAreaWidthDp, cellAreaHeightDp); + int width = (int) (((cellAreaWidthDp - edgeLengthDp) / 2.f) * density); + int height = (int) (((cellAreaHeightDp - edgeLengthDp) / 2.f) * density); + return new Size((int) width, (int) height); + } + + /** + * Given the width and height of the cell area (expressed in distance points) compute the scale + * factor (expressed as a float value) that needs to be applied to relevant dimensions to scale + * the widget proportionally. + * + * @param cellAreaWidthDp Width of the cell area, expressed in distance points. + * @param cellAreaHeightDp Height of the cell area, expressed in distance points. + * @param density Screen density. + * @return Scale factor that should be applied to relevant dimensions to resize the widget + * proportionately. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + float computeScaleFactorForDinoWidget(int cellAreaWidthDp, int cellAreaHeightDp) { + // Compute the paddings to better visually arrange the views inside the widget. + // First, compute the scale factor. The scale factor is based on the reference dimensions + // (ie. dimensions from the UX mocks) vs the on-screen area size (which almost certainly + // will be different than the reference). + // The scale factor reflects how much larger (or smaller) the cell area size is compared + // to the mocks, ie. scale == 1.2 means that edgeSize is 20% larger than the reference size. + final int edgeSize = Math.min(cellAreaWidthDp, cellAreaHeightDp); + return 1.f * edgeSize / mDinoWidgetVariant.widgetWidthDp; + } + + /** + * @param resources Current resources. + * @return Whether widget layout direction is RTL. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + boolean isLayoutDirectionRTL(@NonNull Resources resources) { + return resources.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + void resizeDinoWidgetToFillTargetCellArea( + @NonNull Resources resources, RemoteViews views, int areaWidthDp, int areaHeightDp) { + float density = resources.getDisplayMetrics().density; + + // Screen density is used to compute padding in each direction. + // The left/right and top/bottom dimensions are the same, since we want to center the view + // in the area where we have some non-zero padding. + Size paddings = computeWidgetAreaPaddingForDinoWidgetPx(areaWidthDp, areaHeightDp, density); + views.setViewPadding(R.id.dino_quick_action_area, paddings.getWidth(), paddings.getHeight(), + paddings.getWidth(), paddings.getHeight()); + + // Now use the scale factor to modify all the dimensions that count. + // We depend on the intrinsic view computations to infer a lot of these dimensions; the ones + // below have to be computed by us. + // + // The core dimensions that have to be scaled by us are the paddings around the core widget + // area (where the image is hosted), to make sure the content is properly adjusted. + final float scale = computeScaleFactorForDinoWidget(areaWidthDp, areaHeightDp); + final float contentPaddingVertical = + resources.getDimension(R.dimen.quick_action_search_widget_dino_padding_vertical) + * scale; + final float contentPaddingStart = + resources.getDimension(R.dimen.quick_action_search_widget_dino_padding_start) + * scale; + + // Note: there is no setViewRelativePadding method available for RemoteViews. This means + // we have to be smart about what edge means "start". + final float contentPaddingLeft = isLayoutDirectionRTL(resources) ? 0 : contentPaddingStart; + final float contentPaddingRight = isLayoutDirectionRTL(resources) ? contentPaddingStart : 0; + + views.setViewPadding(R.id.dino_quick_action_button, (int) contentPaddingLeft, + (int) contentPaddingVertical, (int) contentPaddingRight, + (int) contentPaddingVertical); + + // Scale text proportionately, ignoring the system font scaling. We have to apply this to + // avoid cases where the system font setting leads to either: + // - text truncation, + // - overlapping the dino image with text, or + // - making the text so small that it leaves a lot of empty space on the widget. + final float textSize = + resources.getDimension(R.dimen.quick_action_search_widget_dino_text_size) * scale + / resources.getDisplayMetrics().scaledDensity; + views.setFloat(R.id.dino_quick_action_text, "setTextSize", textSize); + } + + /** * Create {@link RemoteViews} for the Dino widget. * * @param context Current context. * @param prefs Structure describing current preferences and feature availability. + * @param portraitModeWidthDp Width of the widget area in portrait mode. + * @param portraitModeHeightDp Height of the widget area in portrait mode. + * @param landscapeModeWidthDp Width of the widget area in landscape mode. + * @param landscapeModeHeightDp Height of the widget area in landscape mode. * @return RemoteViews to be installed on the Dino widget. */ - public @NonNull RemoteViews createDinoWidgetRemoteViews( - @NonNull Context context, @NonNull SearchActivityPreferences prefs) { - return createWidgetRemoteViews(context, R.layout.quick_action_search_widget_dino_layout); + public @NonNull RemoteViews createDinoWidgetRemoteViews(@NonNull Context context, + @NonNull SearchActivityPreferences prefs, int portraitModeWidthDp, + int portraitModeHeightDp, int landscapeModeWidthDp, int landscapeModeHeightDp) { + RemoteViews landscapeViews = + createWidgetRemoteViews(context, R.layout.quick_action_search_widget_dino_layout); + RemoteViews portraitViews = + createWidgetRemoteViews(context, R.layout.quick_action_search_widget_dino_layout); + + // Dino widget is specific; we want to scale up a lot of dimensions based on the actual size + // of the widget area. This makes layout a lot more responsive but also a lot more + // complicated since we have to compute everything manually. + Resources res = context.getApplicationContext().getResources(); + resizeDinoWidgetToFillTargetCellArea( + res, landscapeViews, landscapeModeWidthDp, landscapeModeHeightDp); + resizeDinoWidgetToFillTargetCellArea( + res, portraitViews, portraitModeWidthDp, portraitModeHeightDp); + return new RemoteViews(landscapeViews, portraitViews); } /**
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java index 725eb13..185e6a8 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java
@@ -4,16 +4,23 @@ package org.chromium.chrome.browser.ui.quickactionsearchwidget; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import android.app.Activity; import android.appwidget.AppWidgetManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; import android.content.res.Resources; import android.net.Uri; import android.support.test.InstrumentationRegistry; +import android.util.Size; import android.view.View; import android.widget.FrameLayout; +import android.widget.RemoteViews; import androidx.annotation.LayoutRes; import androidx.test.filters.SmallTest; @@ -24,6 +31,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.chromium.base.IntentUtils; import org.chromium.base.test.BaseActivityTestRule; @@ -43,6 +52,8 @@ import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.embedder_support.util.UrlConstants; +import java.util.Locale; + /** * Tests for the QuickActionSearchWidgetProviderDelegate. */ @@ -62,9 +73,14 @@ private int mXSmallWidgetMinHeightDp; private int mSmallWidgetMinHeightDp; private int mMediumWidgetMinHeightDp; + private int mDinoWidgetEdgeSizeDp; + + @Mock + RemoteViews mMockRemoteViews; @Before public void setUp() { + MockitoAnnotations.initMocks(this); ChromeApplicationTestUtils.setUp(InstrumentationRegistry.getTargetContext()); mContext = InstrumentationRegistry.getInstrumentation() .getTargetContext() @@ -91,6 +107,8 @@ / density); mDefaultWidgetWidthDp = (int) (res.getDimension(R.dimen.quick_action_search_widget_width) / density); + mDinoWidgetEdgeSizeDp = + (int) (res.getDimension(R.dimen.quick_action_search_widget_dino_size) / density); setUpViews(); } @@ -174,7 +192,10 @@ mDefaultWidgetWidthDp, mMediumWidgetMinHeightDp) .apply(mContext, null); mDinoWidgetView = - mDelegate.createDinoWidgetRemoteViews(mContext, prefs).apply(mContext, null); + mDelegate + .createDinoWidgetRemoteViews(mContext, prefs, mDinoWidgetEdgeSizeDp, + mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp) + .apply(mContext, null); } /** @@ -458,4 +479,155 @@ Assert.assertFalse(settings.googleLensVisible); Assert.assertFalse(settings.dinoGameVisible); } + + @Test + @SmallTest + public void computeWidgetAreaPaddingForDinoWidget_noPadding() { + // Dino widget has a square shape. When offered a square cell area - no cropping should be + // performed. + Size s = mDelegate.computeWidgetAreaPaddingForDinoWidgetPx(100, 100, 1.f); + Assert.assertEquals(0, s.getWidth()); + Assert.assertEquals(0, s.getHeight()); + } + + @Test + @SmallTest + public void computeWidgetAreaPaddingForDinoWidget_horizontalPadding() { + // Dino widget has a square shape. + // When offered a wider area, we should crop the sides. + // Note that the input values are in DP, but result carries pixels. + Size s = mDelegate.computeWidgetAreaPaddingForDinoWidgetPx(100, 80, 2.f); + Assert.assertEquals(20, s.getWidth()); + Assert.assertEquals(0, s.getHeight()); + } + + @Test + @SmallTest + public void computeWidgetAreaPaddingForDinoWidget_verticalPadding() { + // Dino widget has a square shape. + // When offered a taller area, we should crop the top and bottom. + // Note that the input values are in DP, but result carries pixels. + Size s = mDelegate.computeWidgetAreaPaddingForDinoWidgetPx(100, 120, 3.f); + Assert.assertEquals(0, s.getWidth()); + Assert.assertEquals(30, s.getHeight()); + } + + @Test + @SmallTest + public void computeScaleFactorForDinoWidget() { + // The scale factor expresses how widget should grow or shrink to properly + // fill up the space. It is computed as a proportion: + // scale factor = target size / reference size + // a scale factor of 1.0 means the area will host the widget as it was designed + // without any scaling. + Resources r = mContext.getResources(); + Assert.assertEquals(1.f, + mDelegate.computeScaleFactorForDinoWidget( + mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp), + 0.001f); + Assert.assertEquals(1.f, + mDelegate.computeScaleFactorForDinoWidget( + mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp * 2), + 0.001f); + Assert.assertEquals(2.f, + mDelegate.computeScaleFactorForDinoWidget( + mDinoWidgetEdgeSizeDp * 3, mDinoWidgetEdgeSizeDp * 2), + 0.001f); + Assert.assertEquals(0.5f, + mDelegate.computeScaleFactorForDinoWidget( + mDinoWidgetEdgeSizeDp, mDinoWidgetEdgeSizeDp / 2), + 0.001f); + } + + @Test + @SmallTest + public void resizeDinoWidgetToFillTargetCellArea_centerInWideArea() { + final Resources r = mContext.getResources(); + final float density = r.getDisplayMetrics().density; + + // Try to place the dino in the area that is half the reference size. + // We should see the widget centered and resized accordingly. + final int areaWidthDp = mDinoWidgetEdgeSizeDp; + final int areaHeightDp = mDinoWidgetEdgeSizeDp / 2; + mDelegate.resizeDinoWidgetToFillTargetCellArea( + r, mMockRemoteViews, areaWidthDp, areaHeightDp); + + // The remaining area is half the size of the widget. + // We divide it further by two to apply the padding on each side. + int padSize = (int) (mDinoWidgetEdgeSizeDp * density / 2.f / 2.f); + verify(mMockRemoteViews) + .setViewPadding(R.id.dino_quick_action_area, padSize, 0, padSize, 0); + } + + @Test + @SmallTest + public void resizeDinoWidgetToFillTargetCellArea_centerInTallArea() { + final Resources r = mContext.getResources(); + final float density = r.getDisplayMetrics().density; + + // Try to place the dino in the area that is half the reference size. + // We should see the widget centered and resized accordingly. + final int areaWidthDp = mDinoWidgetEdgeSizeDp / 2; + final int areaHeightDp = mDinoWidgetEdgeSizeDp; + mDelegate.resizeDinoWidgetToFillTargetCellArea( + r, mMockRemoteViews, areaWidthDp, areaHeightDp); + + // The remaining area is half the size of the widget. + // We divide it further by two to apply the padding on each side. + int padSize = (int) (mDinoWidgetEdgeSizeDp * density / 2.f / 2.f); + verify(mMockRemoteViews) + .setViewPadding(R.id.dino_quick_action_area, 0, padSize, 0, padSize); + } + + @Test + @SmallTest + public void resizeDinoWidgetToFillTargetCellArea_repositionContent() { + final Resources r = mContext.getResources(); + final float density = r.getDisplayMetrics().density; + + // Again, apply half the size of what the widget was designed for. + final int areaWidthDp = mDinoWidgetEdgeSizeDp / 2; + final int areaHeightDp = mDinoWidgetEdgeSizeDp; + mDelegate.resizeDinoWidgetToFillTargetCellArea( + r, mMockRemoteViews, areaWidthDp, areaHeightDp); + + // Since widget is half the size, the button area paddings should be half the size too. + int imagePadLeft = + (int) (r.getDimension(R.dimen.quick_action_search_widget_dino_padding_start) / 2.f); + int imagePadVertical = + (int) (r.getDimension(R.dimen.quick_action_search_widget_dino_padding_vertical) + / 2.f); + + verify(mMockRemoteViews) + .setViewPadding(R.id.dino_quick_action_button, imagePadLeft, imagePadVertical, 0, + imagePadVertical); + } + + @Test + @SmallTest + public void resizeDinoWidgetToFillTargetCellArea_repositionContentRTL() { + final Configuration c = new Configuration(mContext.getResources().getConfiguration()); + c.setLayoutDirection(Locale.forLanguageTag("ar")); // arabic + + final Resources r = spy(mContext.getResources()); + when(r.getConfiguration()).thenReturn(c); + final float density = r.getDisplayMetrics().density; + + // Again, apply half the size of what the widget was designed for. + final int areaWidthDp = mDinoWidgetEdgeSizeDp / 4; + final int areaHeightDp = mDinoWidgetEdgeSizeDp; + mDelegate.resizeDinoWidgetToFillTargetCellArea( + r, mMockRemoteViews, areaWidthDp, areaHeightDp); + + // Since widget is a fraction of the size, that fraction goes into appropriate paddings. + int imagePadRight = + (int) (r.getDimension(R.dimen.quick_action_search_widget_dino_padding_start) / 4.f); + int imagePadVertical = + (int) (r.getDimension(R.dimen.quick_action_search_widget_dino_padding_vertical) + / 4.f); + + verify(mMockRemoteViews) + .setViewPadding(R.id.dino_quick_action_button, 0, imagePadVertical, imagePadRight, + imagePadVertical); + } }
diff --git a/chrome/browser/ui/app_list/app_list_sort_unittest.cc b/chrome/browser/ui/app_list/app_list_sort_unittest.cc index bc64532..8947136 100644 --- a/chrome/browser/ui/app_list/app_list_sort_unittest.cc +++ b/chrome/browser/ui/app_list/app_list_sort_unittest.cc
@@ -4,6 +4,7 @@ #include "base/test/scoped_feature_list.h" +#include "ash/app_list/model/app_list_model.h" #include "ash/constants/ash_features.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_model_updater.h" @@ -238,6 +239,272 @@ std::vector<std::string>({kItemId3, kItemId4, kItemId2, kItemId1})); } +// Verifies that moving an item within the app list resets the nominal app list +// sort order (if the app list is sorted at the time). +TEST_F(TemporaryAppListSortTest, MovingItemsResetsSortOrder) { + RemoveAllExistingItems(); + + std::vector<scoped_refptr<extensions::Extension>> apps; + for (int i = 0; i < 10; ++i) { + const std::string id = GenerateId(base::StringPrintf("app_id_%d", i)); + const std::string name = base::StringPrintf("Item %d", i); + scoped_refptr<extensions::Extension> app = + MakeApp(name, id, extensions::Extension::NO_FLAGS); + apps.push_back(app); + InstallExtension(app.get()); + } + + // Sort with name alphabetical order. + GetChromeModelUpdater()->RequestAppListSort( + ash::AppListSortOrder::kNameAlphabetical); + Commit(); + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Item 0", "Item 1", "Item 2", "Item 3", + "Item 4", "Item 5", "Item 6", "Item 7", + "Item 8", "Item 9"})); + + // Move an item within the app list. + ChromeAppListModelUpdater* model_updater = GetChromeModelUpdater(); + const syncer::StringOrdinal target_position = + model_updater->FindItem(apps[1]->id()) + ->position() + .CreateBetween(model_updater->FindItem(apps[2]->id())->position()); + model_updater->RequestPositionUpdate( + apps[7]->id(), target_position, + ash::RequestPositionUpdateReason::kMoveItem); + + // Verify that the app list is no longer considered sorted - new items are + // added to the first position within the app list. + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Item 0", "Item 1", "Item 7", "Item 2", + "Item 3", "Item 4", "Item 5", "Item 6", + "Item 8", "Item 9"})); + + scoped_refptr<extensions::Extension> new_app = MakeApp( + "Item 10", GenerateId("new_install"), extensions::Extension::NO_FLAGS); + InstallExtension(new_app.get()); + + EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Item 10", "Item 0", "Item 1", "Item 7", + "Item 2", "Item 3", "Item 4", "Item 5", + "Item 6", "Item 8", "Item 9"})); +} + +// Verifies that moving an item from a folder to root apps grid resets the +// nominal app list sort order (if the app list is sorted at the time). +TEST_F(TemporaryAppListSortTest, ReparentingItemToRootResetsSortOrder) { + RemoveAllExistingItems(); + + std::vector<scoped_refptr<extensions::Extension>> apps; + for (int i = 0; i < 10; ++i) { + const std::string id = GenerateId(base::StringPrintf("app_id_%d", i)); + const std::string name = base::StringPrintf("Item %d", i); + scoped_refptr<extensions::Extension> app = + MakeApp(name, id, extensions::Extension::NO_FLAGS); + apps.push_back(app); + InstallExtension(app.get()); + } + + // Create a folder that contains three items. + const std::string kFolderItemId = GenerateId("folder_id"); + syncer::SyncDataList sync_list; + sync_list.push_back(CreateAppRemoteData( + kFolderItemId, "Folder", "", + syncer::StringOrdinal::CreateInitialOrdinal().ToInternalValue(), kUnset, + sync_pb::AppListSpecifics_AppListItemType_TYPE_FOLDER)); + syncer::StringOrdinal child_position = + syncer::StringOrdinal::CreateInitialOrdinal(); + sync_list.push_back( + CreateAppRemoteData(apps[1]->id(), "Item 1", kFolderItemId, + child_position.ToInternalValue(), kUnset)); + child_position = child_position.CreateAfter(); + sync_list.push_back( + CreateAppRemoteData(apps[2]->id(), "Item 2", kFolderItemId, + child_position.ToInternalValue(), kUnset)); + child_position = child_position.CreateAfter(); + sync_list.push_back( + CreateAppRemoteData(apps[3]->id(), "Item 3", kFolderItemId, + child_position.ToInternalValue(), kUnset)); + + app_list_syncable_service()->MergeDataAndStartSyncing( + syncer::APP_LIST, sync_list, + std::make_unique<syncer::FakeSyncChangeProcessor>(), + std::make_unique<syncer::SyncErrorFactoryMock>()); + content::RunAllTasksUntilIdle(); + + // Sort with name alphabetical order. + GetChromeModelUpdater()->RequestAppListSort( + ash::AppListSortOrder::kNameAlphabetical); + Commit(); + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Folder", "Item 0", "Item 1", "Item 2", + "Item 3", "Item 4", "Item 5", "Item 6", + "Item 7", "Item 8", "Item 9"})); + + // Move an from the folder to root apps grid. + ChromeAppListModelUpdater* model_updater = GetChromeModelUpdater(); + const syncer::StringOrdinal target_position = + model_updater->FindItem(apps[6]->id()) + ->position() + .CreateBetween(model_updater->FindItem(apps[7]->id())->position()); + model_updater->RequestMoveItemToRoot(apps[1]->id(), target_position); + + // Verify that the app list is no longer considered sorted - new items are + // added to the first position within the app list. + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Folder", "Item 0", "Item 2", "Item 3", + "Item 4", "Item 5", "Item 6", "Item 1", + "Item 7", "Item 8", "Item 9"})); + + scoped_refptr<extensions::Extension> new_app = MakeApp( + "Item 10", GenerateId("new_install"), extensions::Extension::NO_FLAGS); + InstallExtension(new_app.get()); + + EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Item 10", "Folder", "Item 0", "Item 2", + "Item 3", "Item 4", "Item 5", "Item 6", + "Item 1", "Item 7", "Item 8", "Item 9"})); +} + +// Verifies that merging two items to form a folder resets the nominal app list +// sort order (if the app list is sorted at the time). +TEST_F(TemporaryAppListSortTest, MergingItemsResetsSortOrder) { + RemoveAllExistingItems(); + + std::vector<scoped_refptr<extensions::Extension>> apps; + for (int i = 0; i < 10; ++i) { + const std::string id = GenerateId(base::StringPrintf("app_id_%d", i)); + const std::string name = base::StringPrintf("Item %d", i); + scoped_refptr<extensions::Extension> app = + MakeApp(name, id, extensions::Extension::NO_FLAGS); + apps.push_back(app); + InstallExtension(app.get()); + } + + // Sort with name alphabetical order. + GetChromeModelUpdater()->RequestAppListSort( + ash::AppListSortOrder::kNameAlphabetical); + Commit(); + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Item 0", "Item 1", "Item 2", "Item 3", + "Item 4", "Item 5", "Item 6", "Item 7", + "Item 8", "Item 9"})); + + // Merge two items into a folder. + ChromeAppListModelUpdater* model_updater = GetChromeModelUpdater(); + model_updater->model_for_test()->MergeItems(apps[8]->id(), apps[9]->id()); + + // Verify that the app list is no longer considered sorted - new items are + // added to the first position within the app list. + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Item 0", "Item 1", "Item 2", "Item 3", + "Item 4", "Item 5", "Item 6", "Item 7", + "Item 8", "", "Item 9"})); + + scoped_refptr<extensions::Extension> new_app = MakeApp( + "Item 10", GenerateId("new_install"), extensions::Extension::NO_FLAGS); + InstallExtension(new_app.get()); + + EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Item 10", "Item 0", "Item 1", "Item 2", + "Item 3", "Item 4", "Item 5", "Item 6", + "Item 7", "Item 8", "", "Item 9"})); +} + +// Verifies that moving an item from a folder to root apps grid resets the +// nominal app list sort order (if the app list is sorted at the time). +TEST_F(TemporaryAppListSortTest, ReparentingItemToFolderDoesNotResetSortOrder) { + RemoveAllExistingItems(); + + std::vector<scoped_refptr<extensions::Extension>> apps; + for (int i = 0; i < 10; ++i) { + const std::string id = GenerateId(base::StringPrintf("app_id_%d", i)); + const std::string name = base::StringPrintf("Item %d", i); + scoped_refptr<extensions::Extension> app = + MakeApp(name, id, extensions::Extension::NO_FLAGS); + apps.push_back(app); + InstallExtension(app.get()); + } + + // Create a folder that contains three items. + const std::string kFolderItemId = GenerateId("folder_id"); + syncer::SyncDataList sync_list; + sync_list.push_back(CreateAppRemoteData( + kFolderItemId, "Folder", "", + syncer::StringOrdinal::CreateInitialOrdinal().ToInternalValue(), kUnset, + sync_pb::AppListSpecifics_AppListItemType_TYPE_FOLDER)); + + // Add three apps to the folder. + syncer::StringOrdinal child_position = + syncer::StringOrdinal::CreateInitialOrdinal(); + sync_list.push_back( + CreateAppRemoteData(apps[1]->id(), "Item 1", kFolderItemId, + child_position.ToInternalValue(), kUnset)); + child_position = child_position.CreateAfter(); + sync_list.push_back( + CreateAppRemoteData(apps[2]->id(), "Item 2", kFolderItemId, + child_position.ToInternalValue(), kUnset)); + child_position = child_position.CreateAfter(); + sync_list.push_back( + CreateAppRemoteData(apps[3]->id(), "Item 3", kFolderItemId, + child_position.ToInternalValue(), kUnset)); + + app_list_syncable_service()->MergeDataAndStartSyncing( + syncer::APP_LIST, sync_list, + std::make_unique<syncer::FakeSyncChangeProcessor>(), + std::make_unique<syncer::SyncErrorFactoryMock>()); + content::RunAllTasksUntilIdle(); + + // Sort with name alphabetical order. + GetChromeModelUpdater()->RequestAppListSort( + ash::AppListSortOrder::kNameAlphabetical); + Commit(); + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Folder", "Item 0", "Item 1", "Item 2", + "Item 3", "Item 4", "Item 5", "Item 6", + "Item 7", "Item 8", "Item 9"})); + + // Move an from the folder to root apps grid. + ChromeAppListModelUpdater* model_updater = GetChromeModelUpdater(); + model_updater->RequestMoveItemToFolder( + apps[7]->id(), kFolderItemId, ash::RequestMoveToFolderReason::kMoveItem); + + // Verify that the app list is still considered sorted - new items are + // added to the app list to maintain sorted order. + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Folder", "Item 0", "Item 1", "Item 2", + "Item 3", "Item 4", "Item 5", "Item 6", + "Item 7", "Item 8", "Item 9"})); + + scoped_refptr<extensions::Extension> new_app = MakeApp( + "Item 10", GenerateId("new_install"), extensions::Extension::NO_FLAGS); + InstallExtension(new_app.get()); + + EXPECT_EQ(ash::AppListSortOrder::kNameAlphabetical, GetSortOrderFromPrefs()); + EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string>({"Folder", "Item 0", "Item 1", "Item 10", + "Item 2", "Item 3", "Item 4", "Item 5", + "Item 6", "Item 7", "Item 8", "Item 9"})); +} // Verifies that reverting the temporary name sort order works as expected. TEST_F(TemporaryAppListSortTest, RevertNameOrder) { RemoveAllExistingItems(); @@ -559,6 +826,84 @@ GetOrderedNamesFromSyncableService()); } +// Verifies that the app list under temporary sort works as expected when moving +// an item from a folder to root apps grid. +TEST_F(TemporaryAppListSortTest, HandleMoveItemToRootGrid) { + RemoveAllExistingItems(); + + // Add one folder containing three apps. + const std::string kFolderItemId = GenerateId("folder_id"); + syncer::SyncDataList sync_list; + sync_list.push_back(CreateAppRemoteData( + kFolderItemId, "Folder", "", + syncer::StringOrdinal::CreateInitialOrdinal().ToInternalValue(), kUnset, + sync_pb::AppListSpecifics_AppListItemType_TYPE_FOLDER)); + const std::string kItemId1 = GenerateId("app_id1"); + const std::string kItemId2 = GenerateId("app_id2"); + const std::string kItemId3 = GenerateId("app_id3"); + + syncer::StringOrdinal child_position = + syncer::StringOrdinal::CreateInitialOrdinal(); + sync_list.push_back(CreateAppRemoteData( + kItemId1, "A", kFolderItemId, child_position.ToInternalValue(), kUnset)); + child_position = child_position.CreateAfter(); + sync_list.push_back(CreateAppRemoteData( + kItemId2, "B", kFolderItemId, child_position.ToInternalValue(), kUnset)); + child_position = child_position.CreateAfter(); + sync_list.push_back(CreateAppRemoteData( + kItemId3, "C", kFolderItemId, child_position.ToInternalValue(), kUnset)); + + app_list_syncable_service()->MergeDataAndStartSyncing( + syncer::APP_LIST, sync_list, + std::make_unique<syncer::FakeSyncChangeProcessor>(), + std::make_unique<syncer::SyncErrorFactoryMock>()); + content::RunAllTasksUntilIdle(); + + // Install test apps that were added to the folder. + scoped_refptr<extensions::Extension> app1 = + MakeApp("A", kItemId1, extensions::Extension::NO_FLAGS); + InstallExtension(app1.get()); + scoped_refptr<extensions::Extension> app2 = + MakeApp("B", kItemId2, extensions::Extension::NO_FLAGS); + InstallExtension(app2.get()); + scoped_refptr<extensions::Extension> app3 = + MakeApp("C", kItemId3, extensions::Extension::NO_FLAGS); + InstallExtension(app3.get()); + + // Install an additional app. + const std::string kItemId4 = GenerateId("app_id4"); + scoped_refptr<extensions::Extension> app4 = + MakeApp("D", kItemId4, extensions::Extension::NO_FLAGS); + InstallExtension(app4.get()); + + // Sort with the reverse alphabetical name order and commit. + ChromeAppListModelUpdater* model_updater = GetChromeModelUpdater(); + model_updater->RequestAppListSort( + ash::AppListSortOrder::kNameReverseAlphabetical); + Commit(); + EXPECT_EQ(std::vector<std::string>({"Folder", "D", "C", "B", "A"}), + GetOrderedNamesFromSyncableService()); + + // Sort with the name alphabetical order without committing. + model_updater->RequestAppListSort(ash::AppListSortOrder::kNameAlphabetical); + EXPECT_EQ(ash::AppListSortOrder::kNameReverseAlphabetical, + GetSortOrderFromPrefs()); + EXPECT_EQ(std::vector<std::string>({"Folder", "D", "C", "B", "A"}), + GetOrderedNamesFromSyncableService()); + + // Move an folder item to root apps grid. + model_updater->RequestMoveItemToRoot( + kItemId1, model_updater->FindItem(kItemId4)->position().CreateAfter()); + + // Verify that: + // (1) Temporary sort ends. + // (2) Sort order pref reverts to custom. + EXPECT_FALSE(IsUnderTemporarySort()); + EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); + EXPECT_EQ(std::vector<std::string>({"Folder", "B", "C", "D", "A"}), + GetOrderedNamesFromSyncableService()); +} + // Verifies the temporary sorting behavior with local app installation. TEST_F(TemporaryAppListSortTest, InstallAppLocally) { RemoveAllExistingItems();
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc index 8fc9c2f..f63a118 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -793,6 +793,10 @@ if (is_under_temporary_sort()) { EndTemporarySortAndTakeAction(EndAction::kCommitAndClearSort); } else { + if (order_delegate_) { + order_delegate_->SetAppListPreferredOrder( + ash::AppListSortOrder::kCustom); + } // NOTE: Committing temporary sort will also reset page breaks, so they // don't have to be sanitized again in that case. sync_model_sanitizer_->SanitizePageBreaksForProductivityLauncher( @@ -830,8 +834,14 @@ if (!ash::features::IsProductivityLauncherEnabled()) ClearFolderIfItHasSingleChild(old_parent); - sync_model_sanitizer_->SanitizePageBreaksForProductivityLauncher( - GetTopLevelItemIds(), /*reset_page_breaks=*/false); + if (is_under_temporary_sort()) { + EndTemporarySortAndTakeAction(EndAction::kCommitAndClearSort); + } else { + if (order_delegate_) + order_delegate_->SetAppListPreferredOrder(ash::AppListSortOrder::kCustom); + sync_model_sanitizer_->SanitizePageBreaksForProductivityLauncher( + GetTopLevelItemIds(), /*reset_page_breaks=*/false); + } } void ChromeAppListModelUpdater::RequestAppListSort( @@ -895,6 +905,10 @@ if (temporary_sort_manager_) { EndTemporarySortAndTakeAction(EndAction::kCommitAndClearSort); } else { + if (order_delegate_) { + order_delegate_->SetAppListPreferredOrder( + ash::AppListSortOrder::kCustom); + } // NOTE: Committing temporary sort will also reset page breaks, so they // don't have to be sanitized again in that case. sync_model_sanitizer_->SanitizePageBreaksForProductivityLauncher(
diff --git a/chrome/browser/ui/autofill/edit_address_profile_dialog_controller_impl.cc b/chrome/browser/ui/autofill/edit_address_profile_dialog_controller_impl.cc index cc95ffc..e52b3f6 100644 --- a/chrome/browser/ui/autofill/edit_address_profile_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/edit_address_profile_dialog_controller_impl.cc
@@ -37,6 +37,13 @@ const AutofillProfile* original_profile, AutofillClient::AddressProfileSavePromptCallback address_profile_save_prompt_callback) { + // Don't show the bubble if it's already visible, and inform the backend. + if (dialog_view_) { + std::move(address_profile_save_prompt_callback) + .Run(AutofillClient::SaveAddressProfileOfferUserDecision::kAutoDeclined, + profile); + return; + } address_profile_to_edit_ = profile; original_profile_ = base::OptionalFromPtr(original_profile); address_profile_save_prompt_callback_ =
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..ade0e5a --- /dev/null +++ b/chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller_chromeos_browsertest.cc
@@ -0,0 +1,47 @@ +// 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(); + + // 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/sync/profile_signin_confirmation_helper_unittest.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc index 41e7f7fc..90ef393 100644 --- a/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc +++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
@@ -135,7 +135,8 @@ new sync_preferences::TestingPrefServiceSyncable( /*managed_prefs=*/new TestingPrefStore(), /*supervised_user_prefs=*/new TestingPrefStore(), - /*extension_prefs=*/new TestingPrefStore(), user_prefs_, + /*extension_prefs=*/new TestingPrefStore(), + /*standalone_browser_prefs=*/new TestingPrefStore(), user_prefs_, /*recommended_prefs=*/new TestingPrefStore(), new user_prefs::PrefRegistrySyncable(), new PrefNotifierImpl()); RegisterUserProfilePrefs(pref_service->registry());
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller_browsertest.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller_browsertest.cc index ce45150..1f57c1e 100644 --- a/chrome/browser/ui/views/payments/payment_sheet_view_controller_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h" #include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h" #include "chrome/test/base/ui_test_utils.h" @@ -12,6 +13,7 @@ #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/strings/grit/components_strings.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" @@ -82,6 +84,53 @@ DialogViewID::PAYMENT_SHEET_CONTACT_INFO_SECTION))); } +// The tests in this class correspond to the tests of the same name in +// PaymentSheetViewControllerNoShippingTest, with the basic-card being disabled. +// Parameterized tests are not used because the test setup for both tests are +// too different. +class PaymentSheetViewControllerNoShippingBasicCardDisabledTest + : public PaymentSheetViewControllerNoShippingTest { + public: + PaymentSheetViewControllerNoShippingBasicCardDisabledTest( + const PaymentSheetViewControllerNoShippingBasicCardDisabledTest&) = + delete; + PaymentSheetViewControllerNoShippingBasicCardDisabledTest& operator=( + const PaymentSheetViewControllerNoShippingBasicCardDisabledTest&) = + delete; + + protected: + PaymentSheetViewControllerNoShippingBasicCardDisabledTest() { + feature_list_.InitWithFeatures({}, {::features::kPaymentRequestBasicCard}); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// If shipping and contact info are not requested, their rows should not be +// present. +IN_PROC_BROWSER_TEST_F( + PaymentSheetViewControllerNoShippingBasicCardDisabledTest, + NoShippingNoContactRows) { + std::string payment_method_name; + InstallPaymentApp("a.com", "payment_request_success_responder.js", + &payment_method_name); + + NavigateTo("/payment_request_no_shipping_test.html"); + InvokePaymentRequestUIWithJs("buyWithMethods([{supportedMethods:'" + + payment_method_name + "'}]);"); + + EXPECT_NE(nullptr, dialog_view()->GetViewByID(static_cast<int>( + DialogViewID::PAYMENT_SHEET_SUMMARY_SECTION))); + EXPECT_EQ(nullptr, + dialog_view()->GetViewByID(static_cast<int>( + DialogViewID::PAYMENT_SHEET_SHIPPING_ADDRESS_SECTION))); + EXPECT_EQ(nullptr, dialog_view()->GetViewByID(static_cast<int>( + DialogViewID::PAYMENT_SHEET_SHIPPING_OPTION_SECTION))); + EXPECT_EQ(nullptr, dialog_view()->GetViewByID(static_cast<int>( + DialogViewID::PAYMENT_SHEET_CONTACT_INFO_SECTION))); +} + typedef PaymentRequestBrowserTestBase PaymentHandlerUITest; IN_PROC_BROWSER_TEST_F(PaymentHandlerUITest, BackReturnsToPaymentSheet) {
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.cc index 204d1f2..d860a11 100644 --- a/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.cc +++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.cc
@@ -18,11 +18,18 @@ #include "components/omnibox/browser/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/strings/grit/ui_strings.h" namespace sharing_hub { namespace { +send_tab_to_self::SendTabToSelfBubbleController* GetSendTabToSelfController( + content::WebContents* web_contents) { + return send_tab_to_self::SendTabToSelfBubbleController:: + CreateOrGetFromWebContents(web_contents); +} + bool IsQRCodeDialogOpen(content::WebContents* web_contents) { qrcode_generator::QRCodeGeneratorBubbleController* controller = qrcode_generator::QRCodeGeneratorBubbleController::Get(web_contents); @@ -31,8 +38,7 @@ bool IsSendTabToSelfDialogOpen(content::WebContents* web_contents) { send_tab_to_self::SendTabToSelfBubbleController* controller = - send_tab_to_self::SendTabToSelfBubbleController:: - CreateOrGetFromWebContents(web_contents); + GetSendTabToSelfController(web_contents); return controller && controller->IsBubbleShown(); } @@ -47,6 +53,9 @@ icon_label_bubble_delegate, page_action_icon_delegate) { SetVisible(false); + SetLabel( + l10n_util::GetStringUTF16(IDS_BROWSER_SHARING_OMNIBOX_SENDING_LABEL)); + SetUpForInOutAnimation(); } SharingHubIconView::~SharingHubIconView() = default; @@ -78,6 +87,10 @@ IsSendTabToSelfDialogOpen(web_contents)) { SetHighlighted(true); } + + if (enabled) { + MaybeAnimateSendingToast(); + } } void SharingHubIconView::OnExecuting( @@ -87,10 +100,6 @@ return GetSharingHubVectorIcon(); } -bool SharingHubIconView::ShouldShowLabel() const { - return false; -} - std::u16string SharingHubIconView::GetTextForTooltipAndAccessibleName() const { return l10n_util::GetStringUTF16(IDS_SHARING_HUB_TOOLTIP); } @@ -103,6 +112,20 @@ return SharingHubBubbleController::CreateOrGetFromWebContents(web_contents); } +void SharingHubIconView::MaybeAnimateSendingToast() { + content::WebContents* web_contents = GetWebContents(); + if (!web_contents) { + return; + } + send_tab_to_self::SendTabToSelfBubbleController* controller = + GetSendTabToSelfController(web_contents); + + if (controller && controller->show_message()) { + controller->set_show_message(false); + AnimateIn(absl::nullopt); + } +} + BEGIN_METADATA(SharingHubIconView, PageActionIconView) END_METADATA
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h index 2d895db..d807e9c 100644 --- a/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h +++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_icon_view.h
@@ -30,7 +30,6 @@ // PageActionIconView: views::BubbleDialogDelegate* GetBubble() const override; void UpdateImpl() override; - bool ShouldShowLabel() const override; std::u16string GetTextForTooltipAndAccessibleName() const override; protected: @@ -40,6 +39,9 @@ private: SharingHubBubbleController* GetController() const; + // Shows a "Sending..." animation if a device was selected in the send tab to + // self dialog. + void MaybeAnimateSendingToast(); }; } // namespace sharing_hub
diff --git a/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc b/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc index 82b88e65..c40a55a 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_scroll_container.cc
@@ -9,6 +9,8 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/canvas.h" @@ -185,14 +187,19 @@ scroll_button_container->SetLayoutManager( std::make_unique<views::FlexLayout>()); scroll_button_layout->SetOrientation(views::LayoutOrientation::kHorizontal); + leading_scroll_button_ = scroll_button_container->AddChildView(CreateScrollButton( base::BindRepeating(&TabStripScrollContainer::ScrollTowardsLeadingTab, base::Unretained(this)))); + leading_scroll_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_TAB_SCROLL_LEADING)); trailing_scroll_button_ = scroll_button_container->AddChildView( CreateScrollButton(base::BindRepeating( &TabStripScrollContainer::ScrollTowardsTrailingTab, base::Unretained(this)))); + trailing_scroll_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_TAB_SCROLL_TRAILING)); // The space in dips between the scroll buttons and the NTB. constexpr int kScrollButtonsTrailingMargin = 8;
diff --git a/chrome/browser/ui/web_applications/test/DEPS b/chrome/browser/ui/web_applications/test/DEPS new file mode 100644 index 0000000..545cfc0 --- /dev/null +++ b/chrome/browser/ui/web_applications/test/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + "system_web_app_interactive_uitest\.cc": [ + "+ash/shell.h", + "+ash/wm/window_util.h", + ], +}
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc index adb5f90c..48379b84e 100644 --- a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc +++ b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> #include <string> #include <tuple> #include <utility> @@ -46,15 +47,26 @@ #include "ash/public/cpp/app_menu_constants.h" #include "ash/public/cpp/shelf_item_delegate.h" #include "ash/public/cpp/shelf_model.h" +#include "ash/shell.h" +#include "ash/wm/window_util.h" +#include "base/run_loop.h" +#include "base/scoped_observation.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/ash/crosapi/url_handler_ash.h" #include "chrome/browser/ash/login/login_manager_test.h" #include "chrome/browser/ash/login/test/login_manager_mixin.h" #include "chrome/browser/ash/login/ui/user_adding_screen.h" +#include "chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" +#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" +#include "chrome/common/webui_url_constants.h" +#include "content/public/test/test_utils.h" +#include "ui/wm/public/activation_change_observer.h" // nogncheck +#include "ui/wm/public/activation_client.h" // nogncheck #endif namespace web_app { @@ -803,6 +815,145 @@ } #endif // BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS_ASH) + +// A one shot observer which waits for an activation of any window. +class TestActivationObserver : public wm::ActivationChangeObserver { + public: + TestActivationObserver(const TestActivationObserver&) = delete; + TestActivationObserver& operator=(const TestActivationObserver&) = delete; + + TestActivationObserver() { + activation_observer_.Observe(ash::Shell::Get()->activation_client()); + } + + ~TestActivationObserver() override = default; + + void Wait() { run_loop_.Run(); } + + // wm::ActivationChangeObserver: + void OnWindowActivated(ActivationReason reason, + aura::Window* gained_active, + aura::Window* lost_active) override { + Browser* browser = chrome::FindBrowserWithWindow(gained_active); + // Check that the activated window is actually a browser. + EXPECT_TRUE(browser); + // Check also that the browser is actually an app. + EXPECT_TRUE(browser->is_type_app()); + run_loop_.Quit(); + } + + private: + // The MessageLoopRunner used to spin the message loop. + base::RunLoop run_loop_; + base::ScopedObservation<wm::ActivationClient, wm::ActivationChangeObserver> + activation_observer_{this}; +}; + +// Tests which are exercising OpenUrl called by Lacros in Ash. +class SystemWebAppOpenInAshFromLacrosTests + : public SystemWebAppManagerBrowserTest { + public: + SystemWebAppOpenInAshFromLacrosTests() + : SystemWebAppManagerBrowserTest(/*install_mock=*/false) { + OsUrlHandlerSystemWebAppDelegate::EnableDelegateForTesting(true); + url_handler_ = std::make_unique<crosapi::UrlHandlerAsh>(); + } + + ~SystemWebAppOpenInAshFromLacrosTests() { + OsUrlHandlerSystemWebAppDelegate::EnableDelegateForTesting(false); + } + + // A function to wait until a window activation change was observed. + void LaunchAndWaitForActivationChange(const GURL& url) { + TestActivationObserver observer; + url_handler_->OpenUrl(url); + observer.Wait(); + } + + protected: + std::unique_ptr<crosapi::UrlHandlerAsh> url_handler_; +}; + +// This test will make sure that only accepted URLs will be allowed to create +// applications. +IN_PROC_BROWSER_TEST_P(SystemWebAppOpenInAshFromLacrosTests, + LaunchOnlyAllowedUrls) { + WaitForTestSystemAppInstall(); + + // There might be an initial browser from the testing framework. + int initial_browser_count = BrowserList::GetInstance()->size(); + + // Test that a non descript URL gets rejected. + GURL url1 = GURL("http://www.foo.bar"); + EXPECT_FALSE(ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(url1)); + EXPECT_FALSE(url_handler_->OpenUrlInternal(url1)); + + // Test that an unknown internal os url gets rejected. + GURL url2 = GURL("os://foo-bar"); + EXPECT_FALSE(ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(url2)); + EXPECT_FALSE(url_handler_->OpenUrlInternal(url2)); + + // Test that an unknown internal chrome url gets rejected. + GURL url3 = GURL("chrome://foo-bar"); + EXPECT_FALSE(ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(url3)); + EXPECT_FALSE(url_handler_->OpenUrlInternal(url3)); + + // Test that a known internal url gets accepted. + GURL url4 = GURL("os://version"); + EXPECT_TRUE(ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(url4)); + LaunchAndWaitForActivationChange(url4); + EXPECT_EQ(initial_browser_count + 1, BrowserList::GetInstance()->size()); + EXPECT_EQ(u"ChromeOS-URLs", ash::window_util::GetActiveWindow()->GetTitle()); +} + +// This test will make sure that opening the same system URL multiple times will +// re-use the existing app. +IN_PROC_BROWSER_TEST_P(SystemWebAppOpenInAshFromLacrosTests, + LaunchLacrosDeDuplicationtest) { + WaitForTestSystemAppInstall(); + + // There might be an initial browser from the testing framework. + int initial_browser_count = BrowserList::GetInstance()->size(); + + // Start an application which uses the OS url handler. + LaunchAndWaitForActivationChange(GURL(chrome::kOsUICreditsURL)); + EXPECT_EQ(initial_browser_count + 1, BrowserList::GetInstance()->size()); + EXPECT_EQ(u"ChromeOS-URLs", ash::window_util::GetActiveWindow()->GetTitle()); + + // Start another application. + LaunchAndWaitForActivationChange(GURL(chrome::kOsUIFlagsURL)); + EXPECT_EQ(initial_browser_count + 2, BrowserList::GetInstance()->size()); + EXPECT_EQ(u"Flags", ash::window_util::GetActiveWindow()->GetTitle()); + + // Start an application of the first type and see that no new app got created. + LaunchAndWaitForActivationChange(GURL(chrome::kOsUICreditsURL)); + EXPECT_EQ(initial_browser_count + 2, BrowserList::GetInstance()->size()); + EXPECT_EQ(u"ChromeOS-URLs", ash::window_util::GetActiveWindow()->GetTitle()); +} + +// This test will make sure that opening a different system URL (other than +// flags) will open different windows. +IN_PROC_BROWSER_TEST_P(SystemWebAppOpenInAshFromLacrosTests, + LaunchLacrosCreateNewAppForNewSystemUrl) { + WaitForTestSystemAppInstall(); + + // There might be an initial browser from the testing framework. + int initial_browser_count = BrowserList::GetInstance()->size(); + + // Start an application using the OS Url handler. + LaunchAndWaitForActivationChange(GURL(chrome::kOsUICreditsURL)); + EXPECT_EQ(initial_browser_count + 1, BrowserList::GetInstance()->size()); + EXPECT_EQ(u"ChromeOS-URLs", ash::window_util::GetActiveWindow()->GetTitle()); + + // Start another application using the OS Url handler. + LaunchAndWaitForActivationChange(GURL(chrome::kOsUIComponentsUrl)); + EXPECT_EQ(initial_browser_count + 2, BrowserList::GetInstance()->size()); + EXPECT_EQ(u"ChromeOS-URLs", ash::window_util::GetActiveWindow()->GetTitle()); +} + +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + class SystemWebAppManagerCloseFromScriptsTest : public SystemWebAppManagerBrowserTest { public: @@ -979,4 +1130,8 @@ INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_REGULAR_PROFILE_P( SystemWebAppNewWindowMenuItemTest); #endif +#if BUILDFLAG(IS_CHROMEOS_ASH) +INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_REGULAR_PROFILE_P( + SystemWebAppOpenInAshFromLacrosTests); +#endif } // namespace web_app
diff --git a/chrome/browser/ui/webui/app_management/BUILD.gn b/chrome/browser/ui/webui/app_management/BUILD.gn deleted file mode 100644 index d96d4060..0000000 --- a/chrome/browser/ui/webui/app_management/BUILD.gn +++ /dev/null
@@ -1,11 +0,0 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("mojo_bindings") { - sources = [ "app_management.mojom" ] - - public_deps = [ "//components/services/app_service/public/mojom" ] -}
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc index 3e447716..5801a25e 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/app_management/app_management.mojom.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/intent_constants.h" #include "components/services/app_service/public/cpp/intent_filter_util.h" @@ -32,6 +31,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/components/arc/session/connection_holder.h" @@ -210,6 +210,7 @@ void AppManagementPageHandler::SetPermission( const std::string& app_id, apps::mojom::PermissionPtr permission) { + DLOG(ERROR) << "set permission"; apps::AppServiceProxyFactory::GetForProfile(profile_)->SetPermission( app_id, std::move(permission)); }
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.h b/chrome/browser/ui/webui/app_management/app_management_page_handler.h index 81e50cf1..60047d3 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler.h +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.h
@@ -8,7 +8,6 @@ #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/ui/webui/app_management/app_management.mojom-forward.h" #include "chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/preferred_apps_list_handle.h" @@ -16,6 +15,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom-forward.h" class Profile;
diff --git a/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h b/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h index a8c16ff..1af9a2d3 100644 --- a/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h +++ b/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h
@@ -9,7 +9,7 @@ #include "ash/public/cpp/shelf_model_observer.h" #include "base/memory/raw_ptr.h" -#include "chrome/browser/ui/webui/app_management/app_management.mojom.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" class AppManagementPageHandler; class ShelfControllerHelper;
diff --git a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals.mojom b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals.mojom index fdbc1400..ced4e99 100644 --- a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals.mojom +++ b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals.mojom
@@ -4,17 +4,6 @@ module segmentation_internals.mojom; -// Encapsulates information related to a selected segment. The information -// includes whether the segment is ready and its optimization target. -struct SegmentData { - // Whether the segment is ready. - bool is_ready; - - // Enum value from components/optimization_guide/proto/models.proto. Or -1 - // if the optimization target is empty. - int32 optimization_target; -}; - // Status information about the segmentation service. struct ServiceStatus { // Whether the service is initialized. @@ -24,6 +13,15 @@ int32 intialization_status; }; +// Information about a segment +struct SegmentInfo { + // Target of the optimization. + string optimization_target; + + // Detailed segmentation information. + string segment_data; +}; + // Used by the WebUI page to bootstrap bidirectional communication. interface PageHandlerFactory { // The WebUI calls this method when the page is first initialized. @@ -33,9 +31,6 @@ // Browser-side handler for requests from WebUI page. interface PageHandler { - // Gets the segment result for a given key. - GetSegment(string key) => (SegmentData result); - // Gets the segmentation service status. GetServiceStatus(); }; @@ -51,6 +46,7 @@ int32 status_flag); // Notifies the page when all segment info becomes available from the service. - // |segment_info| is an array of serialized string for all the segment, - OnSegmentInfoAvailable(array<string> segment_info); + // |segment_info| is an array of all segment information stored in the + // database, + OnSegmentInfoAvailable(array<SegmentInfo> segment_info); };
diff --git a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.cc b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.cc index 0fa02fc3..cfcca43 100644 --- a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.cc +++ b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/segmentation_platform/segmentation_platform_service_factory.h" +#include "components/segmentation_platform/public/segmentation_platform_service.h" SegmentationInternalsPageHandlerImpl::SegmentationInternalsPageHandlerImpl( mojo::PendingReceiver<segmentation_internals::mojom::PageHandler> receiver, @@ -26,30 +27,6 @@ service_proxy_->RemoveObserver(this); } -void SegmentationInternalsPageHandlerImpl::GetSegment( - const std::string& key, - GetSegmentCallback callback) { - if (!service_proxy_) { - OnGetSelectedSegmentDone(std::move(callback), - segmentation_platform::SegmentSelectionResult()); - return; - } - service_proxy_->GetSelectedSegment( - key, base::BindOnce( - &SegmentationInternalsPageHandlerImpl::OnGetSelectedSegmentDone, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); -} - -void SegmentationInternalsPageHandlerImpl::OnGetSelectedSegmentDone( - GetSegmentCallback callback, - const segmentation_platform::SegmentSelectionResult& result) { - auto segment_data = segmentation_internals::mojom::SegmentData::New(); - segment_data->is_ready = result.is_ready; - segment_data->optimization_target = - result.segment ? result.segment.value() : -1; - std::move(callback).Run(std::move(segment_data)); -} - void SegmentationInternalsPageHandlerImpl::GetServiceStatus() { if (service_proxy_) { service_proxy_->GetServiceStatus(); @@ -63,6 +40,13 @@ } void SegmentationInternalsPageHandlerImpl::OnSegmentInfoAvailable( - const std::vector<std::string>& segment_info) { - page_->OnSegmentInfoAvailable(segment_info); + const std::vector<std::pair<std::string, std::string>>& segment_info) { + std::vector<segmentation_internals::mojom::SegmentInfoPtr> available_segments; + for (const auto& info : segment_info) { + auto segment_data = segmentation_internals::mojom::SegmentInfo::New(); + segment_data->optimization_target = info.first; + segment_data->segment_data = info.second; + available_segments.push_back(std::move(segment_data)); + } + page_->OnSegmentInfoAvailable(std::move(available_segments)); }
diff --git a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.h b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.h index 6347027..01c96c58 100644 --- a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.h +++ b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_page_handler_impl.h
@@ -34,19 +34,14 @@ const SegmentationInternalsPageHandlerImpl&) = delete; // segmentation_internals::mojom::PageHandler: - void GetSegment(const std::string& key, GetSegmentCallback callback) override; void GetServiceStatus() override; private: - // Called when segment result is retrieved. - void OnGetSelectedSegmentDone( - GetSegmentCallback callback, - const segmentation_platform::SegmentSelectionResult& result); - // segmentation_platform::ServiceProxy::Observer overrides. void OnServiceStatusChanged(bool is_initialized, int status_flag) override; void OnSegmentInfoAvailable( - const std::vector<std::string>& segment_info) override; + const std::vector<std::pair<std::string, std::string>>& segment_info) + override; mojo::Receiver<segmentation_internals::mojom::PageHandler> receiver_; mojo::Remote<segmentation_internals::mojom::Page> page_;
diff --git a/chrome/browser/ui/webui/settings/chromeos/BUILD.gn b/chrome/browser/ui/webui/settings/chromeos/BUILD.gn index 7452b05..c86ea04 100644 --- a/chrome/browser/ui/webui/settings/chromeos/BUILD.gn +++ b/chrome/browser/ui/webui/settings/chromeos/BUILD.gn
@@ -6,7 +6,7 @@ public_deps = [ "constants:mojom_js", "search:mojo_bindings_js", - "//chrome/browser/ui/webui/app_management:mojo_bindings_js", "//chrome/browser/ui/webui/nearby_share/public/mojom:mojom_js", + "//ui/webui/resources/cr_components/app_management:mojo_bindings_js", ] }
diff --git a/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.cc b/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.cc index d4f851d6..fb66843 100644 --- a/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.cc +++ b/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.cc
@@ -11,7 +11,6 @@ #include "base/feature_list.h" #include "chrome/browser/apps/app_service/app_icon/app_icon_source.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/app_management/app_management.mojom.h" #include "chrome/browser/ui/webui/app_management/app_management_page_handler.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" @@ -24,6 +23,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom.h" AppManagementPageHandlerFactory::AppManagementPageHandlerFactory( Profile* profile)
diff --git a/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.h b/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.h index 948daf715..38af42a 100644 --- a/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.h +++ b/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.h
@@ -7,10 +7,10 @@ #include <memory> -#include "chrome/browser/ui/webui/app_management/app_management.mojom.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 "ui/webui/resources/cr_components/app_management/app_management.mojom.h" class Profile;
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h index fc3ecec..67ed6ed7 100644 --- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/time/time.h" -#include "chrome/browser/ui/webui/app_management/app_management.mojom-forward.h" #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h" #include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h" #include "chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.h" @@ -22,6 +21,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "ui/webui/mojo_web_ui_controller.h" +#include "ui/webui/resources/cr_components/app_management/app_management.mojom-forward.h" namespace user_prefs { class PrefRegistrySyncable;
diff --git a/chrome/browser/vr/OWNERS b/chrome/browser/vr/OWNERS index b3e65b53..87d7a56 100644 --- a/chrome/browser/vr/OWNERS +++ b/chrome/browser/vr/OWNERS
@@ -2,11 +2,4 @@ tiborg@chromium.org vollick@chromium.org -# WebXR or Browser Test-related -alcooper@chromium.org - -# WebXR-related. -klausw@chromium.org - -# Browser Test-related. -bsheedy@chromium.org +file://components/webxr/OWNERS
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index f5fa5a9..d080071d 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1639655564-a5a5c0d33ae436f2a30693fdb9d2306eb3190a81.profdata +chrome-linux-main-1639677539-99948628de3a78f947b1b4d59843ea500cf91b69.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index defc11df..459c953 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1639655564-52e53ef7b47860477f68cddce2543fb594359e09.profdata +chrome-mac-main-1639677539-997cb311ab2c03187a535e6bd85a4c81ef7ed1a7.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 87c7f25..8e5ee8c 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1639666549-84a7c26e97b827581984ac991aa2569f15b40ef8.profdata +chrome-win32-main-1639677539-d3b89857331ec31b3fb9a2f0baec586c99a0d583.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index db20818..5e79c5e 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1639655564-53960f02f5072242e6980160d511646ba3082008.profdata +chrome-win64-main-1639677539-e35fba550ec3048b103171c0e33ceac25ceda995.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index d52f939..7e90011 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3443,6 +3443,8 @@ "../browser/chromeos/policy/dlp/dlp_rules_manager_impl_browsertest.cc", "../browser/chromeos/policy/dlp/dlp_rules_manager_test_utils.cc", "../browser/chromeos/policy/dlp/dlp_rules_manager_test_utils.h", + "../browser/chromeos/policy/dlp/mock_dlp_content_manager.cc", + "../browser/chromeos/policy/dlp/mock_dlp_content_manager.h", "../browser/chromeos/policy/dlp/mock_dlp_content_observer.cc", "../browser/chromeos/policy/dlp/mock_dlp_content_observer.h", "../browser/chromeos/policy/dlp/mock_dlp_rules_manager.cc", @@ -3511,6 +3513,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", @@ -6484,6 +6487,8 @@ "../browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc", "../browser/chromeos/policy/dlp/dlp_rules_manager_test_utils.cc", "../browser/chromeos/policy/dlp/dlp_rules_manager_test_utils.h", + "../browser/chromeos/policy/dlp/mock_dlp_content_manager.cc", + "../browser/chromeos/policy/dlp/mock_dlp_content_manager.h", "../browser/chromeos/policy/dlp/mock_dlp_content_observer.cc", "../browser/chromeos/policy/dlp/mock_dlp_content_observer.h", "../browser/chromeos/policy/dlp/mock_dlp_rules_manager.cc", @@ -8607,7 +8612,13 @@ "../browser/ui/views/keyboard_access_browsertest.cc", ] } - if (!is_chromeos_ash) { + if (is_chromeos_ash) { + deps += [ + "//ash:ash", + "//chrome/browser/ash/crosapi:crosapi", + "//ui/wm/public:public", + ] + } else { sources += [ "../browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc" ] deps += [ "../browser/media/router:test_support", @@ -8618,7 +8629,6 @@ if (!is_android) { sources += [ "../browser/ui/web_applications/test/system_web_app_interactive_uitest.cc" ] } - if (use_aura) { sources += [ "../browser/ui/views/tooltip/tooltip_browsertest.cc" ] }
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index 6abe13e..c7dadb2 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc
@@ -750,6 +750,7 @@ testing_prefs_ = new sync_preferences::TestingPrefServiceSyncable( /*managed_prefs=*/new TestingPrefStore, supervised_user_pref_store_, /*extension_prefs=*/new TestingPrefStore, + /*standalone_browser_prefs=*/new TestingPrefStore, /*user_prefs=*/new TestingPrefStore, /*recommended_prefs=*/new TestingPrefStore, new user_prefs::PrefRegistrySyncable, new PrefNotifierImpl);
diff --git a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js index b0919b7e..5e73a2c 100644 --- a/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js +++ b/chrome/test/data/webui/chromeos/diagnostics/input_list_test.js
@@ -4,7 +4,7 @@ import 'chrome://diagnostics/input_list.js'; -import {ConnectionType, KeyboardInfo, MechanicalLayout, NumberPadPresence, PhysicalLayout, TouchDeviceInfo, TouchDeviceType} from 'chrome://diagnostics/diagnostics_types.js'; +import {ConnectionType, KeyboardInfo, MechanicalLayout, NumberPadPresence, PhysicalLayout, TopRowKey, TouchDeviceInfo, TouchDeviceType} from 'chrome://diagnostics/diagnostics_types.js'; import {fakeKeyboards, fakeTouchDevices} from 'chrome://diagnostics/fake_data.js'; import {FakeInputDataProvider} from 'chrome://diagnostics/fake_input_data_provider.js'; import {setInputDataProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js'; @@ -87,6 +87,12 @@ mechanicalLayout: MechanicalLayout.kUnknown, hasAssistantKey: false, numberPadPresent: NumberPadPresence.kUnknown, + topRowKeys: [ + TopRowKey.kBack, TopRowKey.kForward, TopRowKey.kRefresh, + TopRowKey.kFullscreen, TopRowKey.kOverview, + TopRowKey.kScreenBrightnessDown, TopRowKey.kScreenBrightnessUp, + TopRowKey.kVolumeMute, TopRowKey.kVolumeDown, TopRowKey.kVolumeUp + ], }; let keyboardCard; return initializeInputList()
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js index 4b2b57be..78320d8 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_provisioning_page_test.js
@@ -6,11 +6,19 @@ import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js'; import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js'; import {ReimagingProvisioningPage} from 'chrome://shimless-rma/reimaging_provisioning_page.js'; +import {ShimlessRma} from 'chrome://shimless-rma/shimless_rma.js'; import {ProvisioningStatus} from 'chrome://shimless-rma/shimless_rma_types.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; import {flushTasks} from '../../test_util.js'; export function reimagingProvisioningPageTest() { + /** + * ShimlessRma is needed to handle the 'transition-state' event used + * when handling calibration overall progress signals. + * @type {?ShimlessRma} + */ + let shimless_rma_component = null; + /** @type {?ReimagingProvisioningPage} */ let component = null; @@ -27,6 +35,8 @@ }); teardown(() => { + shimless_rma_component.remove(); + shimless_rma_component = null; component.remove(); component = null; service.reset(); @@ -38,6 +48,11 @@ function initializeWaitForProvisioningPage() { assertFalse(!!component); + shimless_rma_component = + /** @type {!ShimlessRma} */ (document.createElement('shimless-rma')); + assertTrue(!!shimless_rma_component); + document.body.appendChild(shimless_rma_component); + component = /** @type {!ReimagingProvisioningPage} */ ( document.createElement('reimaging-provisioning-page')); assertTrue(!!component); @@ -103,4 +118,52 @@ assertDeepEquals(savedResult, expectedResult); }); + + test('ProvisioningFailedBlockingRetry', async () => { + const resolver = new PromiseResolver(); + await initializeWaitForProvisioningPage(); + + const retryButton = + component.shadowRoot.querySelector('#retryProvisioningButton'); + assertTrue(retryButton.hidden); + + let callCount = 0; + service.retryProvisioning = () => { + callCount++; + return resolver.promise; + }; + service.triggerProvisioningObserver( + ProvisioningStatus.kFailedBlocking, 1.0, 0); + await flushTasks(); + + assertFalse(retryButton.hidden); + retryButton.click(); + + await flushTasks(); + assertEquals(1, callCount); + }); + + test('ProvisioningFailedNonBlockingRetry', async () => { + const resolver = new PromiseResolver(); + await initializeWaitForProvisioningPage(); + + const retryButton = + component.shadowRoot.querySelector('#retryProvisioningButton'); + assertTrue(retryButton.hidden); + + let callCount = 0; + service.retryProvisioning = () => { + callCount++; + return resolver.promise; + }; + service.triggerProvisioningObserver( + ProvisioningStatus.kFailedNonBlocking, 1.0, 0); + await flushTasks(); + + assertFalse(retryButton.hidden); + retryButton.click(); + + await flushTasks(); + assertEquals(1, callCount); + }); }
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/permission_item_test.js b/chrome/test/data/webui/settings/chromeos/app_management/permission_item_test.js index a6289d31..73ede3af 100644 --- a/chrome/test/data/webui/settings/chromeos/app_management/permission_item_test.js +++ b/chrome/test/data/webui/settings/chromeos/app_management/permission_item_test.js
@@ -31,12 +31,11 @@ ]) }; - // Add an arc app, and make it the currently selected app. + // Add an arc app, and pass it to permissionItem. const app = await fakeHandler.addApp(null, arcOptions); - app_management.AppManagementStore.getInstance().dispatch( - app_management.actions.updateSelectedAppId(app.id)); permissionItem = document.createElement('app-management-permission-item'); + permissionItem.app_ = app; }); test('Toggle permission', async () => { @@ -44,13 +43,15 @@ replaceBody(permissionItem); await fakeHandler.flushPipesForTesting(); - assertTrue(app_management.util.getPermissionValueBool( + assertTrue(getPermissionValueBool( permissionItem.app_, permissionItem.permissionType)); permissionItem.click(); await test_util.flushTasks(); await fakeHandler.flushPipesForTesting(); - assertFalse(app_management.util.getPermissionValueBool( - permissionItem.app_, permissionItem.permissionType)); + // Store gets updated permission. + const storeData = app_management.AppManagementStore.getInstance().data; + assertFalse(getPermissionValueBool( + storeData.apps[permissionItem.app_.id], permissionItem.permissionType)); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/test_util.js b/chrome/test/data/webui/settings/chromeos/app_management/test_util.js index ed67cae4..27ae275 100644 --- a/chrome/test/data/webui/settings/chromeos/app_management/test_util.js +++ b/chrome/test/data/webui/settings/chromeos/app_management/test_util.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. // clang-format off -// #import {BrowserProxy, FakePageHandler} from 'chrome://os-settings/chromeos/os_settings.js'; +// #import {BrowserProxy, FakePageHandler, AppManagementComponentBrowserProxy} from 'chrome://os-settings/chromeos/os_settings.js'; // #import {TestAppManagementStore} from './test_store.m.js'; // clang-format on @@ -28,6 +28,9 @@ browserProxy.callbackRouter.$.bindNewPipeAndPassRemote()); browserProxy.handler = fakeHandler.getRemote(); + const componentBrowserProxy = + AppManagementComponentBrowserProxy.getInstance(); + componentBrowserProxy.handler = fakeHandler; return fakeHandler; } @@ -120,4 +123,4 @@ } // The element is rendered and display !== 'none' return false; -} \ No newline at end of file +}
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index 5b44c0b..f5f5622 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -213,8 +213,8 @@ VLOG(1) << "Version " << kUpdaterVersion << ", command line: " << command_line->GetCommandLineString(); const int retval = HandleUpdaterCommands(updater_scope, command_line); - DVLOG(1) << __func__ << " (--" << GetUpdaterCommand(command_line) << ")" - << " returned " << retval << "."; + VLOG(1) << __func__ << " (--" << GetUpdaterCommand(command_line) << ")" + << " returned " << retval << "."; return retval; }
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 994662f5..22a5581 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -545,7 +545,7 @@ <message name="IDS_SCANNING_APP_PNG_OPTION_TEXT" desc="The text displayed for the PNG file type option."> PNG </message> - <!-- TODO (kmoed): Remove "translateable="false"" once string is confirmed. --> + <!-- TODO (gavinwill): Remove "translateable="false"" once string is confirmed. --> <message translateable="false" name="IDS_SCANNING_APP_SEARCHABLE_PDF_OPTION_TEXT" desc="The text displayed for the Searchable PDF file type option. This option utilizes the Object Character Recognition (OCR) service to generate a PDF file whose text has been added as a searchable layer."> Searchable PDF </message> @@ -2264,6 +2264,9 @@ <message name="IDS_SHIMLESS_RMA_PROVISIONING_FAILED_NON_BLOCKING" translateable="false" desc="Message to display when provisioning failed, but RMA can continue."> Failed, non blocking. </message> + <message name="IDS_SHIMLESS_RMA_PROVISIONING_FAILED_RETRY_BUTTON_LABEL" translateable="false" desc="The label for the button to retry provisioning."> + Retry provisioning + </message> <!-- Repair complete page --> <message name="IDS_SHIMLESS_RMA_REPAIR_COMPLETED" desc="Title for the page shown when the RMA process repair process is completed."> Repair completed
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt index 05233f5..ef4ad5d 100644 --- a/chromeos/profiles/orderfile.newest.txt +++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@ -chromeos-chrome-orderfile-field-98-4744.1-1639393599-benchmark-98.0.4758.7-r1.orderfile.xz +chromeos-chrome-orderfile-field-98-4744.1-1639393599-benchmark-98.0.4758.8-r1.orderfile.xz
diff --git a/chromeos/services/bluetooth_config/BUILD.gn b/chromeos/services/bluetooth_config/BUILD.gn index 1e23d45..c8ffa64 100644 --- a/chromeos/services/bluetooth_config/BUILD.gn +++ b/chromeos/services/bluetooth_config/BUILD.gn
@@ -157,6 +157,7 @@ "//ash/constants", "//base", "//base/test:test_support", + "//chromeos/services/bluetooth_config/public/cpp:unit_tests", "//components/session_manager/core", "//components/sync_preferences:test_support", "//components/user_manager:test_support",
diff --git a/chromeos/services/bluetooth_config/device_pairing_handler.cc b/chromeos/services/bluetooth_config/device_pairing_handler.cc index 39002a0..878c39d 100644 --- a/chromeos/services/bluetooth_config/device_pairing_handler.cc +++ b/chromeos/services/bluetooth_config/device_pairing_handler.cc
@@ -6,7 +6,10 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/time/default_clock.h" #include "components/device_event_log/device_event_log.h" +#include "device/bluetooth/bluetooth_common.h" +#include "device/bluetooth/chromeos/bluetooth_utils.h" namespace chromeos { namespace bluetooth_config { @@ -29,6 +32,47 @@ passkey_string}); } +device::BluetoothTransport GetBluetoothTransport( + device::BluetoothTransport type) { + switch (type) { + case device::BLUETOOTH_TRANSPORT_CLASSIC: + return device::BLUETOOTH_TRANSPORT_CLASSIC; + case device::BLUETOOTH_TRANSPORT_LE: + return device::BLUETOOTH_TRANSPORT_LE; + case device::BLUETOOTH_TRANSPORT_DUAL: + return device::BLUETOOTH_TRANSPORT_DUAL; + default: + return device::BLUETOOTH_TRANSPORT_INVALID; + } +} + +mojom::PairingResult GetPairingResult( + absl::optional<device::ConnectionFailureReason> failure_reason) { + if (!failure_reason) { + return mojom::PairingResult::kSuccess; + } + + switch (failure_reason.value()) { + case device::ConnectionFailureReason::kAuthTimeout: + FALLTHROUGH; + case device::ConnectionFailureReason::kAuthFailed: + return mojom::PairingResult::kAuthFailed; + + case device::ConnectionFailureReason::kUnknownError: + FALLTHROUGH; + case device::ConnectionFailureReason::kSystemError: + FALLTHROUGH; + case device::ConnectionFailureReason::kFailed: + FALLTHROUGH; + case device::ConnectionFailureReason::kUnknownConnectionError: + FALLTHROUGH; + case device::ConnectionFailureReason::kUnsupportedDevice: + FALLTHROUGH; + case device::ConnectionFailureReason::kNotConnectable: + return mojom::PairingResult::kNonAuthFailure; + } +} + } // namespace DevicePairingHandler::DevicePairingHandler( @@ -50,7 +94,7 @@ << "Could not cancel pairing for device to due device no longer being " "found, identifier: " << current_pairing_device_id_; - FinishCurrentPairingRequest(mojom::PairingResult::kAuthFailed); + FinishCurrentPairingRequest(device::ConnectionFailureReason::kAuthFailed); return; } device->CancelPairing(); @@ -72,6 +116,7 @@ // There should only be one PairDevice request at a time. CHECK(current_pairing_device_id_.empty()); + pairing_start_timestamp_ = base::Time(); pair_device_callback_ = std::move(callback); delegate_.reset(); @@ -84,7 +129,7 @@ BLUETOOTH_LOG(ERROR) << "Pairing failed due to Bluetooth not being " "enabled, device identifier: " << device_id; - FinishCurrentPairingRequest(mojom::PairingResult::kNonAuthFailure); + FinishCurrentPairingRequest(device::ConnectionFailureReason::kFailed); return; } @@ -95,7 +140,7 @@ BLUETOOTH_LOG(ERROR) << "Pairing failed due to device not being " "found, identifier: " << device_id; - FinishCurrentPairingRequest(mojom::PairingResult::kNonAuthFailure); + FinishCurrentPairingRequest(device::ConnectionFailureReason::kFailed); return; } @@ -168,7 +213,7 @@ void DevicePairingHandler::OnDeviceConnect( absl::optional<device::BluetoothDevice::ConnectErrorCode> error_code) { if (!error_code.has_value()) { - FinishCurrentPairingRequest(mojom::PairingResult::kSuccess); + FinishCurrentPairingRequest(absl::nullopt); NotifyFinished(); return; } @@ -182,21 +227,26 @@ case ErrorCode::ERROR_AUTH_FAILED: FALLTHROUGH; case ErrorCode::ERROR_AUTH_REJECTED: - FALLTHROUGH; + FinishCurrentPairingRequest(device::ConnectionFailureReason::kAuthFailed); + return; case ErrorCode::ERROR_AUTH_TIMEOUT: - FinishCurrentPairingRequest(mojom::PairingResult::kAuthFailed); + FinishCurrentPairingRequest( + device::ConnectionFailureReason::kAuthTimeout); return; case ErrorCode::ERROR_FAILED: FALLTHROUGH; case ErrorCode::ERROR_INPROGRESS: - FALLTHROUGH; - case ErrorCode::ERROR_UNKNOWN: - FALLTHROUGH; - case ErrorCode::ERROR_UNSUPPORTED_DEVICE: - FinishCurrentPairingRequest(mojom::PairingResult::kNonAuthFailure); + FinishCurrentPairingRequest(device::ConnectionFailureReason::kFailed); return; - + case ErrorCode::ERROR_UNKNOWN: + FinishCurrentPairingRequest( + device::ConnectionFailureReason::kUnknownError); + return; + case ErrorCode::ERROR_UNSUPPORTED_DEVICE: + FinishCurrentPairingRequest( + device::ConnectionFailureReason::kUnsupportedDevice); + return; default: BLUETOOTH_LOG(ERROR) << "Error code is invalid."; break; @@ -210,7 +260,7 @@ << "OnRequestPinCode failed due to device no longer being " "found, identifier: " << current_pairing_device_id_; - FinishCurrentPairingRequest(mojom::PairingResult::kNonAuthFailure); + FinishCurrentPairingRequest(device::ConnectionFailureReason::kFailed); return; } @@ -224,7 +274,7 @@ << "OnRequestPasskey failed due to device no longer being " "found, identifier: " << current_pairing_device_id_; - FinishCurrentPairingRequest(mojom::PairingResult::kNonAuthFailure); + FinishCurrentPairingRequest(device::ConnectionFailureReason::kFailed); return; } @@ -245,7 +295,7 @@ << "OnConfirmPairing failed due to device no longer being " "found, identifier: " << current_pairing_device_id_; - FinishCurrentPairingRequest(mojom::PairingResult::kNonAuthFailure); + FinishCurrentPairingRequest(device::ConnectionFailureReason::kFailed); return; } @@ -256,9 +306,19 @@ } void DevicePairingHandler::FinishCurrentPairingRequest( - mojom::PairingResult result) { + absl::optional<device::ConnectionFailureReason> failure_reason) { + device::BluetoothDevice* device = FindDevice(current_pairing_device_id_); current_pairing_device_id_.clear(); - std::move(pair_device_callback_).Run(result); + + device::BluetoothTransport transport = + device ? device->GetType() + : device::BluetoothTransport::BLUETOOTH_TRANSPORT_INVALID; + + device::RecordPairingResult( + failure_reason, GetBluetoothTransport(transport), + base::DefaultClock::GetInstance()->Now() - pairing_start_timestamp_); + + std::move(pair_device_callback_).Run(GetPairingResult(failure_reason)); } void DevicePairingHandler::OnDelegateDisconnect() {
diff --git a/chromeos/services/bluetooth_config/device_pairing_handler.h b/chromeos/services/bluetooth_config/device_pairing_handler.h index 61e5572..c9d0e42 100644 --- a/chromeos/services/bluetooth_config/device_pairing_handler.h +++ b/chromeos/services/bluetooth_config/device_pairing_handler.h
@@ -11,6 +11,7 @@ #include "chromeos/services/bluetooth_config/adapter_state_controller.h" #include "chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h" #include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/chromeos/bluetooth_utils.h" #include "mojo/public/cpp/bindings/remote.h" namespace chromeos { @@ -86,9 +87,10 @@ void OnRequestPasskey(const std::string& passkey); void OnConfirmPairing(bool confirmed); - // Invokes |pair_device_callback_| with |result| and resets - // this class' state to be ready for another pairing request. - void FinishCurrentPairingRequest(mojom::PairingResult result); + // Invokes |pair_device_callback_| and resets this class' state to be ready + // for another pairing request. + void FinishCurrentPairingRequest( + absl::optional<device::ConnectionFailureReason> failure_reason); void OnDelegateDisconnect(); @@ -97,6 +99,8 @@ // Flushes queued Mojo messages in unit tests. void FlushForTesting(); + base::Time pairing_start_timestamp_; + // The identifier of the device currently being paired with. This is null if // there is no in-progress pairing attempt. std::string current_pairing_device_id_;
diff --git a/chromeos/services/bluetooth_config/device_pairing_handler_impl_unittest.cc b/chromeos/services/bluetooth_config/device_pairing_handler_impl_unittest.cc index 2cd20d4..171f039 100644 --- a/chromeos/services/bluetooth_config/device_pairing_handler_impl_unittest.cc +++ b/chromeos/services/bluetooth_config/device_pairing_handler_impl_unittest.cc
@@ -6,10 +6,12 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "chromeos/services/bluetooth_config/fake_adapter_state_controller.h" #include "chromeos/services/bluetooth_config/fake_device_pairing_delegate.h" #include "chromeos/services/bluetooth_config/fake_key_entered_handler.h" +#include "device/bluetooth/chromeos/bluetooth_utils.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/bluetooth/test/mock_bluetooth_device.h" #include "testing/gmock/include/gmock/gmock.h" @@ -70,6 +72,18 @@ void DestroyHandler() { device_pairing_handler_.reset(); } + void CheckPairingHistograms(device::BluetoothTransportType type, + int type_count, + int failure_count, + int success_count) { + histogram_tester.ExpectBucketCount( + "Bluetooth.ChromeOS.Pairing.TransportType", type, type_count); + histogram_tester.ExpectBucketCount("Bluetooth.ChromeOS.Pairing.Result", + false, failure_count); + histogram_tester.ExpectBucketCount("Bluetooth.ChromeOS.Pairing.Result", + true, success_count); + } + void AddDevice(std::string* id_out, AuthType auth_type, uint32_t passkey = kDefaultPinCodeNum) { @@ -141,6 +155,10 @@ .WillByDefault(testing::Invoke( [this](const uint32_t passkey) { received_passkey_ = passkey; })); + ON_CALL(*mock_device, GetType()).WillByDefault(testing::Invoke([]() { + return device::BluetoothTransport::BLUETOOTH_TRANSPORT_CLASSIC; + })); + mock_devices_.push_back(std::move(mock_device)); } @@ -200,6 +218,7 @@ } std::string received_pin_code() const { return received_pin_code_; } uint32_t received_passkey() const { return received_passkey_; } + base::HistogramTester histogram_tester; private: std::vector<const device::BluetoothDevice*> GetMockDevices() { @@ -256,6 +275,10 @@ EXPECT_EQ(pairing_result(), mojom::PairingResult::kNonAuthFailure); EXPECT_EQ(num_pairing_attempt_finished_calls(), 0u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); + std::unique_ptr<FakeDevicePairingDelegate> delegate2 = PairDevice(device_id2); EXPECT_TRUE(delegate2->IsMojoPipeConnected()); @@ -263,6 +286,10 @@ InvokePendingConnectCallback(/*success=*/true); EXPECT_EQ(pairing_result(), mojom::PairingResult::kSuccess); EXPECT_EQ(num_pairing_attempt_finished_calls(), 1u); + + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/2, /*failure_count=*/1, + /*success_count=*/1); } TEST_F(DevicePairingHandlerImplTest, DisableBluetoothBeforePairing) { @@ -278,6 +305,11 @@ EXPECT_FALSE(HasPendingConnectCallback()); EXPECT_EQ(pairing_result(), mojom::PairingResult::kNonAuthFailure); EXPECT_EQ(num_pairing_attempt_finished_calls(), 0u); + + // Pairing result metric is only recorded for valid transport types. + CheckPairingHistograms(device::BluetoothTransportType::kInvalid, + /*type_count=*/1, /*failure_count=*/0, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, DisableBluetoothDuringPairing) { @@ -295,6 +327,9 @@ EXPECT_EQ(num_cancel_pairing_calls(), 1u); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); EXPECT_EQ(num_pairing_attempt_finished_calls(), 0u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, DestroyHandlerBeforeConnectFinishes) { @@ -311,6 +346,9 @@ // Destroying the handler should call OnPairingAttemptFinished(); EXPECT_EQ(num_pairing_attempt_finished_calls(), 1u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, DestroyHandlerAfterConnectFinishes) { @@ -332,6 +370,9 @@ // Destroying the handler shouldn't call OnPairingAttemptFinished(); EXPECT_EQ(num_pairing_attempt_finished_calls(), 1u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/0, + /*success_count=*/1); } TEST_F(DevicePairingHandlerImplTest, DisconnectDelegateBeforeConnectFinishes) { @@ -349,6 +390,9 @@ // Disconnecting the pipe should not call OnPairingAttemptFinished(). EXPECT_EQ(num_pairing_attempt_finished_calls(), 0u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, @@ -369,6 +413,9 @@ // Disconnecting the pipe should not call OnPairingAttemptFinished(). EXPECT_EQ(num_pairing_attempt_finished_calls(), 0u); + CheckPairingHistograms(device::BluetoothTransportType::kInvalid, + /*type_count=*/1, /*failure_count=*/0, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, @@ -389,6 +436,9 @@ // Disconnecting the pipe should not call OnPairingAttemptFinished(). EXPECT_EQ(num_pairing_attempt_finished_calls(), 0u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairDeviceNotFound) { @@ -396,6 +446,9 @@ EXPECT_FALSE(HasPendingConnectCallback()); EXPECT_EQ(pairing_result(), mojom::PairingResult::kNonAuthFailure); + CheckPairingHistograms(device::BluetoothTransportType::kInvalid, + /*type_count=*/1, /*failure_count=*/0, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthRequestPinCode) { @@ -410,6 +463,9 @@ InvokePendingConnectCallback(/*success=*/false); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthRequestPinCodeRemoveDevice) { @@ -427,6 +483,9 @@ // Failure result should be returned. EXPECT_TRUE(received_pin_code().empty()); EXPECT_EQ(pairing_result(), mojom::PairingResult::kNonAuthFailure); + CheckPairingHistograms(device::BluetoothTransportType::kInvalid, + /*type_count=*/1, /*failure_count=*/0, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthRequestPasskey) { @@ -441,6 +500,9 @@ InvokePendingConnectCallback(/*success=*/false); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthRequestPasskeyRemoveDevice) { @@ -458,6 +520,9 @@ // Failure result should be returned. EXPECT_EQ(received_passkey(), kUninitializedPasskey); EXPECT_EQ(pairing_result(), mojom::PairingResult::kNonAuthFailure); + CheckPairingHistograms(device::BluetoothTransportType::kInvalid, + /*type_count=*/1, /*failure_count=*/0, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthRequestPasskeyInvalidKey) { @@ -479,6 +544,9 @@ // CancelPairing() should not be called again since we already cancelled the // pairing. EXPECT_EQ(num_cancel_pairing_calls(), 1u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthDisplayPinCode) { @@ -497,6 +565,9 @@ InvokePendingConnectCallback(/*success=*/false); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthDisplayPinCodeDisconnectHandler) { @@ -515,6 +586,11 @@ EnterKeys(device_id, /*num_keys_entered=*/6u); // Number of keys entered should still be zero since pipe is disconnected. EXPECT_EQ(delegate->key_entered_handler()->num_keys_entered(), 0); + + // Metrics is not recorded because pairing did not finish. + CheckPairingHistograms(device::BluetoothTransportType::kInvalid, + /*type_count=*/0, /*failure_count=*/0, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthDisplayPasskey) { @@ -533,6 +609,9 @@ InvokePendingConnectCallback(/*success=*/false); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthDisplayPasskeyPadZeroes) { @@ -547,6 +626,9 @@ InvokePendingConnectCallback(/*success=*/false); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); // Pair a new device. std::string device_id2; @@ -557,6 +639,10 @@ // Passkey displayed should be a 6-digit number, padded with zeroes if needed. EXPECT_EQ(delegate2->displayed_passkey(), "000000"); EXPECT_TRUE(delegate2->key_entered_handler()->IsMojoPipeConnected()); + // Expect value to be 1 since pairing was not finished. + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthConfirmPasskey) { @@ -574,6 +660,9 @@ InvokePendingConnectCallback(/*success=*/false); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); // Pair a new device. std::string device_id2; @@ -592,6 +681,9 @@ // ConfirmPairing() should not be called again, CancelPairing() should. EXPECT_EQ(num_confirm_pairing_calls(), 1u); EXPECT_EQ(num_cancel_pairing_calls(), 1u); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/2, /*failure_count=*/2, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthConfirmPasskeyRemoveDevice) { @@ -611,6 +703,9 @@ // Failure result should be returned. EXPECT_EQ(num_confirm_pairing_calls(), 0u); EXPECT_EQ(pairing_result(), mojom::PairingResult::kNonAuthFailure); + CheckPairingHistograms(device::BluetoothTransportType::kInvalid, + /*type_count=*/1, /*failure_count=*/0, + /*success_count=*/0); } TEST_F(DevicePairingHandlerImplTest, PairAuthAuthorizePairing) { @@ -626,6 +721,9 @@ InvokePendingConnectCallback(/*success=*/false); EXPECT_EQ(pairing_result(), mojom::PairingResult::kAuthFailed); + CheckPairingHistograms(device::BluetoothTransportType::kClassic, + /*type_count=*/1, /*failure_count=*/1, + /*success_count=*/0); } } // namespace bluetooth_config
diff --git a/chromeos/services/bluetooth_config/public/cpp/BUILD.gn b/chromeos/services/bluetooth_config/public/cpp/BUILD.gn index 99e7b17..21e33f0 100644 --- a/chromeos/services/bluetooth_config/public/cpp/BUILD.gn +++ b/chromeos/services/bluetooth_config/public/cpp/BUILD.gn
@@ -8,6 +8,8 @@ sources = [ "cros_bluetooth_config_util.cc", "cros_bluetooth_config_util.h", + "device_image_info.cc", + "device_image_info.h", ] deps = [ @@ -15,3 +17,16 @@ "//chromeos/services/bluetooth_config/public/mojom", ] } + +source_set("unit_tests") { + testonly = true + + sources = [ "device_image_info_unittest.cc" ] + + deps = [ + ":cpp", + "//base", + "//base/test:test_support", + "//testing/gtest", + ] +}
diff --git a/chromeos/services/bluetooth_config/public/cpp/device_image_info.cc b/chromeos/services/bluetooth_config/public/cpp/device_image_info.cc new file mode 100644 index 0000000..d333769 --- /dev/null +++ b/chromeos/services/bluetooth_config/public/cpp/device_image_info.cc
@@ -0,0 +1,75 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/bluetooth_config/public/cpp/device_image_info.h" + +#include "base/values.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace chromeos { +namespace bluetooth_config { + +namespace { + +constexpr char kDefaultImageKey[] = "Default"; +constexpr char kLeftBudImageKey[] = "LeftBud"; +constexpr char kRightBudImageKey[] = "RightBud"; +constexpr char kCaseImageKey[] = "Case"; + +} // namespace + +DeviceImageInfo::DeviceImageInfo(const std::string& default_image, + const std::string& left_bud_image, + const std::string& right_bud_image, + const std::string& case_image) + : default_image_(default_image), + left_bud_image_(left_bud_image), + right_bud_image_(right_bud_image), + case_image_(case_image) {} + +DeviceImageInfo::DeviceImageInfo() = default; + +DeviceImageInfo::DeviceImageInfo(const DeviceImageInfo&) = default; + +DeviceImageInfo& DeviceImageInfo::operator=(const DeviceImageInfo&) = default; + +DeviceImageInfo::~DeviceImageInfo() = default; + +// static +absl::optional<DeviceImageInfo> DeviceImageInfo::FromDictionaryValue( + const base::Value& value) { + if (!value.is_dict()) + return absl::nullopt; + + const std::string* default_image = value.FindStringKey(kDefaultImageKey); + if (!default_image) + return absl::nullopt; + + const std::string* left_bud_image = value.FindStringKey(kLeftBudImageKey); + if (!left_bud_image) + return absl::nullopt; + + const std::string* right_bud_image = value.FindStringKey(kRightBudImageKey); + if (!right_bud_image) + return absl::nullopt; + + const std::string* case_image = value.FindStringKey(kCaseImageKey); + if (!case_image) + return absl::nullopt; + + return DeviceImageInfo(*default_image, *left_bud_image, *right_bud_image, + *case_image); +} + +base::Value DeviceImageInfo::ToDictionaryValue() const { + base::Value dictionary(base::Value::Type::DICTIONARY); + dictionary.SetKey(kDefaultImageKey, base::Value(default_image_)); + dictionary.SetKey(kLeftBudImageKey, base::Value(left_bud_image_)); + dictionary.SetKey(kRightBudImageKey, base::Value(right_bud_image_)); + dictionary.SetKey(kCaseImageKey, base::Value(case_image_)); + return dictionary; +} + +} // namespace bluetooth_config +} // namespace chromeos \ No newline at end of file
diff --git a/chromeos/services/bluetooth_config/public/cpp/device_image_info.h b/chromeos/services/bluetooth_config/public/cpp/device_image_info.h new file mode 100644 index 0000000..694484a --- /dev/null +++ b/chromeos/services/bluetooth_config/public/cpp/device_image_info.h
@@ -0,0 +1,62 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_BLUETOOTH_CONFIG_PUBLIC_CPP_DEVICE_IMAGE_INFO_H_ +#define CHROMEOS_SERVICES_BLUETOOTH_CONFIG_PUBLIC_CPP_DEVICE_IMAGE_INFO_H_ + +#include <string> + +#include "base/values.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace ash { +namespace quick_pair { + +class DeviceImageStore; + +} // namespace quick_pair +} // namespace ash + +namespace chromeos { +namespace bluetooth_config { + +// Stores images as base64 encoded data URLs that can be displayed in UX. +// Provides convenience methods to convert to and from a dictionary so that +// it can be stored on disk. +class DeviceImageInfo { + public: + // Returns null if the provided value does not have the required dictionary + // properties. Should be provided a dictionary created via + // ToDictionaryValue(). + static absl::optional<DeviceImageInfo> FromDictionaryValue( + const base::Value& value); + + DeviceImageInfo(const std::string& default_image, + const std::string& left_bud_image, + const std::string& right_bud_image, + const std::string& case_image); + DeviceImageInfo(); + DeviceImageInfo(const DeviceImageInfo&); + DeviceImageInfo& operator=(const DeviceImageInfo&); + ~DeviceImageInfo(); + + base::Value ToDictionaryValue() const; + + const std::string& default_image() const { return default_image_; } + const std::string& left_bud_image() const { return left_bud_image_; } + const std::string& right_bud_image() const { return right_bud_image_; } + const std::string& case_image() const { return case_image_; } + + private: + friend class ash::quick_pair::DeviceImageStore; + std::string default_image_; + std::string left_bud_image_; + std::string right_bud_image_; + std::string case_image_; +}; + +} // namespace bluetooth_config +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_BLUETOOTH_CONFIG_PUBLIC_CPP_DEVICE_IMAGE_INFO_H_ \ No newline at end of file
diff --git a/chromeos/services/bluetooth_config/public/cpp/device_image_info_unittest.cc b/chromeos/services/bluetooth_config/public/cpp/device_image_info_unittest.cc new file mode 100644 index 0000000..443fe9ac --- /dev/null +++ b/chromeos/services/bluetooth_config/public/cpp/device_image_info_unittest.cc
@@ -0,0 +1,65 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/bluetooth_config/public/cpp/device_image_info.h" + +#include "base/values.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace chromeos { +namespace bluetooth_config { + +namespace { + +constexpr char kTestDefaultImage[] = "default"; +constexpr char kTestLeftBudImage[] = "left_bud"; +constexpr char kTestRightBudImage[] = "right_bud"; +constexpr char kTestCaseImage[] = "case_image"; + +} // namespace + +TEST(DeviceImageInfoTest, ToAndFromDictionaryValueValid) { + DeviceImageInfo image_info(kTestDefaultImage, kTestLeftBudImage, + kTestRightBudImage, kTestCaseImage); + + base::Value image_info_dict = image_info.ToDictionaryValue(); + absl::optional<DeviceImageInfo> image_info_copy = + DeviceImageInfo::FromDictionaryValue(image_info_dict); + EXPECT_TRUE(image_info_copy); + + EXPECT_EQ(kTestDefaultImage, image_info_copy->default_image()); + EXPECT_EQ(kTestLeftBudImage, image_info_copy->left_bud_image()); + EXPECT_EQ(kTestRightBudImage, image_info_copy->right_bud_image()); + EXPECT_EQ(kTestCaseImage, image_info_copy->case_image()); +} + +TEST(DeviceImageInfoTest, ToAndFromDictionaryValueValidDefaultConstructor) { + // Ensure the default construction of DeviceImageInfo works with the + // to/from dictionary methods. + DeviceImageInfo image_info; + + base::Value image_info_dict = image_info.ToDictionaryValue(); + absl::optional<DeviceImageInfo> image_info_copy = + DeviceImageInfo::FromDictionaryValue(image_info_dict); + EXPECT_TRUE(image_info_copy); + + EXPECT_TRUE(image_info_copy->default_image().empty()); + EXPECT_TRUE(image_info_copy->left_bud_image().empty()); + EXPECT_TRUE(image_info_copy->right_bud_image().empty()); + EXPECT_TRUE(image_info_copy->case_image().empty()); +} + +TEST(DeviceImageInfoTest, FromDictionaryValueInvalid) { + // Should correctly handle dictionaries with missing fields. + base::Value invalid_dict(base::Value::Type::DICTIONARY); + EXPECT_FALSE(DeviceImageInfo::FromDictionaryValue(invalid_dict)); + + // Should correctly handle non-dictionary values. + base::Value not_a_dict(777); + EXPECT_FALSE(DeviceImageInfo::FromDictionaryValue(not_a_dict)); +} + +} // namespace bluetooth_config +} // namespace chromeos \ No newline at end of file
diff --git a/components/content_creation/reactions/core/reaction_list_factory.cc b/components/content_creation/reactions/core/reaction_list_factory.cc index 8ade3aca..3e33692 100644 --- a/components/content_creation/reactions/core/reaction_list_factory.cc +++ b/components/content_creation/reactions/core/reaction_list_factory.cc
@@ -32,8 +32,12 @@ std::vector<ReactionMetadata> BuildReactionMetadata() { return { ReactionMetadata( + ReactionType::LAUGH_CRY, + l10n_util::GetStringUTF8(IDS_LIGHTWEIGHT_REACTIONS_TEARS_OF_JOY), + MakeThumbnailUrl("laughcry"), MakeReactionUrl("laughcry"), 48), + ReactionMetadata( ReactionType::HEART, - l10n_util::GetStringUTF8(IDS_LIGHTWEIGHT_REACTIONS_HEART), + l10n_util::GetStringUTF8(IDS_LIGHTWEIGHT_REACTIONS_BEATING_HEART), MakeThumbnailUrl("heart"), MakeReactionUrl("heart"), 48), ReactionMetadata( ReactionType::EMOTIONAL,
diff --git a/components/content_creation/reactions/core/reaction_types.h b/components/content_creation/reactions/core/reaction_types.h index d8cd5c7..b2a00f65 100644 --- a/components/content_creation/reactions/core/reaction_types.h +++ b/components/content_creation/reactions/core/reaction_types.h
@@ -23,8 +23,9 @@ THANKS = 6, UNSURE = 7, HEART = 8, + LAUGH_CRY = 9, - MAX_VALUE = HEART + MAX_VALUE = LAUGH_CRY }; } // namespace content_creation
diff --git a/components/content_creation_strings.grdp b/components/content_creation_strings.grdp index d01cad0..e6d92e6a 100644 --- a/components/content_creation_strings.grdp +++ b/components/content_creation_strings.grdp
@@ -35,8 +35,12 @@ </message> <!-- Lightweight Reactions names, currently only used on Android. --> - <message name="IDS_LIGHTWEIGHT_REACTIONS_HEART" is_accessibility_with_no_ui="true" desc="The accessibility text to read when the heart reaction is selected."> - Heart + <message name="IDS_LIGHTWEIGHT_REACTIONS_TEARS_OF_JOY" is_accessibility_with_no_ui="true" desc="The accessibility text to read when the tears of joy reaction is selected."> + Tears of Joy + </message> + + <message name="IDS_LIGHTWEIGHT_REACTIONS_BEATING_HEART" is_accessibility_with_no_ui="true" desc="The accessibility text to read when the beating heart reaction is selected."> + Beating Heart </message> <message name="IDS_LIGHTWEIGHT_REACTIONS_CLAPPING" is_accessibility_with_no_ui="true" desc="The accessibility text to read when the clapping reaction is selected.">
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index aa92466..ec18cfe 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -963,6 +963,10 @@ 3); // Zero Suggest +const base::FeatureParam<bool> kZeroSuggestCacheCounterfactual( + &omnibox::kZeroSuggestPrefetching, + "ZeroSuggestCacheCounterfactual", + false); const base::FeatureParam<int> kZeroSuggestCacheDurationSec( &omnibox::kZeroSuggestPrefetching, "ZeroSuggestCacheDurationSec",
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index 9f5b032..95498c9 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -552,6 +552,13 @@ kShortBookmarkSuggestionsByTotalInputLengthThreshold; // Zero Suggest +// Indicates whether the user is in the counterfactual group in the experiment +// for prefetching zero prefix suggestions on the NTP. Users in the +// counterfactual group issue a follow-up non-cacheable request if the response +// is loaded from the HTTP cache in order to determine HTTP cache validity. +// This param is tied to omnibox::kZeroSuggestPrefetching and is to be used when +// a valid HTTP cache duration is provided via kZeroSuggestCacheDurationSec. +extern const base::FeatureParam<bool> kZeroSuggestCacheCounterfactual; // Specifies the HTTP cache duration for the zero prefix suggest responses. If // the provided value is a positive number, the cache duration will be sent as a // query string parameter in the zero suggest requests and relayed back in the
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc index 402c279..30e6903 100644 --- a/components/omnibox/browser/zero_suggest_provider.cc +++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -71,7 +71,8 @@ // Keeps track of how many Suggest requests are sent, how many requests were // invalidated, e.g., due to user starting to type, how many responses were -// received, and how many of those responses were loaded from the HTTP cache. +// received, how many of those responses were loaded from the HTTP cache, and of +// those cached responses, how many were out-of-date. // These values are written to logs. New enum values can be added, but existing // enums must never be renumbered or deleted and reused. enum ZeroSuggestRequestsHistogramValue { @@ -79,6 +80,7 @@ ZERO_SUGGEST_REQUEST_INVALIDATED = 2, ZERO_SUGGEST_RESPONSE_RECEIVED = 3, ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE = 4, + ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE_IS_OUT_OF_DATE = 5, ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE }; @@ -222,7 +224,8 @@ weak_ptr_factory_.GetWeakPtr(), is_prefetch), base::BindOnce(&ZeroSuggestProvider::OnURLLoadComplete, base::Unretained(this) /* this owns SimpleURLLoader */, - is_prefetch, base::TimeTicks::Now())); + search_terms_args, is_prefetch, + base::TimeTicks::Now())); } void ZeroSuggestProvider::Stop(bool clear_cached_results, @@ -233,6 +236,7 @@ } loader_.reset(); is_prefetch_loader_ = false; + counterfactual_loader_.reset(); done_ = true; result_type_running_ = NONE; @@ -342,6 +346,7 @@ } void ZeroSuggestProvider::OnURLLoadComplete( + TemplateURLRef::SearchTermsArgs search_terms_args, bool is_prefetch, base::TimeTicks request_time, const network::SimpleURLLoader* source, @@ -352,9 +357,33 @@ LogOmniboxZeroSuggestRequestRoundTripTime( base::TimeTicks::Now() - request_time, is_prefetch); LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_RESPONSE_RECEIVED, is_prefetch); + if (source->LoadedFromCache()) { LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE, is_prefetch); + + // Issue a follow-up non-cacheable request in the counterfactual arm if the + // response is loaded from the HTTP cache. The new response is compared + // against the original cached response to determine HTTP cache validity. + if (OmniboxFieldTrial::kZeroSuggestCacheCounterfactual.Get() && + OmniboxFieldTrial::kZeroSuggestCacheDurationSec.Get() > 0) { + // Make sure the request is not cacheable. + search_terms_args.zero_suggest_cache_duration_sec = 0; + + const std::string& original_response = *response_body; + client() + ->GetRemoteSuggestionsService(/*create_if_necessary=*/true) + ->CreateSuggestionsRequest( + search_terms_args, client()->GetTemplateURLService(), + base::BindOnce( + &ZeroSuggestProvider:: + OnRemoteSuggestionsCounterfactualLoaderAvailable, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce( + &ZeroSuggestProvider::OnCounterfactualURLLoadComplete, + base::Unretained(this) /* this owns SimpleURLLoader */, + is_prefetch, original_response)); + } } const bool results_updated = @@ -374,6 +403,22 @@ } } +void ZeroSuggestProvider::OnCounterfactualURLLoadComplete( + bool original_is_prefetch, + const std::string& original_response, + const network::SimpleURLLoader* source, + std::unique_ptr<std::string> response) { + DCHECK(!source->LoadedFromCache()); + + if (original_response != *response) { + LogOmniboxZeroSuggestRequest( + ZERO_SUGGEST_RESPONSE_LOADED_FROM_HTTP_CACHE_IS_OUT_OF_DATE, + original_is_prefetch); + } + + counterfactual_loader_.reset(); +} + bool ZeroSuggestProvider::UpdateResults(const std::string& json_data) { std::unique_ptr<base::Value> data( SearchSuggestionParser::DeserializeJsonData(json_data)); @@ -442,6 +487,11 @@ LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT, is_prefetch); } +void ZeroSuggestProvider::OnRemoteSuggestionsCounterfactualLoaderAvailable( + std::unique_ptr<network::SimpleURLLoader> loader) { + counterfactual_loader_ = std::move(loader); +} + void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() { matches_.clear();
diff --git a/components/omnibox/browser/zero_suggest_provider.h b/components/omnibox/browser/zero_suggest_provider.h index 82d6314..8320e36 100644 --- a/components/omnibox/browser/zero_suggest_provider.h +++ b/components/omnibox/browser/zero_suggest_provider.h
@@ -130,11 +130,22 @@ // Called when the network request for suggestions has completed. // `is_prefetch` and `request_time` are bound to this callback and indicate if // the request is a prefetch one and the time it was issued respectively. - void OnURLLoadComplete(bool is_prefetch, + void OnURLLoadComplete(TemplateURLRef::SearchTermsArgs search_terms_args, + bool is_prefetch, base::TimeTicks request_time, const network::SimpleURLLoader* source, std::unique_ptr<std::string> response_body); + // Called when the counterfactual network request for suggestions has + // completed. `original_is_prefetch` and `original_response` are bound to this + // callback and indicate if the original request was a prefetch one and the + // original cached response received in OnURLLoadComplete() respectively. + void OnCounterfactualURLLoadComplete( + bool original_is_prefetch, + const std::string& original_response, + const network::SimpleURLLoader* source, + std::unique_ptr<std::string> response_body); + // The function updates |results_| with data parsed from |json_data|. // // * The update is not performed if |json_data| is invalid. @@ -170,6 +181,11 @@ bool is_prefetch, std::unique_ptr<network::SimpleURLLoader> loader); + // Serves the same purpose as OnRemoteSuggestionsLoaderAvailable for the + // counterfactual requests. + void OnRemoteSuggestionsCounterfactualLoaderAvailable( + std::unique_ptr<network::SimpleURLLoader> loader); + // Whether zero suggest suggestions are allowed in the given context. // Invoked early, confirms all the external conditions for ZeroSuggest are // met. @@ -220,6 +236,9 @@ // when the provider is stopped. bool is_prefetch_loader_; + // Loader used to retrieve counterfactual results. + std::unique_ptr<network::SimpleURLLoader> counterfactual_loader_; + // The verbatim match for the current text, which is always a URL. AutocompleteMatch current_text_match_;
diff --git a/components/optimization_guide/core/hints_manager.cc b/components/optimization_guide/core/hints_manager.cc index 394d4c18..800f4243 100644 --- a/components/optimization_guide/core/hints_manager.cc +++ b/components/optimization_guide/core/hints_manager.cc
@@ -302,6 +302,7 @@ hint_cache_( std::make_unique<HintCache>(hint_store, features::MaxHostKeyedHintCacheSize())), + batch_update_hints_fetchers_(features::MaxConcurrentBatchUpdateFetches()), page_navigation_hints_fetchers_( features::MaxConcurrentPageNavigationFetches()), hints_fetcher_factory_(std::make_unique<HintsFetcherFactory>( @@ -671,11 +672,6 @@ if (top_hosts.empty() && active_tab_urls_to_refresh.empty()) return; - if (!batch_update_hints_fetcher_) { - DCHECK(hints_fetcher_factory_); - batch_update_hints_fetcher_ = hints_fetcher_factory_->BuildInstance(); - } - // Add hosts of active tabs to list of hosts to fetch for. Since we are mainly // fetching for updated information on tabs, add those to the front of the // list. @@ -695,7 +691,12 @@ registered_optimization_types_, active_tab_urls_to_refresh, top_hosts); - batch_update_hints_fetcher_->FetchOptimizationGuideServiceHints( + if (!active_tabs_batch_update_hints_fetcher_) { + DCHECK(hints_fetcher_factory_); + active_tabs_batch_update_hints_fetcher_ = + hints_fetcher_factory_->BuildInstance(); + } + active_tabs_batch_update_hints_fetcher_->FetchOptimizationGuideServiceHints( top_hosts, active_tab_urls_to_refresh, registered_optimization_types_, proto::CONTEXT_BATCH_UPDATE_ACTIVE_TABS, application_locale_, base::BindOnce(&HintsManager::OnHintsForActiveTabsFetched, @@ -729,9 +730,12 @@ const base::flat_set<std::string>& page_navigation_hosts_requested, absl::optional<std::unique_ptr<proto::GetHintsResponse>> get_hints_response) { + if (navigation_url) { + CleanUpFetcherForNavigation(*navigation_url); + } + if (!get_hints_response.has_value() || !get_hints_response.value()) { if (navigation_url) { - CleanUpFetcherForNavigation(*navigation_url); PrepareToInvokeRegisteredCallbacks(*navigation_url); } return; @@ -776,7 +780,6 @@ navigation_data_weak_ptr.MaybeValid()); if (navigation_url) { - CleanUpFetcherForNavigation(*navigation_url); PrepareToInvokeRegisteredCallbacks(*navigation_url); } } @@ -809,7 +812,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!url.has_host()) { - std::move(callback).Run(); + MaybeRunUpdateClosure(std::move(callback)); return; } @@ -825,34 +828,44 @@ std::move(callback))); } -void HintsManager::FetchHintsForURLs(std::vector<GURL> target_urls, +void HintsManager::FetchHintsForURLs(const std::vector<GURL>& urls, proto::RequestContext request_context) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Collect hosts, stripping duplicates, but preserving the ordering. + InsertionOrderedSet<GURL> target_urls; InsertionOrderedSet<std::string> target_hosts; - for (const auto& url : target_urls) { + for (const auto& url : urls) { target_hosts.insert(url.host()); + target_urls.insert(url); } if (target_hosts.empty() && target_urls.empty()) return; - if (!batch_update_hints_fetcher_) { - DCHECK(hints_fetcher_factory_); - batch_update_hints_fetcher_ = hints_fetcher_factory_->BuildInstance(); - } + MaybeLogGetHintRequestInfo(request_context, registered_optimization_types_, + target_urls.vector(), target_hosts.vector()); + + std::pair<int32_t, HintsFetcher*> request_id_and_fetcher = + CreateAndTrackBatchUpdateHintsFetcher(); // Use the batch update hints fetcher for fetches off the SRP since we are - // not fetching for the current navigation, even though we are fetching using - // the page navigation context. However, since we do want to load the hints - // returned, we pass this through to the page navigation callback. - batch_update_hints_fetcher_->FetchOptimizationGuideServiceHints( - target_hosts.vector(), target_urls, registered_optimization_types_, - request_context, application_locale_, - base::BindOnce(&HintsManager::OnPageNavigationHintsFetched, - weak_ptr_factory_.GetWeakPtr(), nullptr, absl::nullopt, - target_urls, target_hosts.set())); + // not fetching for the current navigation. + // + // Caller does not expect to be notified when relevant hints have been fetched + // and stored. + request_id_and_fetcher.second->FetchOptimizationGuideServiceHints( + target_hosts.vector(), target_urls.vector(), + registered_optimization_types_, request_context, application_locale_, + base::BindOnce( + &HintsManager::OnBatchUpdateHintsFetched, + weak_ptr_factory_.GetWeakPtr(), request_id_and_fetcher.first, + request_context, target_hosts.set(), target_urls.set(), + registered_optimization_types_, + base::DoNothingAs<void( + const GURL&, const base::flat_map< + proto::OptimizationType, + OptimizationGuideDecisionWithMetadata>&)>())); } void HintsManager::OnHintLoaded(base::OnceClosure callback, @@ -864,7 +877,7 @@ // Run the callback now that the hint is loaded. This is used as a signal by // tests. - std::move(callback).Run(); + MaybeRunUpdateClosure(std::move(callback)); } void HintsManager::RegisterOptimizationTypes( @@ -1015,46 +1028,51 @@ urls_to_fetch.vector(), hosts_to_fetch.vector()); // Fetch the data for the entries we don't have all information for. - if (!batch_update_hints_fetcher_) { - DCHECK(hints_fetcher_factory_); - batch_update_hints_fetcher_ = hints_fetcher_factory_->BuildInstance(); - } - batch_update_hints_fetcher_->FetchOptimizationGuideServiceHints( + std::pair<int32_t, HintsFetcher*> request_id_and_fetcher = + CreateAndTrackBatchUpdateHintsFetcher(); + request_id_and_fetcher.second->FetchOptimizationGuideServiceHints( hosts_to_fetch.vector(), urls_to_fetch.vector(), registered_optimization_types_, request_context, application_locale_, - base::BindOnce(&HintsManager::OnOnDemandHintsFetched, - weak_ptr_factory_.GetWeakPtr(), hosts_to_fetch.set(), - urls_to_fetch.set(), optimization_types, callback)); + base::BindOnce(&HintsManager::OnBatchUpdateHintsFetched, + weak_ptr_factory_.GetWeakPtr(), + request_id_and_fetcher.first, request_context, + hosts_to_fetch.set(), urls_to_fetch.set(), + optimization_types, callback)); } -void HintsManager::OnOnDemandHintsFetched( +void HintsManager::OnBatchUpdateHintsFetched( + int32_t request_id, + proto::RequestContext request_context, const base::flat_set<std::string>& hosts_requested, const base::flat_set<GURL>& urls_requested, const base::flat_set<proto::OptimizationType>& optimization_types, OnDemandOptimizationGuideDecisionRepeatingCallback callback, absl::optional<std::unique_ptr<proto::GetHintsResponse>> get_hints_response) { + CleanUpBatchUpdateHintsFetcher(request_id); + if (!get_hints_response.has_value() || !get_hints_response.value()) { - OnReadyToInvokeOnDemandHintsCallbackForURLs(urls_requested, - optimization_types, callback); + OnBatchUpdateHintsStored(urls_requested, optimization_types, callback); return; } - // TODO(crbug/1278015: Figure out if the update time duration is the right + // TODO(crbug/1278015): Figure out if the update time duration is the right // one. hint_cache_->UpdateFetchedHints( std::move(*get_hints_response), clock_->Now() + features::GetActiveTabsFetchRefreshDuration(), hosts_requested, urls_requested, - base::BindOnce(&HintsManager::OnReadyToInvokeOnDemandHintsCallbackForURLs, + base::BindOnce(&HintsManager::OnBatchUpdateHintsStored, weak_ptr_factory_.GetWeakPtr(), urls_requested, optimization_types, callback)); - if (switches::IsDebugLogsEnabled()) - DVLOG(0) << "OptimizationGuide: OnOnDemandHintsFetched complete"; + if (switches::IsDebugLogsEnabled()) { + DVLOG(0) << "OptimizationGuide: OnBatchUpdateHintsFetched for " + << proto::RequestContext_Name(request_context) << " complete"; + } } -void HintsManager::OnReadyToInvokeOnDemandHintsCallbackForURLs( +void HintsManager::OnBatchUpdateHintsStored( const base::flat_set<GURL>& urls, const base::flat_set<proto::OptimizationType>& optimization_types, OnDemandOptimizationGuideDecisionRepeatingCallback callback) { @@ -1071,6 +1089,27 @@ } } +std::pair<int32_t, HintsFetcher*> +HintsManager::CreateAndTrackBatchUpdateHintsFetcher() { + DCHECK(hints_fetcher_factory_); + std::unique_ptr<HintsFetcher> hints_fetcher = + hints_fetcher_factory_->BuildInstance(); + HintsFetcher* hints_fetcher_ptr = hints_fetcher.get(); + batch_update_hints_fetchers_.Put(batch_update_hints_fetcher_request_id_++, + std::move(hints_fetcher)); + UMA_HISTOGRAM_COUNTS_100( + "OptimizationGuide.HintsManager.ConcurrentBatchUpdateFetches", + batch_update_hints_fetchers_.size()); + return std::make_pair(batch_update_hints_fetcher_request_id_, + hints_fetcher_ptr); +} + +void HintsManager::CleanUpBatchUpdateHintsFetcher(int32_t request_id) { + auto it = batch_update_hints_fetchers_.Peek(request_id); + if (it != batch_update_hints_fetchers_.end()) + batch_update_hints_fetchers_.Erase(it); +} + void HintsManager::InvokeOnDemandHintsCallbackForURL( const GURL& url, const base::flat_set<proto::OptimizationType>& optimization_types,
diff --git a/components/optimization_guide/core/hints_manager.h b/components/optimization_guide/core/hints_manager.h index 549652e..94aaa3d 100644 --- a/components/optimization_guide/core/hints_manager.h +++ b/components/optimization_guide/core/hints_manager.h
@@ -134,11 +134,6 @@ // and in memory ones. void ClearHostKeyedHints(); - // Returns the current batch update hints fetcher. - HintsFetcher* batch_update_hints_fetcher() const { - return batch_update_hints_fetcher_.get(); - } - // Overrides |hints_fetcher_factory| for testing. void SetHintsFetcherFactoryForTesting( std::unique_ptr<HintsFetcherFactory> hints_fetcher_factory); @@ -164,7 +159,7 @@ void OnDeferredStartup(); // Fetch the hints for the given URLs with the provided |request_context|. - void FetchHintsForURLs(std::vector<GURL> target_urls, + void FetchHintsForURLs(const std::vector<GURL>& target_urls, proto::RequestContext request_context); // PushNotificationManager::Delegate: @@ -194,6 +189,7 @@ private: friend class ::OptimizationGuideTestAppInterfaceWrapper; + friend class HintsManagerTest; // Processes the optimization filters contained in the hints component. void ProcessOptimizationFilters( @@ -249,10 +245,12 @@ absl::optional<std::unique_ptr<proto::GetHintsResponse>> get_hints_response); - // Called when the on demand hints have been fetched from the remote + // Called when the batch update hints have been fetched from the remote // Optimization Guide Service and are ready for parsing. This is used when - // fetching hints on demand. - void OnOnDemandHintsFetched( + // fetching hints on demand or from SRP. + void OnBatchUpdateHintsFetched( + int32_t request_id, + proto::RequestContext request_context, const base::flat_set<std::string>& hosts_fetched, const base::flat_set<GURL>& urls_fetched, const base::flat_set<proto::OptimizationType>& optimization_types, @@ -260,13 +258,26 @@ absl::optional<std::unique_ptr<proto::GetHintsResponse>> get_hints_response); - // Called when information is ready such that we can invoke the on-demand - // hints callback. - void OnReadyToInvokeOnDemandHintsCallbackForURLs( + // Called when information is ready such that we can invoke any callbacks that + // require returning decisions to consumer features. + // + // TODO(crbug/1279536): Clean this up when we clean up some of the existing + // interfaces. + void OnBatchUpdateHintsStored( const base::flat_set<GURL>& urls_fetched, const base::flat_set<proto::OptimizationType>& optimization_types, OnDemandOptimizationGuideDecisionRepeatingCallback callback); + // Creates a hints fetcher and stores it in |batch_update_hints_fetchers_| and + // returns the request ID associated with the fetch. It is expected to call + // `CleanUpBatchUpdateHintsFetcher` with the returned request ID once the + // fetch has finished. + std::pair<int32_t, HintsFetcher*> CreateAndTrackBatchUpdateHintsFetcher(); + + // Called to inform |this| that the batch fetcher with |request_id| is no + // longer needed removes the request from |batch_update_hints_fetchers_| + void CleanUpBatchUpdateHintsFetcher(int32_t request_id); + // Returns decisions for |url| and |optimization_types| based on what's cached // locally. base::flat_map<proto::OptimizationType, OptimizationGuideDecisionWithMetadata> @@ -366,6 +377,20 @@ HintsFetcherFactory* GetHintsFetcherFactory(); + // Returns the number of batch update hints fetches initiated. + // + // Exposed here for testing. + int32_t num_batch_update_hints_fetches_initiated() const { + return batch_update_hints_fetcher_request_id_; + } + + // Returns the current active tabs batch update hints fetcher. + // + // Exposed here for testing. + HintsFetcher* active_tabs_batch_update_hints_fetcher() const { + return active_tabs_batch_update_hints_fetcher_.get(); + } + // The information of the latest component delivered by // |optimization_guide_service_|. absl::optional<HintsComponentInfo> hints_component_info_; @@ -412,9 +437,15 @@ // fetched from the remote Optimization Guide Service. std::unique_ptr<HintCache> hint_cache_; - // The fetcher that handles making requests for hints for multiple hosts from + // The fetcher that handles making requests for hints for active tabs from // the remote Optimization Guide Service. - std::unique_ptr<HintsFetcher> batch_update_hints_fetcher_; + std::unique_ptr<HintsFetcher> active_tabs_batch_update_hints_fetcher_; + + // A map from request ID to the fetcher that handles making requests for hints + // for multiple hosts from the remote Optimization Guide Service. + base::LRUCache<int32_t, std::unique_ptr<HintsFetcher>> + batch_update_hints_fetchers_; + int32_t batch_update_hints_fetcher_request_id_ = 0; // A cache keyed by navigation URL to the fetcher making a request for a hint // for that URL and/or host to the remote Optimization Guide Service that
diff --git a/components/optimization_guide/core/hints_manager_unittest.cc b/components/optimization_guide/core/hints_manager_unittest.cc index c405660..8dd0d40 100644 --- a/components/optimization_guide/core/hints_manager_unittest.cc +++ b/components/optimization_guide/core/hints_manager_unittest.cc
@@ -453,9 +453,13 @@ HintsManager* hints_manager() const { return hints_manager_.get(); } - TestHintsFetcher* batch_update_hints_fetcher() const { + int32_t num_batch_update_hints_fetches_initiated() const { + return hints_manager()->num_batch_update_hints_fetches_initiated(); + } + + TestHintsFetcher* active_tabs_batch_update_hints_fetcher() const { return static_cast<TestHintsFetcher*>( - hints_manager()->batch_update_hints_fetcher()); + hints_manager()->active_tabs_batch_update_hints_fetcher()); } GURL url_with_hints() const { @@ -1565,7 +1569,7 @@ MoveClockForwardBy(base::Seconds(kUpdateFetchHintsTimeSecs)); EXPECT_EQ(0, top_host_provider->get_num_top_hosts_called()); // Hints fetcher should not even be created. - EXPECT_FALSE(batch_update_hints_fetcher()); + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); } TEST_F(HintsManagerTest, @@ -1794,7 +1798,8 @@ { { features::kRemoteOptimizationGuideFetching, - {{"max_concurrent_page_navigation_fetches", "2"}}, + {{"max_concurrent_page_navigation_fetches", "2"}, + {"max_concurrent_batch_update_fetches", "2"}}, }, }, {features::kRemoteOptimizationGuideFetchingAnonymousDataConsent}); @@ -1820,7 +1825,7 @@ // Force timer to expire and schedule a hints fetch. MoveClockForwardBy(base::Seconds(kUpdateFetchHintsTimeSecs)); // Hints fetcher should not even be created. - EXPECT_FALSE(batch_update_hints_fetcher()); + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); } TEST_F(HintsManagerFetchingTest, @@ -1841,8 +1846,8 @@ // Force timer to expire and schedule a hints fetch but the fetch is not made. MoveClockForwardBy(base::Seconds(kUpdateFetchHintsTimeSecs)); EXPECT_EQ(0, top_host_provider->get_num_top_hosts_called()); - // Hints fetcher should not be created. - EXPECT_FALSE(batch_update_hints_fetcher()); + // Hints fetcher should not even be created. + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); } TEST_F(HintsManagerFetchingTest, @@ -1873,8 +1878,8 @@ // Force timer to expire after random delay and schedule a hints fetch. MoveClockForwardBy(base::Seconds(60 * 2)); EXPECT_EQ(0, top_host_provider->get_num_top_hosts_called()); - // Hints fetcher should not be created. - EXPECT_FALSE(batch_update_hints_fetcher()); + // Hints fetcher should not even be created. + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); } TEST_F(HintsManagerFetchingTest, HintsFetcherEnabledNoHostsOrUrlsToFetch) { @@ -1901,15 +1906,15 @@ MoveClockForwardBy(base::Seconds(60 * 2)); EXPECT_EQ(1, top_host_provider->get_num_top_hosts_called()); EXPECT_EQ(1, tab_url_provider()->get_num_urls_called()); - // Hints fetcher should not be even created. - EXPECT_FALSE(batch_update_hints_fetcher()); + // Hints fetcher should not even be created. + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); // Move it forward again to make sure timer is scheduled. MoveClockForwardBy(base::Seconds(kUpdateFetchHintsTimeSecs)); EXPECT_EQ(2, top_host_provider->get_num_top_hosts_called()); EXPECT_EQ(2, tab_url_provider()->get_num_urls_called()); - // Still no hosts or URLs, so hints fetcher should still not be even created. - EXPECT_FALSE(batch_update_hints_fetcher()); + // Hints fetcher should not even be created. + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); } TEST_F(HintsManagerFetchingTest, HintsFetcherEnabledNoHostsButHasUrlsToFetch) { @@ -1940,10 +1945,13 @@ MoveClockForwardBy(base::Seconds(60 * 2)); EXPECT_EQ(1, top_host_provider->get_num_top_hosts_called()); EXPECT_EQ(1, tab_url_provider()->get_num_urls_called()); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); - EXPECT_EQ("en-US", batch_update_hints_fetcher()->locale_requested()); - EXPECT_EQ(proto::RequestContext::CONTEXT_BATCH_UPDATE_ACTIVE_TABS, - batch_update_hints_fetcher()->request_context_requested()); + EXPECT_EQ(1, + active_tabs_batch_update_hints_fetcher()->num_fetches_requested()); + EXPECT_EQ("en-US", + active_tabs_batch_update_hints_fetcher()->locale_requested()); + EXPECT_EQ( + proto::RequestContext::CONTEXT_BATCH_UPDATE_ACTIVE_TABS, + active_tabs_batch_update_hints_fetcher()->request_context_requested()); histogram_tester.ExpectBucketCount( "OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor", 2, 1); @@ -1952,7 +1960,8 @@ EXPECT_EQ(2, top_host_provider->get_num_top_hosts_called()); EXPECT_EQ(2, tab_url_provider()->get_num_urls_called()); // Urls didn't change and we have all URLs cached in store. - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); + EXPECT_EQ(1, + active_tabs_batch_update_hints_fetcher()->num_fetches_requested()); histogram_tester.ExpectBucketCount( "OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor", 0, 1); } @@ -1982,7 +1991,7 @@ RunUntilIdle(); histogram_tester.ExpectTotalCount( "OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor", 0); - EXPECT_EQ(nullptr, batch_update_hints_fetcher()); + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); EXPECT_EQ(0, tab_url_provider()->get_num_urls_called()); // Force timer to expire after random delay and schedule a hints fetch that @@ -1991,14 +2000,16 @@ histogram_tester.ExpectBucketCount( "OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor", 2, 1); EXPECT_EQ(1, tab_url_provider()->get_num_urls_called()); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); + EXPECT_EQ(1, + active_tabs_batch_update_hints_fetcher()->num_fetches_requested()); // Move it forward again to make sure timer is scheduled. MoveClockForwardBy(base::Seconds(kUpdateFetchHintsTimeSecs)); histogram_tester.ExpectBucketCount( "OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor", 0, 1); EXPECT_EQ(2, tab_url_provider()->get_num_urls_called()); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); + EXPECT_EQ(1, + active_tabs_batch_update_hints_fetcher()->num_fetches_requested()); } // Verifies the deferred startup mode that fetches hints for active tab URLs on @@ -2035,14 +2046,16 @@ histogram_tester.ExpectBucketCount( "OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor", 2, 1); EXPECT_EQ(1, tab_url_provider()->get_num_urls_called()); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); + EXPECT_EQ(1, + active_tabs_batch_update_hints_fetcher()->num_fetches_requested()); // Move it forward again to make sure timer is scheduled. MoveClockForwardBy(base::Seconds(kUpdateFetchHintsTimeSecs)); histogram_tester.ExpectBucketCount( "OptimizationGuide.HintsManager.ActiveTabUrlsToFetchFor", 0, 1); EXPECT_EQ(2, tab_url_provider()->get_num_urls_called()); - EXPECT_EQ(1, batch_update_hints_fetcher()->num_fetches_requested()); + EXPECT_EQ(1, + active_tabs_batch_update_hints_fetcher()->num_fetches_requested()); } TEST_F(HintsManagerFetchingTest, @@ -3172,6 +3185,54 @@ }, run_loop.get())); run_loop->Run(); + + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.HintsManager.ConcurrentBatchUpdateFetches", 1, 1); +} + +TEST_F(HintsManagerFetchingTest, BatchUpdateCalledMoreThanMaxConcurrent) { + base::HistogramTester histogram_tester; + + hints_manager()->RegisterOptimizationTypes({proto::COMPRESS_PUBLIC_IMAGES}); + InitializeWithDefaultConfig("1.0.0.0"); + + // Set to online so fetch is activated. + SetConnectionOnline(); + + hints_manager()->SetHintsFetcherFactoryForTesting( + BuildTestHintsFetcherFactory( + {HintsFetcherEndState::kFetchSuccessWithURLHints})); + + // Call this over the max count. + hints_manager()->CanApplyOptimizationOnDemand( + {url_with_url_keyed_hint()}, {proto::COMPRESS_PUBLIC_IMAGES}, + proto::RequestContext::CONTEXT_BOOKMARKS, + base::DoNothingAs<void( + const GURL&, + const base::flat_map<proto::OptimizationType, + OptimizationGuideDecisionWithMetadata>&)>()); + hints_manager()->CanApplyOptimizationOnDemand( + {url_with_url_keyed_hint()}, {proto::COMPRESS_PUBLIC_IMAGES}, + proto::RequestContext::CONTEXT_BOOKMARKS, + base::DoNothingAs<void( + const GURL&, + const base::flat_map<proto::OptimizationType, + OptimizationGuideDecisionWithMetadata>&)>()); + hints_manager()->CanApplyOptimizationOnDemand( + {url_with_url_keyed_hint()}, {proto::COMPRESS_PUBLIC_IMAGES}, + proto::RequestContext::CONTEXT_BOOKMARKS, + base::DoNothingAs<void( + const GURL&, + const base::flat_map<proto::OptimizationType, + OptimizationGuideDecisionWithMetadata>&)>()); + + // The third one is over the max and should evict another one. + histogram_tester.ExpectTotalCount( + "OptimizationGuide.HintsManager.ConcurrentBatchUpdateFetches", 3); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.HintsManager.ConcurrentBatchUpdateFetches", 1, 1); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.HintsManager.ConcurrentBatchUpdateFetches", 2, 2); } TEST_F( @@ -3286,7 +3347,7 @@ // Force timer to expire and schedule a hints fetch. MoveClockForwardBy(base::Seconds(kUpdateFetchHintsTimeSecs)); // Hints fetcher should not even be created. - EXPECT_FALSE(batch_update_hints_fetcher()); + EXPECT_FALSE(active_tabs_batch_update_hints_fetcher()); } } // namespace optimization_guide
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index 66f80905..cff2fd0 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -233,6 +233,15 @@ "active_tabs_staleness_tolerance_in_days", 90)); } +size_t MaxConcurrentBatchUpdateFetches() { + // If overridden, this needs to be large enough where we do not thrash the + // inflight batch update fetches since if we approach the limit here, we will + // abort the oldest batch update fetch that is in flight. + return GetFieldTrialParamByFeatureAsInt(kRemoteOptimizationGuideFetching, + "max_concurrent_batch_update_fetches", + 20); +} + size_t MaxConcurrentPageNavigationFetches() { // If overridden, this needs to be large enough where we do not thrash the // inflight page navigations since if we approach the limit here, we will @@ -258,14 +267,15 @@ "max_store_duration_for_host_model_features_in_days", 7)); } -base::TimeDelta StoredModelsInactiveDuration() { +base::TimeDelta StoredModelsValidDuration() { // TODO(crbug.com/1234054) This field should not be changed without VERY - // careful consideration. Any model that is on device and expires will be - // removed and triggered to refetch so any feature relying on the model could - // have a period of time without a valid model. + // careful consideration. This is the default duration for models that do not + // specify retention, so changing this can cause models to be removed and + // refetch would only apply to newer models. Any feature relying on the model + // would have a period of time without a valid model, and would need to push a + // new version. return base::Days(GetFieldTrialParamByFeatureAsInt( - kOptimizationTargetPrediction, "inactive_duration_for_models_in_days", - 30)); + kOptimizationTargetPrediction, "valid_duration_for_models_in_days", 30)); } base::TimeDelta URLKeyedHintValidCacheDuration() {
diff --git a/components/optimization_guide/core/optimization_guide_features.h b/components/optimization_guide/core/optimization_guide_features.h index 80010d3..1596ac1 100644 --- a/components/optimization_guide/core/optimization_guide_features.h +++ b/components/optimization_guide/core/optimization_guide_features.h
@@ -107,7 +107,11 @@ base::TimeDelta GetActiveTabsStalenessTolerance(); // Returns the max number of concurrent fetches to the remote Optimization Guide -// Service that should be allowed. +// Service that should be allowed for batch updates +size_t MaxConcurrentBatchUpdateFetches(); + +// Returns the max number of concurrent fetches to the remote Optimization Guide +// Service that should be allowed for navigations. size_t MaxConcurrentPageNavigationFetches(); // Returns the minimum number of seconds to randomly delay before starting to @@ -130,7 +134,7 @@ // The maximum duration for which models can remain in the // OptimizationGuideStore without being loaded. -base::TimeDelta StoredModelsInactiveDuration(); +base::TimeDelta StoredModelsValidDuration(); // The amount of time URL-keyed hints within the hint cache will be // allowed to be used and not be purged.
diff --git a/components/optimization_guide/core/optimization_guide_store.cc b/components/optimization_guide/core/optimization_guide_store.cc index 97a50f7..635cac8 100644 --- a/components/optimization_guide/core/optimization_guide_store.cc +++ b/components/optimization_guide/core/optimization_guide_store.cc
@@ -3,10 +3,13 @@ // found in the LICENSE file. #include "components/optimization_guide/core/optimization_guide_store.h" +#include <memory> +#include <string> #include "base/bind.h" #include "base/callback_helpers.h" #include "base/files/file_util.h" +#include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/sequence_checker.h" @@ -20,6 +23,7 @@ #include "components/optimization_guide/core/optimization_guide_features.h" #include "components/optimization_guide/core/optimization_guide_util.h" #include "components/optimization_guide/proto/hint_cache.pb.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace optimization_guide { @@ -62,9 +66,7 @@ // recorded when it goes out of scope and its destructor is called. class ScopedLoadMetadataResultRecorder { public: - ScopedLoadMetadataResultRecorder() - : result_(OptimizationGuideHintCacheLevelDBStoreLoadMetadataResult:: - kSuccess) {} + ScopedLoadMetadataResultRecorder() = default; ~ScopedLoadMetadataResultRecorder() { UMA_HISTOGRAM_ENUMERATION( "OptimizationGuide.HintCacheLevelDBStore.LoadMetadataResult", result_); @@ -76,7 +78,8 @@ } private: - OptimizationGuideHintCacheLevelDBStoreLoadMetadataResult result_; + OptimizationGuideHintCacheLevelDBStoreLoadMetadataResult result_ = + OptimizationGuideHintCacheLevelDBStoreLoadMetadataResult::kSuccess; }; void RecordStatusChange(OptimizationGuideStore::Status status) { @@ -963,14 +966,30 @@ bool had_entries_to_update_or_remove = !update_vector->empty() || !remove_vector->empty(); for (const auto& entry : *entries) { - bool should_delete_download_file = had_entries_to_update_or_remove; + absl::optional<std::string> delete_download_file; + if (had_entries_to_update_or_remove && + entry.second.has_prediction_model() && + !entry.second.prediction_model().model().download_url().empty()) { + delete_download_file = + entry.second.prediction_model().model().download_url(); + } + // Only check expiry if we weren't explicitly passed in entries to update or // remove. if (!had_entries_to_update_or_remove) { + if (entry.second.keep_beyond_valid_duration()) { + continue; + } if (entry.second.has_expiry_time_secs()) { if (entry.second.expiry_time_secs() <= now_since_epoch) { + // Update the entry to remove the model. + if (entry.second.has_prediction_model() && + !entry.second.prediction_model().model().download_url().empty()) { + delete_download_file = + entry.second.prediction_model().model().download_url(); + } + remove_vector->push_back(entry.first); - should_delete_download_file = true; proto::OptimizationTarget optimization_target = GetOptimizationTargetFromPredictionModelEntryKey(entry.first); base::UmaHistogramBoolean( @@ -984,20 +1003,17 @@ update_vector->push_back(entry); update_vector->back().second.set_expiry_time_secs( now_since_epoch + - features::StoredModelsInactiveDuration().InSeconds()); + features::StoredModelsValidDuration().InSeconds()); } } // Delete files (the model itself and any additional files) that are // provided by the model in its directory. - if (should_delete_download_file && entry.second.has_prediction_model() && - !entry.second.prediction_model().model().download_url().empty()) { - // |GetFilePathFromPredictionModel| only returns nullopt when - // |model().download_url()| is empty. + if (delete_download_file) { + // |StringToFilePath| only returns nullopt when + // |delete_download_file| is empty. base::FilePath model_file_path = - StringToFilePath( - entry.second.prediction_model().model().download_url()) - .value(); + StringToFilePath(*delete_download_file).value(); base::FilePath path_to_delete; // Backwards compatibility: Once upon a time (<M93), model files were @@ -1043,9 +1059,8 @@ *out_prediction_model_entry_key = GetPredictionModelEntryKeyPrefix() + base::NumberToString(static_cast<int>(optimization_target)); - if (entry_keys_->find(*out_prediction_model_entry_key) != entry_keys_->end()) - return true; - return false; + return entry_keys_->find(*out_prediction_model_entry_key) != + entry_keys_->end(); } bool OptimizationGuideStore::RemovePredictionModelFromEntryKey( @@ -1107,6 +1122,17 @@ std::move(callback).Run(std::move(loaded_prediction_model)); return; } + // Also ensure that nothing is returned if the model is expired. + int64_t now_since_epoch = + base::Time::Now().ToDeltaSinceWindowsEpoch().InSeconds(); + if (!entry->keep_beyond_valid_duration() && + entry->expiry_time_secs() <= now_since_epoch) { + // Leave the actual model deletions to |PurgeInactiveModels| and return + // early. + std::unique_ptr<proto::PredictionModel> loaded_prediction_model(nullptr); + std::move(callback).Run(std::move(loaded_prediction_model)); + return; + } std::unique_ptr<proto::PredictionModel> loaded_prediction_model( entry->release_prediction_model());
diff --git a/components/optimization_guide/core/optimization_guide_store.h b/components/optimization_guide/core/optimization_guide_store.h index 76c36ce..3aebca22 100644 --- a/components/optimization_guide/core/optimization_guide_store.h +++ b/components/optimization_guide/core/optimization_guide_store.h
@@ -179,6 +179,7 @@ // Removes all models that have not been loaded in the max inactive duration // configured. |entry_keys| is updated after the inactive models are removed. + // Respects models' |keep_beyond_valid_duration| setting. void PurgeInactiveModels(); // Creates and returns a StoreUpdateData object for Prediction Models. This @@ -196,9 +197,9 @@ std::unique_ptr<StoreUpdateData> prediction_models_update_data, base::OnceClosure callback); - // Finds the entry key for the prediction model if it is known to the store. - // Returns true if an entry key is found and |out_prediction_model_entry_key| - // is populated with the matching key. + // Finds the entry key for the prediction model if it is still valid in the + // store. Returns true if an entry key is valid and + // |out_prediction_model_entry_key| is populated with any matching key. // Virtualized for testing. virtual bool FindPredictionModelEntryKey( proto::OptimizationTarget optimization_target,
diff --git a/components/optimization_guide/core/optimization_guide_store_unittest.cc b/components/optimization_guide/core/optimization_guide_store_unittest.cc index b1ea475..9bd9d7e 100644 --- a/components/optimization_guide/core/optimization_guide_store_unittest.cc +++ b/components/optimization_guide/core/optimization_guide_store_unittest.cc
@@ -176,20 +176,24 @@ StoreUpdateData* update_data, optimization_guide::proto::OptimizationTarget optimization_target, absl::optional<base::FilePath> model_file_path = absl::nullopt, - base::flat_set<base::FilePath> additional_file_paths = {}) { + absl::optional<proto::ModelInfo> info = absl::nullopt, + absl::optional<base::Time> expiry_time = absl::nullopt) { std::unique_ptr<optimization_guide::proto::PredictionModel> prediction_model = CreatePredictionModel(); + if (info) + prediction_model->mutable_model_info()->MergeFrom(*info); prediction_model->mutable_model_info()->set_optimization_target( optimization_target); + if (expiry_time) { + auto diff = expiry_time.value() - base::Time::Now(); + prediction_model->mutable_model_info() + ->mutable_valid_duration() + ->set_seconds(diff.InSeconds()); + } if (model_file_path) { prediction_model->mutable_model()->set_download_url( FilePathToString(*model_file_path)); } - for (const base::FilePath& additional_file : additional_file_paths) { - prediction_model->mutable_model_info() - ->add_additional_files() - ->set_file_path(FilePathToString(additional_file)); - } update_data->CopyPredictionModelIntoUpdateData(*prediction_model); } @@ -1945,7 +1949,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); SeedPredictionModelUpdateData(update_data.get(), proto::OPTIMIZATION_TARGET_UNKNOWN); @@ -1971,7 +1975,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); SeedPredictionModelUpdateData(update_data.get(), proto::OPTIMIZATION_TARGET_UNKNOWN); @@ -1994,7 +1998,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); SeedPredictionModelUpdateData(update_data.get(), proto::OPTIMIZATION_TARGET_UNKNOWN); @@ -2034,7 +2038,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); SeedPredictionModelUpdateData(update_data.get(), proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD); @@ -2076,6 +2080,46 @@ EXPECT_FALSE(last_loaded_prediction_model()); } +TEST_F(OptimizationGuideStoreTest, LoadPredictionModelOnExpiredModel) { + base::HistogramTester histogram_tester; + size_t initial_hint_count = 10; + MetadataSchemaState schema_state = MetadataSchemaState::kValid; + SeedInitialData(schema_state, initial_hint_count); + CreateDatabase(); + InitializeStore(schema_state); + + // Add an update with models that are "inactive". + base::Time update_time = base::Time().Now(); + std::unique_ptr<StoreUpdateData> update_data = + guide_store()->CreateUpdateDataForPredictionModels( + update_time - + optimization_guide::features::StoredModelsValidDuration()); + ASSERT_TRUE(update_data); + SeedPredictionModelUpdateData( + update_data.get(), proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, + /*model_file_path=*/absl::nullopt, + /*info=*/{}, + update_time - optimization_guide::features::StoredModelsValidDuration()); + UpdatePredictionModels(std::move(update_data)); + // Since models haven't been purged yet it will initially show up as valid. + OptimizationGuideStore::EntryKey entry_key; + EXPECT_TRUE(guide_store()->FindPredictionModelEntryKey( + proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, &entry_key)); + guide_store()->LoadPredictionModel( + entry_key, + base::BindOnce(&OptimizationGuideStoreTest::OnPredictionModelLoaded, + base::Unretained(this))); + // OnPredictionModelLoaded callback + db()->GetCallback(true); + // After load completes, the key will still exist until after purge. + EXPECT_TRUE(guide_store()->FindPredictionModelEntryKey( + proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, &entry_key)); + + // Verify that the OnPredictionModelLoaded callback runs when the store is + // unavailable and that the prediction model was correctly not available. + EXPECT_FALSE(last_loaded_prediction_model()); +} + TEST_F(OptimizationGuideStoreTest, LoadPredictionModelWithUpdateInFlight) { base::HistogramTester histogram_tester; MetadataSchemaState schema_state = MetadataSchemaState::kValid; @@ -2087,7 +2131,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); SeedPredictionModelUpdateData(update_data.get(), proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD); @@ -2117,7 +2161,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); SeedPredictionModelUpdateData(update_data.get(), proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, @@ -2164,7 +2208,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); base::FilePath model_file_path = temp_dir().AppendASCII("model.tflite"); @@ -2173,9 +2217,12 @@ base::FilePath additional_file_path = temp_dir().AppendASCII("doesntexist"); - SeedPredictionModelUpdateData( - update_data.get(), proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, - temp_dir().AppendASCII("doesntexist"), {additional_file_path}); + proto::ModelInfo info; + info.add_additional_files()->set_file_path( + FilePathToString(additional_file_path)); + SeedPredictionModelUpdateData(update_data.get(), + proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, + temp_dir().AppendASCII("doesntexist"), info); UpdatePredictionModels(std::move(update_data)); OptimizationGuideStore::EntryKey entry_key; @@ -2221,7 +2268,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); base::FilePath model_file_path = temp_dir().AppendASCII("model.tflite"); @@ -2232,10 +2279,12 @@ temp_dir().AppendASCII("additional_file.txt"); ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(additional_file_path, "ah!", 3)); - + proto::ModelInfo info; + info.add_additional_files()->set_file_path( + FilePathToString(additional_file_path)); SeedPredictionModelUpdateData(update_data.get(), proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, - model_file_path, {additional_file_path}); + model_file_path, info); UpdatePredictionModels(std::move(update_data)); OptimizationGuideStore::EntryKey entry_key; @@ -2277,7 +2326,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); base::FilePath file_path = temp_dir().AppendASCII("file"); ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(file_path, "boo", 3)); @@ -2324,7 +2373,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); base::FilePath old_file_path = old_dir.AppendASCII("model.tflite"); ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(old_file_path, "boo", 3)); @@ -2341,7 +2390,7 @@ std::unique_ptr<StoreUpdateData> update_data2 = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data2); base::FilePath new_file_path = new_dir.AppendASCII("model.tflite"); ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(new_file_path, "boo", 3)); @@ -2380,7 +2429,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); base::FilePath old_file_path = old_dir.AppendASCII("model_v1.tflite"); ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(old_file_path, "boo", 3)); @@ -2397,7 +2446,7 @@ std::unique_ptr<StoreUpdateData> update_data2 = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data2); base::FilePath new_file_path = new_dir.Append(GetBaseFileNameForModels()); ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(new_file_path, "boo", 3)); @@ -2429,7 +2478,7 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); base::FilePath file_path = temp_dir().AppendASCII("file"); ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(file_path, "boo", 3)); @@ -2669,17 +2718,22 @@ std::unique_ptr<StoreUpdateData> update_data = guide_store()->CreateUpdateDataForPredictionModels( update_time - - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data); - SeedPredictionModelUpdateData(update_data.get(), - proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD); + base::FilePath old_file_path = temp_dir().AppendASCII("model_v1.tflite"); + ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(old_file_path, "boo", 3)); + SeedPredictionModelUpdateData( + update_data.get(), proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, + old_file_path, + /*info=*/{}, + update_time - optimization_guide::features::StoredModelsValidDuration()); UpdatePredictionModels(std::move(update_data)); // Add an update with models that are "active". std::unique_ptr<StoreUpdateData> update_data2 = guide_store()->CreateUpdateDataForPredictionModels( update_time + - optimization_guide::features::StoredModelsInactiveDuration()); + optimization_guide::features::StoredModelsValidDuration()); ASSERT_TRUE(update_data2); SeedPredictionModelUpdateData(update_data2.get(), proto::OPTIMIZATION_TARGET_LANGUAGE_DETECTION); @@ -2695,9 +2749,12 @@ ASSERT_TRUE(success); PurgeInactiveModels(); - + RunUntilIdle(); + // The expired model should be removed. EXPECT_FALSE(guide_store()->FindPredictionModelEntryKey( proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, &entry_key)); + EXPECT_FALSE(base::PathExists(old_file_path)); + // Should not purge models that are still active. EXPECT_TRUE(guide_store()->FindPredictionModelEntryKey( proto::OPTIMIZATION_TARGET_LANGUAGE_DETECTION, &entry_key)); @@ -2708,4 +2765,121 @@ "OptimizationGuide.PredictionModelExpired.LanguageDetection", 0); } +struct ValidityTestCase { + std::string test_name; + bool keep_beyond_valid_duration; + bool initially_expired; + bool expect_kept; +}; + +class OptimizationGuideStoreValidityTest + : public OptimizationGuideStoreTest, + public ::testing::WithParamInterface<ValidityTestCase> {}; + +TEST_P(OptimizationGuideStoreValidityTest, PurgeInactiveModels) { + const ValidityTestCase& test_case = GetParam(); + base::HistogramTester histogram_tester; + + MetadataSchemaState schema_state = MetadataSchemaState::kValid; + SeedInitialData(schema_state, 0); + CreateDatabase(); + InitializeStore(schema_state); + + // Add an update with one model according to ValidityTestCase settings. + base::Time update_time = base::Time().Now(); + if (test_case.initially_expired) { + update_time -= optimization_guide::features::StoredModelsValidDuration(); + } else { + update_time += optimization_guide::features::StoredModelsValidDuration(); + } + std::unique_ptr<StoreUpdateData> update_data = + guide_store()->CreateUpdateDataForPredictionModels(update_time); + ASSERT_TRUE(update_data); + proto::ModelInfo info; + info.set_keep_beyond_valid_duration(test_case.keep_beyond_valid_duration); + base::FilePath old_file_path = temp_dir().AppendASCII("model_v1.tflite"); + ASSERT_EQ(static_cast<int32_t>(3), base::WriteFile(old_file_path, "boo", 3)); + SeedPredictionModelUpdateData(update_data.get(), + proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, + old_file_path, info, update_time); + UpdatePredictionModels(std::move(update_data)); + + // Add an update with models that are "active" and should be unaffected. + std::unique_ptr<StoreUpdateData> update_data2 = + guide_store()->CreateUpdateDataForPredictionModels( + base::Time().Now() + + optimization_guide::features::StoredModelsValidDuration()); + ASSERT_TRUE(update_data2); + SeedPredictionModelUpdateData(update_data2.get(), + proto::OPTIMIZATION_TARGET_LANGUAGE_DETECTION); + UpdatePredictionModels(std::move(update_data2)); + + // Make sure both models are in the store. + OptimizationGuideStore::EntryKey entry_key; + bool success = guide_store()->FindPredictionModelEntryKey( + proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, &entry_key); + ASSERT_TRUE(success); + EXPECT_TRUE(base::PathExists(old_file_path)); + + success = guide_store()->FindPredictionModelEntryKey( + proto::OPTIMIZATION_TARGET_LANGUAGE_DETECTION, &entry_key); + ASSERT_TRUE(success); + + PurgeInactiveModels(); + RunUntilIdle(); + // Verify that the model file, entry key and histogram match expectations for + // PageLoad. + EXPECT_EQ(test_case.expect_kept, + guide_store()->FindPredictionModelEntryKey( + proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, &entry_key)); + EXPECT_EQ(test_case.expect_kept, base::PathExists(old_file_path)); + + if (test_case.expect_kept) { + histogram_tester.ExpectTotalCount( + "OptimizationGuide.PredictionModelExpired.PainfulPageLoad", 0); + } else { + histogram_tester.ExpectTotalCount( + "OptimizationGuide.PredictionModelExpired.PainfulPageLoad", 1); + } + // Verify that the other model is not deleted. + EXPECT_TRUE(guide_store()->FindPredictionModelEntryKey( + proto::OPTIMIZATION_TARGET_LANGUAGE_DETECTION, &entry_key)); + histogram_tester.ExpectTotalCount( + "OptimizationGuide.PredictionModelExpired.LanguageDetection", 0); +} +INSTANTIATE_TEST_SUITE_P( + OptimizationGuideStoreValidityTests, + OptimizationGuideStoreValidityTest, + testing::ValuesIn<ValidityTestCase>({ + { + "KeepDespiteInvalidModel", + /*keep_beyond_valid_duration=*/true, + /*initially_expired=*/true, + /*expect_kept=*/true, + }, + { + "KeepAndInitiallyValid", + /*keep_beyond_valid_duration=*/true, + /*initially_expired=*/false, + /*expect_kept=*/true, + }, + { + "DeleteAndInitiallyValid", + /*keep_beyond_valid_duration=*/false, + /*initially_expired=*/false, + /*expect_kept=*/true, + }, + // Only in this case should the model be removed. + { + "DeleteAndInvalidModel", + /*keep_beyond_valid_duration=*/false, + /*initially_expired=*/true, + /*expect_kept=*/false, + }, + }), + [](const testing::TestParamInfo< + OptimizationGuideStoreValidityTest::ParamType>& info) { + return info.param.test_name; + }); + } // namespace optimization_guide
diff --git a/components/optimization_guide/core/store_update_data.cc b/components/optimization_guide/core/store_update_data.cc index 0afd12d3e..74dcc732 100644 --- a/components/optimization_guide/core/store_update_data.cc +++ b/components/optimization_guide/core/store_update_data.cc
@@ -200,8 +200,19 @@ proto::StoreEntry entry_proto; entry_proto.set_entry_type(static_cast<proto::StoreEntryType>( OptimizationGuideStore::StoreEntryType::kPredictionModel)); + + base::TimeDelta expiry_duration; + if (prediction_model.model_info().has_valid_duration()) { + expiry_duration = + base::Seconds(prediction_model.model_info().valid_duration().seconds()); + } else { + expiry_duration = features::StoredFetchedHintsFreshnessDuration(); + } + expiry_time_ = base::Time::Now() + expiry_duration; entry_proto.set_expiry_time_secs( - expiry_time_->ToDeltaSinceWindowsEpoch().InSeconds()); + expiry_time_.value().ToDeltaSinceWindowsEpoch().InSeconds()); + entry_proto.set_keep_beyond_valid_duration( + prediction_model.model_info().keep_beyond_valid_duration()); entry_proto.mutable_prediction_model()->CopyFrom(prediction_model); entries_to_save_->emplace_back(std::move(prediction_model_entry_key), std::move(entry_proto));
diff --git a/components/optimization_guide/core/store_update_data_unittest.cc b/components/optimization_guide/core/store_update_data_unittest.cc index edac180..9a38940 100644 --- a/components/optimization_guide/core/store_update_data_unittest.cc +++ b/components/optimization_guide/core/store_update_data_unittest.cc
@@ -122,9 +122,11 @@ proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD); model_info->add_supported_model_engine_versions( proto::ModelEngineVersion::MODEL_ENGINE_VERSION_DECISION_TREE); + model_info->set_keep_beyond_valid_duration(false); - base::Time expected_expiry_time = - base::Time::Now() + features::StoredModelsInactiveDuration(); + model_info->mutable_valid_duration()->set_seconds(3); + + base::Time expected_expiry_time = base::Time::Now() + base::Seconds(3); std::unique_ptr<StoreUpdateData> prediction_model_update = StoreUpdateData::CreatePredictionModelStoreUpdateData( expected_expiry_time); @@ -143,6 +145,8 @@ found_prediction_model_entry = true; EXPECT_EQ(expected_expiry_time.ToDeltaSinceWindowsEpoch().InSeconds(), store_entry.expiry_time_secs()); + EXPECT_EQ(store_entry.keep_beyond_valid_duration(), + model_info->keep_beyond_valid_duration()); break; } }
diff --git a/components/optimization_guide/proto/hint_cache.proto b/components/optimization_guide/proto/hint_cache.proto index a27430d3..e89dec2 100644 --- a/components/optimization_guide/proto/hint_cache.proto +++ b/components/optimization_guide/proto/hint_cache.proto
@@ -59,4 +59,6 @@ optional PredictionModel prediction_model = 6; // The actual HostModelFeature data. optional HostModelFeatures host_model_features = 7; + // Whether to delete a model once expiry_time_secs is past. + optional bool keep_beyond_valid_duration = 8; }
diff --git a/components/optimization_guide/proto/models.proto b/components/optimization_guide/proto/models.proto index ea953cc..e36ff0c 100644 --- a/components/optimization_guide/proto/models.proto +++ b/components/optimization_guide/proto/models.proto
@@ -200,7 +200,7 @@ // Metadata for a prediction model for a specific optimization target. // -// Next ID: 8 +// Next ID: 10 message ModelInfo { reserved 3; @@ -223,6 +223,11 @@ // This does not need to be sent to the server in the request for an update to // this model. The server will ignore this if sent. repeated AdditionalModelFile additional_files = 7; + // How long the model will remain valid in client storage. If + // |keep_beyond_valid_duration| is true, will be ignored. + optional Duration valid_duration = 8; + // Whether to delete the model once valid_duration has passed. + optional bool keep_beyond_valid_duration = 9; // Mechanism used for model owners to attach metadata to the request or // response. //
diff --git a/components/prefs/BUILD.gn b/components/prefs/BUILD.gn index 0dd1a50a..e8d2069 100644 --- a/components/prefs/BUILD.gn +++ b/components/prefs/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") + component("prefs") { sources = [ "command_line_pref_store.cc", @@ -63,6 +65,13 @@ ] deps += [ "android:jni_headers" ] } + + if (is_chromeos_ash) { + sources += [ + "standalone_browser_pref_store.cc", + "standalone_browser_pref_store.h", + ] + } } static_library("test_support") {
diff --git a/components/prefs/pref_service.cc b/components/prefs/pref_service.cc index ae6cdad..3644899d 100644 --- a/components/prefs/pref_service.cc +++ b/components/prefs/pref_service.cc
@@ -435,8 +435,8 @@ pref_value_store_ = pref_value_store_->CloneAndSpecialize( managed_prefs, supervised_user_prefs, extension_prefs, nullptr /* command_line_prefs */, nullptr /* user_prefs */, - recommended_prefs, nullptr /* default_prefs */, pref_notifier_.get(), - std::move(delegate)); + nullptr /* standalone_browser_prefs */, recommended_prefs, + nullptr /* default_prefs */, pref_notifier_.get(), std::move(delegate)); // Notify |pref_notifier_| on all changed values. for (const auto& kv : pref_changed_map) {
diff --git a/components/prefs/pref_service_factory.cc b/components/prefs/pref_service_factory.cc index 2d4cad0..db6fcfe 100644 --- a/components/prefs/pref_service_factory.cc +++ b/components/prefs/pref_service_factory.cc
@@ -34,9 +34,10 @@ auto pref_notifier = std::make_unique<PrefNotifierImpl>(); auto pref_value_store = std::make_unique<PrefValueStore>( managed_prefs_.get(), supervised_user_prefs_.get(), - extension_prefs_.get(), command_line_prefs_.get(), user_prefs_.get(), - recommended_prefs_.get(), pref_registry->defaults().get(), - pref_notifier.get(), std::move(delegate)); + extension_prefs_.get(), standalone_browser_prefs_.get(), + command_line_prefs_.get(), user_prefs_.get(), recommended_prefs_.get(), + pref_registry->defaults().get(), pref_notifier.get(), + std::move(delegate)); return std::make_unique<PrefService>( std::move(pref_notifier), std::move(pref_value_store), user_prefs_.get(), std::move(pref_registry), read_error_callback_, async_);
diff --git a/components/prefs/pref_service_factory.h b/components/prefs/pref_service_factory.h index 2683d36..8c5ca7f 100644 --- a/components/prefs/pref_service_factory.h +++ b/components/prefs/pref_service_factory.h
@@ -43,6 +43,10 @@ extension_prefs_.swap(prefs); } + void set_standalone_browser_prefs(scoped_refptr<PrefStore> prefs) { + standalone_browser_prefs_.swap(prefs); + } + void set_command_line_prefs(scoped_refptr<PrefStore> prefs) { command_line_prefs_.swap(prefs); } @@ -87,6 +91,7 @@ scoped_refptr<PrefStore> managed_prefs_; scoped_refptr<PrefStore> supervised_user_prefs_; scoped_refptr<PrefStore> extension_prefs_; + scoped_refptr<PrefStore> standalone_browser_prefs_; scoped_refptr<PrefStore> command_line_prefs_; scoped_refptr<PersistentPrefStore> user_prefs_; scoped_refptr<PrefStore> recommended_prefs_;
diff --git a/components/prefs/pref_service_unittest.cc b/components/prefs/pref_service_unittest.cc index b31ed70..4af2d84 100644 --- a/components/prefs/pref_service_unittest.cc +++ b/components/prefs/pref_service_unittest.cc
@@ -499,9 +499,10 @@ auto pref_notifier = std::make_unique<PrefNotifierImpl>(); auto pref_value_store = std::make_unique<PrefValueStore>( nullptr /* managed_prefs */, nullptr /* supervised_user_prefs */, - nullptr /* extension_prefs */, new TestingPrefStore(), - user_pref_store_.get(), nullptr /* recommended_prefs */, - pref_registry_->defaults().get(), pref_notifier.get()); + nullptr /* extension_prefs */, nullptr /* standalone_browser_prefs */, + new TestingPrefStore(), user_pref_store_.get(), + nullptr /* recommended_prefs */, pref_registry_->defaults().get(), + pref_notifier.get()); pref_service_ = std::make_unique<PrefService>( std::move(pref_notifier), std::move(pref_value_store), user_pref_store_, pref_registry_, base::DoNothing(), false);
diff --git a/components/prefs/pref_value_store.cc b/components/prefs/pref_value_store.cc index 4a238d06..efa4027 100644 --- a/components/prefs/pref_value_store.cc +++ b/components/prefs/pref_value_store.cc
@@ -49,6 +49,7 @@ PrefValueStore::PrefValueStore(PrefStore* managed_prefs, PrefStore* supervised_user_prefs, PrefStore* extension_prefs, + PrefStore* standalone_browser_prefs, PrefStore* command_line_prefs, PrefStore* user_prefs, PrefStore* recommended_prefs, @@ -61,6 +62,7 @@ InitPrefStore(MANAGED_STORE, managed_prefs); InitPrefStore(SUPERVISED_USER_STORE, supervised_user_prefs); InitPrefStore(EXTENSION_STORE, extension_prefs); + InitPrefStore(STANDALONE_BROWSER_STORE, standalone_browser_prefs); InitPrefStore(COMMAND_LINE_STORE, command_line_prefs); InitPrefStore(USER_STORE, user_prefs); InitPrefStore(RECOMMENDED_STORE, recommended_prefs); @@ -69,8 +71,8 @@ CheckInitializationCompleted(); if (delegate_) { delegate_->Init(managed_prefs, supervised_user_prefs, extension_prefs, - command_line_prefs, user_prefs, recommended_prefs, - default_prefs, pref_notifier); + standalone_browser_prefs, command_line_prefs, user_prefs, + recommended_prefs, default_prefs, pref_notifier); } } @@ -80,6 +82,7 @@ PrefStore* managed_prefs, PrefStore* supervised_user_prefs, PrefStore* extension_prefs, + PrefStore* standalone_browser_prefs, PrefStore* command_line_prefs, PrefStore* user_prefs, PrefStore* recommended_prefs, @@ -93,6 +96,8 @@ supervised_user_prefs = GetPrefStore(SUPERVISED_USER_STORE); if (!extension_prefs) extension_prefs = GetPrefStore(EXTENSION_STORE); + if (!standalone_browser_prefs) + standalone_browser_prefs = GetPrefStore(STANDALONE_BROWSER_STORE); if (!command_line_prefs) command_line_prefs = GetPrefStore(COMMAND_LINE_STORE); if (!user_prefs) @@ -103,9 +108,9 @@ default_prefs = GetPrefStore(DEFAULT_STORE); return std::make_unique<PrefValueStore>( - managed_prefs, supervised_user_prefs, extension_prefs, command_line_prefs, - user_prefs, recommended_prefs, default_prefs, pref_notifier, - std::move(delegate)); + managed_prefs, supervised_user_prefs, extension_prefs, + standalone_browser_prefs, command_line_prefs, user_prefs, + recommended_prefs, default_prefs, pref_notifier, std::move(delegate)); } bool PrefValueStore::GetValue(const std::string& name,
diff --git a/components/prefs/pref_value_store.h b/components/prefs/pref_value_store.h index 9808056..ea483807 100644 --- a/components/prefs/pref_value_store.h +++ b/components/prefs/pref_value_store.h
@@ -45,6 +45,7 @@ virtual void Init(PrefStore* managed_prefs, PrefStore* supervised_user_prefs, PrefStore* extension_prefs, + PrefStore* standalone_browser_prefs, PrefStore* command_line_prefs, PrefStore* user_prefs, PrefStore* recommended_prefs, @@ -64,15 +65,19 @@ }; // PrefStores must be listed here in order from highest to lowest priority. - // MANAGED contains all managed preference values that are provided by + // MANAGED contains all managed preferences that are provided by // mandatory policies (e.g. Windows Group Policy or cloud policy). // SUPERVISED_USER contains preferences that are valid for supervised users. - // EXTENSION contains preference values set by extensions. - // COMMAND_LINE contains preference values set by command-line switches. - // USER contains all user-set preference values. + // EXTENSION contains preferences set by extensions. + // STANDALONE_BROWSER contains system preferences inherited from a separate + // Chrome instance. One relevant source is extension prefs in lacros + // passed to ash, so these prefs have similar precedence to extension + // prefs. + // COMMAND_LINE contains preferences set by command-line switches. + // USER contains all user-set preferences. // RECOMMENDED contains all preferences that are provided by recommended // policies. - // DEFAULT contains all application default preference values. + // DEFAULT contains all application default preferences. enum PrefStoreType { // INVALID_STORE is not associated with an actual PrefStore but used as // an invalid marker, e.g. as a return value. @@ -80,6 +85,7 @@ MANAGED_STORE = 0, SUPERVISED_USER_STORE, EXTENSION_STORE, + STANDALONE_BROWSER_STORE, COMMAND_LINE_STORE, USER_STORE, RECOMMENDED_STORE, @@ -105,6 +111,7 @@ PrefValueStore(PrefStore* managed_prefs, PrefStore* supervised_user_prefs, PrefStore* extension_prefs, + PrefStore* standalone_browser_prefs, PrefStore* command_line_prefs, PrefStore* user_prefs, PrefStore* recommended_prefs, @@ -125,6 +132,7 @@ PrefStore* managed_prefs, PrefStore* supervised_user_prefs, PrefStore* extension_prefs, + PrefStore* standalone_browser_prefs, PrefStore* command_line_prefs, PrefStore* user_prefs, PrefStore* recommended_prefs,
diff --git a/components/prefs/pref_value_store_unittest.cc b/components/prefs/pref_value_store_unittest.cc index 3964813..2871964 100644 --- a/components/prefs/pref_value_store_unittest.cc +++ b/components/prefs/pref_value_store_unittest.cc
@@ -41,6 +41,7 @@ const char kSupervisedUserPref[] = "this.pref.supervised_user"; const char kCommandLinePref[] = "this.pref.command_line"; const char kExtensionPref[] = "this.pref.extension"; +const char kStandaloneBrowserPref[] = "this.pref.standalone_browser"; const char kUserPref[] = "this.pref.user"; const char kRecommendedPref[] = "this.pref.recommended"; const char kDefaultPref[] = "this.pref.default"; @@ -63,10 +64,18 @@ const char kExtensionValue[] = "extension:extension"; } +namespace standalone_browser_pref { +const char kManagedValue[] = "standalone_browser:managed"; +const char kSupervisedUserValue[] = "standalone_browser:supervised_user"; +const char kExtensionValue[] = "standalone_browser:extension"; +const char kStandaloneBrowserValue[] = "standalone_browser:standalone_browser"; +} // namespace standalone_browser_pref + namespace command_line_pref { const char kManagedValue[] = "command_line:managed"; const char kSupervisedUserValue[] = "command_line:supervised_user"; const char kExtensionValue[] = "command_line:extension"; +const char kStandaloneBrowserValue[] = "command_line:standalone_browser"; const char kCommandLineValue[] = "command_line:command_line"; } @@ -74,6 +83,7 @@ const char kManagedValue[] = "user:managed"; const char kSupervisedUserValue[] = "supervised_user:supervised_user"; const char kExtensionValue[] = "user:extension"; +const char kStandaloneBrowserValue[] = "user:standalone_browser"; const char kCommandLineValue[] = "user:command_line"; const char kUserValue[] = "user:user"; } @@ -82,6 +92,7 @@ const char kManagedValue[] = "recommended:managed"; const char kSupervisedUserValue[] = "recommended:supervised_user"; const char kExtensionValue[] = "recommended:extension"; +const char kStandaloneBrowserValue[] = "recommended:standalone_browser"; const char kCommandLineValue[] = "recommended:command_line"; const char kUserValue[] = "recommended:user"; const char kRecommendedValue[] = "recommended:recommended"; @@ -91,6 +102,7 @@ const char kManagedValue[] = "default:managed"; const char kSupervisedUserValue[] = "default:supervised_user"; const char kExtensionValue[] = "default:extension"; +const char kStandaloneBrowserValue[] = "default:standalone_browser"; const char kCommandLineValue[] = "default:command_line"; const char kUserValue[] = "default:user"; const char kRecommendedValue[] = "default:recommended"; @@ -104,6 +116,7 @@ CreateManagedPrefs(); CreateSupervisedUserPrefs(); CreateExtensionPrefs(); + CreateStandaloneBrowserPrefs(); CreateCommandLinePrefs(); CreateUserPrefs(); CreateRecommendedPrefs(); @@ -113,9 +126,10 @@ // Create a fresh PrefValueStore. pref_value_store_ = std::make_unique<PrefValueStore>( managed_pref_store_.get(), supervised_user_pref_store_.get(), - extension_pref_store_.get(), command_line_pref_store_.get(), - user_pref_store_.get(), recommended_pref_store_.get(), - default_pref_store_.get(), &pref_notifier_); + extension_pref_store_.get(), standalone_browser_pref_store_.get(), + command_line_pref_store_.get(), user_pref_store_.get(), + recommended_pref_store_.get(), default_pref_store_.get(), + &pref_notifier_); pref_value_store_->set_callback( base::BindRepeating(&MockPrefModelAssociator::ProcessPrefChange, @@ -152,6 +166,20 @@ extension_pref::kExtensionValue); } + void CreateStandaloneBrowserPrefs() { + standalone_browser_pref_store_ = new TestingPrefStore; + standalone_browser_pref_store_->SetString( + prefs::kManagedPref, standalone_browser_pref::kManagedValue); + standalone_browser_pref_store_->SetString( + prefs::kSupervisedUserPref, + standalone_browser_pref::kSupervisedUserValue); + standalone_browser_pref_store_->SetString( + prefs::kExtensionPref, standalone_browser_pref::kExtensionValue); + standalone_browser_pref_store_->SetString( + prefs::kStandaloneBrowserPref, + standalone_browser_pref::kStandaloneBrowserValue); + } + void CreateCommandLinePrefs() { command_line_pref_store_ = new TestingPrefStore; command_line_pref_store_->SetString( @@ -164,6 +192,9 @@ prefs::kExtensionPref, command_line_pref::kExtensionValue); command_line_pref_store_->SetString( + prefs::kStandaloneBrowserPref, + command_line_pref::kStandaloneBrowserValue); + command_line_pref_store_->SetString( prefs::kCommandLinePref, command_line_pref::kCommandLineValue); } @@ -182,6 +213,8 @@ user_pref_store_->SetString( prefs::kExtensionPref, user_pref::kExtensionValue); + user_pref_store_->SetString(prefs::kStandaloneBrowserPref, + user_pref::kStandaloneBrowserValue); user_pref_store_->SetString( prefs::kUserPref, user_pref::kUserValue); @@ -202,6 +235,9 @@ prefs::kExtensionPref, recommended_pref::kExtensionValue); recommended_pref_store_->SetString( + prefs::kStandaloneBrowserPref, + recommended_pref::kStandaloneBrowserValue); + recommended_pref_store_->SetString( prefs::kUserPref, recommended_pref::kUserValue); recommended_pref_store_->SetString( @@ -223,6 +259,8 @@ default_pref_store_->SetString( prefs::kExtensionPref, default_pref::kExtensionValue); + default_pref_store_->SetString(prefs::kStandaloneBrowserPref, + default_pref::kStandaloneBrowserValue); default_pref_store_->SetString( prefs::kUserPref, default_pref::kUserValue); @@ -251,6 +289,7 @@ scoped_refptr<TestingPrefStore> managed_pref_store_; scoped_refptr<TestingPrefStore> supervised_user_pref_store_; scoped_refptr<TestingPrefStore> extension_pref_store_; + scoped_refptr<TestingPrefStore> standalone_browser_pref_store_; scoped_refptr<TestingPrefStore> command_line_pref_store_; scoped_refptr<TestingPrefStore> user_pref_store_; scoped_refptr<TestingPrefStore> recommended_pref_store_; @@ -480,6 +519,7 @@ managed_pref_store_->SetInitializationCompleted(); supervised_user_pref_store_->SetInitializationCompleted(); extension_pref_store_->SetInitializationCompleted(); + standalone_browser_pref_store_->SetInitializationCompleted(); command_line_pref_store_->SetInitializationCompleted(); recommended_pref_store_->SetInitializationCompleted(); default_pref_store_->SetInitializationCompleted(); @@ -499,6 +539,8 @@ EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( prefs::kExtensionPref)); EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( + prefs::kStandaloneBrowserPref)); + EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( prefs::kCommandLinePref)); EXPECT_FALSE(pref_value_store_->PrefValueInManagedStore( prefs::kUserPref)); @@ -518,6 +560,8 @@ EXPECT_TRUE(pref_value_store_->PrefValueInExtensionStore( prefs::kExtensionPref)); EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore( + prefs::kStandaloneBrowserPref)); + EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore( prefs::kCommandLinePref)); EXPECT_FALSE(pref_value_store_->PrefValueInExtensionStore( prefs::kUserPref)); @@ -536,6 +580,8 @@ prefs::kSupervisedUserPref)); EXPECT_TRUE(pref_value_store_->PrefValueInUserStore( prefs::kExtensionPref)); + EXPECT_TRUE( + pref_value_store_->PrefValueInUserStore(prefs::kStandaloneBrowserPref)); EXPECT_TRUE(pref_value_store_->PrefValueInUserStore( prefs::kCommandLinePref)); EXPECT_TRUE(pref_value_store_->PrefValueInUserStore( @@ -556,6 +602,8 @@ EXPECT_TRUE(pref_value_store_->PrefValueFromExtensionStore( prefs::kExtensionPref)); EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore( + prefs::kStandaloneBrowserPref)); + EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore( prefs::kCommandLinePref)); EXPECT_FALSE(pref_value_store_->PrefValueFromExtensionStore( prefs::kUserPref)); @@ -574,6 +622,8 @@ prefs::kSupervisedUserPref)); EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore( prefs::kExtensionPref)); + EXPECT_FALSE( + pref_value_store_->PrefValueFromUserStore(prefs::kStandaloneBrowserPref)); EXPECT_FALSE(pref_value_store_->PrefValueFromUserStore( prefs::kCommandLinePref)); EXPECT_TRUE(pref_value_store_->PrefValueFromUserStore( @@ -594,6 +644,8 @@ EXPECT_FALSE(pref_value_store_->PrefValueFromRecommendedStore( prefs::kExtensionPref)); EXPECT_FALSE(pref_value_store_->PrefValueFromRecommendedStore( + prefs::kStandaloneBrowserPref)); + EXPECT_FALSE(pref_value_store_->PrefValueFromRecommendedStore( prefs::kCommandLinePref)); EXPECT_FALSE(pref_value_store_->PrefValueFromRecommendedStore( prefs::kUserPref)); @@ -613,6 +665,8 @@ EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore( prefs::kExtensionPref)); EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore( + prefs::kStandaloneBrowserPref)); + EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore( prefs::kCommandLinePref)); EXPECT_FALSE(pref_value_store_->PrefValueFromDefaultStore( prefs::kUserPref)); @@ -632,6 +686,8 @@ EXPECT_FALSE(pref_value_store_->PrefValueUserModifiable( prefs::kExtensionPref)); EXPECT_FALSE(pref_value_store_->PrefValueUserModifiable( + prefs::kStandaloneBrowserPref)); + EXPECT_FALSE(pref_value_store_->PrefValueUserModifiable( prefs::kCommandLinePref)); EXPECT_TRUE(pref_value_store_->PrefValueUserModifiable( prefs::kUserPref)); @@ -651,6 +707,8 @@ EXPECT_TRUE(pref_value_store_->PrefValueExtensionModifiable( prefs::kExtensionPref)); EXPECT_TRUE(pref_value_store_->PrefValueExtensionModifiable( + prefs::kStandaloneBrowserPref)); + EXPECT_TRUE(pref_value_store_->PrefValueExtensionModifiable( prefs::kCommandLinePref)); EXPECT_TRUE(pref_value_store_->PrefValueExtensionModifiable( prefs::kUserPref));
diff --git a/components/prefs/standalone_browser_pref_store.cc b/components/prefs/standalone_browser_pref_store.cc new file mode 100644 index 0000000..08f31942 --- /dev/null +++ b/components/prefs/standalone_browser_pref_store.cc
@@ -0,0 +1,7 @@ +// 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 "components/prefs/standalone_browser_pref_store.h" + +StandaloneBrowserPrefStore::~StandaloneBrowserPrefStore() = default;
diff --git a/components/prefs/standalone_browser_pref_store.h b/components/prefs/standalone_browser_pref_store.h new file mode 100644 index 0000000..dc1e8b7 --- /dev/null +++ b/components/prefs/standalone_browser_pref_store.h
@@ -0,0 +1,27 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PREFS_STANDALONE_BROWSER_PREF_STORE_H_ +#define COMPONENTS_PREFS_STANDALONE_BROWSER_PREF_STORE_H_ + +#include "components/prefs/prefs_export.h" +#include "components/prefs/value_map_pref_store.h" + +// A PrefStore implementation that holds preferences sent by another browser +// instance. For example, in ash, this prefstore holds the value of +// extension-controlled system prefs set in lacros (e.g. the screen magnifier) +// TODO(crbug.com/1218145): Implement persistence. +class COMPONENTS_PREFS_EXPORT StandaloneBrowserPrefStore + : public ValueMapPrefStore { + public: + StandaloneBrowserPrefStore() = default; + StandaloneBrowserPrefStore(const StandaloneBrowserPrefStore&) = delete; + StandaloneBrowserPrefStore& operator=(const StandaloneBrowserPrefStore&) = + delete; + + protected: + ~StandaloneBrowserPrefStore() override; +}; + +#endif // COMPONENTS_PREFS_STANDALONE_BROWSER_PREF_STORE_H_
diff --git a/components/prefs/testing_pref_service.cc b/components/prefs/testing_pref_service.cc index fb06790..998a7370 100644 --- a/components/prefs/testing_pref_service.cc +++ b/components/prefs/testing_pref_service.cc
@@ -19,6 +19,7 @@ TestingPrefStore* managed_prefs, TestingPrefStore* supervised_user_prefs, TestingPrefStore* extension_prefs, + TestingPrefStore* standalone_browser_prefs, TestingPrefStore* user_prefs, TestingPrefStore* recommended_prefs, PrefRegistry* pref_registry, @@ -28,6 +29,7 @@ std::make_unique<PrefValueStore>(managed_prefs, supervised_user_prefs, extension_prefs, + standalone_browser_prefs, /*command_line_prefs=*/nullptr, user_prefs, recommended_prefs, @@ -42,6 +44,7 @@ managed_prefs_(managed_prefs), supervised_user_prefs_(supervised_user_prefs), extension_prefs_(extension_prefs), + standalone_browser_prefs_(standalone_browser_prefs), user_prefs_(user_prefs), recommended_prefs_(recommended_prefs) {} @@ -50,6 +53,7 @@ /*managed_prefs=*/new TestingPrefStore(), /*supervised_user_prefs=*/new TestingPrefStore(), /*extension_prefs=*/new TestingPrefStore(), + /*standalone_browser_prefs=*/new TestingPrefStore(), /*user_prefs=*/new TestingPrefStore(), /*recommended_prefs=*/new TestingPrefStore(), new PrefRegistrySimple(),
diff --git a/components/prefs/testing_pref_service.h b/components/prefs/testing_pref_service.h index 7ec1954..cd05b48 100644 --- a/components/prefs/testing_pref_service.h +++ b/components/prefs/testing_pref_service.h
@@ -79,6 +79,7 @@ TestingPrefServiceBase(TestingPrefStore* managed_prefs, TestingPrefStore* supervised_user_prefs, TestingPrefStore* extension_prefs, + TestingPrefStore* standalone_browser_prefs, TestingPrefStore* user_prefs, TestingPrefStore* recommended_prefs, ConstructionPrefRegistry* pref_registry, @@ -102,6 +103,7 @@ scoped_refptr<TestingPrefStore> managed_prefs_; scoped_refptr<TestingPrefStore> supervised_user_prefs_; scoped_refptr<TestingPrefStore> extension_prefs_; + scoped_refptr<TestingPrefStore> standalone_browser_prefs_; scoped_refptr<TestingPrefStore> user_prefs_; scoped_refptr<TestingPrefStore> recommended_prefs_; }; @@ -130,6 +132,7 @@ TestingPrefStore* managed_prefs, TestingPrefStore* supervised_user_prefs, TestingPrefStore* extension_prefs, + TestingPrefStore* standalone_browser_prefs, TestingPrefStore* user_prefs, TestingPrefStore* recommended_prefs, PrefRegistry* pref_registry, @@ -269,6 +272,7 @@ managed_prefs_->SetInitializationCompleted(); supervised_user_prefs_->SetInitializationCompleted(); extension_prefs_->SetInitializationCompleted(); + standalone_browser_prefs_->SetInitializationCompleted(); recommended_prefs_->SetInitializationCompleted(); // |user_prefs_| is initialized in PrefService constructor so no need to // set initialization status again.
diff --git a/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc b/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc index 73104b01..f4bd833a 100644 --- a/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc +++ b/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc
@@ -534,8 +534,10 @@ EventType::USER_STATE_ENABLED); if (!latest_enabled_event) { - // this code path could be possible if ESB was enabled via policy but - // later disabled by the user, since policy enables/disables are not tracked + // This code path could be possible if ESB was enabled via policy but + // later disabled by the user, since policy enables/disables are not + // tracked. It's also possible if it's been longer than kEventMaxDurationDay + // days since the latest enabled event. return "NeverEnabled"; } const auto hours_since_enabled =
diff --git a/components/segmentation_platform/internal/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java b/components/segmentation_platform/internal/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java index 76c27ba..38f34d5d 100644 --- a/components/segmentation_platform/internal/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java +++ b/components/segmentation_platform/internal/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java
@@ -35,6 +35,12 @@ mNativePtr, this, segmentationKey, callback); } + @Override + public SegmentSelectionResult getCachedSegmentResult(String segmentationKey) { + return SegmentationPlatformServiceImplJni.get().getCachedSegmentResult( + mNativePtr, this, segmentationKey); + } + @CalledByNative private void clearNativePtr() { mNativePtr = 0; @@ -53,5 +59,7 @@ void getSelectedSegment(long nativeSegmentationPlatformServiceAndroid, SegmentationPlatformServiceImpl caller, String segmentationKey, Callback<SegmentSelectionResult> callback); + SegmentSelectionResult getCachedSegmentResult(long nativeSegmentationPlatformServiceAndroid, + SegmentationPlatformServiceImpl caller, String segmentationKey); } }
diff --git a/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc b/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc index 738d40fc..d580aa7 100644 --- a/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc +++ b/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc
@@ -85,6 +85,16 @@ } ScopedJavaLocalRef<jobject> +SegmentationPlatformServiceAndroid::GetCachedSegmentResult( + JNIEnv* env, + const JavaParamRef<jobject>& jcaller, + const JavaParamRef<jstring>& j_segmentation_key) { + return CreateJavaSegmentSelectionResult( + env, segmentation_platform_service_->GetCachedSegmentResult( + ConvertJavaStringToUTF8(env, j_segmentation_key))); +} + +ScopedJavaLocalRef<jobject> SegmentationPlatformServiceAndroid::GetJavaObject() { return ScopedJavaLocalRef<jobject>(java_obj_); }
diff --git a/components/segmentation_platform/internal/android/segmentation_platform_service_android.h b/components/segmentation_platform/internal/android/segmentation_platform_service_android.h index c9225b0..86ad117a 100644 --- a/components/segmentation_platform/internal/android/segmentation_platform_service_android.h +++ b/components/segmentation_platform/internal/android/segmentation_platform_service_android.h
@@ -30,6 +30,11 @@ const JavaParamRef<jstring>& j_segmentation_key, const JavaParamRef<jobject>& j_callback); + ScopedJavaLocalRef<jobject> GetCachedSegmentResult( + JNIEnv* env, + const JavaParamRef<jobject>& jcaller, + const JavaParamRef<jstring>& j_segmentation_key); + ScopedJavaLocalRef<jobject> GetJavaObject(); private:
diff --git a/components/segmentation_platform/internal/database/metadata_utils.cc b/components/segmentation_platform/internal/database/metadata_utils.cc index 0ba1fe92..574f6807 100644 --- a/components/segmentation_platform/internal/database/metadata_utils.cc +++ b/components/segmentation_platform/internal/database/metadata_utils.cc
@@ -4,8 +4,12 @@ #include "components/segmentation_platform/internal/database/metadata_utils.h" +#include <inttypes.h> + #include "base/metrics/metrics_hashes.h" #include "base/notreached.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/time/time.h" #include "components/optimization_guide/proto/models.pb.h" #include "components/segmentation_platform/internal/database/signal_key.h" @@ -40,6 +44,36 @@ return 0; } } + +std::string FeatureToString(const proto::Feature& feature) { + std::string result; + if (feature.has_type()) { + result = "type:" + proto::SignalType_Name(feature.type()) + ", "; + } + if (feature.has_name()) { + result.append("name:" + feature.name() + ", "); + } + if (feature.has_name_hash()) { + result.append( + base::StringPrintf("name_hash:0x%" PRIx64 ", ", feature.name_hash())); + } + if (feature.has_bucket_count()) { + result.append(base::StringPrintf("bucket_count:%" PRIu64 ", ", + feature.bucket_count())); + } + if (feature.has_tensor_length()) { + result.append(base::StringPrintf("tensor_length:%" PRIu64 ", ", + feature.tensor_length())); + } + if (feature.has_aggregation()) { + result.append("aggregation:" + + proto::Aggregation_Name(feature.aggregation())); + } + if (base::EndsWith(result, ", ")) + result.resize(result.size() - 2); + return result; +} + } // namespace ValidationResult ValidateSegmentInfo(const proto::SegmentInfo& segment_info) { @@ -222,5 +256,38 @@ return discrete_result; } +std::string SegmetationModelMetadataToString( + const proto::SegmentationModelMetadata& model_metadata) { + std::string result; + for (const auto& feature : model_metadata.features()) { + result.append("feature:{" + FeatureToString(feature) + "}, "); + } + if (model_metadata.has_time_unit()) { + result.append( + "time_unit:" + proto::TimeUnit_Name(model_metadata.time_unit()) + ", "); + } + if (model_metadata.has_bucket_duration()) { + result.append(base::StringPrintf("bucket_duration:%" PRIu64 ", ", + model_metadata.bucket_duration())); + } + if (model_metadata.has_signal_storage_length()) { + result.append(base::StringPrintf("signal_storage_length:%" PRId64 ", ", + model_metadata.signal_storage_length())); + } + if (model_metadata.has_min_signal_collection_length()) { + result.append( + base::StringPrintf("min_signal_collection_length:%" PRId64 ", ", + model_metadata.min_signal_collection_length())); + } + if (model_metadata.has_result_time_to_live()) { + result.append(base::StringPrintf("result_time_to_live:%" PRId64, + model_metadata.result_time_to_live())); + } + + if (base::EndsWith(result, ", ")) + result.resize(result.size() - 2); + return result; +} + } // namespace metadata_utils } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/database/metadata_utils.h b/components/segmentation_platform/internal/database/metadata_utils.h index fde9258..537c3c1 100644 --- a/components/segmentation_platform/internal/database/metadata_utils.h +++ b/components/segmentation_platform/internal/database/metadata_utils.h
@@ -84,6 +84,9 @@ float input_score, const proto::SegmentationModelMetadata& metadata); +std::string SegmetationModelMetadataToString( + const proto::SegmentationModelMetadata& model_metadata); + } // namespace metadata_utils } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/database/metadata_utils_unittest.cc b/components/segmentation_platform/internal/database/metadata_utils_unittest.cc index 2692ffd7..4780296 100644 --- a/components/segmentation_platform/internal/database/metadata_utils_unittest.cc +++ b/components/segmentation_platform/internal/database/metadata_utils_unittest.cc
@@ -506,4 +506,28 @@ metadata)); } +TEST_F(MetadataUtilsTest, SegmetationModelMetadataToString) { + proto::SegmentationModelMetadata metadata; + ASSERT_TRUE( + metadata_utils::SegmetationModelMetadataToString(metadata).empty()); + + proto::Feature feature; + feature.set_type(proto::SignalType::UNKNOWN_SIGNAL_TYPE); + feature.set_name("test name"); + feature.set_aggregation(proto::Aggregation::COUNT); + feature.set_bucket_count(456); + *metadata.add_features() = feature; + + std::string expected = + "feature:{type:UNKNOWN_SIGNAL_TYPE, name:test name, bucket_count:456, " + "aggregation:COUNT}"; + ASSERT_EQ(metadata_utils::SegmetationModelMetadataToString(metadata), + expected); + + metadata.set_bucket_duration(10); + metadata.set_min_signal_collection_length(7); + ASSERT_EQ(metadata_utils::SegmetationModelMetadataToString(metadata), + expected + ", bucket_duration:10, min_signal_collection_length:7"); +} + } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc b/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc index 3e7c2a5..7cbce72 100644 --- a/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc +++ b/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc
@@ -22,6 +22,11 @@ FROM_HERE, base::BindOnce(std::move(callback), SegmentSelectionResult())); } +SegmentSelectionResult DummySegmentationPlatformService::GetCachedSegmentResult( + const std::string& segmentation_key) { + return SegmentSelectionResult(); +} + void DummySegmentationPlatformService::EnableMetrics( bool signal_collection_allowed) {} } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/dummy_segmentation_platform_service.h b/components/segmentation_platform/internal/dummy_segmentation_platform_service.h index 7102adc..67df2fd 100644 --- a/components/segmentation_platform/internal/dummy_segmentation_platform_service.h +++ b/components/segmentation_platform/internal/dummy_segmentation_platform_service.h
@@ -27,6 +27,8 @@ // SegmentationPlatformService overrides. void GetSelectedSegment(const std::string& segmentation_key, SegmentSelectionCallback callback) override; + SegmentSelectionResult GetCachedSegmentResult( + const std::string& segmentation_key) override; void EnableMetrics(bool signal_collection_allowed) override; };
diff --git a/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc b/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc index accf532..645967d 100644 --- a/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc +++ b/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc
@@ -47,6 +47,8 @@ &DummySegmentationPlatformServiceTest::OnGetSelectedSegment, base::Unretained(this), loop.QuitClosure(), expected)); loop.Run(); + ASSERT_EQ(expected, + segmentation_platform_service_->GetCachedSegmentResult("some_key")); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc index c76de96..1150f3e 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl.cc +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
@@ -103,8 +103,7 @@ std::move(signal_storage_config_db), clock); segmentation_result_prefs_ = std::make_unique<SegmentationResultPrefs>(pref_service); - proxy_ = - std::make_unique<ServiceProxyImpl>(this, segment_info_database_.get()); + proxy_ = std::make_unique<ServiceProxyImpl>(segment_info_database_.get()); // Construct signal processors. user_action_signal_handler_ = @@ -158,6 +157,13 @@ selector->GetSelectedSegment(std::move(callback)); } +SegmentSelectionResult SegmentationPlatformServiceImpl::GetCachedSegmentResult( + const std::string& segmentation_key) { + CHECK(segment_selectors_.find(segmentation_key) != segment_selectors_.end()); + auto& selector = segment_selectors_.at(segmentation_key); + return selector->GetCachedSegmentResult(); +} + void SegmentationPlatformServiceImpl::EnableMetrics( bool signal_collection_allowed) { signal_filter_processor_->EnableMetrics(signal_collection_allowed);
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl.h b/components/segmentation_platform/internal/segmentation_platform_service_impl.h index fca4bd55..85bb2e0 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl.h +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl.h
@@ -112,6 +112,8 @@ // SegmentationPlatformService overrides. void GetSelectedSegment(const std::string& segmentation_key, SegmentSelectionCallback callback) override; + SegmentSelectionResult GetCachedSegmentResult( + const std::string& segmentation_key) override; void EnableMetrics(bool signal_collection_allowed) override; ServiceProxy* GetServiceProxy() override;
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc index 6e0f7f98..24243366 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc
@@ -175,6 +175,20 @@ loop.Run(); } + void AssertCachedSegment( + const std::string& segmentation_key, + bool is_ready, + OptimizationTarget expected = + OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN) { + SegmentSelectionResult result; + result.is_ready = is_ready; + if (is_ready) + result.segment = expected; + ASSERT_EQ(result, + segmentation_platform_service_impl_->GetCachedSegmentResult( + segmentation_key)); + } + protected: base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; @@ -253,6 +267,11 @@ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE); AssertSelectedSegment(kTestSegmentationKey2, false); AssertSelectedSegment(kTestSegmentationKey3, false); + AssertCachedSegment( + kTestSegmentationKey1, true, + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE); + AssertCachedSegment(kTestSegmentationKey2, false); + AssertCachedSegment(kTestSegmentationKey3, false); mem_impl->OnSegmentationModelUpdated( OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE, metadata); @@ -278,6 +297,11 @@ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE); AssertSelectedSegment(kTestSegmentationKey2, false); AssertSelectedSegment(kTestSegmentationKey3, false); + AssertCachedSegment( + kTestSegmentationKey1, true, + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE); + AssertCachedSegment(kTestSegmentationKey2, false); + AssertCachedSegment(kTestSegmentationKey3, false); } TEST_F(SegmentationPlatformServiceImplTest, @@ -352,6 +376,13 @@ kTestSegmentationKey2, true, OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE); AssertSelectedSegment(kTestSegmentationKey3, false); + AssertCachedSegment( + kTestSegmentationKey1, true, + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE); + AssertCachedSegment( + kTestSegmentationKey2, true, + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE); + AssertCachedSegment(kTestSegmentationKey3, false); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/segment_selector.h b/components/segmentation_platform/internal/selection/segment_selector.h index e86615cb..af20d2a 100644 --- a/components/segmentation_platform/internal/selection/segment_selector.h +++ b/components/segmentation_platform/internal/selection/segment_selector.h
@@ -28,9 +28,13 @@ using SegmentSelectionCallback = base::OnceCallback<void(const SegmentSelectionResult&)>; - // Client API. Returns the selected segment from the last session. If none, - // returns empty result. + // Client API. Returns the selected segment from the last session + // asynchronously. If none, returns empty result. virtual void GetSelectedSegment(SegmentSelectionCallback callback) = 0; + + // Client API. Returns the cached selected segment from the last session + // synchronously. + virtual SegmentSelectionResult GetCachedSegmentResult() = 0; }; } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.cc b/components/segmentation_platform/internal/selection/segment_selector_impl.cc index d444276..73a6f60 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_impl.cc +++ b/components/segmentation_platform/internal/selection/segment_selector_impl.cc
@@ -54,6 +54,10 @@ base::BindOnce(std::move(callback), selected_segment_last_session_)); } +SegmentSelectionResult SegmentSelectorImpl::GetCachedSegmentResult() { + return selected_segment_last_session_; +} + void SegmentSelectorImpl::OnModelExecutionCompleted( OptimizationTarget segment_id) { // If the |segment_id| is not in config, then skip any updates early.
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.h b/components/segmentation_platform/internal/selection/segment_selector_impl.h index d48bd83..70f665df 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_impl.h +++ b/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -41,6 +41,7 @@ // SegmentSelector overrides. void GetSelectedSegment(SegmentSelectionCallback callback) override; + SegmentSelectionResult GetCachedSegmentResult() override; // ModelExecutionScheduler::Observer overrides.
diff --git a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc index 63bf8d353..11ba9bf5 100644 --- a/components/segmentation_platform/internal/selection/segment_selector_unittest.cc +++ b/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
@@ -301,6 +301,7 @@ result.segment = segment_id0; result.is_ready = true; GetSelectedSegment(result); + ASSERT_EQ(result, segment_selector_->GetCachedSegmentResult()); // Add results for a new segment. base::Time result_timestamp = base::Time::Now(); @@ -312,6 +313,7 @@ // GetSelectedSegment should still return value from previous session. GetSelectedSegment(result); + ASSERT_EQ(result, segment_selector_->GetCachedSegmentResult()); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/service_proxy_impl.cc b/components/segmentation_platform/internal/service_proxy_impl.cc index c399021..5e67333 100644 --- a/components/segmentation_platform/internal/service_proxy_impl.cc +++ b/components/segmentation_platform/internal/service_proxy_impl.cc
@@ -8,6 +8,7 @@ #include "base/strings/stringprintf.h" #include "components/optimization_guide/core/optimization_guide_util.h" +#include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/segmentation_platform_service_impl.h" namespace segmentation_platform { @@ -22,6 +23,12 @@ segment_info.segment_id()) + "\n"; } + if (segment_info.has_model_metadata()) { + result.append("model_metadata: { " + + metadata_utils::SegmetationModelMetadataToString( + segment_info.model_metadata()) + + " }\n"); + } if (segment_info.has_prediction_result()) { const auto prediction_result = segment_info.prediction_result(); std::string prediction_result_str = base::StringPrintf( @@ -34,11 +41,9 @@ return result; } -ServiceProxyImpl::ServiceProxyImpl(SegmentationPlatformService* service, - SegmentInfoDatabase* segment_db) +ServiceProxyImpl::ServiceProxyImpl(SegmentInfoDatabase* segment_db) : is_service_initialized_(false), service_status_flag_(0), - service_(service), segment_db_(segment_db) {} ServiceProxyImpl::~ServiceProxyImpl() = default; @@ -71,19 +76,15 @@ OnServiceStatusChanged(is_service_initialized_, service_status_flag_); } -void ServiceProxyImpl::GetSelectedSegment( - const std::string& segmentation_key, - SegmentationPlatformService::SegmentSelectionCallback callback) { - service_->GetSelectedSegment(segmentation_key, std::move(callback)); -} - // Called after retrieving all the segmentation info from the DB. void ServiceProxyImpl::OnGetAllSegmentationInfo( std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>> - segment_infos) { - std::vector<std::string> result; - for (const auto& segment_info : segment_infos) { - result.emplace_back(SegmentInfoToString(segment_info.second)); + segment_info) { + std::vector<std::pair<std::string, std::string>> result; + for (const auto& info : segment_info) { + result.emplace_back(std::make_pair( + optimization_guide::GetStringNameForOptimizationTarget(info.first), + SegmentInfoToString(info.second))); } for (Observer& obs : observers_)
diff --git a/components/segmentation_platform/internal/service_proxy_impl.h b/components/segmentation_platform/internal/service_proxy_impl.h index d9d83bf..067a99e 100644 --- a/components/segmentation_platform/internal/service_proxy_impl.h +++ b/components/segmentation_platform/internal/service_proxy_impl.h
@@ -21,8 +21,7 @@ // component and/or debug UI. class ServiceProxyImpl : public ServiceProxy { public: - ServiceProxyImpl(SegmentationPlatformService* service, - SegmentInfoDatabase* segment_db); + explicit ServiceProxyImpl(SegmentInfoDatabase* segment_db); ~ServiceProxyImpl() override; // Helper method to convert |segment_info| to string. @@ -38,9 +37,6 @@ // Returns the current status of the segmentation service. void GetServiceStatus() override; - void GetSelectedSegment( - const std::string& segmentation_key, - SegmentationPlatformService::SegmentSelectionCallback callback) override; // Called when segmentation service status changed. void OnServiceStatusChanged(bool is_initialized, int status_flag); @@ -49,11 +45,10 @@ // Called after retrieving all the segmentation info from the DB. void OnGetAllSegmentationInfo( std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>> - segment_infos); + segment_info); bool is_service_initialized_; int service_status_flag_; - SegmentationPlatformService* service_; SegmentInfoDatabase* segment_db_; base::ObserverList<ServiceProxy::Observer> observers_;
diff --git a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc index 02ca55a..8c91940 100644 --- a/components/segmentation_platform/internal/service_proxy_impl_unittest.cc +++ b/components/segmentation_platform/internal/service_proxy_impl_unittest.cc
@@ -7,6 +7,7 @@ #include "base/strings/string_number_conversions.h" #include "components/leveldb_proto/public/proto_database.h" #include "components/leveldb_proto/testing/fake_db.h" +#include "components/optimization_guide/core/optimization_guide_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace segmentation_platform { @@ -39,8 +40,7 @@ db_ = db.get(); segment_db_ = std::make_unique<SegmentInfoDatabase>(std::move(db)); - service_proxy_impl_ = - std::make_unique<ServiceProxyImpl>(nullptr, segment_db_.get()); + service_proxy_impl_ = std::make_unique<ServiceProxyImpl>(segment_db_.get()); service_proxy_impl_->AddObserver(this); } @@ -56,7 +56,8 @@ } void OnSegmentInfoAvailable( - const std::vector<std::string>& segment_info) override { + const std::vector<std::pair<std::string, std::string>>& segment_info) + override { segment_info_ = segment_info; } @@ -68,7 +69,7 @@ raw_ptr<leveldb_proto::test::FakeDB<proto::SegmentInfo>> db_{nullptr}; std::unique_ptr<SegmentInfoDatabase> segment_db_; std::unique_ptr<ServiceProxyImpl> service_proxy_impl_; - std::vector<std::string> segment_info_; + std::vector<std::pair<std::string, std::string>> segment_info_; }; TEST_F(ServiceProxyImplTest, GetServiceStatus) { @@ -98,7 +99,11 @@ service_proxy_impl_->OnServiceStatusChanged(true, 7); db_->LoadCallback(true); ASSERT_EQ(segment_info_.size(), 1u); - ASSERT_EQ(segment_info_.at(0), ServiceProxyImpl::SegmentInfoToString(info)); + ASSERT_EQ(segment_info_.at(0).first, + optimization_guide::GetStringNameForOptimizationTarget( + OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB)); + ASSERT_EQ(segment_info_.at(0).second, + ServiceProxyImpl::SegmentInfoToString(info)); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/public/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformService.java b/components/segmentation_platform/public/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformService.java index e3378e9..c300ec6 100644 --- a/components/segmentation_platform/public/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformService.java +++ b/components/segmentation_platform/public/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformService.java
@@ -12,10 +12,18 @@ */ public interface SegmentationPlatformService { /** - * Called to get the segment selection result from the backend. + * Called to get the segment selection result asynchronously from the backend. * @param segmentationKey The key to be used to distinguish between different segmentation - * usages. Currently unused. + * usages. * @param callback The callback that contains the result of segmentation. */ void getSelectedSegment(String segmentationKey, Callback<SegmentSelectionResult> callback); + + /** + * Called to get the segment selection result synchronously from the backend. + * @param segmentationKey The key to be used to distinguish between different segmentation + * usages. + * @return The result of segment selection + */ + SegmentSelectionResult getCachedSegmentResult(String segmentationKey); } \ No newline at end of file
diff --git a/components/segmentation_platform/public/segmentation_platform_service.h b/components/segmentation_platform/public/segmentation_platform_service.h index cb74dbc4..7b93a8d 100644 --- a/components/segmentation_platform/public/segmentation_platform_service.h +++ b/components/segmentation_platform/public/segmentation_platform_service.h
@@ -50,10 +50,16 @@ using SegmentSelectionCallback = base::OnceCallback<void(const SegmentSelectionResult&)>; - // Called to get the selected segment. If none, returns empty result. + // Called to get the selected segment asynchronously. If none, returns empty + // result. virtual void GetSelectedSegment(const std::string& segmentation_key, SegmentSelectionCallback callback) = 0; + // Called to get the selected segment synchronously. If none, returns empty + // result. + virtual SegmentSelectionResult GetCachedSegmentResult( + const std::string& segmentation_key) = 0; + // Called to enable or disable metrics collection. Must be explicitly called // on startup. virtual void EnableMetrics(bool signal_collection_allowed) = 0;
diff --git a/components/segmentation_platform/public/service_proxy.h b/components/segmentation_platform/public/service_proxy.h index 8b1f914..6e9711d1 100644 --- a/components/segmentation_platform/public/service_proxy.h +++ b/components/segmentation_platform/public/service_proxy.h
@@ -5,10 +5,10 @@ #ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SERVICE_PROXY_H_ #define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SERVICE_PROXY_H_ +#include <utility> #include <vector> #include "base/observer_list_types.h" -#include "components/segmentation_platform/public/segmentation_platform_service.h" namespace segmentation_platform { @@ -21,7 +21,7 @@ // Called whenever the servoice status changes. virtual void OnServiceStatusChanged(bool is_initialized, int status_flag) {} virtual void OnSegmentInfoAvailable( - const std::vector<std::string>& segment_info) {} + const std::vector<std::pair<std::string, std::string>>& segment_info) {} }; virtual ~ServiceProxy() = default; @@ -35,11 +35,6 @@ // Returns the current status of the segmentation service. virtual void GetServiceStatus() = 0; - // Called to get the selected segment. If none, returns empty result. - virtual void GetSelectedSegment( - const std::string& segmentation_key, - SegmentationPlatformService::SegmentSelectionCallback callback) = 0; - protected: ServiceProxy() = default; };
diff --git a/components/sync_preferences/pref_service_syncable.cc b/components/sync_preferences/pref_service_syncable.cc index 3db63fd..84e4126 100644 --- a/components/sync_preferences/pref_service_syncable.cc +++ b/components/sync_preferences/pref_service_syncable.cc
@@ -114,6 +114,7 @@ nullptr, // managed nullptr, // supervised_user incognito_extension_pref_store, + nullptr, // standalone_browser_prefs nullptr, // command_line_prefs incognito_pref_store.get(), nullptr, // recommended
diff --git a/components/sync_preferences/pref_service_syncable_factory.cc b/components/sync_preferences/pref_service_syncable_factory.cc index 9f7b4f01..e6c6054 100644 --- a/components/sync_preferences/pref_service_syncable_factory.cc +++ b/components/sync_preferences/pref_service_syncable_factory.cc
@@ -51,9 +51,10 @@ auto pref_notifier = std::make_unique<PrefNotifierImpl>(); auto pref_value_store = std::make_unique<PrefValueStore>( managed_prefs_.get(), supervised_user_prefs_.get(), - extension_prefs_.get(), command_line_prefs_.get(), user_prefs_.get(), - recommended_prefs_.get(), pref_registry->defaults().get(), - pref_notifier.get(), /*delegate=*/nullptr); + extension_prefs_.get(), standalone_browser_prefs_.get(), + command_line_prefs_.get(), user_prefs_.get(), recommended_prefs_.get(), + pref_registry->defaults().get(), pref_notifier.get(), + /*delegate=*/nullptr); return std::make_unique<PrefServiceSyncable>( std::move(pref_notifier), std::move(pref_value_store), user_prefs_.get(), std::move(pref_registry), pref_model_associator_client_,
diff --git a/components/sync_preferences/pref_service_syncable_unittest.cc b/components/sync_preferences/pref_service_syncable_unittest.cc index a9658bf..64fac4c 100644 --- a/components/sync_preferences/pref_service_syncable_unittest.cc +++ b/components/sync_preferences/pref_service_syncable_unittest.cc
@@ -403,6 +403,7 @@ new TestingPrefStore, new TestingPrefStore, new TestingPrefStore, + new TestingPrefStore, user_prefs_.get(), new TestingPrefStore, pref_registry_->defaults().get(), @@ -933,8 +934,9 @@ std::unique_ptr<PrefNotifierImpl>(pref_notifier_), std::make_unique<PrefValueStore>( new TestingPrefStore, new TestingPrefStore, new TestingPrefStore, - new TestingPrefStore, user_prefs_.get(), new TestingPrefStore, - pref_registry_->defaults().get(), pref_notifier_), + new TestingPrefStore, new TestingPrefStore, user_prefs_.get(), + new TestingPrefStore, pref_registry_->defaults().get(), + pref_notifier_), user_prefs_, pref_registry_, &client_, /*read_error_callback=*/base::DoNothing(), /*async=*/false);
diff --git a/components/sync_preferences/testing_pref_service_syncable.cc b/components/sync_preferences/testing_pref_service_syncable.cc index e2fd19c..454bbf8e 100644 --- a/components/sync_preferences/testing_pref_service_syncable.cc +++ b/components/sync_preferences/testing_pref_service_syncable.cc
@@ -18,6 +18,7 @@ TestingPrefServiceBase(TestingPrefStore* managed_prefs, TestingPrefStore* supervised_user_prefs, TestingPrefStore* extension_prefs, + TestingPrefStore* standalone_browser_prefs, TestingPrefStore* user_prefs, TestingPrefStore* recommended_prefs, user_prefs::PrefRegistrySyncable* pref_registry, @@ -27,6 +28,7 @@ std::make_unique<PrefValueStore>(managed_prefs, supervised_user_prefs, extension_prefs, + standalone_browser_prefs, /*command_line_prefs=*/nullptr, user_prefs, recommended_prefs, @@ -42,6 +44,7 @@ false), managed_prefs_(managed_prefs), extension_prefs_(extension_prefs), + standalone_browser_prefs_(standalone_browser_prefs), user_prefs_(user_prefs), recommended_prefs_(recommended_prefs) {} @@ -53,6 +56,7 @@ /*managed_prefs=*/new TestingPrefStore(), /*supervised_user_prefs=*/new TestingPrefStore(), /*extension_prefs=*/new TestingPrefStore(), + /*standalone_browser_prefs=*/new TestingPrefStore(), /*user_prefs=*/new TestingPrefStore(), /*recommended_prefs=*/new TestingPrefStore(), new user_prefs::PrefRegistrySyncable(), @@ -62,6 +66,7 @@ TestingPrefStore* managed_prefs, TestingPrefStore* supervised_user_prefs, TestingPrefStore* extension_prefs, + TestingPrefStore* standalone_browser_prefs, TestingPrefStore* user_prefs, TestingPrefStore* recommended_prefs, user_prefs::PrefRegistrySyncable* pref_registry, @@ -71,6 +76,7 @@ managed_prefs, supervised_user_prefs, extension_prefs, + standalone_browser_prefs, user_prefs, recommended_prefs, pref_registry,
diff --git a/components/sync_preferences/testing_pref_service_syncable.h b/components/sync_preferences/testing_pref_service_syncable.h index e7564e61d5..cd95a28 100644 --- a/components/sync_preferences/testing_pref_service_syncable.h +++ b/components/sync_preferences/testing_pref_service_syncable.h
@@ -35,6 +35,7 @@ TestingPrefServiceSyncable(TestingPrefStore* managed_prefs, TestingPrefStore* supervised_user_prefs, TestingPrefStore* extension_prefs, + TestingPrefStore* standalone_browser_prefs, TestingPrefStore* user_prefs, TestingPrefStore* recommended_prefs, user_prefs::PrefRegistrySyncable* pref_registry, @@ -60,6 +61,7 @@ TestingPrefServiceBase(TestingPrefStore* managed_prefs, TestingPrefStore* supervised_user_prefs, TestingPrefStore* extension_prefs, + TestingPrefStore* standalone_browser_prefs, TestingPrefStore* user_prefs, TestingPrefStore* recommended_prefs, user_prefs::PrefRegistrySyncable* pref_registry,
diff --git a/components/test/data/payments/no_shipping.js b/components/test/data/payments/no_shipping.js index 19c77135..c804f83 100644 --- a/components/test/data/payments/no_shipping.js +++ b/components/test/data/payments/no_shipping.js
@@ -10,12 +10,22 @@ * Launches the PaymentRequest UI that does not require a shipping address. */ function buy() { // eslint-disable-line no-unused-vars + buyWithMethods([ + { + supportedMethods: 'basic-card', + data: {supportedNetworks: ['visa', 'mastercard']}, + }, + ]); +} + +/** + * Launches the PaymentRequest UI that does not require a shipping address. + * @param {String} methodData - An array of payment method objects. + */ +function buyWithMethods(methodData) { try { new PaymentRequest( - [{ - supportedMethods: 'basic-card', - data: {supportedNetworks: ['visa', 'mastercard']}, - }], + methodData, { total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}, displayItems: [
diff --git a/components/viz/common/gpu/vulkan_in_process_context_provider.cc b/components/viz/common/gpu/vulkan_in_process_context_provider.cc index c2b5ef56..38838e9 100644 --- a/components/viz/common/gpu/vulkan_in_process_context_provider.cc +++ b/components/viz/common/gpu/vulkan_in_process_context_provider.cc
@@ -132,9 +132,24 @@ GrVkGetProc get_proc = [](const char* proc_name, VkInstance instance, VkDevice device) { if (device) { - if (std::strcmp("vkCreateGraphicsPipelines", proc_name) == 0) + // Using vkQueue*Hook for all vkQueue* methods here to make both chrome + // side access and skia side access to the same queue thread safe. + // vkQueue*Hook routes all skia side access to the same + // VulkanFunctionPointers vkQueue* api which chrome uses and is under the + // lock. + if (std::strcmp("vkCreateGraphicsPipelines", proc_name) == 0) { return reinterpret_cast<PFN_vkVoidFunction>( &gpu::CreateGraphicsPipelinesHook); + } else if (std::strcmp("vkQueueSubmit", proc_name) == 0) { + return reinterpret_cast<PFN_vkVoidFunction>( + &gpu::VulkanQueueSubmitHook); + } else if (std::strcmp("vkQueueWaitIdle", proc_name) == 0) { + return reinterpret_cast<PFN_vkVoidFunction>( + &gpu::VulkanQueueWaitIdleHook); + } else if (std::strcmp("vkQueuePresentKHR", proc_name) == 0) { + return reinterpret_cast<PFN_vkVoidFunction>( + &gpu::VulkanQueuePresentKHRHook); + } return vkGetDeviceProcAddr(device, proc_name); } return vkGetInstanceProcAddr(instance, proc_name);
diff --git a/components/webxr/OWNERS b/components/webxr/OWNERS index 2310121..d37fd2d1 100644 --- a/components/webxr/OWNERS +++ b/components/webxr/OWNERS
@@ -1,2 +1,7 @@ alcooper@chromium.org +bajones@chromium.org bialpio@chromium.org +klausw@chromium.org + +# WebXR Test related +bsheedy@chromium.org
diff --git a/components/webxr/android/arcore_device_provider.cc b/components/webxr/android/arcore_device_provider.cc index 6bb16b5..714e8c0 100644 --- a/components/webxr/android/arcore_device_provider.cc +++ b/components/webxr/android/arcore_device_provider.cc
@@ -19,16 +19,7 @@ ArCoreDeviceProvider::~ArCoreDeviceProvider() = default; -void ArCoreDeviceProvider::Initialize( - base::RepeatingCallback<void(device::mojom::XRDeviceId, - device::mojom::VRDisplayInfoPtr, - device::mojom::XRDeviceDataPtr, - mojo::PendingRemote<device::mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(device::mojom::XRDeviceId)> - remove_device_callback, - base::OnceClosure initialization_complete, - device::XrFrameSinkClientFactory xr_frame_sink_client_factory) { +void ArCoreDeviceProvider::Initialize(device::VRDeviceProviderClient* client) { if (device::IsArCoreSupported()) { DVLOG(2) << __func__ << ": ARCore is supported, creating device"; @@ -37,14 +28,14 @@ std::make_unique<device::ArImageTransportFactory>(), std::make_unique<webxr::MailboxToSurfaceBridgeFactoryImpl>(), std::make_unique<webxr::ArCoreJavaUtils>(compositor_delegate_provider_), - std::move(xr_frame_sink_client_factory)); + client->GetXrFrameSinkClientFactory()); - add_device_callback.Run( + client->AddRuntime( arcore_device_->GetId(), arcore_device_->GetVRDisplayInfo(), arcore_device_->GetDeviceData(), arcore_device_->BindXRRuntime()); } initialized_ = true; - std::move(initialization_complete).Run(); + client->OnProviderInitialized(); } bool ArCoreDeviceProvider::Initialized() {
diff --git a/components/webxr/android/arcore_device_provider.h b/components/webxr/android/arcore_device_provider.h index 15b43d1..74af836b 100644 --- a/components/webxr/android/arcore_device_provider.h +++ b/components/webxr/android/arcore_device_provider.h
@@ -28,16 +28,7 @@ ArCoreDeviceProvider& operator=(const ArCoreDeviceProvider&) = delete; ~ArCoreDeviceProvider() override; - void Initialize( - base::RepeatingCallback<void( - device::mojom::XRDeviceId, - device::mojom::VRDisplayInfoPtr, - device::mojom::XRDeviceDataPtr, - mojo::PendingRemote<device::mojom::XRRuntime>)> add_device_callback, - base::RepeatingCallback<void(device::mojom::XRDeviceId)> - remove_device_callback, - base::OnceClosure initialization_complete, - device::XrFrameSinkClientFactory xr_frame_sink_client_factory) override; + void Initialize(device::VRDeviceProviderClient* client) override; bool Initialized() override; private:
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 2dc83679..626b8f5 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -414,8 +414,7 @@ "attribution_reporting/attribution_utils.h", "attribution_reporting/rate_limit_table.cc", "attribution_reporting/rate_limit_table.h", - "attribution_reporting/sent_report.cc", - "attribution_reporting/sent_report.h", + "attribution_reporting/send_result.h", "attribution_reporting/sql_utils.cc", "attribution_reporting/sql_utils.h", "attribution_reporting/storable_source.cc",
diff --git a/content/browser/attribution_reporting/attribution_internals_browsertest.cc b/content/browser/attribution_reporting/attribution_internals_browsertest.cc index 26147bf..1cc378c 100644 --- a/content/browser/attribution_reporting/attribution_internals_browsertest.cc +++ b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
@@ -17,6 +17,7 @@ #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_storage.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_controller.h" @@ -337,22 +338,22 @@ OverrideWebUIAttributionManager(); - manager_.NotifyReportSent(SentReport(ReportBuilder(SourceBuilder(now).Build()) - .SetReportTime(now + base::Hours(3)) - .Build(), - SentReport::Status::kSent, + manager_.NotifyReportSent(ReportBuilder(SourceBuilder(now).Build()) + .SetReportTime(now + base::Hours(3)) + .Build(), + SendResult(SendResult::Status::kSent, /*http_response_code=*/200)); - manager_.NotifyReportSent(SentReport(ReportBuilder(SourceBuilder(now).Build()) - .SetReportTime(now + base::Hours(4)) - .SetPriority(-1) - .Build(), - SentReport::Status::kDropped, + manager_.NotifyReportSent(ReportBuilder(SourceBuilder(now).Build()) + .SetReportTime(now + base::Hours(4)) + .SetPriority(-1) + .Build(), + SendResult(SendResult::Status::kDropped, /*http_response_code=*/0)); - manager_.NotifyReportSent(SentReport(ReportBuilder(SourceBuilder(now).Build()) - .SetReportTime(now + base::Hours(5)) - .SetPriority(-2) - .Build(), - SentReport::Status::kFailure, + manager_.NotifyReportSent(ReportBuilder(SourceBuilder(now).Build()) + .SetReportTime(now + base::Hours(5)) + .SetPriority(-2) + .Build(), + SendResult(SendResult::Status::kFailure, /*http_response_code=*/0)); ON_CALL(manager_, GetPendingReportsForWebUI) .WillByDefault(InvokeCallback<std::vector<AttributionReport>>( @@ -492,8 +493,8 @@ .WillOnce(InvokeCallback<std::vector<AttributionReport>>({report})); report.set_report_time(report.report_time() + base::Hours(1)); - manager_.NotifyReportSent(SentReport(report, SentReport::Status::kSent, - /*http_response_code=*/200)); + manager_.NotifyReportSent(report, SendResult(SendResult::Status::kSent, + /*http_response_code=*/200)); EXPECT_CALL(manager_, ClearData) .WillOnce([](base::Time delete_begin, base::Time delete_end,
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc index f8edee2..34c1bea 100644 --- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc +++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -15,7 +15,7 @@ #include "content/browser/attribution_reporting/attribution_manager_impl.h" #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_storage.h" -#include "content/browser/attribution_reporting/sent_report.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/browser/attribution_reporting/storable_source.h" #include "content/browser/storage_partition_impl.h" #include "content/public/browser/browser_context.h" @@ -212,31 +212,33 @@ } } -void AttributionInternalsHandlerImpl::OnReportSent(const SentReport& info) { +void AttributionInternalsHandlerImpl::OnReportSent( + const AttributionReport& report, + const SendResult& info) { mojom::WebUIAttributionReport::Status status; switch (info.status) { - case SentReport::Status::kSent: + case SendResult::Status::kSent: status = mojom::WebUIAttributionReport::Status::kSent; break; - case SentReport::Status::kDropped: + case SendResult::Status::kDropped: status = mojom::WebUIAttributionReport::Status::kProhibitedByBrowserPolicy; break; - case SentReport::Status::kFailure: + case SendResult::Status::kFailure: status = mojom::WebUIAttributionReport::Status::kNetworkError; break; - case SentReport::Status::kTransientFailure: - case SentReport::Status::kOffline: - case SentReport::Status::kRemovedFromQueue: + case SendResult::Status::kTransientFailure: + case SendResult::Status::kOffline: + case SendResult::Status::kRemovedFromQueue: NOTREACHED(); return; } - auto report = - WebUIAttributionReport(info.report, info.http_response_code, status); + auto web_report = + WebUIAttributionReport(report, info.http_response_code, status); for (auto& observer : observers_) { - observer->OnReportSent(report.Clone()); + observer->OnReportSent(web_report.Clone()); } }
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.h b/content/browser/attribution_reporting/attribution_internals_handler_impl.h index 7198ed978..7d0fc9d 100644 --- a/content/browser/attribution_reporting/attribution_internals_handler_impl.h +++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.h
@@ -68,7 +68,8 @@ void OnReportsChanged() override; void OnSourceDeactivated( const AttributionStorage::DeactivatedSource& deactivated_source) override; - void OnReportSent(const SentReport& info) override; + void OnReportSent(const AttributionReport& report, + const SendResult& info) override; void OnReportDropped( const AttributionStorage::CreateReportResult& result) override;
diff --git a/content/browser/attribution_reporting/attribution_manager.h b/content/browser/attribution_reporting/attribution_manager.h index 196b764..570e54d 100644 --- a/content/browser/attribution_reporting/attribution_manager.h +++ b/content/browser/attribution_reporting/attribution_manager.h
@@ -12,7 +12,6 @@ #include "base/observer_list_types.h" #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_storage.h" -#include "content/browser/attribution_reporting/sent_report.h" namespace base { class Time; @@ -29,6 +28,8 @@ class StorableSource; class WebContents; +struct SendResult; + // Interface that mediates data flow between the network, storage layer, and // blink. class AttributionManager { @@ -58,7 +59,8 @@ virtual void OnSourceDeactivated( const AttributionStorage::DeactivatedSource& source) {} - virtual void OnReportSent(const SentReport& info) {} + virtual void OnReportSent(const AttributionReport& report, + const SendResult& info) {} virtual void OnReportDropped( const AttributionStorage::CreateReportResult& result) {}
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc index 745cb28..f3fd8d3 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -21,6 +21,7 @@ #include "content/browser/attribution_reporting/attribution_reporter_impl.h" #include "content/browser/attribution_reporting/attribution_storage_delegate_impl.h" #include "content/browser/attribution_reporting/attribution_storage_sql.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/browser/attribution_reporting/storable_source.h" #include "content/browser/attribution_reporting/storable_trigger.h" #include "content/browser/storage_partition_impl.h" @@ -84,20 +85,20 @@ } ConversionReportSendOutcome ConvertToConversionReportSendOutcome( - SentReport::Status status) { + SendResult::Status status) { switch (status) { - case SentReport::Status::kSent: + case SendResult::Status::kSent: return ConversionReportSendOutcome::kSent; - case SentReport::Status::kTransientFailure: - case SentReport::Status::kFailure: + case SendResult::Status::kTransientFailure: + case SendResult::Status::kFailure: return ConversionReportSendOutcome::kFailed; - case SentReport::Status::kOffline: - case SentReport::Status::kRemovedFromQueue: + case SendResult::Status::kOffline: + case SendResult::Status::kRemovedFromQueue: // Offline reports and reports removed from the queue before being sent // should never record an outcome. NOTREACHED(); return ConversionReportSendOutcome::kFailed; - case SentReport::Status::kDropped: + case SendResult::Status::kDropped: return ConversionReportSendOutcome::kDropped; } } @@ -425,23 +426,23 @@ reporter_->AddReportsToQueue(std::move(reports)); } -void AttributionManagerImpl::OnReportSent(SentReport info) { - DCHECK(info.report.report_id().has_value()); +void AttributionManagerImpl::OnReportSent(AttributionReport report, + SendResult info) { + DCHECK(report.report_id().has_value()); // If there was a transient failure, and another attempt is allowed, // update the report's DB state to reflect that. Otherwise, delete the report // from storage if it wasn't skipped due to the browser being offline. bool should_retry = false; - if (info.status == SentReport::Status::kTransientFailure) { - info.report.set_failed_send_attempts(info.report.failed_send_attempts() + - 1); + if (info.status == SendResult::Status::kTransientFailure) { + report.set_failed_send_attempts(report.failed_send_attempts() + 1); const absl::optional<base::TimeDelta> delay = attribution_policy_->GetFailedReportDelay( - info.report.failed_send_attempts()); + report.failed_send_attempts()); if (delay.has_value()) { should_retry = true; - info.report.set_report_time(info.report.report_time() + *delay); + report.set_report_time(report.report_time() + *delay); } } @@ -452,7 +453,7 @@ // occur. attribution_storage_ .AsyncCall(&AttributionStorage::UpdateReportForSendFailure) - .WithArgs(*info.report.report_id(), info.report.report_time()) + .WithArgs(*report.report_id(), report.report_time()) .Then(base::BindOnce( [](base::WeakPtr<AttributionManagerImpl> manager, AttributionReport report, bool success) { @@ -465,17 +466,17 @@ manager->NotifyReportsChanged(); }, - weak_factory_.GetWeakPtr(), info.report)); - } else if (info.status == SentReport::Status::kOffline || - info.status == SentReport::Status::kRemovedFromQueue) { + weak_factory_.GetWeakPtr(), report)); + } else if (info.status == SendResult::Status::kOffline || + info.status == SendResult::Status::kRemovedFromQueue) { // Remove the ID from the set so that subsequent attempts will not be // deduplicated. - size_t num_removed = queued_reports_.erase(*info.report.report_id()); + size_t num_removed = queued_reports_.erase(*report.report_id()); DCHECK_EQ(num_removed, 1u); } else { RecordDeleteEvent(DeleteEvent::kStarted); attribution_storage_.AsyncCall(&AttributionStorage::DeleteReport) - .WithArgs(*info.report.report_id()) + .WithArgs(*report.report_id()) .Then(base::BindOnce( [](base::WeakPtr<AttributionManagerImpl> manager, AttributionReport::Id report_id, bool succeeded) { @@ -491,7 +492,7 @@ manager->NotifyReportsChanged(); } }, - weak_factory_.GetWeakPtr(), *info.report.report_id())); + weak_factory_.GetWeakPtr(), *report.report_id())); base::UmaHistogramEnumeration( "Conversion.ReportSendOutcome", @@ -505,21 +506,20 @@ // ID, remove the ID from the wait-set; if it was the last such ID, // run the callback. if (!send_reports_for_web_ui_callback_.is_null() && - pending_report_ids_for_internals_ui_.erase(*info.report.report_id()) > - 0 && + pending_report_ids_for_internals_ui_.erase(*report.report_id()) > 0 && pending_report_ids_for_internals_ui_.empty()) { std::move(send_reports_for_web_ui_callback_).Run(); } // TODO(apaseltiner): Consider surfacing retry attempts in internals UI. - if (info.status != SentReport::Status::kSent && - info.status != SentReport::Status::kFailure && - info.status != SentReport::Status::kDropped) { + if (info.status != SendResult::Status::kSent && + info.status != SendResult::Status::kFailure && + info.status != SendResult::Status::kDropped) { return; } for (Observer& observer : observers_) - observer.OnReportSent(info); + observer.OnReportSent(report, info); } void AttributionManagerImpl::NotifySourcesChanged() {
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.h b/content/browser/attribution_reporting/attribution_manager_impl.h index 0cdcf98..8661c494 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.h +++ b/content/browser/attribution_reporting/attribution_manager_impl.h
@@ -20,7 +20,6 @@ #include "content/browser/attribution_reporting/attribution_manager.h" #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_storage.h" -#include "content/browser/attribution_reporting/sent_report.h" #include "content/common/content_export.h" #include "storage/browser/quota/special_storage_policy.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -38,6 +37,8 @@ class StoragePartitionImpl; +struct SendResult; + // Provides access to the manager owned by the default StoragePartition. class AttributionManagerProviderImpl : public AttributionManager::Provider { public: @@ -153,7 +154,7 @@ void OnGetReportsToSendFromWebUI(base::OnceClosure done, std::vector<AttributionReport> reports); - void OnReportSent(SentReport info); + void OnReportSent(AttributionReport report, SendResult info); void OnReportStored(AttributionStorage::CreateReportResult result);
diff --git a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc index aa68480..be71091 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl_unittest.cc
@@ -28,7 +28,7 @@ #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_storage.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" -#include "content/browser/attribution_reporting/sent_report.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/browser/attribution_reporting/storable_source.h" #include "content/browser/attribution_reporting/storable_trigger.h" #include "content/public/test/browser_task_environment.h" @@ -79,7 +79,10 @@ (const DeactivatedSource& source), (override)); - MOCK_METHOD(void, OnReportSent, (const SentReport& info), (override)); + MOCK_METHOD(void, + OnReportSent, + (const AttributionReport& report, const SendResult& info), + (override)); MOCK_METHOD(void, OnReportDropped, @@ -91,6 +94,11 @@ class TestAttributionReporter : public AttributionManagerImpl::AttributionReporter { public: + struct CallbackData { + AttributionReport report; + SendResult info; + }; + TestAttributionReporter() = default; ~TestAttributionReporter() override = default; @@ -101,13 +109,14 @@ for (auto& report : reports) { added_reports_.push_back(report); - SentReport info(std::move(report), sent_report_status_, + SendResult info(send_result_status_, /*http_response_code=*/0); if (should_run_report_sent_callbacks_) { - report_sent_callback_.Run(std::move(info)); + report_sent_callback_.Run(std::move(report), std::move(info)); } else { - deferred_callbacks_.push_back(std::move(info)); + deferred_callbacks_.push_back( + {.report = std::move(report), .info = std::move(info)}); } } @@ -117,14 +126,15 @@ void RunDeferredCallbacks() { for (auto& deferred_callback : deferred_callbacks_) { - report_sent_callback_.Run(std::move(deferred_callback)); + report_sent_callback_.Run(std::move(deferred_callback.report), + std::move(deferred_callback.info)); } deferred_callbacks_.clear(); } void RemoveAllReportsFromQueue() override { for (auto& deferred_callback : deferred_callbacks_) { - deferred_callback.status = SentReport::Status::kRemovedFromQueue; + deferred_callback.info.status = SendResult::Status::kRemovedFromQueue; } RunDeferredCallbacks(); } @@ -133,8 +143,8 @@ should_run_report_sent_callbacks_ = should_run_report_sent_callbacks; } - void SetSentReportStatus(SentReport::Status status) { - sent_report_status_ = status; + void SetSendResultStatus(SendResult::Status status) { + send_result_status_ = status; } const std::vector<AttributionReport>& added_reports() const { @@ -152,18 +162,20 @@ } void SetReportSentCallback( - base::RepeatingCallback<void(SentReport)> report_sent_callback) { + base::RepeatingCallback<void(AttributionReport, SendResult)> + report_sent_callback) { report_sent_callback_ = std::move(report_sent_callback); } private: - base::RepeatingCallback<void(SentReport)> report_sent_callback_; + base::RepeatingCallback<void(AttributionReport, SendResult)> + report_sent_callback_; bool should_run_report_sent_callbacks_ = false; - SentReport::Status sent_report_status_ = SentReport::Status::kSent; + SendResult::Status send_result_status_ = SendResult::Status::kSent; size_t expected_num_reports_ = 0u; std::vector<AttributionReport> added_reports_; base::OnceClosure quit_closure_; - std::vector<SentReport> deferred_callbacks_; + std::vector<CallbackData> deferred_callbacks_; }; // Time after impression that a conversion can first be sent. See @@ -310,7 +322,7 @@ QueuedReportFailedWithShouldRetry_QueuedAgain) { base::HistogramTester histograms; test_reporter_->ShouldRunReportSentCallbacks(true); - test_reporter_->SetSentReportStatus(SentReport::Status::kTransientFailure); + test_reporter_->SetSendResultStatus(SendResult::Status::kTransientFailure); attribution_manager_->HandleSource( SourceBuilder(clock().Now()).SetExpiry(kImpressionExpiry).Build()); @@ -330,7 +342,7 @@ QueuedReportFailedWithoutShouldRetry_NotQueuedAgain) { base::HistogramTester histograms; test_reporter_->ShouldRunReportSentCallbacks(true); - test_reporter_->SetSentReportStatus(SentReport::Status::kFailure); + test_reporter_->SetSendResultStatus(SendResult::Status::kFailure); attribution_manager_->HandleSource( SourceBuilder(clock().Now()).SetExpiry(kImpressionExpiry).Build()); @@ -361,7 +373,7 @@ TEST_F(AttributionManagerImplTest, QueuedReportAlwaysFails_StopsSending) { base::HistogramTester histograms; test_reporter_->ShouldRunReportSentCallbacks(false); - test_reporter_->SetSentReportStatus(SentReport::Status::kTransientFailure); + test_reporter_->SetSendResultStatus(SendResult::Status::kTransientFailure); attribution_manager_->HandleSource( SourceBuilder(clock().Now()).SetExpiry(kImpressionExpiry).Build()); @@ -426,7 +438,7 @@ TEST_F(AttributionManagerImplTest, QueuedReportOffline_NoFailureIncrement) { base::HistogramTester histograms; test_reporter_->ShouldRunReportSentCallbacks(true); - test_reporter_->SetSentReportStatus(SentReport::Status::kTransientFailure); + test_reporter_->SetSendResultStatus(SendResult::Status::kTransientFailure); attribution_manager_->HandleSource( SourceBuilder(clock().Now()).SetExpiry(kImpressionExpiry).Build()); @@ -438,7 +450,7 @@ // into the queue 2 times. EXPECT_THAT(test_reporter_->added_reports(), SizeIs(3)); - test_reporter_->SetSentReportStatus(SentReport::Status::kOffline); + test_reporter_->SetSendResultStatus(SendResult::Status::kOffline); task_environment_.FastForwardBy(base::Minutes(30)); EXPECT_THAT(test_reporter_->added_reports(), SizeIs(3)); @@ -495,23 +507,23 @@ observation(&observer); observation.Observe(attribution_manager_.get()); - EXPECT_CALL(observer, - OnReportSent(Field( - &SentReport::report, - Property(&AttributionReport::impression, - Property(&StorableSource::source_event_id, 1u))))); - EXPECT_CALL(observer, - OnReportSent(Field( - &SentReport::report, - Property(&AttributionReport::impression, - Property(&StorableSource::source_event_id, 2u))))); - EXPECT_CALL(observer, - OnReportSent(Field( - &SentReport::report, - Property(&AttributionReport::impression, - Property(&StorableSource::source_event_id, 3u))))); + EXPECT_CALL( + observer, + OnReportSent(Property(&AttributionReport::impression, + Property(&StorableSource::source_event_id, 1u)), + _)); + EXPECT_CALL( + observer, + OnReportSent(Property(&AttributionReport::impression, + Property(&StorableSource::source_event_id, 2u)), + _)); + EXPECT_CALL( + observer, + OnReportSent(Property(&AttributionReport::impression, + Property(&StorableSource::source_event_id, 3u)), + _)); - test_reporter_->SetSentReportStatus(SentReport::Status::kSent); + test_reporter_->SetSendResultStatus(SendResult::Status::kSent); attribution_manager_->HandleSource(SourceBuilder(clock().Now()) .SetSourceEventId(1) .SetExpiry(kImpressionExpiry) @@ -521,7 +533,7 @@ kAttributionManagerQueueReportsInterval); // This one should be stored, as its status is `kDropped`. - test_reporter_->SetSentReportStatus(SentReport::Status::kDropped); + test_reporter_->SetSendResultStatus(SendResult::Status::kDropped); attribution_manager_->HandleSource(SourceBuilder(clock().Now()) .SetSourceEventId(2) .SetExpiry(kImpressionExpiry) @@ -530,7 +542,7 @@ task_environment_.FastForwardBy(kFirstReportingWindow - kAttributionManagerQueueReportsInterval); - test_reporter_->SetSentReportStatus(SentReport::Status::kSent); + test_reporter_->SetSendResultStatus(SendResult::Status::kSent); attribution_manager_->HandleSource(SourceBuilder(clock().Now()) .SetSourceEventId(3) .SetExpiry(kImpressionExpiry) @@ -540,7 +552,7 @@ kAttributionManagerQueueReportsInterval); // This one shouldn't be stored, as it will be retried. - test_reporter_->SetSentReportStatus(SentReport::Status::kTransientFailure); + test_reporter_->SetSendResultStatus(SendResult::Status::kTransientFailure); attribution_manager_->HandleSource(SourceBuilder(clock().Now()) .SetSourceEventId(4) .SetExpiry(kImpressionExpiry)
diff --git a/content/browser/attribution_reporting/attribution_network_sender_impl.cc b/content/browser/attribution_reporting/attribution_network_sender_impl.cc index d0caf9d..d8ed1983 100644 --- a/content/browser/attribution_reporting/attribution_network_sender_impl.cc +++ b/content/browser/attribution_reporting/attribution_network_sender_impl.cc
@@ -10,11 +10,7 @@ #include "base/bind.h" #include "base/check.h" #include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/time/time.h" -#include "content/browser/attribution_reporting/attribution_report.h" -#include "content/browser/attribution_reporting/attribution_utils.h" -#include "content/browser/attribution_reporting/sent_report.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/public/browser/storage_partition.h" #include "net/base/isolation_info.h" #include "net/base/load_flags.h" @@ -43,29 +39,6 @@ kMaxValue = kExternalError }; -// Called when a network request is started for |report|, for logging metrics. -void LogMetricsOnReportSend(const AttributionReport& report) { - // Reports sent from the WebUI should not log metrics. - if (report.report_time() == base::Time::Min()) - return; - - // Use a large time range to capture users that might not open the browser for - // a long time while a conversion report is pending. Revisit this range if it - // is non-ideal for real world data. - base::Time now = base::Time::Now(); - base::Time original_report_time = - ComputeReportTime(report.impression(), report.conversion_time()); - base::TimeDelta time_since_original_report_time = now - original_report_time; - base::UmaHistogramCustomTimes( - "Conversions.ExtraReportDelay2", time_since_original_report_time, - base::Seconds(1), base::Days(24), /*buckets=*/100); - - base::TimeDelta time_from_conversion_to_report_send = - report.report_time() - report.conversion_time(); - UMA_HISTOGRAM_COUNTS_1000("Conversions.TimeFromConversionToReportSend", - time_from_conversion_to_report_send.InHours()); -} - } // namespace AttributionNetworkSenderImpl::AttributionNetworkSenderImpl( @@ -75,7 +48,8 @@ AttributionNetworkSenderImpl::~AttributionNetworkSenderImpl() = default; void AttributionNetworkSenderImpl::SendReport( - AttributionReport report, + GURL report_url, + std::string report_body, ReportSentCallback sent_callback) { // The browser process URLLoaderFactory is not created by default, so don't // create it until it is directly needed. @@ -85,7 +59,7 @@ } auto resource_request = std::make_unique<network::ResourceRequest>(); - resource_request->url = report.ReportURL(); + resource_request->url = std::move(report_url); resource_request->method = net::HttpRequestHeaders::kPostMethod; resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; resource_request->load_flags = @@ -129,7 +103,6 @@ std::move(simple_url_loader)); simple_url_loader_ptr->SetTimeoutDuration(base::Seconds(30)); - std::string report_body = report.ReportBody(); simple_url_loader_ptr->AttachStringForUpload(report_body, "application/json"); // Retry once on network change. A network change during DNS resolution @@ -141,14 +114,12 @@ network::SimpleURLLoader::RETRY_ON_NAME_NOT_RESOLVED; simple_url_loader_ptr->SetRetryOptions(/*max_retries=*/1, retry_mode); - LogMetricsOnReportSend(report); - // Unretained is safe because the URLLoader is owned by |this| and will be // deleted before |this|. simple_url_loader_ptr->DownloadHeadersOnly( url_loader_factory_.get(), base::BindOnce(&AttributionNetworkSenderImpl::OnReportSent, - base::Unretained(this), std::move(it), std::move(report), + base::Unretained(this), std::move(it), std::move(sent_callback))); } @@ -159,7 +130,6 @@ void AttributionNetworkSenderImpl::OnReportSent( UrlLoaderList::iterator it, - AttributionReport report, ReportSentCallback sent_callback, scoped_refptr<net::HttpResponseHeaders> headers) { network::SimpleURLLoader* loader = it->get(); @@ -201,15 +171,14 @@ net_error == net::ERR_CONNECTION_ABORTED || net_error == net::ERR_CONNECTION_RESET); - SentReport::Status report_status = + SendResult::Status report_status = (status == Status::kOk) - ? SentReport::Status::kSent - : (should_retry ? SentReport::Status::kTransientFailure - : SentReport::Status::kFailure); + ? SendResult::Status::kSent + : (should_retry ? SendResult::Status::kTransientFailure + : SendResult::Status::kFailure); std::move(sent_callback) - .Run(SentReport(std::move(report), report_status, - headers ? headers->response_code() : 0)); + .Run(SendResult(report_status, headers ? headers->response_code() : 0)); } } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_network_sender_impl.h b/content/browser/attribution_reporting/attribution_network_sender_impl.h index 5dfa485..958398f 100644 --- a/content/browser/attribution_reporting/attribution_network_sender_impl.h +++ b/content/browser/attribution_reporting/attribution_network_sender_impl.h
@@ -26,8 +26,6 @@ class StoragePartition; -class AttributionReport; - // Implemented a NetworkSender capable of issuing POST requests for complete // conversions. Maintains a set of all ongoing UrlLoaders used for posting // conversion reports. Created and owned by AttributionReporterImpl. @@ -48,7 +46,8 @@ // seconds. // |sent_callback| is run after the request finishes, whether or not it // succeeded, - void SendReport(AttributionReport report, + void SendReport(GURL report_url, + std::string report_body, ReportSentCallback sent_callback) override; // Tests inject a TestURLLoaderFactory so they can mock the network response. @@ -61,7 +60,6 @@ // Called when headers are available for a sent report. void OnReportSent(UrlLoaderList::iterator it, - AttributionReport report, ReportSentCallback sent_callback, scoped_refptr<net::HttpResponseHeaders> headers);
diff --git a/content/browser/attribution_reporting/attribution_network_sender_impl_unittest.cc b/content/browser/attribution_reporting/attribution_network_sender_impl_unittest.cc index 565f333a..de6a54d 100644 --- a/content/browser/attribution_reporting/attribution_network_sender_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_network_sender_impl_unittest.cc
@@ -13,7 +13,7 @@ #include "base/test/mock_callback.h" #include "base/time/time.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" -#include "content/browser/attribution_reporting/sent_report.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/public/browser/browser_context.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_browser_context.h" @@ -67,7 +67,7 @@ // |task_environment_| must be initialized first. content::BrowserTaskEnvironment task_environment_; - base::MockCallback<base::OnceCallback<void(SentReport)>> callback_; + base::MockCallback<base::OnceCallback<void(SendResult)>> callback_; // Unique ptr so it can be reset during testing. std::unique_ptr<AttributionNetworkSenderImpl> network_sender_; @@ -79,14 +79,18 @@ TEST_F(AttributionNetworkSenderTest, ConversionReportReceived_NetworkRequestMade) { - network_sender_->SendReport(DefaultReport(), base::DoNothing()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( kReportUrl, "")); } TEST_F(AttributionNetworkSenderTest, LoadFlags) { - network_sender_->SendReport(DefaultReport(), base::DoNothing()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); int load_flags = test_url_loader_factory_.GetPendingRequest(0)->request.load_flags; EXPECT_TRUE(load_flags & net::LOAD_BYPASS_CACHE); @@ -94,8 +98,11 @@ } TEST_F(AttributionNetworkSenderTest, Isolation) { - network_sender_->SendReport(DefaultReport(), base::DoNothing()); - network_sender_->SendReport(DefaultReport(), base::DoNothing()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); const network::ResourceRequest& request1 = test_url_loader_factory_.GetPendingRequest(0)->request; @@ -142,7 +149,8 @@ .Build(); AttributionReport report = ReportBuilder(impression).SetTriggerData(5).Build(); - network_sender_->SendReport(report, base::DoNothing()); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); const network::ResourceRequest* pending_request; EXPECT_TRUE( @@ -161,7 +169,8 @@ .SetConversionOrigin(url::Origin::Create(GURL("https://sub.b.com"))) .Build(); AttributionReport report = ReportBuilder(impression).Build(); - network_sender_->SendReport(report, base::DoNothing()); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); const network::ResourceRequest* pending_request; EXPECT_TRUE(test_url_loader_factory_.IsPending( @@ -178,10 +187,11 @@ TEST_F(AttributionNetworkSenderTest, ReportSent_CallbackFired) { auto report = DefaultReport(); - EXPECT_CALL(callback_, Run(SentReport(report, SentReport::Status::kSent, + EXPECT_CALL(callback_, Run(SendResult(SendResult::Status::kSent, net::HttpStatusCode::HTTP_OK))); - network_sender_->SendReport(std::move(report), callback_.Get()); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( kReportUrl, "")); @@ -190,7 +200,9 @@ TEST_F(AttributionNetworkSenderTest, SenderDeletedDuringRequest_NoCrash) { EXPECT_CALL(callback_, Run).Times(0); - network_sender_->SendReport(DefaultReport(), callback_.Get()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); network_sender_.reset(); EXPECT_FALSE(test_url_loader_factory_.SimulateResponseForPendingRequest( @@ -201,12 +213,12 @@ auto report = DefaultReport(); // Verify that the sent callback runs if the request times out. - // TODO(apaseltiner): Should we propagate the timeout via the SentReport + // TODO(apaseltiner): Should we propagate the timeout via the SendResult // instead of just setting |http_response_code = 0|? - EXPECT_CALL(callback_, - Run(SentReport(report, SentReport::Status::kTransientFailure, - /*http_response_code=*/0))); - network_sender_->SendReport(std::move(report), callback_.Get()); + EXPECT_CALL(callback_, Run(SendResult(SendResult::Status::kTransientFailure, + /*http_response_code=*/0))); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); // The request should time out after 30 seconds. @@ -219,22 +231,24 @@ ReportRequestFailsWithTargetedError_ShouldRetrySet) { struct { int net_error; - SentReport::Status expected_status; + SendResult::Status expected_status; } kTestCases[] = { - {net::ERR_INTERNET_DISCONNECTED, SentReport::Status::kTransientFailure}, - {net::ERR_TIMED_OUT, SentReport::Status::kTransientFailure}, - {net::ERR_CONNECTION_ABORTED, SentReport::Status::kTransientFailure}, - {net::ERR_CONNECTION_TIMED_OUT, SentReport::Status::kTransientFailure}, - {net::ERR_CONNECTION_REFUSED, SentReport::Status::kFailure}, - {net::ERR_CERT_DATE_INVALID, SentReport::Status::kFailure}, - {net::OK, SentReport::Status::kFailure}, + {net::ERR_INTERNET_DISCONNECTED, SendResult::Status::kTransientFailure}, + {net::ERR_TIMED_OUT, SendResult::Status::kTransientFailure}, + {net::ERR_CONNECTION_ABORTED, SendResult::Status::kTransientFailure}, + {net::ERR_CONNECTION_TIMED_OUT, SendResult::Status::kTransientFailure}, + {net::ERR_CONNECTION_REFUSED, SendResult::Status::kFailure}, + {net::ERR_CERT_DATE_INVALID, SendResult::Status::kFailure}, + {net::OK, SendResult::Status::kFailure}, }; for (const auto& test_case : kTestCases) { EXPECT_CALL(callback_, - Run(Field(&SentReport::status, test_case.expected_status))); + Run(Field(&SendResult::status, test_case.expected_status))); - network_sender_->SendReport(DefaultReport(), callback_.Get()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); // By default, headers are not sent for network errors. @@ -261,9 +275,10 @@ kSendHeadersOnNetworkError); auto report = DefaultReport(); - EXPECT_CALL(callback_, Run(SentReport(report, SentReport::Status::kFailure, + EXPECT_CALL(callback_, Run(SendResult(SendResult::Status::kFailure, net::HttpStatusCode::HTTP_OK))); - network_sender_->SendReport(std::move(report), callback_.Get()); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); // Ensure the request was replied to. EXPECT_EQ(0, test_url_loader_factory_.NumPending()); @@ -273,10 +288,11 @@ ReportRequestFailsWithHttpError_ShouldRetryNotSet) { auto report = DefaultReport(); EXPECT_CALL(callback_, - Run(SentReport(report, SentReport::Status::kFailure, + Run(SendResult(SendResult::Status::kFailure, net::HttpStatusCode::HTTP_BAD_REQUEST))); - network_sender_->SendReport(std::move(report), callback_.Get()); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( @@ -291,7 +307,9 @@ EXPECT_CALL(callback_, Run); - network_sender_->SendReport(DefaultReport(), callback_.Get()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); // Simulate the request failing due to network change. @@ -321,7 +339,9 @@ { base::HistogramTester histograms; - network_sender_->SendReport(DefaultReport(), base::DoNothing()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); EXPECT_EQ(1, test_url_loader_factory_.NumPending()); // Simulate the request failing due to network change. @@ -351,11 +371,12 @@ EXPECT_CALL(callback_, Run).Times(0); EXPECT_CALL(checkpoint, Call(1)); EXPECT_CALL(callback_, - Run(SentReport(report, SentReport::Status::kFailure, + Run(SendResult(SendResult::Status::kFailure, net::HttpStatusCode::HTTP_BAD_REQUEST))); } - network_sender_->SendReport(std::move(report), callback_.Get()); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); checkpoint.Call(1); // We should run the sent callback even if there is an http error. @@ -367,7 +388,9 @@ EXPECT_CALL(callback_, Run).Times(10); for (int i = 0; i < 10; i++) { - network_sender_->SendReport(DefaultReport(), callback_.Get()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + callback_.Get()); } EXPECT_EQ(10, test_url_loader_factory_.NumPending()); @@ -384,7 +407,9 @@ // All OK. { base::HistogramTester histograms; - network_sender_->SendReport(DefaultReport(), base::DoNothing()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( kReportUrl, "")); // kOk = 0. @@ -395,7 +420,9 @@ // Internal error. { base::HistogramTester histograms; - network_sender_->SendReport(DefaultReport(), base::DoNothing()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); network::URLLoaderCompletionStatus completion_status(net::ERR_FAILED); EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( GURL(kReportUrl), completion_status, @@ -407,7 +434,9 @@ } { base::HistogramTester histograms; - network_sender_->SendReport(DefaultReport(), base::DoNothing()); + auto report = DefaultReport(); + network_sender_->SendReport(report.ReportURL(), report.ReportBody(), + base::DoNothing()); EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( kReportUrl, "", net::HTTP_UNAUTHORIZED)); // kExternalError = 2. @@ -418,15 +447,4 @@ } } -TEST_F(AttributionNetworkSenderTest, TimeFromConversionToReportSendHistogram) { - base::HistogramTester histograms; - auto report = DefaultReport(); - report.set_report_time(base::Time() + base::Hours(5)); - network_sender_->SendReport(std::move(report), base::DoNothing()); - EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest( - kReportUrl, "")); - histograms.ExpectUniqueSample("Conversions.TimeFromConversionToReportSend", 5, - 1); -} - } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_reporter_impl.cc b/content/browser/attribution_reporting/attribution_reporter_impl.cc index 88e79ee0..c8600306 100644 --- a/content/browser/attribution_reporting/attribution_reporter_impl.cc +++ b/content/browser/attribution_reporting/attribution_reporter_impl.cc
@@ -4,22 +4,56 @@ #include "content/browser/attribution_reporting/attribution_reporter_impl.h" +#include <string> + #include "base/bind.h" #include "base/callback.h" +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/time/clock.h" +#include "base/time/time.h" #include "content/browser/attribution_reporting/attribution_manager.h" #include "content/browser/attribution_reporting/attribution_network_sender_impl.h" #include "content/browser/attribution_reporting/attribution_report.h" -#include "content/browser/attribution_reporting/sent_report.h" +#include "content/browser/attribution_reporting/attribution_utils.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/browser/storage_partition_impl.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/network_service_instance.h" #include "content/public/common/content_client.h" #include "services/network/public/cpp/network_connection_tracker.h" +#include "url/gurl.h" namespace content { +namespace { + +// Called when |report| is to be sent over network, for logging metrics. +void LogMetricsOnReportSend(const AttributionReport& report) { + // Reports sent from the WebUI should not log metrics. + if (report.report_time() == base::Time::Min()) + return; + + // Use a large time range to capture users that might not open the browser for + // a long time while a conversion report is pending. Revisit this range if it + // is non-ideal for real world data. + base::Time now = base::Time::Now(); + base::Time original_report_time = + ComputeReportTime(report.impression(), report.conversion_time()); + base::TimeDelta time_since_original_report_time = now - original_report_time; + base::UmaHistogramCustomTimes( + "Conversions.ExtraReportDelay2", time_since_original_report_time, + base::Seconds(1), base::Days(24), /*buckets=*/100); + + base::TimeDelta time_from_conversion_to_report_send = + report.report_time() - report.conversion_time(); + UMA_HISTOGRAM_COUNTS_1000("Conversions.TimeFromConversionToReportSend", + time_from_conversion_to_report_send.InHours()); +} + +} // namespace + AttributionReporterImpl::AttributionReporterImpl( StoragePartitionImpl* storage_partition, const base::Clock* clock, @@ -59,8 +93,8 @@ while (!report_queue_.empty()) { AttributionReport report = report_queue_.top(); report_queue_.pop(); - callback_.Run(SentReport(std::move(report), - SentReport::Status::kRemovedFromQueue, + callback_.Run(std::move(report), + SendResult(SendResult::Status::kRemovedFromQueue, /*http_response_code=*/0)); } } @@ -103,18 +137,23 @@ // If there's no network connection, drop the report and tell the manager to // retry it later. if (offline_) { - callback_.Run(SentReport(std::move(report), SentReport::Status::kOffline, - /*http_response_code=*/0)); + callback_.Run(std::move(report), SendResult(SendResult::Status::kOffline, + /*http_response_code=*/0)); } else { - network_sender_->SendReport(std::move(report), callback_); + LogMetricsOnReportSend(report); + + GURL report_url = report.ReportURL(); + std::string report_body = report.ReportBody(); + network_sender_->SendReport(std::move(report_url), std::move(report_body), + base::BindOnce(callback_, std::move(report))); } } else { // If measurement is disallowed, just drop the report on the floor. We need // to make sure we forward that the report was "sent" to ensure it is // deleted from storage, etc. This simulates sending the report through a // null channel. - callback_.Run(SentReport(std::move(report), SentReport::Status::kDropped, - /*http_response_code=*/0)); + callback_.Run(std::move(report), SendResult(SendResult::Status::kDropped, + /*http_response_code=*/0)); } MaybeScheduleNextReport(); }
diff --git a/content/browser/attribution_reporting/attribution_reporter_impl.h b/content/browser/attribution_reporting/attribution_reporter_impl.h index 1877b23..ca0719cb 100644 --- a/content/browser/attribution_reporting/attribution_reporter_impl.h +++ b/content/browser/attribution_reporting/attribution_reporter_impl.h
@@ -8,6 +8,7 @@ #include <stdint.h> #include <memory> #include <queue> +#include <string> #include <vector> #include "base/callback_forward.h" @@ -19,6 +20,8 @@ #include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/shared_url_loader_factory.h" +class GURL; + namespace base { class Clock; } // namespace base @@ -27,7 +30,7 @@ class StoragePartitionImpl; -struct SentReport; +struct SendResult; // This class is responsible for managing the dispatch of conversion reports to // an AttributionReporterImpl::NetworkSender. It maintains a queue of reports @@ -45,15 +48,16 @@ virtual ~NetworkSender() = default; // Callback used to notify caller that the requested report has been sent. - using ReportSentCallback = base::OnceCallback<void(SentReport)>; + using ReportSentCallback = base::OnceCallback<void(SendResult)>; // Generates and sends a conversion report matching |report|. This should // generate a secure POST request with no-credentials. - virtual void SendReport(AttributionReport report, + virtual void SendReport(GURL report_url, + std::string report_body, ReportSentCallback sent_callback) = 0; }; - using Callback = base::RepeatingCallback<void(SentReport)>; + using Callback = base::RepeatingCallback<void(AttributionReport, SendResult)>; AttributionReporterImpl(StoragePartitionImpl* storage_partition, const base::Clock* clock,
diff --git a/content/browser/attribution_reporting/attribution_reporter_impl_unittest.cc b/content/browser/attribution_reporting/attribution_reporter_impl_unittest.cc index 50cba88..95a1df3 100644 --- a/content/browser/attribution_reporting/attribution_reporter_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_reporter_impl_unittest.cc
@@ -5,9 +5,12 @@ #include "content/browser/attribution_reporting/attribution_reporter_impl.h" #include "base/memory/raw_ptr.h" +#include "base/strings/stringprintf.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" +#include "base/time/time.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" -#include "content/browser/attribution_reporting/sent_report.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/browser/storage_partition_impl.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/network_service_instance.h" @@ -30,15 +33,23 @@ using Checkpoint = ::testing::MockFunction<void(int step)>; +const char kDefaultReportOrigin[] = "https://report.test/"; + // Create a report which should be sent at |report_time|. Impression // data/conversion data/conversion id are all the same for simplicity. AttributionReport GetReport(base::Time report_time, - AttributionReport::Id conversion_id) { + AttributionReport::Id conversion_id, + base::Time conversion_time = base::Time(), + url::Origin reporting_origin = url::Origin::Create( + GURL(kDefaultReportOrigin))) { // Construct impressions with a null impression time as it is not used for // reporting. - return ReportBuilder(SourceBuilder(base::Time()).Build()) + return ReportBuilder(SourceBuilder(base::Time()) + .SetReportingOrigin(std::move(reporting_origin)) + .Build()) .SetReportTime(report_time) .SetReportId(conversion_id) + .SetConversionTime(conversion_time) .Build(); } @@ -46,17 +57,16 @@ public: MOCK_METHOD(void, SendReport, - (AttributionReport report, ReportSentCallback callback), + (GURL url, std::string report_body, ReportSentCallback callback), (override)); }; -auto InvokeCallbackWith(SentReport::Status status, +auto InvokeCallbackWith(SendResult::Status status, int http_response_code = 200) { return - [=](AttributionReport report, + [=](GURL url, std::string report_body, AttributionReporterImpl::NetworkSender::ReportSentCallback callback) { - std::move(callback).Run( - SentReport(std::move(report), status, http_response_code)); + std::move(callback).Run(SendResult(status, http_response_code)); }; } @@ -103,11 +113,11 @@ ReportAddedWithImmediateReportTime_ReportSent) { const auto report = GetReport(clock().Now(), AttributionReport::Id(1)); - EXPECT_CALL(*sender_, SendReport(report, _)) - .WillOnce(InvokeCallbackWith(SentReport::Status::kSent)); + EXPECT_CALL(*sender_, SendReport(report.ReportURL(), report.ReportBody(), _)) + .WillOnce(InvokeCallbackWith(SendResult::Status::kSent)); - EXPECT_CALL(callback_, Run(SentReport(report, SentReport::Status::kSent, - /*http_response_code=*/200))); + EXPECT_CALL(callback_, Run(report, SendResult(SendResult::Status::kSent, + /*http_response_code=*/200))); reporter_->AddReportsToQueue({report}); @@ -121,11 +131,11 @@ const auto report = GetReport(clock().Now() - base::Hours(10), AttributionReport::Id(1)); - EXPECT_CALL(*sender_, SendReport(report, _)) - .WillOnce(InvokeCallbackWith(SentReport::Status::kSent)); + EXPECT_CALL(*sender_, SendReport(report.ReportURL(), report.ReportBody(), _)) + .WillOnce(InvokeCallbackWith(SendResult::Status::kSent)); - EXPECT_CALL(callback_, Run(SentReport(report, SentReport::Status::kSent, - /*http_response_code=*/200))); + EXPECT_CALL(callback_, Run(report, SendResult(SendResult::Status::kSent, + /*http_response_code=*/200))); reporter_->AddReportsToQueue({report}); @@ -141,8 +151,8 @@ EXPECT_CALL(*sender_, SendReport).Times(0); EXPECT_CALL(callback_, - Run(SentReport(report, SentReport::Status::kRemovedFromQueue, - /*http_response_code=*/0))); + Run(report, SendResult(SendResult::Status::kRemovedFromQueue, + /*http_response_code=*/0))); reporter_->AddReportsToQueue({report}); @@ -167,7 +177,8 @@ EXPECT_CALL(checkpoint, Call(1)); EXPECT_CALL(*sender_, SendReport).Times(0); EXPECT_CALL(checkpoint, Call(2)); - EXPECT_CALL(*sender_, SendReport(report, _)); + EXPECT_CALL(*sender_, + SendReport(report.ReportURL(), report.ReportBody(), _)); } reporter_->AddReportsToQueue({report}); @@ -186,7 +197,8 @@ // A duplicate report should be scheduled, as it is up to the manager to // perform deduplication. - EXPECT_CALL(*sender_, SendReport(report, _)).Times(2); + EXPECT_CALL(*sender_, SendReport(report.ReportURL(), report.ReportBody(), _)) + .Times(2); reporter_->AddReportsToQueue({report}); reporter_->AddReportsToQueue({report}); @@ -202,9 +214,11 @@ { InSequence seq; - EXPECT_CALL(*sender_, SendReport(report, _)); + EXPECT_CALL(*sender_, + SendReport(report.ReportURL(), report.ReportBody(), _)); EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*sender_, SendReport(report, _)); + EXPECT_CALL(*sender_, + SendReport(report.ReportURL(), report.ReportBody(), _)); } reporter_->AddReportsToQueue({report}); @@ -227,14 +241,20 @@ for (int i = 1; i < 10; i++) { EXPECT_CALL(checkpoint, Call(i)); + auto origin = + url::Origin::Create(GURL(base::StringPrintf("https://%d.com/", i))); + auto report = - GetReport(clock().Now() + base::Minutes(i), AttributionReport::Id(i)); + GetReport(clock().Now() + base::Minutes(i), AttributionReport::Id(i), + base::Time(), std::move(origin)); - EXPECT_CALL(*sender_, SendReport(report, _)) - .WillOnce(InvokeCallbackWith(SentReport::Status::kSent)); + EXPECT_CALL(*sender_, + SendReport(report.ReportURL(), report.ReportBody(), _)) + .WillOnce(InvokeCallbackWith(SendResult::Status::kSent)); - EXPECT_CALL(callback_, Run(SentReport(report, SentReport::Status::kSent, - /*http_response_code=*/200))); + EXPECT_CALL(callback_, + Run(report, SendResult(SendResult::Status::kSent, + /*http_response_code=*/200))); reports.push_back(std::move(report)); } @@ -259,14 +279,20 @@ for (int i = 1; i < 10; i++) { EXPECT_CALL(checkpoint, Call(i)); + auto origin = + url::Origin::Create(GURL(base::StringPrintf("https://%d.com/", i))); + auto report = - GetReport(clock().Now() + base::Minutes(i), AttributionReport::Id(i)); + GetReport(clock().Now() + base::Minutes(i), AttributionReport::Id(i), + base::Time(), std::move(origin)); - EXPECT_CALL(*sender_, SendReport(report, _)) - .WillOnce(InvokeCallbackWith(SentReport::Status::kSent)); + EXPECT_CALL(*sender_, + SendReport(report.ReportURL(), report.ReportBody(), _)) + .WillOnce(InvokeCallbackWith(SendResult::Status::kSent)); - EXPECT_CALL(callback_, Run(SentReport(report, SentReport::Status::kSent, - /*http_response_code=*/200))); + EXPECT_CALL(callback_, + Run(report, SendResult(SendResult::Status::kSent, + /*http_response_code=*/200))); reports.push_back(std::move(report)); } @@ -300,8 +326,8 @@ EXPECT_CALL(*sender_, SendReport).Times(0); - EXPECT_CALL(callback_, Run(SentReport(report, SentReport::Status::kDropped, - /*http_response_code=*/0))); + EXPECT_CALL(callback_, Run(report, SendResult(SendResult::Status::kDropped, + /*http_response_code=*/0))); reporter_->AddReportsToQueue({report}); @@ -327,23 +353,24 @@ EXPECT_CALL(*sender_, SendReport).Times(0); EXPECT_CALL(callback_, - Run(SentReport(report1_1, SentReport::Status::kOffline, - /*http_response_code=*/0))); + Run(report1_1, SendResult(SendResult::Status::kOffline, + /*http_response_code=*/0))); EXPECT_CALL(checkpoint, Call(1)); EXPECT_CALL(*sender_, SendReport).Times(0); EXPECT_CALL(callback_, - Run(SentReport(report2_1, SentReport::Status::kOffline, - /*http_response_code=*/0))); + Run(report2_1, SendResult(SendResult::Status::kOffline, + /*http_response_code=*/0))); EXPECT_CALL(checkpoint, Call(2)); EXPECT_CALL(*sender_, SendReport) - .WillOnce(InvokeCallbackWith(SentReport::Status::kSent)); - EXPECT_CALL(callback_, Run(SentReport(report1_2, SentReport::Status::kSent, + .WillOnce(InvokeCallbackWith(SendResult::Status::kSent)); + EXPECT_CALL(callback_, + Run(report1_2, SendResult(SendResult::Status::kSent, /*http_response_code=*/200))); EXPECT_CALL(checkpoint, Call(3)); EXPECT_CALL(*sender_, SendReport).Times(0); EXPECT_CALL(callback_, - Run(SentReport(report2_2, SentReport::Status::kOffline, - /*http_response_code=*/0))); + Run(report2_2, SendResult(SendResult::Status::kOffline, + /*http_response_code=*/0))); } SetOffline(true); @@ -368,4 +395,21 @@ task_environment_.FastForwardBy(base::Minutes(1)); } +TEST_F(AttributionReporterImplTest, TimeFromConversionToReportSendHistogram) { + base::HistogramTester histograms; + + const base::TimeDelta delay = base::Hours(5); + const auto report = + GetReport(/*report_time=*/clock().Now() + delay, AttributionReport::Id(1), + /*conversion_time=*/clock().Now()); + + EXPECT_CALL(*sender_, SendReport(report.ReportURL(), report.ReportBody(), _)); + + reporter_->AddReportsToQueue({report}); + task_environment_.FastForwardBy(delay); + + histograms.ExpectUniqueSample("Conversions.TimeFromConversionToReportSend", 5, + 1); +} + } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_test_utils.cc b/content/browser/attribution_reporting/attribution_test_utils.cc index 3208cf0..5b372db 100644 --- a/content/browser/attribution_reporting/attribution_test_utils.cc +++ b/content/browser/attribution_reporting/attribution_test_utils.cc
@@ -145,9 +145,10 @@ observer.OnSourceDeactivated(source); } -void MockAttributionManager::NotifyReportSent(const SentReport& info) { +void MockAttributionManager::NotifyReportSent(const AttributionReport& report, + const SendResult& info) { for (Observer& observer : observers_) - observer.OnReportSent(info); + observer.OnReportSent(report, info); } void MockAttributionManager::NotifyReportDropped( @@ -352,9 +353,9 @@ return tie(a) == tie(b); } -bool operator==(const SentReport& a, const SentReport& b) { - const auto tie = [](const SentReport& info) { - return std::make_tuple(info.report, info.status, info.http_response_code); +bool operator==(const SendResult& a, const SendResult& b) { + const auto tie = [](const SendResult& info) { + return std::make_tuple(info.status, info.http_response_code); }; return tie(a) == tie(b); } @@ -509,32 +510,32 @@ << "}"; } -std::ostream& operator<<(std::ostream& out, SentReport::Status status) { +std::ostream& operator<<(std::ostream& out, SendResult::Status status) { switch (status) { - case SentReport::Status::kSent: + case SendResult::Status::kSent: out << "kSent"; break; - case SentReport::Status::kTransientFailure: + case SendResult::Status::kTransientFailure: out << "kTransientFailure"; break; - case SentReport::Status::kFailure: + case SendResult::Status::kFailure: out << "kFailure"; break; - case SentReport::Status::kDropped: + case SendResult::Status::kDropped: out << "kDropped"; break; - case SentReport::Status::kOffline: + case SendResult::Status::kOffline: out << "kOffline"; break; - case SentReport::Status::kRemovedFromQueue: + case SendResult::Status::kRemovedFromQueue: out << "kRemovedFromQueue"; break; } return out; } -std::ostream& operator<<(std::ostream& out, const SentReport& info) { - return out << "{report=" << info.report << ",status=" << info.status +std::ostream& operator<<(std::ostream& out, const SendResult& info) { + return out << "{status=" << info.status << ",http_response_code=" << info.http_response_code << "}"; }
diff --git a/content/browser/attribution_reporting/attribution_test_utils.h b/content/browser/attribution_reporting/attribution_test_utils.h index c5bc8b59..b927d70 100644 --- a/content/browser/attribution_reporting/attribution_test_utils.h +++ b/content/browser/attribution_reporting/attribution_test_utils.h
@@ -24,7 +24,7 @@ #include "content/browser/attribution_reporting/attribution_report.h" #include "content/browser/attribution_reporting/attribution_storage.h" #include "content/browser/attribution_reporting/rate_limit_table.h" -#include "content/browser/attribution_reporting/sent_report.h" +#include "content/browser/attribution_reporting/send_result.h" #include "content/browser/attribution_reporting/storable_source.h" #include "content/browser/attribution_reporting/storable_trigger.h" #include "content/test/test_content_browser_client.h" @@ -196,7 +196,8 @@ void NotifyReportsChanged(); void NotifySourceDeactivated( const AttributionStorage::DeactivatedSource& source); - void NotifyReportSent(const SentReport& info); + void NotifyReportSent(const AttributionReport& report, + const SendResult& info); void NotifyReportDropped( const AttributionStorage::CreateReportResult& result); @@ -331,7 +332,7 @@ bool operator==(const AttributionReport& a, const AttributionReport& b); -bool operator==(const SentReport& a, const SentReport& b); +bool operator==(const SendResult& a, const SendResult& b); bool operator==(const AttributionStorage::DeactivatedSource& a, const AttributionStorage::DeactivatedSource& b); @@ -354,9 +355,9 @@ std::ostream& operator<<(std::ostream& out, const AttributionReport& report); -std::ostream& operator<<(std::ostream& out, SentReport::Status status); +std::ostream& operator<<(std::ostream& out, SendResult::Status status); -std::ostream& operator<<(std::ostream& out, const SentReport& info); +std::ostream& operator<<(std::ostream& out, const SendResult& info); std::ostream& operator<<(std::ostream& out, StorableSource::AttributionLogic attribution_logic);
diff --git a/content/browser/attribution_reporting/sent_report.h b/content/browser/attribution_reporting/send_result.h similarity index 65% rename from content/browser/attribution_reporting/sent_report.h rename to content/browser/attribution_reporting/send_result.h index 9cd78d5..d4d7732 100644 --- a/content/browser/attribution_reporting/sent_report.h +++ b/content/browser/attribution_reporting/send_result.h
@@ -2,18 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_SENT_REPORT_H_ -#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_SENT_REPORT_H_ +#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_SEND_RESULT_H_ +#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_SEND_RESULT_H_ -#include "base/time/time.h" -#include "content/browser/attribution_reporting/attribution_report.h" #include "content/common/content_export.h" namespace content { // Struct that contains data about sent reports. Some info is displayed in the // Conversion Internals WebUI. -struct CONTENT_EXPORT SentReport { +struct CONTENT_EXPORT SendResult { enum class Status { kSent, // The report failed without receiving response headers. @@ -30,14 +28,13 @@ kRemovedFromQueue, }; - SentReport(AttributionReport report, Status status, int http_response_code); - SentReport(const SentReport& other); - SentReport& operator=(const SentReport& other); - SentReport(SentReport&& other); - SentReport& operator=(SentReport&& other); - ~SentReport(); - - AttributionReport report; + SendResult(Status status, int http_response_code) + : status(status), http_response_code(http_response_code) {} + SendResult(const SendResult& other) = default; + SendResult& operator=(const SendResult& other) = default; + SendResult(SendResult&& other) = default; + SendResult& operator=(SendResult&& other) = default; + ~SendResult() = default; Status status; @@ -50,4 +47,4 @@ } // namespace content -#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_SENT_REPORT_H_ +#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_SEND_RESULT_H_
diff --git a/content/browser/attribution_reporting/sent_report.cc b/content/browser/attribution_reporting/sent_report.cc deleted file mode 100644 index 0f77409..0000000 --- a/content/browser/attribution_reporting/sent_report.cc +++ /dev/null
@@ -1,23 +0,0 @@ -// 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 "content/browser/attribution_reporting/sent_report.h" - -namespace content { - -SentReport::SentReport(AttributionReport report, - Status status, - int http_response_code) - : report(std::move(report)), - status(status), - http_response_code(http_response_code) {} - -SentReport::SentReport(const SentReport& other) = default; -SentReport& SentReport::operator=(const SentReport& other) = default; -SentReport::SentReport(SentReport&& other) = default; -SentReport& SentReport::operator=(SentReport&& other) = default; - -SentReport::~SentReport() = default; - -} // namespace content
diff --git a/content/browser/back_forward_cache_features_browsertest.cc b/content/browser/back_forward_cache_features_browsertest.cc index 39ce9992..62aea25 100644 --- a/content/browser/back_forward_cache_features_browsertest.cc +++ b/content/browser/back_forward_cache_features_browsertest.cc
@@ -2321,8 +2321,16 @@ // Tests that the short vibration sequence on the page stops after it enters // bfcache. +// http://crbug.com/1280741 +#if defined(OS_MAC) +#define MAYBE_ShortVibrationSequenceStopsAfterEnteringCache \ + DISABLED_ShortVibrationSequenceStopsAfterEnteringCache +#else +#define MAYBE_ShortVibrationSequenceStopsAfterEnteringCache \ + ShortVibrationSequenceStopsAfterEnteringCache +#endif IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, - ShortVibrationSequenceStopsAfterEnteringCache) { + MAYBE_ShortVibrationSequenceStopsAfterEnteringCache) { ASSERT_TRUE(embedded_test_server()->Start()); TestVibrationManager vibration_manager;
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index cddf902..963313e0 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -1022,7 +1022,10 @@ EXPECT_THAT(console_messages_, ElementsAre("first page", "second page")); } -IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigationPreservesMessages) { +// TODO(crbug.com/1280531): Disabled due to flakiness. Flaky on mac and linux +// la-cros +IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, + DISABLED_NavigationPreservesMessages) { ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html"); NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index d48b487..b92684a 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -194,11 +194,14 @@ } // namespace -PageHandler::PageHandler(EmulationHandler* emulation_handler, - BrowserHandler* browser_handler, - bool allow_unsafe_operations) +PageHandler::PageHandler( + EmulationHandler* emulation_handler, + BrowserHandler* browser_handler, + bool allow_unsafe_operations, + absl::optional<url::Origin> navigation_initiator_origin) : DevToolsDomainHandler(Page::Metainfo::domainName), allow_unsafe_operations_(allow_unsafe_operations), + navigation_initiator_origin_(navigation_initiator_origin), enabled_(false), screencast_enabled_(false), screencast_quality_(kDefaultScreenshotQuality), @@ -520,6 +523,15 @@ params.referrer = Referrer(GURL(referrer.fromMaybe("")), policy); params.transition_type = type; params.frame_tree_node_id = frame_tree_node->frame_tree_node_id(); + if (navigation_initiator_origin_.has_value()) { + // When this agent has an initiator origin defined, ensure that its + // navigations are considered renderer-initiated by that origin, such that + // URL spoof defenses are in effect. (crbug.com/1192417) + params.is_renderer_initiated = true; + params.initiator_origin = *navigation_initiator_origin_; + params.source_site_instance = SiteInstance::CreateForURL( + host_->GetBrowserContext(), navigation_initiator_origin_->GetURL()); + } // Handler may be destroyed while navigating if the session // gets disconnected as a result of access checks. base::WeakPtr<PageHandler> weak_self = weak_factory_.GetWeakPtr();
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index e8a0df8..1b7edbd 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -63,7 +63,8 @@ public: PageHandler(EmulationHandler* emulation_handler, BrowserHandler* browser_handler, - bool allow_unsafe_operations); + bool allow_unsafe_operations, + absl::optional<url::Origin> navigation_initiator_origin); PageHandler(const PageHandler&) = delete; PageHandler& operator=(const PageHandler&) = delete; @@ -209,6 +210,7 @@ void OnDownloadDestroyed(download::DownloadItem* item) override; const bool allow_unsafe_operations_; + const absl::optional<url::Origin> navigation_initiator_origin_; bool enabled_; bool bypass_csp_ = false;
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 9aaf942..fdb3757 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -294,6 +294,14 @@ if (!ShouldAllowSession(session)) return false; + if (frame_tree_node_ && !frame_tree_node_->parent() && + frame_tree_node_->is_on_initial_empty_document()) { + // Since the DevTools protocol can be used to modify the initial empty + // document of a tab, notify the browser that the pending URL shouldn't be + // displayed anymore to eliminate a URL spoof risk. + frame_host_->DidAccessInitialMainDocument(); + } + auto emulation_handler = std::make_unique<protocol::EmulationHandler>(); protocol::EmulationHandler* emulation_handler_ptr = emulation_handler.get(); @@ -348,7 +356,8 @@ GetId(), auto_attacher_.get(), session->GetRootSession())); session->AddHandler(std::make_unique<protocol::PageHandler>( emulation_handler_ptr, browser_handler_ptr, - session->GetClient()->AllowUnsafeOperations())); + session->GetClient()->AllowUnsafeOperations(), + session->GetClient()->GetNavigationInitiatorOrigin())); session->AddHandler(std::make_unique<protocol::SecurityHandler>()); if (!frame_tree_node_ || !frame_tree_node_->parent()) { session->AddHandler(
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index cf91da5..90a3111a 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4427,6 +4427,7 @@ // Sets a default value for before_unload_end_time so that the browser // survives a hacked renderer. base::TimeTicks before_unload_end_time = renderer_before_unload_end_time; + base::TimeDelta browser_to_renderer_ipc_time_delta; if (!renderer_before_unload_start_time.is_null() && !renderer_before_unload_end_time.is_null()) { base::TimeTicks before_unload_completed_time = base::TimeTicks::Now(); @@ -4448,6 +4449,19 @@ converter.ToLocalTimeTicks(blink::RemoteTimeTicks::FromTimeTicks( renderer_before_unload_end_time)); before_unload_end_time = browser_before_unload_end_time.ToTimeTicks(); + if (base::FeatureList::IsEnabled( + features::kIncludeIpcOverheadInNavigationStart)) { + const blink::LocalTimeTicks browser_before_unload_start_time = + converter.ToLocalTimeTicks(blink::RemoteTimeTicks::FromTimeTicks( + renderer_before_unload_start_time)); + browser_to_renderer_ipc_time_delta = + browser_before_unload_start_time.ToTimeTicks() - + send_before_unload_start_time_; + } + } else if (base::FeatureList::IsEnabled( + features::kIncludeIpcOverheadInNavigationStart)) { + browser_to_renderer_ipc_time_delta = + (renderer_before_unload_start_time - send_before_unload_start_time_); } base::TimeDelta on_before_unload_overhead_time = @@ -4490,7 +4504,12 @@ proceed, before_unload_end_time); } }, - weak_ptr_factory_.GetWeakPtr(), before_unload_end_time, proceed, + // The overhead of the browser->renderer IPC may be non trivial. Account + // for it here. Ideally this would also include the time to execute the + // JS, but we would need to exclude the time spent waiting for a dialog, + // which is tricky. + weak_ptr_factory_.GetWeakPtr(), + before_unload_end_time - browser_to_renderer_ipc_time_delta, proceed, unload_ack_is_for_navigation_); if (is_frame_being_destroyed) {
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 2d918fcf..de1ab4c9 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -678,10 +678,6 @@ } void RenderViewHostImpl::ClosePage() { - // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done. - VLOG(1) << "RenderViewHostImpl::ClosePage() IsRenderViewLive() = " - << IsRenderViewLive() - << ", SuddenTerminationAllowed() = " << SuddenTerminationAllowed(); is_waiting_for_page_close_completion_ = true; if (IsRenderViewLive() && !SuddenTerminationAllowed()) {
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 72099de3..9b276a3 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1108,6 +1108,16 @@ DCHECK(GetFocusedWidget()); if (actual_range) *actual_range = requested_range; + + // Check selection bounds first (currently populated only for EditContext) + const absl::optional<gfx::Rect> text_selection_bound = + GetTextInputManager()->GetTextSelectionBounds(); + if (text_selection_bound) { + *rect = text_selection_bound.value(); + return true; + } + + // If no selection bounds, fall back to use selection region. *rect = GetTextInputManager() ->GetSelectionRegion(GetFocusedWidget()->GetView()) ->caret_rect;
diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc index 9565175e..eda0259 100644 --- a/content/browser/webui/web_ui_data_source_impl.cc +++ b/content/browser/webui/web_ui_data_source_impl.cc
@@ -12,12 +12,15 @@ #include <vector> #include "base/bind.h" +#include "base/callback.h" +#include "base/check.h" #include "base/check_op.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted_memory.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/thread_pool.h" #include "base/trace_event/trace_event.h" #include "content/grit/content_resources.h" #include "content/public/browser/content_browser_client.h" @@ -52,6 +55,24 @@ namespace { +void GetDataResourceBytesOnWorkerThread( + int resource_id, + URLDataSource::GotDataCallback callback) { + base::ThreadPool::CreateSequencedTaskRunner( + {base::TaskPriority::USER_BLOCKING, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()}) + ->PostTask( + FROM_HERE, + base::BindOnce( + [](int resource_id, URLDataSource::GotDataCallback callback) { + ContentClient* content_client = GetContentClient(); + DCHECK(content_client); + std::move(callback).Run( + content_client->GetDataResourceBytes(resource_id)); + }, + resource_id, std::move(callback))); +} + std::string CleanUpPath(const std::string& path) { // Remove the query string for named resource lookups. std::string clean_path = path.substr(0, path.find_first_of('?')); @@ -351,9 +372,7 @@ if (resource_id == kNonExistentResource) { std::move(callback).Run(nullptr); } else { - scoped_refptr<base::RefCountedMemory> response( - GetContentClient()->GetDataResourceBytes(resource_id)); - std::move(callback).Run(response.get()); + GetDataResourceBytesOnWorkerThread(resource_id, std::move(callback)); } }
diff --git a/content/browser/xr/OWNERS b/content/browser/xr/OWNERS index 5682b9d7..d95d28c 100644 --- a/content/browser/xr/OWNERS +++ b/content/browser/xr/OWNERS
@@ -1,5 +1 @@ -alcooper@chromium.org -klausw@chromium.org - -# Browser Test-related. -bsheedy@chromium.org +file://components/webxr/OWNERS
diff --git a/content/browser/xr/service/isolated_device_provider.cc b/content/browser/xr/service/isolated_device_provider.cc index ee25ce2..f7b0c40 100644 --- a/content/browser/xr/service/isolated_device_provider.cc +++ b/content/browser/xr/service/isolated_device_provider.cc
@@ -16,19 +16,8 @@ namespace content { void IsolatedVRDeviceProvider::Initialize( - base::RepeatingCallback<void(device::mojom::XRDeviceId, - device::mojom::VRDisplayInfoPtr, - device::mojom::XRDeviceDataPtr, - mojo::PendingRemote<device::mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(device::mojom::XRDeviceId)> - remove_device_callback, - base::OnceClosure initialization_complete, - device::XrFrameSinkClientFactory xr_frame_sink_client_factory) { - add_device_callback_ = std::move(add_device_callback); - remove_device_callback_ = std::move(remove_device_callback); - initialization_complete_ = std::move(initialization_complete); - + device::VRDeviceProviderClient* client) { + client_ = client; SetupDeviceProvider(); } @@ -41,8 +30,8 @@ mojo::PendingRemote<device::mojom::XRCompositorHost> compositor_host, device::mojom::XRDeviceDataPtr device_data, device::mojom::XRDeviceId device_id) { - add_device_callback_.Run(device_id, nullptr, std::move(device_data), - std::move(device)); + client_->AddRuntime(device_id, nullptr, std::move(device_data), + std::move(device)); auto* integration_client = GetXrIntegrationClient(); if (!integration_client) @@ -56,7 +45,7 @@ } void IsolatedVRDeviceProvider::OnDeviceRemoved(device::mojom::XRDeviceId id) { - remove_device_callback_.Run(id); + client_->RemoveRuntime(id); ui_host_map_.erase(id); } @@ -65,7 +54,7 @@ // should be removed. for (auto& entry : ui_host_map_) { auto id = entry.first; - remove_device_callback_.Run(id); + client_->RemoveRuntime(id); } ui_host_map_.clear(); @@ -88,7 +77,7 @@ void IsolatedVRDeviceProvider::OnDevicesEnumerated() { if (!initialized_) { initialized_ = true; - std::move(initialization_complete_).Run(); + client_->OnProviderInitialized(); } // Either we've hit the max retries and given up (in which case we don't have
diff --git a/content/browser/xr/service/isolated_device_provider.h b/content/browser/xr/service/isolated_device_provider.h index f65036e1..3bf72be 100644 --- a/content/browser/xr/service/isolated_device_provider.h +++ b/content/browser/xr/service/isolated_device_provider.h
@@ -26,16 +26,7 @@ ~IsolatedVRDeviceProvider() override; // If the VR API requires initialization that should happen here. - void Initialize( - base::RepeatingCallback<void( - device::mojom::XRDeviceId, - device::mojom::VRDisplayInfoPtr, - device::mojom::XRDeviceDataPtr, - mojo::PendingRemote<device::mojom::XRRuntime>)> add_device_callback, - base::RepeatingCallback<void(device::mojom::XRDeviceId)> - remove_device_callback, - base::OnceClosure initialization_complete, - device::XrFrameSinkClientFactory xr_frame_sink_client_factory) override; + void Initialize(device::VRDeviceProviderClient* client) override; // Returns true if initialization is complete. bool Initialized() override; @@ -56,15 +47,7 @@ int retry_count_ = 0; mojo::Remote<device::mojom::IsolatedXRRuntimeProvider> device_provider_; - // TODO(crbug.com/1090029): Wrap XRDeviceId + VRDisplayInfo into XRDeviceData - base::RepeatingCallback<void(device::mojom::XRDeviceId, - device::mojom::VRDisplayInfoPtr, - device::mojom::XRDeviceDataPtr, - mojo::PendingRemote<device::mojom::XRRuntime>)> - add_device_callback_; - base::RepeatingCallback<void(device::mojom::XRDeviceId)> - remove_device_callback_; - base::OnceClosure initialization_complete_; + device::VRDeviceProviderClient* client_ = nullptr; mojo::Receiver<device::mojom::IsolatedXRRuntimeProviderClient> receiver_{ this};
diff --git a/content/browser/xr/service/xr_runtime_manager_impl.cc b/content/browser/xr/service/xr_runtime_manager_impl.cc index 0bcc089c..2a212db0 100644 --- a/content/browser/xr/service/xr_runtime_manager_impl.cc +++ b/content/browser/xr/service/xr_runtime_manager_impl.cc
@@ -503,14 +503,10 @@ continue; } - provider->Initialize( - base::BindRepeating(&XRRuntimeManagerImpl::AddRuntime, - base::Unretained(this)), - base::BindRepeating(&XRRuntimeManagerImpl::RemoveRuntime, - base::Unretained(this)), - base::BindOnce(&XRRuntimeManagerImpl::OnProviderInitialized, - base::Unretained(this)), - base::BindRepeating(&FrameSinkClientFactory)); + // It is acceptable for the providers to potentially take/keep a reference + // to ourselves here, since we own the providers and can guarantee that they + // will not outlive us. + provider->Initialize(this); } providers_initialized_ = true; @@ -573,6 +569,11 @@ service->RuntimesChanged(); } +device::XrFrameSinkClientFactory +XRRuntimeManagerImpl::GetXrFrameSinkClientFactory() { + return base::BindRepeating(&FrameSinkClientFactory); +} + void XRRuntimeManagerImpl::ForEachRuntime( base::RepeatingCallback<void(BrowserXRRuntime*)> fn) { for (auto& runtime : runtimes_) {
diff --git a/content/browser/xr/service/xr_runtime_manager_impl.h b/content/browser/xr/service/xr_runtime_manager_impl.h index 0f8ced4..c6aa700 100644 --- a/content/browser/xr/service/xr_runtime_manager_impl.h +++ b/content/browser/xr/service/xr_runtime_manager_impl.h
@@ -23,6 +23,7 @@ #include "content/public/browser/gpu_data_manager_observer.h" #include "content/public/browser/xr_integration_client.h" #include "content/public/browser/xr_runtime_manager.h" +#include "device/vr/public/cpp/vr_device_provider.h" #include "device/vr/public/mojom/vr_service.mojom-forward.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -38,7 +39,8 @@ class CONTENT_EXPORT XRRuntimeManagerImpl : public XRRuntimeManager, public base::RefCounted<XRRuntimeManagerImpl>, - public content::GpuDataManagerObserver { + public content::GpuDataManagerObserver, + public device::VRDeviceProviderClient { public: friend base::RefCounted<XRRuntimeManagerImpl>; static constexpr auto kRefCountPreference = @@ -92,6 +94,16 @@ void ForEachRuntime( base::RepeatingCallback<void(BrowserXRRuntime*)> fn) override; + // VRDeviceProviderClient implementation + void AddRuntime( + device::mojom::XRDeviceId id, + device::mojom::VRDisplayInfoPtr info, + device::mojom::XRDeviceDataPtr device_data, + mojo::PendingRemote<device::mojom::XRRuntime> runtime) override; + void RemoveRuntime(device::mojom::XRDeviceId id) override; + void OnProviderInitialized() override; + device::XrFrameSinkClientFactory GetXrFrameSinkClientFactory() override; + private: // Constructor also used by tests to supply an arbitrary list of providers static scoped_refptr<XRRuntimeManagerImpl> CreateInstance( @@ -108,15 +120,8 @@ ~XRRuntimeManagerImpl() override; void InitializeProviders(); - void OnProviderInitialized(); bool AreAllProvidersInitialized(); - void AddRuntime(device::mojom::XRDeviceId id, - device::mojom::VRDisplayInfoPtr info, - device::mojom::XRDeviceDataPtr device_data, - mojo::PendingRemote<device::mojom::XRRuntime> runtime); - void RemoveRuntime(device::mojom::XRDeviceId id); - bool IsInitializedOnCompatibleAdapter(BrowserXRRuntimeImpl* runtime); // Gets the system default immersive-vr runtime if available.
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java index 3d36dae..3d7479e 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java
@@ -21,6 +21,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner; @@ -285,7 +286,10 @@ @Test @SmallTest - public void test_buttonWithListboxPopup() { + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.Q, + message = "Fails on Android 11: https://crbug.com/1280713") + public void + test_buttonWithListboxPopup() { performHtmlTest("button-with-listbox-popup.html"); } @@ -1107,7 +1111,10 @@ @Test @SmallTest - public void test_selectmenu() { + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.Q, + message = "Fails on Android 11: https://crbug.com/1280713") + public void + test_selectmenu() { performHtmlTest("selectmenu.html"); } @@ -1344,4 +1351,4 @@ public void test_wbr() { performHtmlTest("wbr.html"); } -} \ No newline at end of file +}
diff --git a/content/public/browser/devtools_agent_host_client.cc b/content/public/browser/devtools_agent_host_client.cc index e6f7cd5..8d5455e 100644 --- a/content/public/browser/devtools_agent_host_client.cc +++ b/content/public/browser/devtools_agent_host_client.cc
@@ -39,4 +39,9 @@ return false; } +absl::optional<url::Origin> +DevToolsAgentHostClient::GetNavigationInitiatorOrigin() { + return absl::nullopt; +} + } // namespace content
diff --git a/content/public/browser/devtools_agent_host_client.h b/content/public/browser/devtools_agent_host_client.h index 221e9da..cb13d3c6 100644 --- a/content/public/browser/devtools_agent_host_client.h +++ b/content/public/browser/devtools_agent_host_client.h
@@ -7,6 +7,8 @@ #include "base/containers/span.h" #include "content/common/content_export.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "url/origin.h" class GURL; namespace content { @@ -52,6 +54,13 @@ // that are already privileged, such as local automation clients. virtual bool AllowUnsafeOperations(); + // A value to use as NavigationController::LoadURLParams::initiator_origin. + // If set, navigations would also be treated as renderer-initiated. + // This is useful e.g. for Chrome Extensions so that their calls to + // Page.navigate would be treated as renderer-initiated naviation subject to + // URL spoofing protection. + virtual absl::optional<url::Origin> GetNavigationInitiatorOrigin(); + // Determines protocol message format. virtual bool UsesBinaryProtocol(); };
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 1743ca8..5046fce 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -384,6 +384,20 @@ const base::Feature kIdleDetection{"IdleDetection", base::FEATURE_ENABLED_BY_DEFAULT}; +// Historically most navigations required IPC from browser to renderer and +// from renderer back to browser. This was done to check for before-unload +// handlers on the current page and occurred regardless of whether a +// before-unload handler was present. The navigation start time (as used in +// various metrics) is the time the renderer initiates the IPC back to the +// browser. If this feature is enabled, the navigation start time takes into +// account the cost of the IPC from the browser to renderer. More specifically: +// navigation_start = time_renderer_sends_ipc_to_browser - +// (time_renderer_receives_ipc - time_browser_sends_ipc) +// Note that navigation_start does not take into account the amount of time the +// renderer spends processing the IPC (that is, executing script). +const base::Feature kIncludeIpcOverheadInNavigationStart{ + "IncludeIpcOverheadInNavigationStart", base::FEATURE_DISABLED_BY_DEFAULT}; + // Kill switch for the GetInstalledRelatedApps API. const base::Feature kInstalledApp{"InstalledApp", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index e730daa..db74c78 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -93,6 +93,7 @@ CONTENT_EXPORT extern const base::Feature kGreaseUACH; CONTENT_EXPORT extern const base::Feature kHistoryPreventSandboxedNavigation; CONTENT_EXPORT extern const base::Feature kIdleDetection; +CONTENT_EXPORT extern const base::Feature kIncludeIpcOverheadInNavigationStart; CONTENT_EXPORT extern const base::Feature kInstalledApp; CONTENT_EXPORT extern const base::Feature kInstalledAppProvider; CONTENT_EXPORT extern const base::Feature kInstalledAppsInCbd;
diff --git a/content/services/isolated_xr_device/OWNERS b/content/services/isolated_xr_device/OWNERS index 4c4713b..d95d28c 100644 --- a/content/services/isolated_xr_device/OWNERS +++ b/content/services/isolated_xr_device/OWNERS
@@ -1,2 +1 @@ -alcooper@chromium.org -klausw@chromium.org +file://components/webxr/OWNERS
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 4f9cb153..bd4f90f 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
@@ -128,6 +128,7 @@ crbug.com/1099955 [ swiftshader-gl angle-disabled win ] WebglExtension_EXT_shader_texture_lod [ Skip ] crbug.com/1099955 [ swiftshader-gl angle-disabled linux ] WebglExtension_EXT_texture_compression_bptc [ Skip ] crbug.com/1099955 [ swiftshader-gl angle-disabled win ] WebglExtension_EXT_texture_compression_bptc [ Skip ] +crbug.com/1280666 [ swiftshader-gl angle-disabled mac ] WebglExtension_WEBGL_compressed_texture_s3tc_srgb [ Skip ] crbug.com/1099955 [ angle-swiftshader no-swiftshader-gl linux ] WebglExtension_EXT_disjoint_timer_query [ Skip ] crbug.com/1099955 [ angle-swiftshader no-swiftshader-gl mac ] WebglExtension_EXT_disjoint_timer_query [ Skip ] crbug.com/1099955 [ angle-swiftshader no-swiftshader-gl win ] WebglExtension_EXT_disjoint_timer_query [ Skip ]
diff --git a/content/web_test/browser/web_test_control_host.cc b/content/web_test/browser/web_test_control_host.cc index 6f8dc9e..4fb06885 100644 --- a/content/web_test/browser/web_test_control_host.cc +++ b/content/web_test/browser/web_test_control_host.cc
@@ -794,7 +794,7 @@ if (!renderer_dump_result_->layout) { DCHECK_EQ(0, waiting_for_layout_dumps_); - main_window_->web_contents()->ForEachRenderFrameHost( + main_window_->web_contents()->GetMainFrame()->ForEachRenderFrameHost( base::BindLambdaForTesting([&](RenderFrameHost* render_frame_host) { if (!render_frame_host->IsRenderFrameLive()) return;
diff --git a/device/bluetooth/chromeos/bluetooth_utils.cc b/device/bluetooth/chromeos/bluetooth_utils.cc index b0ab4d9a..02c5939c 100644 --- a/device/bluetooth/chromeos/bluetooth_utils.cc +++ b/device/bluetooth/chromeos/bluetooth_utils.cc
@@ -39,18 +39,6 @@ constexpr base::TimeDelta kMaxDeviceSelectionDuration = base::Seconds(30); -// This enum is tied directly to a UMA enum defined in -// //tools/metrics/histograms/enums.xml, and should always reflect it (do not -// change one without changing the other). -enum class BluetoothTransportType { - kUnknown = 0, - kClassic = 1, - kLE = 2, - kDual = 3, - kInvalid = 4, - kMaxValue = kInvalid -}; - // Get limited number of devices from |devices| and // prioritize paired/connecting devices over other devices. BluetoothAdapter::DeviceList GetLimitedNumDevices(
diff --git a/device/bluetooth/chromeos/bluetooth_utils.h b/device/bluetooth/chromeos/bluetooth_utils.h index b78a3e4..d1ec8ae 100644 --- a/device/bluetooth/chromeos/bluetooth_utils.h +++ b/device/bluetooth/chromeos/bluetooth_utils.h
@@ -98,6 +98,18 @@ kMaxValue = kSuccess, }; +// This enum is tied directly to a UMA enum defined in +// //tools/metrics/histograms/enums.xml, and should always reflect it (do not +// change one without changing the other). +enum class BluetoothTransportType { + kUnknown = 0, + kClassic = 1, + kLE = 2, + kDual = 3, + kInvalid = 4, + kMaxValue = kInvalid +}; + // Return filtered devices based on the filter type and max number of devices. DEVICE_BLUETOOTH_EXPORT device::BluetoothAdapter::DeviceList FilterBluetoothDeviceList(const BluetoothAdapter::DeviceList& devices,
diff --git a/device/vr/OWNERS b/device/vr/OWNERS index 49db46fe..205aeab 100644 --- a/device/vr/OWNERS +++ b/device/vr/OWNERS
@@ -1,6 +1,4 @@ -alcooper@chromium.org -bajones@chromium.org -bialpio@chromium.org +file://components/webxr/OWNERS per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/device/vr/android/arcore/OWNERS b/device/vr/android/arcore/OWNERS deleted file mode 100644 index 8f984dc5..0000000 --- a/device/vr/android/arcore/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -bialpio@chromium.org -klausw@chromium.org
diff --git a/device/vr/android/gvr/gvr_device_provider.cc b/device/vr/android/gvr/gvr_device_provider.cc index a5c20859..6055202 100644 --- a/device/vr/android/gvr/gvr_device_provider.cc +++ b/device/vr/android/gvr/gvr_device_provider.cc
@@ -14,15 +14,7 @@ GvrDeviceProvider::GvrDeviceProvider() = default; GvrDeviceProvider::~GvrDeviceProvider() = default; -void GvrDeviceProvider::Initialize( - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, - base::OnceClosure initialization_complete, - XrFrameSinkClientFactory xr_frame_sink_client_factory) { +void GvrDeviceProvider::Initialize(VRDeviceProviderClient* client) { // We only expose GvrDevice if // - we could potentially install VRServices to support presentation, and // - this build is a bundle and, thus, supports installing the VR module. @@ -30,12 +22,12 @@ vr_device_ = base::WrapUnique(new GvrDevice()); } if (vr_device_) { - add_device_callback.Run(vr_device_->GetId(), vr_device_->GetVRDisplayInfo(), - vr_device_->GetDeviceData(), - vr_device_->BindXRRuntime()); + client->AddRuntime(vr_device_->GetId(), vr_device_->GetVRDisplayInfo(), + vr_device_->GetDeviceData(), + vr_device_->BindXRRuntime()); } initialized_ = true; - std::move(initialization_complete).Run(); + client->OnProviderInitialized(); } bool GvrDeviceProvider::Initialized() {
diff --git a/device/vr/android/gvr/gvr_device_provider.h b/device/vr/android/gvr/gvr_device_provider.h index 0de4b21..46afc96 100644 --- a/device/vr/android/gvr/gvr_device_provider.h +++ b/device/vr/android/gvr/gvr_device_provider.h
@@ -24,16 +24,7 @@ ~GvrDeviceProvider() override; - void Initialize( - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, - base::OnceClosure initialization_complete, - XrFrameSinkClientFactory xr_frame_sink_client_factory) override; - + void Initialize(VRDeviceProviderClient* client) override; bool Initialized() override; private:
diff --git a/device/vr/openxr/OWNERS b/device/vr/openxr/OWNERS index 49a9910..0b752de 100644 --- a/device/vr/openxr/OWNERS +++ b/device/vr/openxr/OWNERS
@@ -1,3 +1,2 @@ -alcooper@chromium.org -bajones@chromium.org +file://components/webxr/OWNERS rafael.cintron@microsoft.com
diff --git a/device/vr/orientation/orientation_device_provider.cc b/device/vr/orientation/orientation_device_provider.cc index 2ac2eb2..c2bca59 100644 --- a/device/vr/orientation/orientation_device_provider.cc +++ b/device/vr/orientation/orientation_device_provider.cc
@@ -19,28 +19,19 @@ VROrientationDeviceProvider::~VROrientationDeviceProvider() = default; -void VROrientationDeviceProvider::Initialize( - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, - base::OnceClosure initialization_complete, - XrFrameSinkClientFactory xr_frame_sink_client_factory) { +void VROrientationDeviceProvider::Initialize(VRDeviceProviderClient* client) { if (device_ && device_->IsAvailable()) { - add_device_callback.Run(device_->GetId(), device_->GetVRDisplayInfo(), - device_->GetDeviceData(), device_->BindXRRuntime()); + client->AddRuntime(device_->GetId(), device_->GetVRDisplayInfo(), + device_->GetDeviceData(), device_->BindXRRuntime()); return; } if (!device_) { + client_ = client; device_ = std::make_unique<VROrientationDevice>( sensor_provider_.get(), base::BindOnce(&VROrientationDeviceProvider::DeviceInitialized, base::Unretained(this))); - add_device_callback_ = add_device_callback; - initialized_callback_ = std::move(initialization_complete); } } @@ -56,13 +47,12 @@ // If the device successfully connected to the orientation APIs, provide it. if (device_->IsAvailable()) { - add_device_callback_.Run(device_->GetId(), device_->GetVRDisplayInfo(), - device_->GetDeviceData(), - device_->BindXRRuntime()); + client_->AddRuntime(device_->GetId(), device_->GetVRDisplayInfo(), + device_->GetDeviceData(), device_->BindXRRuntime()); } initialized_ = true; - std::move(initialized_callback_).Run(); + client_->OnProviderInitialized(); } } // namespace device
diff --git a/device/vr/orientation/orientation_device_provider.h b/device/vr/orientation/orientation_device_provider.h index 3a4ae644..1f46dab6 100644 --- a/device/vr/orientation/orientation_device_provider.h +++ b/device/vr/orientation/orientation_device_provider.h
@@ -29,15 +29,7 @@ ~VROrientationDeviceProvider() override; - void Initialize( - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, - base::OnceClosure initialization_complete, - XrFrameSinkClientFactory xr_frame_sink_client_factory) override; + void Initialize(VRDeviceProviderClient* client) override; bool Initialized() override; @@ -49,13 +41,7 @@ mojo::Remote<device::mojom::SensorProvider> sensor_provider_; std::unique_ptr<VROrientationDevice> device_; - - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback_; - base::OnceClosure initialized_callback_; + VRDeviceProviderClient* client_ = nullptr; }; } // namespace device
diff --git a/device/vr/orientation/orientation_device_provider_unittest.cc b/device/vr/orientation/orientation_device_provider_unittest.cc index cb14e07..cb1f37d 100644 --- a/device/vr/orientation/orientation_device_provider_unittest.cc +++ b/device/vr/orientation/orientation_device_provider_unittest.cc
@@ -94,58 +94,6 @@ return init_params; } - base::RepeatingCallback<void(device::mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime> device)> - DeviceAndIdCallbackFailIfCalled() { - return base::BindRepeating( - [](device::mojom::XRDeviceId id, mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime> device) { FAIL(); }); - } - - base::RepeatingCallback<void(device::mojom::XRDeviceId)> - DeviceIdCallbackFailIfCalled() { - return base::BindRepeating([](device::mojom::XRDeviceId id) { FAIL(); }); - } - - base::RepeatingCallback<void(device::mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime> device)> - DeviceAndIdCallbackMustBeCalled(base::RunLoop* loop) { - return base::BindRepeating( - [](base::OnceClosure quit_closure, device::mojom::XRDeviceId id, - mojom::VRDisplayInfoPtr info, mojom::XRDeviceDataPtr data, - mojo::PendingRemote<mojom::XRRuntime> device) { - ASSERT_TRUE(device); - ASSERT_TRUE(info); - ASSERT_TRUE(data); - std::move(quit_closure).Run(); - }, - loop->QuitClosure()); - } - - base::RepeatingCallback<void(device::mojom::XRDeviceId)> - DeviceIdCallbackMustBeCalled(base::RunLoop* loop) { - return base::BindRepeating( - [](base::OnceClosure quit_closure, device::mojom::XRDeviceId id) { - std::move(quit_closure).Run(); - }, - loop->QuitClosure()); - } - - base::OnceClosure ClosureFailIfCalled() { - return base::BindOnce([]() { FAIL(); }); - } - - base::OnceClosure ClosureMustBeCalled(base::RunLoop* loop) { - return base::BindOnce( - [](base::OnceClosure quit_closure) { std::move(quit_closure).Run(); }, - loop->QuitClosure()); - } - // Needed for MakeRequest to work. base::test::TaskEnvironment task_environment_; @@ -161,6 +109,56 @@ mojo::Remote<mojom::SensorClient> sensor_client_; }; +class MockOrientationDeviceProviderClient : public VRDeviceProviderClient { + public: + MockOrientationDeviceProviderClient(base::RunLoop* wait_for_device, + base::RunLoop* wait_for_init) + : wait_for_device_(wait_for_device), wait_for_init_(wait_for_init) {} + ~MockOrientationDeviceProviderClient() override = default; + void AddRuntime( + device::mojom::XRDeviceId id, + device::mojom::VRDisplayInfoPtr info, + device::mojom::XRDeviceDataPtr device_data, + mojo::PendingRemote<device::mojom::XRRuntime> runtime) override { + if (wait_for_device_) { + ASSERT_TRUE(info); + ASSERT_TRUE(device_data); + ASSERT_TRUE(runtime); + wait_for_device_->Quit(); + return; + } + + // If we were created without a wait_for_device runloop, then the test + // is not expecting us to be called. + FAIL(); + } + + void RemoveRuntime(device::mojom::XRDeviceId id) override { + // The only devices that actually create an Orientation device cannot + // physically remove the orientation sensors, so this should never be + // called. + FAIL(); + } + + void OnProviderInitialized() override { + if (!wait_for_init_) { + FAIL(); + } + + wait_for_init_->Quit(); + } + + device::XrFrameSinkClientFactory GetXrFrameSinkClientFactory() override { + ADD_FAILURE(); + + return base::BindRepeating(&FrameSinkClientFactory); + } + + private: + base::RunLoop* wait_for_device_ = nullptr; + base::RunLoop* wait_for_init_ = nullptr; +}; + TEST_F(VROrientationDeviceProviderTest, InitializationTest) { // Check that without running anything, the provider will not be initialized. EXPECT_FALSE(provider_->Initialized()); @@ -170,10 +168,9 @@ base::RunLoop wait_for_device; base::RunLoop wait_for_init; - provider_->Initialize(DeviceAndIdCallbackMustBeCalled(&wait_for_device), - DeviceIdCallbackFailIfCalled(), - ClosureMustBeCalled(&wait_for_init), - base::BindRepeating(&FrameSinkClientFactory)); + MockOrientationDeviceProviderClient client(&wait_for_device, &wait_for_init); + + provider_->Initialize(&client); InitializeDevice(FakeInitParams()); @@ -186,10 +183,8 @@ TEST_F(VROrientationDeviceProviderTest, InitializationCallbackFailureTest) { base::RunLoop wait_for_init; - provider_->Initialize(DeviceAndIdCallbackFailIfCalled(), - DeviceIdCallbackFailIfCalled(), - ClosureMustBeCalled(&wait_for_init), - base::BindRepeating(&FrameSinkClientFactory)); + MockOrientationDeviceProviderClient client(nullptr, &wait_for_init); + provider_->Initialize(&client); InitializeDevice(nullptr);
diff --git a/device/vr/public/cpp/vr_device_provider.cc b/device/vr/public/cpp/vr_device_provider.cc index 9919bad..d938f9ab 100644 --- a/device/vr/public/cpp/vr_device_provider.cc +++ b/device/vr/public/cpp/vr_device_provider.cc
@@ -8,4 +8,7 @@ VRDeviceProvider::VRDeviceProvider() = default; VRDeviceProvider::~VRDeviceProvider() = default; + +VRDeviceProviderClient::VRDeviceProviderClient() = default; +VRDeviceProviderClient::~VRDeviceProviderClient() = default; } // namespace device
diff --git a/device/vr/public/cpp/vr_device_provider.h b/device/vr/public/cpp/vr_device_provider.h index 0725439..1b7a0ab7 100644 --- a/device/vr/public/cpp/vr_device_provider.h +++ b/device/vr/public/cpp/vr_device_provider.h
@@ -13,22 +13,30 @@ namespace device { +class COMPONENT_EXPORT(VR_PUBLIC_CPP) VRDeviceProviderClient { + public: + VRDeviceProviderClient(); + virtual ~VRDeviceProviderClient(); + + // TODO(crbug.com/1090029): Wrap XRDeviceId + VRDisplayInfo into XRDeviceData + virtual void AddRuntime( + device::mojom::XRDeviceId id, + device::mojom::VRDisplayInfoPtr info, + device::mojom::XRDeviceDataPtr device_data, + mojo::PendingRemote<device::mojom::XRRuntime> runtime) = 0; + virtual void RemoveRuntime(device::mojom::XRDeviceId id) = 0; + virtual void OnProviderInitialized() = 0; + virtual XrFrameSinkClientFactory GetXrFrameSinkClientFactory() = 0; +}; + class COMPONENT_EXPORT(VR_PUBLIC_CPP) VRDeviceProvider { public: VRDeviceProvider(); virtual ~VRDeviceProvider(); // If the VR API requires initialization that should happen here. - virtual void Initialize( - base::RepeatingCallback<void(mojom::XRDeviceId id, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(mojom::XRDeviceId id)> - remove_device_callback, - base::OnceClosure initialization_complete, - XrFrameSinkClientFactory xr_frame_sink_client_factory) = 0; + // Note that the client must be guaranteed to outlive the device provider. + virtual void Initialize(VRDeviceProviderClient* client) = 0; // Returns true if initialization is complete. virtual bool Initialized() = 0;
diff --git a/device/vr/test/fake_vr_device_provider.cc b/device/vr/test/fake_vr_device_provider.cc index 1888b724..c4a7f65 100644 --- a/device/vr/test/fake_vr_device_provider.cc +++ b/device/vr/test/fake_vr_device_provider.cc
@@ -17,9 +17,9 @@ VRDeviceBase* device_base = static_cast<VRDeviceBase*>(device.get()); devices_.push_back(std::move(device)); if (initialized_) - add_device_callback_.Run( - device_base->GetId(), device_base->GetVRDisplayInfo(), - device_base->GetDeviceData(), device_base->BindXRRuntime()); + client_->AddRuntime(device_base->GetId(), device_base->GetVRDisplayInfo(), + device_base->GetDeviceData(), + device_base->BindXRRuntime()); } void FakeVRDeviceProvider::RemoveDevice(mojom::XRDeviceId device_id) { @@ -29,30 +29,21 @@ return static_cast<VRDeviceBase*>(device.get())->GetId() == device_id; }); if (initialized_) - remove_device_callback_.Run(device_id); + client_->RemoveRuntime(device_id); devices_.erase(it); } -void FakeVRDeviceProvider::Initialize( - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, - base::OnceClosure initialization_complete, - XrFrameSinkClientFactory xr_frame_sink_client_factory) { - add_device_callback_ = std::move(add_device_callback); - remove_device_callback_ = std::move(remove_device_callback); +void FakeVRDeviceProvider::Initialize(VRDeviceProviderClient* client) { + client_ = client; for (std::unique_ptr<VRDeviceBase>& device : devices_) { auto* device_base = static_cast<VRDeviceBase*>(device.get()); - add_device_callback_.Run( - device_base->GetId(), device_base->GetVRDisplayInfo(), - device_base->GetDeviceData(), device_base->BindXRRuntime()); + client_->AddRuntime(device_base->GetId(), device_base->GetVRDisplayInfo(), + device_base->GetDeviceData(), + device_base->BindXRRuntime()); } initialized_ = true; - std::move(initialization_complete).Run(); + client_->OnProviderInitialized(); } bool FakeVRDeviceProvider::Initialized() {
diff --git a/device/vr/test/fake_vr_device_provider.h b/device/vr/test/fake_vr_device_provider.h index 8eed663..e456a282 100644 --- a/device/vr/test/fake_vr_device_provider.h +++ b/device/vr/test/fake_vr_device_provider.h
@@ -29,26 +29,13 @@ void AddDevice(std::unique_ptr<VRDeviceBase> device); void RemoveDevice(mojom::XRDeviceId device_id); - void Initialize( - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback, - base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback, - base::OnceClosure initialization_complete, - XrFrameSinkClientFactory xr_frame_sink_client_factory) override; + void Initialize(VRDeviceProviderClient* client) override; bool Initialized() override; private: std::vector<std::unique_ptr<VRDeviceBase>> devices_; bool initialized_; - base::RepeatingCallback<void(mojom::XRDeviceId, - mojom::VRDisplayInfoPtr, - mojom::XRDeviceDataPtr, - mojo::PendingRemote<mojom::XRRuntime>)> - add_device_callback_; - base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback_; + VRDeviceProviderClient* client_ = nullptr; }; } // namespace device
diff --git a/gin/gin_features.cc b/gin/gin_features.cc index ab83bb9..84e42279 100644 --- a/gin/gin_features.cc +++ b/gin/gin_features.cc
@@ -119,15 +119,10 @@ const base::Feature kV8SlowHistogramsScriptAblation{ "V8SlowHistogramsScriptAblation", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables the V8 virtual memory cage. -const base::Feature kV8VirtualMemoryCage { - "V8VirtualMemoryCage", -#if defined(V8_HEAP_SANDBOX) - // The cage is required for the V8 Heap Sandbox. - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif -}; +// Enables the experimental V8 sandbox. This is called V8VirtualMemoryCage +// instead of V8Sandbox for historical reasons. +// TODO(1218005) remove this once the finch trial has ended. +const base::Feature kV8VirtualMemoryCage{"V8VirtualMemoryCage", + base::FEATURE_DISABLED_BY_DEFAULT}; } // namespace features
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc index f576fc90..63992eb 100644 --- a/gin/v8_initializer.cc +++ b/gin/v8_initializer.cc
@@ -352,29 +352,40 @@ // of the virtual memory cage, already use V8's random number generator. v8::V8::SetEntropySource(&GenerateEntropy); -#if defined(V8_VIRTUAL_MEMORY_CAGE) - static_assert(ARCH_CPU_64_BITS, - "V8 virtual memory cage can only work in 64-bit builds"); - // For now, creating the virtual memory cage is optional, and we only do it - // if the correpsonding feature is enabled. In the future, it will be - // mandatory when compiling with V8_VIRTUAL_MEMORY_CAGE. - bool v8_cage_is_initialized = false; - if (base::FeatureList::IsEnabled(features::kV8VirtualMemoryCage)) { - v8_cage_is_initialized = v8::V8::InitializeVirtualMemoryCage(); +#if defined(V8_SANDBOX) + static_assert(ARCH_CPU_64_BITS, "V8 sandbox can only work in 64-bit builds"); + // For now, initializing the sandbox is optional, and we only do it if the + // correpsonding feature is enabled. In the future, it will be mandatory when + // compiling with V8_SANDBOX. + // However, if V8 uses sandboxed pointers, then the sandbox must be + // initialized as sandboxed pointers are simply offsets inside the sandbox. +#if defined(V8_SANDBOXED_POINTERS) + bool must_initialize_sandbox = true; +#else + bool must_initialize_sandbox = false; +#endif - // Record the size of the virtual memory cage, in GB. The size will always - // be a power of two, so we use a sparse histogram to capture it. - // If the initialization failed, this API will return zero. - // The main reason for capturing this histogram here instead of having V8 - // do it is that there are no Isolates available yet, which are required - // for recording histograms in V8. - size_t size = v8::V8::GetVirtualMemoryCageSizeInBytes(); + bool v8_sandbox_is_initialized = false; + if (must_initialize_sandbox || + base::FeatureList::IsEnabled(features::kV8VirtualMemoryCage)) { + v8_sandbox_is_initialized = v8::V8::InitializeSandbox(); + CHECK(!must_initialize_sandbox || v8_sandbox_is_initialized); + + // Record the size of the sandbox, in GB. The size will always be a power + // of two, so we use a sparse histogram to capture it. If the + // initialization failed, this API will return zero. The main reason for + // capturing this histogram here instead of having V8 do it is that there + // are no Isolates available yet, which are required for recording + // histograms in V8. + size_t size = v8::V8::GetSandboxSizeInBytes(); int sizeInGB = size >> 30; DCHECK(base::bits::IsPowerOfTwo(size)); DCHECK(size == 0 || sizeInGB > 0); + // This uses the term "cage" instead of "sandbox" for historical reasons. + // TODO(1218005) remove this once the finch trial has ended. base::UmaHistogramSparse("V8.VirtualMemoryCageSizeGB", sizeInGB); } -#endif +#endif // V8_SANDBOX SetFlags(mode, js_command_line_flags); @@ -390,27 +401,28 @@ v8_is_initialized = true; -#if defined(V8_VIRTUAL_MEMORY_CAGE) - if (v8_cage_is_initialized) { +#if defined(V8_SANDBOX) + if (v8_sandbox_is_initialized) { // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. This should match enum // V8VirtualMemoryCageMode in \tools\metrics\histograms\enums.xml + // This uses the term "cage" instead of "sandbox" for historical reasons. + // TODO(1218005) remove this once the finch trial has ended. enum class VirtualMemoryCageMode { kSecure = 0, kInsecure = 1, kMaxValue = kInsecure, }; base::UmaHistogramEnumeration("V8.VirtualMemoryCageMode", - v8::V8::IsUsingSecureVirtualMemoryCage() + v8::V8::IsSandboxConfiguredSecurely() ? VirtualMemoryCageMode::kSecure : VirtualMemoryCageMode::kInsecure); - // When the virtual memory cage is enabled, ArrayBuffers must be located - // inside the cage. To achieve that, PA's ConfigurablePool is created inside - // the cage and Blink will create the ArrayBuffer partition inside that - // Pool if it is enabled. - v8::PageAllocator* cage_page_allocator = - v8::V8::GetVirtualMemoryCagePageAllocator(); + // When the sandbox is enabled, ArrayBuffers must be allocated inside of + // it. To achieve that, PA's ConfigurablePool is created inside the sandbox + // and Blink then creates the ArrayBuffer partition in that Pool. + v8::VirtualAddressSpace* sandbox_address_space = + v8::V8::GetSandboxAddressSpace(); const size_t max_pool_size = base::internal::PartitionAddressSpace::ConfigurablePoolMaxSize(); const size_t min_pool_size = @@ -421,7 +433,7 @@ // virtual memory is expensive on these OSes. if (base::win::GetVersion() < base::win::Version::WIN8_1) { // The size chosen here should be synchronized with the size of the - // virtual memory reservation for the V8 cage on these platforms. + // virtual memory reservation for the V8 sandbox on these platforms. // Currently, that is 8GB, of which 4GB are used for V8's pointer // compression region. // TODO(saelo) give this constant a proper name and maybe move it @@ -436,19 +448,19 @@ // the size on failure until it succeeds. void* pool_base = nullptr; while (!pool_base && pool_size >= min_pool_size) { - pool_base = cage_page_allocator->AllocatePages( - nullptr, pool_size, pool_size, v8::PageAllocator::kNoAccess); + pool_base = reinterpret_cast<void*>(sandbox_address_space->AllocatePages( + 0, pool_size, pool_size, v8::PagePermissions::kNoAccess)); if (!pool_base) { pool_size /= 2; } } - // The V8 cage is guaranteed to be large enough to host the pool. + // The V8 sandbox is guaranteed to be large enough to host the pool. CHECK(pool_base); base::internal::PartitionAddressSpace::InitConfigurablePool(pool_base, pool_size); // TODO(saelo) maybe record the size of the Pool into UMA. } -#endif +#endif // V8_SANDBOX } // static
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py index 9c6b23d..f62f571 100755 --- a/gpu/vulkan/generate_bindings.py +++ b/gpu/vulkan/generate_bindings.py
@@ -345,7 +345,14 @@ pdecl += text + tail n = len(params) - callstat = 'return gpu::GetVulkanFunctionPointers()->%s(' % func + callstat = '' + if (func == 'vkQueueSubmit' or func == 'vkQueueWaitIdle' + or func == 'vkQueuePresentKHR'): + callstat = '''base::AutoLockMaybe auto_lock + (gpu::GetVulkanFunctionPointers()->per_queue_lock_map[queue].get()); + \n''' + + callstat += 'return gpu::GetVulkanFunctionPointers()->%s(' % func paramdecl = '(' if n > 0: paramnames = (''.join(t for t in p.itertext()) @@ -376,7 +383,9 @@ #include "base/compiler_specific.h" #include "base/component_export.h" +#include "base/containers/flat_map.h" #include "base/native_library.h" +#include "base/synchronization/lock.h" #include "build/build_config.h" #include "ui/gfx/extension_set.h" @@ -431,6 +440,12 @@ base::NativeLibrary vulkan_loader_library = nullptr; + // This is used to allow thread safe access to a given vulkan queue when + // multiple gpu threads are accessing it. Note that this map will be only + // accessed by multiple gpu threads concurrently to read the data, so it + // should be thread safe to use this map by multiple threads. + base::flat_map<VkQueue, std::unique_ptr<base::Lock>> per_queue_lock_map; + template<typename T> class VulkanFunction; template <typename R, typename ...Args>
diff --git a/gpu/vulkan/vulkan_device_queue.cc b/gpu/vulkan/vulkan_device_queue.cc index 19b8242..663cf99 100644 --- a/gpu/vulkan/vulkan_device_queue.cc +++ b/gpu/vulkan/vulkan_device_queue.cc
@@ -392,6 +392,20 @@ VkQueue vk_queue, uint32_t vk_queue_index, gfx::ExtensionSet enabled_extensions) { + // Currently VulkanDeviceQueue for drdc thread(aka CompositorGpuThread) uses + // the same vulkan queue as the gpu main thread. Now since both gpu main and + // drdc threads would be accessing/submitting work to the same queue, all the + // queue access should be made thread safe. This is done by using locks. This + // lock is per |vk_queue|. Note that we are intentionally overwriting a + // previous lock if any. + // Since the map itself would be accessed by multiple gpu threads, we need to + // ensure that the access are thread safe. Here the locks are created and + // written into the map only when drdc thread is initialized which happens + // during GpuServiceImpl init. At this point none of the gpu threads would be + // doing read access until GpuServiceImpl init completed. Hence its safe to + // access map here. + GetVulkanFunctionPointers()->per_queue_lock_map[vk_queue] = + std::make_unique<base::Lock>(); return InitCommon(vk_physical_device, vk_device, vk_queue, vk_queue_index, enabled_extensions); } @@ -410,6 +424,15 @@ if (VK_NULL_HANDLE != owned_vk_device_) { vkDestroyDevice(owned_vk_device_, nullptr); owned_vk_device_ = VK_NULL_HANDLE; + + // Clear all the entries from this map since the device and hence all the + // generated queue(and their corresponding lock) from this device is + // destroyed. + // This happens when VulkanDeviceQueue is destroyed on gpu main thread + // during GpuServiceImpl destruction which happens after CompositorGpuThread + // is destroyed. Hence CompositorGpuThread would not be accessing the map at + // this point and its thread safe to delete map entries here. + GetVulkanFunctionPointers()->per_queue_lock_map.clear(); } vk_device_ = VK_NULL_HANDLE; vk_queue_ = VK_NULL_HANDLE;
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h index 79716f2..7df1278 100644 --- a/gpu/vulkan/vulkan_function_pointers.h +++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -15,7 +15,9 @@ #include "base/compiler_specific.h" #include "base/component_export.h" +#include "base/containers/flat_map.h" #include "base/native_library.h" +#include "base/synchronization/lock.h" #include "build/build_config.h" #include "ui/gfx/extension_set.h" @@ -69,6 +71,12 @@ base::NativeLibrary vulkan_loader_library = nullptr; + // This is used to allow thread safe access to a given vulkan queue when + // multiple gpu threads are accessing it. Note that this map will be only + // accessed by multiple gpu threads concurrently to read the data, so it + // should be thread safe to use this map by multiple threads. + base::flat_map<VkQueue, std::unique_ptr<base::Lock>> per_queue_lock_map; + template <typename T> class VulkanFunction; template <typename R, typename... Args> @@ -959,10 +967,16 @@ uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) { + base::AutoLockMaybe auto_lock( + gpu::GetVulkanFunctionPointers()->per_queue_lock_map[queue].get()); + return gpu::GetVulkanFunctionPointers()->vkQueueSubmit(queue, submitCount, pSubmits, fence); } ALWAYS_INLINE VkResult vkQueueWaitIdle(VkQueue queue) { + base::AutoLockMaybe auto_lock( + gpu::GetVulkanFunctionPointers()->per_queue_lock_map[queue].get()); + return gpu::GetVulkanFunctionPointers()->vkQueueWaitIdle(queue); } ALWAYS_INLINE VkResult vkResetCommandBuffer(VkCommandBuffer commandBuffer, @@ -1148,6 +1162,9 @@ } ALWAYS_INLINE VkResult vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) { + base::AutoLockMaybe auto_lock( + gpu::GetVulkanFunctionPointers()->per_queue_lock_map[queue].get()); + return gpu::GetVulkanFunctionPointers()->vkQueuePresentKHR(queue, pPresentInfo); }
diff --git a/gpu/vulkan/vulkan_util.cc b/gpu/vulkan/vulkan_util.cc index eaf2533a..cd9961b 100644 --- a/gpu/vulkan/vulkan_util.cc +++ b/gpu/vulkan/vulkan_util.cc
@@ -11,6 +11,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "gpu/config/gpu_info.h" // nogncheck #include "gpu/config/vulkan_info.h" @@ -32,6 +33,7 @@ #define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531 namespace gpu { + namespace { #if defined(OS_ANDROID) @@ -147,6 +149,25 @@ pCreateInfos, pAllocator, pPipelines); } +VkResult VulkanQueueSubmitHook(VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence) { + TRACE_EVENT0("gpu", "VulkanQueueSubmitHook"); + return vkQueueSubmit(queue, submitCount, pSubmits, fence); +} + +VkResult VulkanQueueWaitIdleHook(VkQueue queue) { + TRACE_EVENT0("gpu", "VulkanQueueWaitIdleHook"); + return vkQueueWaitIdle(queue); +} + +VkResult VulkanQueuePresentKHRHook(VkQueue queue, + const VkPresentInfoKHR* pPresentInfo) { + TRACE_EVENT0("gpu", "VulkanQueuePresentKHRHook"); + return vkQueuePresentKHR(queue, pPresentInfo); +} + bool CheckVulkanCompabilities(const VulkanInfo& vulkan_info, const GPUInfo& gpu_info, std::string enable_by_device_name) {
diff --git a/gpu/vulkan/vulkan_util.h b/gpu/vulkan/vulkan_util.h index c2be5c9..f7f8b8c 100644 --- a/gpu/vulkan/vulkan_util.h +++ b/gpu/vulkan/vulkan_util.h
@@ -87,6 +87,23 @@ const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +// Below vulkanQueue*Hook methods are used to ensure that Skia calls the correct +// version of those methods which are made thread safe by using locks. See +// vulkan_function_pointers.h vkQueue* method references for more details. +COMPONENT_EXPORT(VULKAN) +VKAPI_ATTR VkResult VKAPI_CALL +VulkanQueueSubmitHook(VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence); + +COMPONENT_EXPORT(VULKAN) +VKAPI_ATTR VkResult VKAPI_CALL VulkanQueueWaitIdleHook(VkQueue queue); + +COMPONENT_EXPORT(VULKAN) +VKAPI_ATTR VkResult VKAPI_CALL +VulkanQueuePresentKHRHook(VkQueue queue, const VkPresentInfoKHR* pPresentInfo); + COMPONENT_EXPORT(VULKAN) bool CheckVulkanCompabilities(const VulkanInfo& vulkan_info, const GPUInfo& gpu_info,
diff --git a/ios/chrome/app/memory_monitor.mm b/ios/chrome/app/memory_monitor.mm index fec4714..af110b1 100644 --- a/ios/chrome/app/memory_monitor.mm +++ b/ios/chrome/app/memory_monitor.mm
@@ -35,7 +35,6 @@ base::BlockingType::WILL_BLOCK); const int free_memory = static_cast<int>(base::SysInfo::AmountOfAvailablePhysicalMemory() / 1024); - crash_keys::SetCurrentFreeMemoryInKB(free_memory); NSURL* fileURL = [[NSURL alloc] initFileURLWithPath:NSHomeDirectory()]; NSDictionary* results = [fileURL resourceValuesForKeys:@[ @@ -48,9 +47,14 @@ results[NSURLVolumeAvailableCapacityForImportantUsageKey]; free_disk_space_kilobytes = [available_bytes integerValue] / 1024; } - crash_keys::SetCurrentFreeDiskInKB(free_disk_space_kilobytes); - [[PreviousSessionInfo sharedInstance] - updateAvailableDeviceStorage:(NSInteger)free_disk_space_kilobytes]; + + // As a workaround to crbug.com/1247282, dispatch back to the main thread. + dispatch_async(dispatch_get_main_queue(), ^{ + crash_keys::SetCurrentFreeMemoryInKB(free_memory); + crash_keys::SetCurrentFreeDiskInKB(free_disk_space_kilobytes); + [[PreviousSessionInfo sharedInstance] + updateAvailableDeviceStorage:(NSInteger)free_disk_space_kilobytes]; + }); } // Invokes |UpdateMemoryValues| and schedules itself to be called after
diff --git a/ios/chrome/browser/omaha/omaha_service.mm b/ios/chrome/browser/omaha/omaha_service.mm index 33b1f58..281c550 100644 --- a/ios/chrome/browser/omaha/omaha_service.mm +++ b/ios/chrome/browser/omaha/omaha_service.mm
@@ -710,21 +710,24 @@ } void OmahaService::PersistStates() { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + // As a workaround to crbug.com/1247282, dispatch back to the main thread. + dispatch_async(dispatch_get_main_queue(), ^{ + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - [defaults setDouble:next_tries_time_.ToCFAbsoluteTime() - forKey:kNextTriesTimesKey]; - [defaults setDouble:current_ping_time_.ToCFAbsoluteTime() - forKey:kCurrentPingKey]; - [defaults setDouble:last_sent_time_.ToCFAbsoluteTime() - forKey:kLastSentTimeKey]; - [defaults setInteger:number_of_tries_ forKey:kNumberTriesKey]; - [defaults setObject:base::SysUTF8ToNSString(last_sent_version_.GetString()) - forKey:kLastSentVersionKey]; - [defaults setInteger:last_server_date_ forKey:kLastServerDateKey]; + [defaults setDouble:next_tries_time_.ToCFAbsoluteTime() + forKey:kNextTriesTimesKey]; + [defaults setDouble:current_ping_time_.ToCFAbsoluteTime() + forKey:kCurrentPingKey]; + [defaults setDouble:last_sent_time_.ToCFAbsoluteTime() + forKey:kLastSentTimeKey]; + [defaults setInteger:number_of_tries_ forKey:kNumberTriesKey]; + [defaults setObject:base::SysUTF8ToNSString(last_sent_version_.GetString()) + forKey:kLastSentVersionKey]; + [defaults setInteger:last_server_date_ forKey:kLastServerDateKey]; - // Save critical state information for usage reporting. - [defaults synchronize]; + // Save critical state information for usage reporting. + [defaults synchronize]; + }); } void OmahaService::OnURLLoadComplete(
diff --git a/ios/chrome/browser/omaha/omaha_service_unittest.mm b/ios/chrome/browser/omaha/omaha_service_unittest.mm index d349e42..8b34c85 100644 --- a/ios/chrome/browser/omaha/omaha_service_unittest.mm +++ b/ios/chrome/browser/omaha/omaha_service_unittest.mm
@@ -12,6 +12,7 @@ #include "base/cxx17_backports.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#import "base/test/ios/wait_util.h" #include "components/metrics/metrics_pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "components/version_info/version_info.h" @@ -701,6 +702,7 @@ base::Time now = base::Time::Now(); OmahaService service(false); service.StartInternal(); + base::test::ios::SpinRunLoopWithMinDelay(base::Milliseconds(1)); service.set_upgrade_recommended_callback(base::BindRepeating( &OmahaServiceTest::OnNeedUpdate, base::Unretained(this))); @@ -710,9 +712,11 @@ service.current_ping_time_ = now + base::Seconds(3); service.last_sent_version_ = base::Version(version_string); service.PersistStates(); + base::test::ios::SpinRunLoopWithMinDelay(base::Milliseconds(1)); OmahaService service2(false); service2.StartInternal(); + base::test::ios::SpinRunLoopWithMinDelay(base::Milliseconds(1)); EXPECT_EQ(service.number_of_tries_, 5); EXPECT_EQ(service2.last_sent_time_, now - base::Seconds(1));
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 9ae1fee1..3d2fe12 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -1067,8 +1067,7 @@ // WebStateObserver has a webUsage callback. if (!active) { if (IsSingleNtpEnabled()) { - [_ntpCoordinator stop]; - [_ntpCoordinator disconnect]; + [self stopNTP]; } else { for (const auto& element : _ntpCoordinatorsForWebStates) [element.second stop]; @@ -2773,6 +2772,32 @@ reading_list::ADDED_VIA_CURRENT_APP); } +#pragma mark - Private SingleNTP feature helper methods + +// Checks if there are any WebStates showing an NTP at this time. If not, then +// deconstructs |ntpCoordinator|. +- (void)stopNTPIfNeeded { + DCHECK(IsSingleNtpEnabled()); + BOOL activeNTP = NO; + WebStateList* webStateList = self.browser->GetWebStateList(); + for (int i = 0; i < webStateList->count(); i++) { + NewTabPageTabHelper* iterNtpHelper = + NewTabPageTabHelper::FromWebState(webStateList->GetWebStateAt(i)); + if (iterNtpHelper->IsActive()) { + activeNTP = YES; + } + } + if (!activeNTP) { + [self stopNTP]; + } +} + +- (void)stopNTP { + [_ntpCoordinator stop]; + [_ntpCoordinator disconnect]; + _ntpCoordinator = nullptr; +} + #pragma mark - ** Protocol Implementations and Helpers ** #pragma mark - ThumbStripSupporting @@ -4088,6 +4113,9 @@ webState->WasHidden(); webState->SetKeepRenderProcessAlive(false); + if (IsSingleNtpEnabled()) { + [self stopNTPIfNeeded]; + } [self uninstallDelegatesForWebState:webState]; } @@ -4707,6 +4735,7 @@ } else { // Set to nullptr to save NTP scroll offset before navigation. self.ntpCoordinator.webState = nullptr; + [self stopNTPIfNeeded]; } } else { if (NTPHelper->IsActive()) {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h index 02fc22b..4360bdc6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.h
@@ -11,7 +11,6 @@ @class ContentSuggestionsSectionInformation; @class ContentSuggestionsViewController; @protocol ContentSuggestionsDataSource; -@protocol SnackbarCommands; @protocol SuggestedContent; // Enum defining the type of a ContentSuggestions. @@ -37,8 +36,6 @@ @property(nonatomic, weak) ContentSuggestionsViewController* collectionViewController; -@property(nonatomic, weak) id<SnackbarCommands> dispatcher; - // Returns whether the section should use the default, non-card style. - (BOOL)shouldUseCustomStyleForSection:(NSInteger)section;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm index f448313..d8ecbcbe 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_updater.mm
@@ -11,7 +11,6 @@ #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/commands/snackbar_commands.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_header_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_text_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/suggested_content.h" @@ -105,9 +104,6 @@ } } -NSString* const kContentSuggestionsCollectionUpdaterSnackbarCategory = - @"ContentSuggestionsCollectionUpdaterSnackbarCategory"; - } // namespace @interface ContentSuggestionsCollectionUpdater ()<ContentSuggestionsDataSink> @@ -134,7 +130,6 @@ @synthesize promoAdded = _promoAdded; @synthesize sectionIdentifiersFromContentSuggestions = _sectionIdentifiersFromContentSuggestions; -@synthesize dispatcher = _dispatcher; - (instancetype)init { self = [super init];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 4718e8c..87b682c 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -225,9 +225,6 @@ setDataSource:self.contentSuggestionsMediator]; self.suggestionsViewController.suggestionCommandHandler = self.ntpMediator; self.suggestionsViewController.audience = self; - id<SnackbarCommands> dispatcher = - static_cast<id<SnackbarCommands>>(self.browser->GetCommandDispatcher()); - self.suggestionsViewController.dispatcher = dispatcher; self.suggestionsViewController.contentSuggestionsEnabled = self.contentSuggestionsEnabled;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h index b406ab0..d9766a8 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h
@@ -16,7 +16,6 @@ @protocol ContentSuggestionsHeaderControlling; @protocol ContentSuggestionsMenuProvider; @protocol ContentSuggestionsViewControllerAudience; -@protocol SnackbarCommands; @protocol SuggestedContent; // CollectionViewController to display the suggestions items. @@ -53,7 +52,6 @@ @property(nonatomic, weak) id<ContentSuggestionsMenuProvider> menuProvider; - (void)setDataSource:(id<ContentSuggestionsDataSource>)dataSource; -- (void)setDispatcher:(id<SnackbarCommands>)dispatcher; // Removes the entry at |indexPath|, from the collection and its model. - (void)dismissEntryAtIndexPath:(NSIndexPath*)indexPath;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index ca086bc..e8ddcc6 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -74,10 +74,6 @@ self.collectionUpdater.dataSource = dataSource; } -- (void)setDispatcher:(id<SnackbarCommands>)dispatcher { - self.collectionUpdater.dispatcher = dispatcher; -} - - (void)dismissEntryAtIndexPath:(NSIndexPath*)indexPath { if (!indexPath || ![self.collectionViewModel hasItemAtIndexPath:indexPath]) { return;
diff --git a/ios/chrome/browser/ui/follow/BUILD.gn b/ios/chrome/browser/ui/follow/BUILD.gn new file mode 100644 index 0000000..0e3c605 --- /dev/null +++ b/ios/chrome/browser/ui/follow/BUILD.gn
@@ -0,0 +1,25 @@ +# 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. + +source_set("utils") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "follow_util.h", + "follow_util.mm", + ] + deps = [ + ":enums", + "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/signin", + "//ios/chrome/browser/ui/ntp:feature_flags", + "//ios/web/public", + "//url", + ] +} + +source_set("enums") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ "follow_action_state.h" ] + deps = [] +}
diff --git a/ios/chrome/browser/ui/follow/follow_action_state.h b/ios/chrome/browser/ui/follow/follow_action_state.h new file mode 100644 index 0000000..dcc45ddf --- /dev/null +++ b/ios/chrome/browser/ui/follow/follow_action_state.h
@@ -0,0 +1,21 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FOLLOW_FOLLOW_ACTION_STATE_H_ +#define IOS_CHROME_BROWSER_UI_FOLLOW_FOLLOW_ACTION_STATE_H_ + +#import <Foundation/Foundation.h> + +// The state of the "Follow" action. e.g. The state the Follow button in the +// Overflow menu. +typedef NS_ENUM(NSInteger, FollowActionState) { + // "Follow" action is hidden. + FollowActionStateHidden, + // "Follow" action is shown but disabled. + FollowActionStateDisabled, + // "Follow" action is shown and enabled. + FollowActionStateEnabld, +}; + +#endif // IOS_CHROME_BROWSER_UI_FOLLOW_FOLLOW_ACTION_STATE_H_
diff --git a/ios/chrome/browser/ui/follow/follow_util.h b/ios/chrome/browser/ui/follow/follow_util.h new file mode 100644 index 0000000..b1f48f6 --- /dev/null +++ b/ios/chrome/browser/ui/follow/follow_util.h
@@ -0,0 +1,20 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FOLLOW_FOLLOW_UTIL_H_ +#define IOS_CHROME_BROWSER_UI_FOLLOW_FOLLOW_UTIL_H_ + +#import "ios/chrome/browser/ui/follow/follow_action_state.h" + +namespace web { +class WebState; +} + +class ChromeBrowserState; + +// Returns the Follow action state for |webState| and |browserState|. +FollowActionState GetFollowActionState(web::WebState* webState, + ChromeBrowserState* browserState); + +#endif // IOS_CHROME_BROWSER_UI_FOLLOW_FOLLOW_UTIL_H_
diff --git a/ios/chrome/browser/ui/follow/follow_util.mm b/ios/chrome/browser/ui/follow/follow_util.mm new file mode 100644 index 0000000..e362b41 --- /dev/null +++ b/ios/chrome/browser/ui/follow/follow_util.mm
@@ -0,0 +1,45 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/follow/follow_util.h" + +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/signin/authentication_service.h" +#import "ios/chrome/browser/signin/authentication_service_factory.h" +#import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" +#include "ios/web/public/web_client.h" +#import "ios/web/public/web_state.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +FollowActionState GetFollowActionState(web::WebState* webState, + ChromeBrowserState* browserState) { + // This method should be called only if the feature flag has been enabled. + DCHECK(IsWebChannelsEnabled()); + + if (!webState) { + return FollowActionStateHidden; + } + const GURL& URL = webState->GetLastCommittedURL(); + // Show the follow action when: + // 1. The page url is valid; + // 2. Users are not on NTP or Chrome internal pages. + if (URL.is_valid() && !web::GetWebClient()->IsAppSpecificURL(URL)) { + AuthenticationService* authenticationService = + AuthenticationServiceFactory::GetForBrowserState(browserState); + // Enable the follow action when: + // 1. Users are not in incognito mode; + // 2. Users have signed in. + if (!browserState->IsOffTheRecord() && + authenticationService->GetPrimaryIdentity( + signin::ConsentLevel::kSignin)) { + return FollowActionStateEnabld; + } + return FollowActionStateDisabled; + } + return FollowActionStateHidden; +}
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 59fed81..664274c 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 @@ -9e047a28d10f5b853fe0dfb64fe67d179099152c \ No newline at end of file +95a39bd853c4a850d82d434b322533a2cf0590f9 \ 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 63ebf9d..e18454d 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 @@ -aa6edb01f2b107a0938adafd8d8463176f4042ce \ No newline at end of file +8a38987169ae6e831b0e4d3ca88e0d73fd9f2fd6 \ 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 683486a..a4038fa 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 @@ -e59d5b4441830b3d9a0b7354e54fab8015e9bb87 \ No newline at end of file +cb3396a7bd4c91fb3774082f210707b7665756f6 \ 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 f3afa38d..2d9c89d 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 @@ -10f1152b1c97d9b515f624b9d05e1c9a114a3646 \ No newline at end of file +ae92db71fb0111f45ad7cae7e1e6f8f20d88ad5f \ 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 8143ab6c..6500f2e 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 @@ -dba0d452b306e945bb03337b860ca2adaa2a8247 \ No newline at end of file +5f6ca1c0036a0369cc56e6c9a47268dc2c83eaa6 \ 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 89abbda..0da7cee0 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 @@ -9fb8cc2a92e61c92e0990275a09d043d27e2fd96 \ No newline at end of file +024b670b5a6e00d74e56ab72c3f43e118c4638be \ 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 22fd1f6..06d389d4 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 @@ -54582bcfc5760d57cca499bbc7a2566f8058aa48 \ No newline at end of file +07589b09e0a517c5b802cb6124c195c01499120c \ 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 d216e14..cbf3f39 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 @@ -fb14c686c6bb3a097b99b910f312ea1cc16ebf5a \ No newline at end of file +449afd79f99e49c767c89cdc901bacd9a549a930 \ 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 0ff8a20..bb01fcc 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 @@ -8d7b0af697109952d9761d1c320aa9b144e88864 \ No newline at end of file +5bdaec458dab64e911682eda7f4a1db4396939f3 \ 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 912566d..9eb08154 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 @@ -0c626e59c734eecd29969a07dceefa9b6d8caa2c \ No newline at end of file +5d35711ca11e6a3157dea16a298372c89441ebb6 \ No newline at end of file
diff --git a/media/BUILD.gn b/media/BUILD.gn index 81e70ad..732da98 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -37,6 +37,7 @@ "ENABLE_HLS_DEMUXER=$enable_hls_demuxer", "ENABLE_LIBGAV1_DECODER=$enable_libgav1_decoder", "ENABLE_LIBRARY_CDMS=$enable_library_cdms", + "ENABLE_LIBAOM=$enable_libaom", "ENABLE_LIBVPX=$media_use_libvpx", "ENABLE_LOGGING_OVERRIDE=$enable_logging_override", "ENABLE_MEDIA_DRM_STORAGE=$enable_media_drm_storage",
diff --git a/media/DEPS b/media/DEPS index 380bdc8eb..0cd29bc 100644 --- a/media/DEPS +++ b/media/DEPS
@@ -17,6 +17,7 @@ "+third_party/re2", "+third_party/dav1d", "+third_party/ffmpeg", + "+third_party/libaom", "+third_party/libdrm", "+third_party/libgav1", "+third_party/libvpx",
diff --git a/media/gpu/v4l2/test/v4l2_ioctl_shim.cc b/media/gpu/v4l2/test/v4l2_ioctl_shim.cc index 861e22ca..4a535a9 100644 --- a/media/gpu/v4l2/test/v4l2_ioctl_shim.cc +++ b/media/gpu/v4l2/test/v4l2_ioctl_shim.cc
@@ -49,7 +49,8 @@ V4L2_REQUEST_CODE_AND_STRING(VIDIOC_STREAMON), V4L2_REQUEST_CODE_AND_STRING(VIDIOC_S_EXT_CTRLS), V4L2_REQUEST_CODE_AND_STRING(MEDIA_IOC_REQUEST_ALLOC), - V4L2_REQUEST_CODE_AND_STRING(MEDIA_REQUEST_IOC_QUEUE)}; + V4L2_REQUEST_CODE_AND_STRING(MEDIA_REQUEST_IOC_QUEUE), + V4L2_REQUEST_CODE_AND_STRING(MEDIA_REQUEST_IOC_REINIT)}; // Finds corresponding defined V4L2 request code name // for a given V4L2 request code value. @@ -251,7 +252,8 @@ template <> bool V4L2IoctlShim::Ioctl(int request_code, int arg) const { - DCHECK(request_code == static_cast<int>(MEDIA_REQUEST_IOC_QUEUE)); + DCHECK(request_code == static_cast<int>(MEDIA_REQUEST_IOC_QUEUE) || + request_code == static_cast<int>(MEDIA_REQUEST_IOC_REINIT)); const int ret = ioctl(arg, request_code); @@ -471,8 +473,6 @@ } bool V4L2IoctlShim::MediaIocRequestAlloc(int* media_request_fd) const { - // TODO(stevecho): need to use the file descriptor representing the request - // for MEDIA_REQUEST_IOC_QUEUE() call to queue to the request. LOG_ASSERT(media_request_fd != nullptr) << "|media_request_fd| check failed.\n"; @@ -495,6 +495,15 @@ return ret; } +bool V4L2IoctlShim::MediaRequestIocReinit( + const std::unique_ptr<V4L2Queue>& queue) const { + int req_fd = queue->media_request_fd(); + + const bool ret = Ioctl(MEDIA_REQUEST_IOC_REINIT, req_fd); + + return ret; +} + bool V4L2IoctlShim::QueryFormat(enum v4l2_buf_type type, uint32_t fourcc) const { struct v4l2_fmtdesc fmtdesc;
diff --git a/media/gpu/v4l2/test/v4l2_ioctl_shim.h b/media/gpu/v4l2/test/v4l2_ioctl_shim.h index 4ce56c2..cc9dcfc 100644 --- a/media/gpu/v4l2/test/v4l2_ioctl_shim.h +++ b/media/gpu/v4l2/test/v4l2_ioctl_shim.h
@@ -174,6 +174,10 @@ bool MediaRequestIocQueue(const std::unique_ptr<V4L2Queue>& queue) const WARN_UNUSED_RESULT; + // Re-initializes the previously allocated request for reuse. + bool MediaRequestIocReinit(const std::unique_ptr<V4L2Queue>& queue) const + WARN_UNUSED_RESULT; + // Verifies |v4l_fd| supports |compressed_format| for OUTPUT queues // and |uncompressed_format| for CAPTURE queues, respectively. bool VerifyCapabilities(uint32_t compressed_format,
diff --git a/media/gpu/v4l2/test/vp9_decoder.cc b/media/gpu/v4l2/test/vp9_decoder.cc index f50e2f19..4e66fadf 100644 --- a/media/gpu/v4l2/test/vp9_decoder.cc +++ b/media/gpu/v4l2/test/vp9_decoder.cc
@@ -418,6 +418,9 @@ // TODO(stevecho): call RefreshReferenceSlots() once decoded buffer is ready. + if (!v4l2_ioctl_->MediaRequestIocReinit(OUTPUT_queue_)) + LOG(ERROR) << "MEDIA_REQUEST_IOC_REINIT failed."; + return Vp9Decoder::kOk; }
diff --git a/media/media_options.gni b/media/media_options.gni index 2f3ad54..7462349 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -9,6 +9,7 @@ import("//build/config/features.gni") import("//media/gpu/args.gni") import("//testing/libfuzzer/fuzzer_test.gni") +import("//third_party/libaom/options.gni") import("//third_party/libgav1/options.gni") declare_args() {
diff --git a/media/renderers/BUILD.gn b/media/renderers/BUILD.gn index 00083fe..e240678c 100644 --- a/media/renderers/BUILD.gn +++ b/media/renderers/BUILD.gn
@@ -76,6 +76,8 @@ "win/media_foundation_source_wrapper.h", "win/media_foundation_stream_wrapper.cc", "win/media_foundation_stream_wrapper.h", + "win/media_foundation_texture_pool.cc", + "win/media_foundation_texture_pool.h", "win/media_foundation_video_stream.cc", "win/media_foundation_video_stream.h", ] @@ -146,6 +148,7 @@ sources += [ "win/media_foundation_renderer_integration_test.cc", "win/media_foundation_renderer_unittest.cc", + "win/media_foundation_texture_pool_unittest.cc", ] deps += [ "//media/test:pipeline_integration_test_base" ] libs = [
diff --git a/media/renderers/win/media_foundation_renderer.cc b/media/renderers/win/media_foundation_renderer.cc index 3180b36..f0c8be5 100644 --- a/media/renderers/win/media_foundation_renderer.cc +++ b/media/renderers/win/media_foundation_renderer.cc
@@ -27,6 +27,7 @@ #include "media/base/cdm_context.h" #include "media/base/media_log.h" #include "media/base/timestamp_constants.h" +#include "media/base/win/dxgi_device_manager.h" #include "media/base/win/mf_helpers.h" #include "media/base/win/mf_initializer.h" @@ -184,6 +185,30 @@ if (dxgi_device_manager_) { RETURN_IF_FAILED(creation_attributes->SetUnknown( MF_MEDIA_ENGINE_DXGI_MANAGER, dxgi_device_manager_.Get())); + + // TODO(crbug.com/1276067): We'll investigate scenarios to see if we can use + // the on-screen video window size and not the native video size. + if (in_frame_server_mode_) { + gfx::Size max_video_size; + bool has_video = false; + for (auto* stream : media_resource->GetAllStreams()) { + if (stream->type() == media::DemuxerStream::VIDEO) { + has_video = true; + gfx::Size video_size = stream->video_decoder_config().natural_size(); + if (video_size.height() > max_video_size.height()) { + max_video_size.set_height(video_size.height()); + } + + if (video_size.width() > max_video_size.width()) { + max_video_size.set_width(video_size.width()); + } + } + } + + if (has_video) { + RETURN_IF_FAILED(InitializeTexturePool(max_video_size)); + } + } } RETURN_IF_FAILED( @@ -492,6 +517,29 @@ std::move(callback).Run(true); } +HRESULT MediaFoundationRenderer::InitializeTexturePool(const gfx::Size& size) { + DXGIDeviceScopedHandle dxgi_device_handle(dxgi_device_manager_.Get()); + ComPtr<ID3D11Device> d3d11_device = dxgi_device_handle.GetDevice(); + + if (d3d11_device.Get() == nullptr) { + return E_UNEXPECTED; + } + + // TODO(crbug.com/1276067): change |size| to instead use the required + // size of the output (for example if the video is only 1280x720 instead + // of a source frame of 1920x1080 we'd use the 1280x720 texture size). + // However we also need to investigate the scenario of WebGL and 360 video + // where they need the original frame size instead of the window size due + // to later image processing. + auto callback = [](std::vector<MediaFoundationFrameInfo> frame_textures, + const gfx::Size& texture_size) {}; + + RETURN_IF_FAILED(texture_pool_.Initialize( + d3d11_device.Get(), base::BindRepeating(callback), size)); + + return S_OK; +} + HRESULT MediaFoundationRenderer::UpdateVideoStream(const gfx::Rect& rect) { ComPtr<IMFMediaEngineEx> mf_media_engine_ex; RETURN_IF_FAILED(mf_media_engine_.As(&mf_media_engine_ex)); @@ -734,6 +782,10 @@ ignore_result(UpdateVideoStream(test_rect)); } + if (in_frame_server_mode_) { + InitializeTexturePool(native_video_size_); + } + renderer_client_->OnVideoNaturalSizeChange(native_video_size_); }
diff --git a/media/renderers/win/media_foundation_renderer.h b/media/renderers/win/media_foundation_renderer.h index 64933657..64b20d7 100644 --- a/media/renderers/win/media_foundation_renderer.h +++ b/media/renderers/win/media_foundation_renderer.h
@@ -29,6 +29,7 @@ #include "media/renderers/win/media_foundation_protection_manager.h" #include "media/renderers/win/media_foundation_renderer_extension.h" #include "media/renderers/win/media_foundation_source_wrapper.h" +#include "media/renderers/win/media_foundation_texture_pool.h" namespace media { @@ -119,7 +120,7 @@ HRESULT SetSourceOnMediaEngine(); HRESULT UpdateVideoStream(const gfx::Rect& rect); HRESULT PauseInternal(); - + HRESULT InitializeTexturePool(const gfx::Size& size); void OnVideoNaturalSizeChange(); // Renderer methods are running in the same sequence. @@ -139,7 +140,7 @@ Microsoft::WRL::ComPtr<MediaEngineExtension> mf_media_engine_extension_; Microsoft::WRL::ComPtr<MediaFoundationSourceWrapper> mf_source_; // This enables MFMediaEngine to use hardware acceleration for video decoding - // and vdieo processing. + // and video processing. Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> dxgi_device_manager_; // Current duration of the media. @@ -172,6 +173,16 @@ Microsoft::WRL::ComPtr<MediaFoundationProtectionManager> content_protection_manager_; + // Texture pool of ID3D11Texture2D for the media engine to draw video frames + // when the media engine is in frame server mode instead of Direct + // Composition mode. + MediaFoundationTexturePool texture_pool_; + + // When in frame server mode we need to manage the DX textures and provide + // frames to the renderer. + // Disabled until we move + bool in_frame_server_mode_ = false; + // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<MediaFoundationRenderer> weak_factory_{this}; };
diff --git a/media/renderers/win/media_foundation_texture_pool.cc b/media/renderers/win/media_foundation_texture_pool.cc new file mode 100644 index 0000000..8aeead3 --- /dev/null +++ b/media/renderers/win/media_foundation_texture_pool.cc
@@ -0,0 +1,130 @@ +// 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 <dxgi1_2.h> + +#include "media/base/win/mf_helpers.h" +#include "media/renderers/win/media_foundation_texture_pool.h" + +namespace { + +using Microsoft::WRL::ComPtr; + +// The Texture Count was determined empirically initially having a count of 30 +// and running many different video presentations in frame server mode and +// recording the number of textures in use and the count never exceeded 2. +// Therefore for a max of 2 in flight with the 3 being written requires that +// we allocate 3 textures. +constexpr int kTexturePoolCount = 3; + +} // namespace + +namespace media { + +MediaFoundationFrameInfo::MediaFoundationFrameInfo() = default; +MediaFoundationFrameInfo::~MediaFoundationFrameInfo() = default; +MediaFoundationFrameInfo::MediaFoundationFrameInfo( + MediaFoundationFrameInfo&& other) = default; + +MediaFoundationTexturePool::TextureInfo::TextureInfo() + : texture_in_use_(false) {} +MediaFoundationTexturePool::TextureInfo::~TextureInfo() = default; +MediaFoundationTexturePool::TextureInfo::TextureInfo(const TextureInfo& other) = + default; +MediaFoundationTexturePool::TextureInfo& +MediaFoundationTexturePool::TextureInfo::operator=( + const MediaFoundationTexturePool::TextureInfo& other) = default; + +MediaFoundationTexturePool::MediaFoundationTexturePool() = default; +MediaFoundationTexturePool::~MediaFoundationTexturePool() = default; + +// TODO(crbug.com/1278157): The pool should release the textures when the media +// engine is idling to save resources. +HRESULT MediaFoundationTexturePool::Initialize( + ID3D11Device* device, + FramePoolInitializedCallback frame_pool_cb, + const gfx::Size& frame_size) { + D3D11_TEXTURE2D_DESC desc{ + static_cast<UINT>(frame_size.width()), + static_cast<UINT>(frame_size.height()), + 1, + 1, + // TODO(crbug.com/1276134): Need to handle higher bit-depths like HDR. + DXGI_FORMAT_R8G8B8A8_UNORM, + {1, 0}, + D3D11_USAGE_DEFAULT, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + 0, + D3D11_RESOURCE_MISC_SHARED_NTHANDLE | + D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX}; + + std::vector<MediaFoundationFrameInfo> frame_infos; + bool callback_is_valid = !frame_pool_cb.is_null(); + if (callback_is_valid) { + frame_infos.reserve(kTexturePoolCount); + } + + // We can be reinitialized so remove all the previous textures from our + // pool. + texture_pool_.clear(); + + for (int i = 0; i < kTexturePoolCount; ++i) { + auto texture_info_element = std::make_unique<TextureInfo>(); + auto texture_token = base::UnguessableToken::Create(); + + ComPtr<ID3D11Texture2D> d3d11_video_frame; + RETURN_IF_FAILED( + device->CreateTexture2D(&desc, nullptr, &d3d11_video_frame)); + SetDebugName(d3d11_video_frame.Get(), "Media_MFFrameServerMode_Pool"); + + ComPtr<IDXGIResource1> d3d11_video_frame_resource; + RETURN_IF_FAILED(d3d11_video_frame.As(&d3d11_video_frame_resource)); + + HANDLE shared_texture_handle; + RETURN_IF_FAILED(d3d11_video_frame_resource->CreateSharedHandle( + nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, + nullptr, &shared_texture_handle)); + + base::win::ScopedHandle scoped_shared_texture_handle; + scoped_shared_texture_handle.Set(shared_texture_handle); + shared_texture_handle = nullptr; + texture_pool_[texture_token].texture_ = std::move(d3d11_video_frame); + texture_pool_[texture_token].texture_in_use_ = false; + + if (callback_is_valid) { + MediaFoundationFrameInfo frame_info; + frame_info.dxgi_handle = std::move(scoped_shared_texture_handle); + frame_info.token = texture_token; + frame_infos.emplace_back(std::move(frame_info)); + } + } + + if (callback_is_valid) { + frame_pool_cb.Run(std::move(frame_infos), frame_size); + } + + return S_OK; +} + +ComPtr<ID3D11Texture2D> MediaFoundationTexturePool::AcquireTexture( + base::UnguessableToken* texture_token) { + for (auto& texture_item : texture_pool_) { + if (!texture_item.second.texture_in_use_) { + *texture_token = texture_item.first; + texture_item.second.texture_in_use_ = true; + return texture_item.second.texture_; + } + } + + return nullptr; +} + +void MediaFoundationTexturePool::ReleaseTexture( + const base::UnguessableToken& texture_token) { + if (texture_pool_.count(texture_token) > 0) { + texture_pool_.at(texture_token).texture_in_use_ = false; + } +} + +} // namespace media \ No newline at end of file
diff --git a/media/renderers/win/media_foundation_texture_pool.h b/media/renderers/win/media_foundation_texture_pool.h new file mode 100644 index 0000000..fe01055 --- /dev/null +++ b/media/renderers/win/media_foundation_texture_pool.h
@@ -0,0 +1,79 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_TEXTURE_POOL_H_ +#define MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_TEXTURE_POOL_H_ + +#include <d3d11.h> +#include <wrl/client.h> +#include <map> + +#include "base/callback.h" +#include "base/containers/flat_map.h" +#include "base/unguessable_token.h" +#include "base/win/scoped_handle.h" +#include "media/base/media_export.h" +#include "ui/gfx/geometry/size.h" + +namespace media { + +struct MEDIA_EXPORT MediaFoundationFrameInfo { + MediaFoundationFrameInfo(); + ~MediaFoundationFrameInfo(); + MediaFoundationFrameInfo(MediaFoundationFrameInfo&& other); + base::win::ScopedHandle dxgi_handle; + base::UnguessableToken token; +}; + +using FramePoolInitializedCallback = base::RepeatingCallback<void( + std::vector<MediaFoundationFrameInfo> frame_textures, + const gfx::Size& texture_size)>; + +// This object will create a pool D3D11Texture2Ds that the video frames in the +// Media Foundation Media Engine will draw to. By having this pool we don't +// need to create a D3D11Texture2D and associated Shared Image mailbox for +// each video frame. To coordinate the Shared Images in the +// MediaFoundationRendererClient each texture has a |texture_token| to signal +// which texture is ready to be displayed and which texture is ready for +// reuse. +class MEDIA_EXPORT MediaFoundationTexturePool { + public: + MediaFoundationTexturePool(); + ~MediaFoundationTexturePool(); + MediaFoundationTexturePool(const MediaFoundationTexturePool& other) = delete; + MediaFoundationTexturePool& operator=( + const MediaFoundationTexturePool& other) = delete; + + // Initializes the texture pool with a specific size. Once the textures are + // created the callback will be called passing the information about the + // textures. The method can be called multiple times, which will release the + // previously allocated textures and create a new set of textures on the + // device with the frame size. + // Any event that changes the frame size will be calling this method to + // change the texture size. The callback will eventually call into the Media + // Foundation Renderer which will create the Shared Images with the DX shared + // handle. Examples of callers are CreateMediaEngine and + // OnVideoNaturalSizeChange in the MediaFoundationRenderer + HRESULT Initialize(ID3D11Device* device, + FramePoolInitializedCallback frame_pool_cb, + const gfx::Size& frame_size); + Microsoft::WRL::ComPtr<ID3D11Texture2D> AcquireTexture( + base::UnguessableToken* texture_token); + void ReleaseTexture(const base::UnguessableToken& texture_token); + + private: + struct TextureInfo { + TextureInfo(); + ~TextureInfo(); + TextureInfo(const TextureInfo& other); + TextureInfo& operator=(const TextureInfo& other); + + Microsoft::WRL::ComPtr<ID3D11Texture2D> texture_; + bool texture_in_use_; + }; + + base::flat_map<base::UnguessableToken, TextureInfo> texture_pool_; +}; +} // namespace media +#endif \ No newline at end of file
diff --git a/media/renderers/win/media_foundation_texture_pool_unittest.cc b/media/renderers/win/media_foundation_texture_pool_unittest.cc new file mode 100644 index 0000000..f4b7939 --- /dev/null +++ b/media/renderers/win/media_foundation_texture_pool_unittest.cc
@@ -0,0 +1,542 @@ +// 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 "media/renderers/win/media_foundation_texture_pool.h" + +#include "base/test/mock_callback.h" +#include "base/test/task_environment.h" +#include "media/base/mock_filters.h" +#include "media/base/test_helpers.h" +#include "media/base/win/test_utils.h" + +#include <d3d11.h> +#include <dxgi1_2.h> +#include <wrl/client.h> + +using Microsoft::WRL::ComPtr; + +namespace media { +class MockD3D11Texture2D; + +class MockD3D11Resource final : public IDXGIResource1 { + public: + MockD3D11Resource() {} + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, + void** ppvObject) override; + ULONG STDMETHODCALLTYPE AddRef(void) override { + return InterlockedIncrement(&refcount_); + } + + ULONG STDMETHODCALLTYPE Release(void) override { + ULONG refcount = InterlockedDecrement(&refcount_); + if (refcount == 0) { + refcount_ = 0xBAADF00D; + delete this; + } + return refcount; + } + + // IDXGIResource1 + HRESULT STDMETHODCALLTYPE + CreateSubresourceSurface(UINT index, IDXGISurface2** ppSurface) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateSharedHandle(const SECURITY_ATTRIBUTES* pAttributes, + DWORD dwAccess, + LPCWSTR lpName, + HANDLE* pHandle) override; + + // IDXGIResource + HRESULT STDMETHODCALLTYPE GetSharedHandle(HANDLE* pSharedHandle) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE GetUsage(DXGI_USAGE* pUsage) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + SetEvictionPriority(UINT eviction_priority) override; + HRESULT STDMETHODCALLTYPE + GetEvictionPriority(UINT* eviction_priority) override; + + // IDXGIDeviceSubObject + HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void** ppDevice) override { + return E_NOTIMPL; + } + + // IDXGIObject + HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void** ppParent) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID guid, + UINT* pDataSize, + void* pData) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid, + UINT DataSize, + const void* pData) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + SetPrivateDataInterface(REFGUID guid, const IUnknown* pData) override; + + private: + MockD3D11Texture2D* parent_; + volatile ULONG refcount_ = 1; +}; + +class MockD3D11Texture2D final : public ID3D11Texture2D { + private: + MockD3D11Texture2D(const D3D11_TEXTURE2D_DESC* texture_description) + : resource_(new MockD3D11Resource()) { + memcpy(&texture_description_, texture_description, + sizeof(D3D11_TEXTURE2D_DESC)); + } + + public: + static HRESULT CreateInstance(const D3D11_TEXTURE2D_DESC* texture_description, + ID3D11Texture2D** texture2D); + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, + void** ppvObject) override { + if (ppvObject == nullptr) { + return E_POINTER; + } + if (FAILED(QueryInterfaceInternal(riid, ppvObject))) { + if (resource_ != nullptr) + return resource_->QueryInterface(riid, ppvObject); + else + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE QueryInterfaceInternal(REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) { + return E_POINTER; + } + + if (riid == IID_ID3D11Texture2D || riid == IID_IUnknown) { + *ppvObject = static_cast<ID3D11Texture2D*>(this); + } else if (riid == IID_ID3D11Resource) { + *ppvObject = static_cast<ID3D11Resource*>(this); + } else if (riid == IID_ID3D11DeviceChild) { + *ppvObject = static_cast<ID3D11DeviceChild*>(this); + } else { + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; + } + + ULONG STDMETHODCALLTYPE AddRef(void) override { + return InterlockedIncrement(&refcount_); + } + + ULONG STDMETHODCALLTYPE Release(void) override { + ULONG refcount = InterlockedDecrement(&refcount_); + if (refcount == 0) { + refcount_ = 0xBAADF00D; + delete this; + } + return refcount; + } + + // ID3D11Texture2D + void STDMETHODCALLTYPE GetDesc(D3D11_TEXTURE2D_DESC* description) override { + memset(description, 0, sizeof(D3D11_TEXTURE2D_DESC)); + } + + // ID3D11Resource + void STDMETHODCALLTYPE + GetType(D3D11_RESOURCE_DIMENSION* resource_dimension) override { + *resource_dimension = + D3D11_RESOURCE_DIMENSION::D3D11_RESOURCE_DIMENSION_TEXTURE2D; + } + void STDMETHODCALLTYPE SetEvictionPriority(UINT eviction_priority) override { + eviction_priority_ = eviction_priority; + } + UINT STDMETHODCALLTYPE GetEvictionPriority() override { + return eviction_priority_; + } + + // ID3D11DeviceChild + void STDMETHODCALLTYPE GetDevice(ID3D11Device** ppDevice) override { + device_.CopyTo(ppDevice); + } + HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID guid, + UINT* pDataSize, + void* pData) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid, + UINT DataSize, + const void* pData) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + SetPrivateDataInterface(REFGUID guid, const IUnknown* pData) override { + // Our tests aren't checking for this right now + return S_OK; + } + + private: + volatile ULONG refcount_ = 1; + UINT eviction_priority_ = 0; + D3D11_TEXTURE2D_DESC texture_description_; + ComPtr<ID3D11Device> device_; + ComPtr<IDXGIResource1> resource_; +}; + +class MockD3D11Device : public ID3D11Device { + public: + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, + void** ppvObject) override { + if (ppvObject == nullptr) { + return E_POINTER; + } + + if (riid == IID_ID3D11Device || riid == IID_IUnknown) { + *ppvObject = this; + return S_OK; + } + + return E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef(void) override { return 1; } + ULONG STDMETHODCALLTYPE Release(void) override { return 1; } + + HRESULT STDMETHODCALLTYPE + CreateBuffer(const D3D11_BUFFER_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Buffer** ppBuffer) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateTexture1D(const D3D11_TEXTURE1D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture1D** ppTexture1D) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateTexture2D(const D3D11_TEXTURE2D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture2D** ppTexture2D) override; + HRESULT STDMETHODCALLTYPE + CreateTexture3D(const D3D11_TEXTURE3D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture3D** ppTexture3D) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateShaderResourceView(ID3D11Resource* pResource, + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + ID3D11ShaderResourceView** ppSRView) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateUnorderedAccessView(ID3D11Resource* pResource, + const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc, + ID3D11UnorderedAccessView** ppUAView) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateRenderTargetView(ID3D11Resource* pResource, + const D3D11_RENDER_TARGET_VIEW_DESC* pDesc, + ID3D11RenderTargetView** ppRTView) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateDepthStencilView(ID3D11Resource* pResource, + const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc, + ID3D11DepthStencilView** ppDepthStencilView) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateInputLayout(const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs, + UINT NumElements, + const void* pShaderBytecodeWithInputSignature, + SIZE_T BytecodeLength, + ID3D11InputLayout** ppInputLayout) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateVertexShader(const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11VertexShader** ppVertexShader) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateGeometryShader(const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11GeometryShader** ppGeometryShader) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput( + const void* pShaderBytecode, + SIZE_T BytecodeLength, + const D3D11_SO_DECLARATION_ENTRY* pSODeclaration, + UINT NumEntries, + const UINT* pBufferStrides, + UINT NumStrides, + UINT RasterizedStream, + ID3D11ClassLinkage* pClassLinkage, + ID3D11GeometryShader** ppGeometryShader) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreatePixelShader(const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11PixelShader** ppPixelShader) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateHullShader(const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11HullShader** ppHullShader) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateDomainShader(const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11DomainShader** ppDomainShader) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateComputeShader(const void* pShaderBytecode, + SIZE_T BytecodeLength, + ID3D11ClassLinkage* pClassLinkage, + ID3D11ComputeShader** ppComputeShader) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateClassLinkage(ID3D11ClassLinkage** ppLinkage) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateBlendState(const D3D11_BLEND_DESC* pBlendStateDesc, + ID3D11BlendState** ppBlendState) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE CreateDepthStencilState( + const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc, + ID3D11DepthStencilState** ppDepthStencilState) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateRasterizerState(const D3D11_RASTERIZER_DESC* pRasterizerDesc, + ID3D11RasterizerState** ppRasterizerState) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateSamplerState(const D3D11_SAMPLER_DESC* pSamplerDesc, + ID3D11SamplerState** ppSamplerState) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE CreateQuery(const D3D11_QUERY_DESC* pQueryDesc, + ID3D11Query** ppQuery) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreatePredicate(const D3D11_QUERY_DESC* pPredicateDesc, + ID3D11Predicate** ppPredicate) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateCounter(const D3D11_COUNTER_DESC* pCounterDesc, + ID3D11Counter** ppCounter) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CreateDeferredContext(UINT ContextFlags, + ID3D11DeviceContext** ppDeferredContext) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE OpenSharedResource(HANDLE hResource, + REFIID ReturnedInterface, + void** ppResource) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE CheckFormatSupport(DXGI_FORMAT Format, + UINT* pFormatSupport) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CheckMultisampleQualityLevels(DXGI_FORMAT Format, + UINT SampleCount, + UINT* pNumQualityLevels) override { + return E_NOTIMPL; + } + void STDMETHODCALLTYPE + CheckCounterInfo(D3D11_COUNTER_INFO* pCounterInfo) override {} + HRESULT STDMETHODCALLTYPE CheckCounter(const D3D11_COUNTER_DESC* pDesc, + D3D11_COUNTER_TYPE* pType, + UINT* pActiveCounters, + LPSTR szName, + UINT* pNameLength, + LPSTR szUnits, + UINT* pUnitsLength, + LPSTR szDescription, + UINT* pDescriptionLength) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + CheckFeatureSupport(D3D11_FEATURE Feature, + void* pFeatureSupportData, + UINT FeatureSupportDataSize) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID guid, + UINT* pDataSize, + void* pData) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid, + UINT DataSize, + const void* pData) override { + return E_NOTIMPL; + } + HRESULT STDMETHODCALLTYPE + SetPrivateDataInterface(REFGUID guid, const IUnknown* pData) override { + return E_NOTIMPL; + } + D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void) override { + return D3D_FEATURE_LEVEL_11_1; + } + UINT STDMETHODCALLTYPE GetCreationFlags(void) override { return 0; } + HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void) override { + return E_NOTIMPL; + } + void STDMETHODCALLTYPE + GetImmediateContext(ID3D11DeviceContext** ppImmediateContext) override {} + HRESULT STDMETHODCALLTYPE SetExceptionMode(UINT RaiseFlags) override { + return E_NOTIMPL; + } + UINT STDMETHODCALLTYPE GetExceptionMode(void) override { return 0; } +}; + +// MockD3D11Resource +HRESULT STDMETHODCALLTYPE MockD3D11Resource::QueryInterface(REFIID riid, + void** ppvObject) { + if (ppvObject == nullptr) { + return E_POINTER; + } + + if (riid == IID_IDXGIResource1) { + *ppvObject = static_cast<IDXGIResource1*>(this); + } else if (riid == IID_IDXGIResource) { + *ppvObject = static_cast<IDXGIResource*>(this); + } else if (riid == IID_IDXGIDeviceSubObject) { + *ppvObject = static_cast<IDXGIDeviceSubObject*>(this); + } else if (riid == IID_IDXGIObject) { + *ppvObject = static_cast<IDXGIObject*>(this); + } else if (parent_ != nullptr) { + return parent_->QueryInterfaceInternal(riid, ppvObject); + } else { + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +MockD3D11Resource::SetEvictionPriority(UINT eviction_priority) { + parent_->SetEvictionPriority(eviction_priority); + return S_OK; +} +HRESULT STDMETHODCALLTYPE +MockD3D11Resource::GetEvictionPriority(UINT* eviction_priority) { + *eviction_priority = parent_->GetEvictionPriority(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +MockD3D11Resource::SetPrivateDataInterface(REFGUID guid, + const IUnknown* pData) { + return parent_->SetPrivateDataInterface(guid, pData); +} + +HRESULT STDMETHODCALLTYPE +MockD3D11Resource::CreateSharedHandle(const SECURITY_ATTRIBUTES* pAttributes, + DWORD dwAccess, + LPCWSTR lpName, + HANDLE* pHandle) { + // Using an event to create a valid nt handle + *pHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (*pHandle == nullptr) { + return HRESULT_FROM_WIN32(GetLastError()); + } + return S_OK; +} + +HRESULT MockD3D11Texture2D::CreateInstance( + const D3D11_TEXTURE2D_DESC* texture_description, + ID3D11Texture2D** texture2D) { + MockD3D11Texture2D* mock_texture = + new MockD3D11Texture2D(texture_description); + if (!mock_texture) { + return E_OUTOFMEMORY; + } + + *texture2D = mock_texture; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +MockD3D11Device::CreateTexture2D(const D3D11_TEXTURE2D_DESC* pDesc, + const D3D11_SUBRESOURCE_DATA* pInitialData, + ID3D11Texture2D** ppTexture2D) { + return MockD3D11Texture2D::CreateInstance(pDesc, ppTexture2D); +} + +class MediaFoundationTexturePoolTest : public testing::Test { + public: + MediaFoundationTexturePoolTest() {} + base::WeakPtrFactory<MediaFoundationTexturePoolTest> weak_factory_{this}; +}; + +TEST_F(MediaFoundationTexturePoolTest, VerifyTextureInitialization) { + MockD3D11Device mock_d3d_device; + media::MediaFoundationTexturePool test; + base::WaitableEvent wait_event; + gfx::Size frame_size(1920, 1080); + + class SpecialCallback { + private: + base::WaitableEvent* wait_event_; + gfx::Size* frame_size_; + + public: + SpecialCallback(base::WaitableEvent* wait_event, gfx::Size* frame_size) + : wait_event_(wait_event), frame_size_(frame_size) {} + + void Invoke(std::vector<media::MediaFoundationFrameInfo> frame_textures, + const gfx::Size& texture_size) { + EXPECT_EQ(texture_size.width(), frame_size_->width()); + EXPECT_EQ(texture_size.height(), frame_size_->height()); + wait_event_->Signal(); + } + } callback(&wait_event, &frame_size); + + EXPECT_HRESULT_SUCCEEDED( + test.Initialize(&mock_d3d_device, + base::BindRepeating(&SpecialCallback::Invoke, + base::Unretained(&callback)), + frame_size)); + wait_event.Wait(); +} + +} // namespace media \ No newline at end of file
diff --git a/media/video/BUILD.gn b/media/video/BUILD.gn index a17b1df..e267390 100644 --- a/media/video/BUILD.gn +++ b/media/video/BUILD.gn
@@ -76,6 +76,15 @@ configs += [ "//media:subcomponent_config" ] + if (enable_libaom) { + sources += [ + "av1_video_encoder.cc", + "av1_video_encoder.h", + ] + + public_deps += [ "//third_party/libaom" ] + } + if (media_use_libvpx) { sources += [ "vpx_video_encoder.cc",
diff --git a/media/video/av1_video_encoder.cc b/media/video/av1_video_encoder.cc new file mode 100644 index 0000000..c1a669f --- /dev/null +++ b/media/video/av1_video_encoder.cc
@@ -0,0 +1,406 @@ +// 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 "media/video/av1_video_encoder.h" + +#include <cmath> + +#include "base/cxx17_backports.h" +#include "base/logging.h" +#include "base/numerics/checked_math.h" +#include "base/strings/stringprintf.h" +#include "base/system/sys_info.h" +#include "base/time/time.h" +#include "base/trace_event/trace_event.h" +#include "media/base/bind_to_current_loop.h" +#include "media/base/svc_scalability_mode.h" +#include "media/base/timestamp_constants.h" +#include "media/base/video_frame.h" +#include "media/base/video_util.h" +#include "third_party/libaom/source/libaom/aom/aomcx.h" +#include "third_party/libyuv/include/libyuv/convert.h" + +namespace media { + +namespace { + +void FreeCodecCtx(aom_codec_ctx_t* codec_ctx) { + if (codec_ctx->name) { + // Codec has been initialized, we need to destroy it. + auto error = aom_codec_destroy(codec_ctx); + DCHECK_EQ(error, AOM_CODEC_OK); + } + delete codec_ctx; +} + +int GetNumberOfThreads(int width) { + // Default to 1 thread for less than VGA. + int desired_threads = 1; + + if (width >= 3840) + desired_threads = 16; + else if (width >= 2560) + desired_threads = 8; + else if (width >= 1280) + desired_threads = 4; + else if (width >= 640) + desired_threads = 2; + + // Clamp to the number of available logical processors/cores. + desired_threads = + std::min(desired_threads, base::SysInfo::NumberOfProcessors()); + + return desired_threads; +} + +Status SetUpAomConfig(const VideoEncoder::Options& opts, + aom_codec_enc_cfg_t* config) { + if (opts.frame_size.width() <= 0 || opts.frame_size.height() <= 0) + return Status(StatusCode::kEncoderUnsupportedConfig, + "Negative width or height values."); + + if (!opts.frame_size.GetCheckedArea().IsValid()) + return Status(StatusCode::kEncoderUnsupportedConfig, "Frame is too large."); + + config->g_profile = 0; // main + config->g_input_bit_depth = 8; + config->g_pass = AOM_RC_ONE_PASS; + config->g_lag_in_frames = 0; + config->rc_max_quantizer = 56; + config->rc_min_quantizer = 10; + config->rc_dropframe_thresh = 0; // Don't drop frames + + config->rc_undershoot_pct = 50; + config->rc_overshoot_pct = 50; + config->rc_buf_initial_sz = 600; + config->rc_buf_optimal_sz = 600; + config->rc_buf_sz = 1000; + config->g_error_resilient = 0; + + config->g_timebase.num = 1; + config->g_timebase.den = base::Time::kMicrosecondsPerSecond; + + // Set the number of threads based on the image width and num of cores. + config->g_threads = GetNumberOfThreads(opts.frame_size.width()); + + // Insert keyframes at will with a given max interval + if (opts.keyframe_interval.has_value()) { + config->kf_mode = AOM_KF_AUTO; + config->kf_min_dist = 0; + config->kf_max_dist = opts.keyframe_interval.value(); + } + + if (opts.bitrate.has_value()) { + auto& bitrate = opts.bitrate.value(); + config->rc_target_bitrate = bitrate.target() / 1000; + switch (bitrate.mode()) { + case Bitrate::Mode::kVariable: + config->rc_end_usage = AOM_VBR; + break; + case Bitrate::Mode::kConstant: + config->rc_end_usage = AOM_CBR; + break; + } + } else { + // Default that gives about 2mbps to HD video + config->rc_end_usage = AOM_VBR; + config->rc_target_bitrate = + int{(opts.frame_size.GetCheckedArea() * 2) + .ValueOrDefault(std::numeric_limits<int>::max())}; + } + + config->g_w = opts.frame_size.width(); + config->g_h = opts.frame_size.height(); + + if (opts.scalability_mode.has_value()) { + return Status(StatusCode::kEncoderUnsupportedConfig, + "Unsupported number of temporal layers."); + } + return OkStatus(); +} + +} // namespace + +Av1VideoEncoder::Av1VideoEncoder() : codec_(nullptr, FreeCodecCtx) {} + +void Av1VideoEncoder::Initialize(VideoCodecProfile profile, + const Options& options, + OutputCB output_cb, + StatusCB done_cb) { + done_cb = BindToCurrentLoop(std::move(done_cb)); + if (codec_) { + std::move(done_cb).Run(StatusCode::kEncoderInitializeTwice); + return; + } + profile_ = profile; + if (profile < AV1PROFILE_MIN || profile > AV1PROFILE_MAX) { + auto status = Status(StatusCode::kEncoderUnsupportedProfile) + .WithData("profile", profile); + std::move(done_cb).Run(status); + return; + } + + // libaom is compiled with CONFIG_REALTIME_ONLY, so we can't use anything + // but AOM_USAGE_REALTIME. + auto error = aom_codec_enc_config_default(aom_codec_av1_cx(), &config_, + AOM_USAGE_REALTIME); + if (error != AOM_CODEC_OK) { + auto status = Status(StatusCode::kEncoderInitializationError, + "Failed to get default AOM config.") + .WithData("error_code", error); + std::move(done_cb).Run(status); + return; + } + + Status status = SetUpAomConfig(options, &config_); + if (!status.is_ok()) { + std::move(done_cb).Run(status); + return; + } + + // Initialize an encoder instance. + aom_codec_unique_ptr codec(new aom_codec_ctx_t, FreeCodecCtx); + codec->name = nullptr; + aom_codec_flags_t flags = 0; + error = aom_codec_enc_init(codec.get(), aom_codec_av1_cx(), &config_, flags); + if (error != AOM_CODEC_OK) { + status = Status(StatusCode::kEncoderInitializationError, + "aom_codec_enc_init() failed.") + .WithData("error_code", error) + .WithData("error_message", aom_codec_err_to_string(error)); + std::move(done_cb).Run(status); + return; + } + DCHECK_NE(codec->name, nullptr); + +#define CALL_AOM_CONTROL(key, value) \ + do { \ + error = aom_codec_control(codec.get(), (key), (value)); \ + if (error != AOM_CODEC_OK) { \ + status = Status(StatusCode::kEncoderInitializationError, \ + "Setting " #key " failed.") \ + .WithData("error_code", error) \ + .WithData("error_message", aom_codec_err_to_string(error)); \ + std::move(done_cb).Run(status); \ + return; \ + } \ + } while (false) + + CALL_AOM_CONTROL(AV1E_SET_ROW_MT, 1); + CALL_AOM_CONTROL(AV1E_SET_COEFF_COST_UPD_FREQ, 3); + CALL_AOM_CONTROL(AV1E_SET_MODE_COST_UPD_FREQ, 3); + CALL_AOM_CONTROL(AV1E_SET_MV_COST_UPD_FREQ, 3); + + CALL_AOM_CONTROL(AV1E_SET_ENABLE_TPL_MODEL, 0); + CALL_AOM_CONTROL(AV1E_SET_DELTAQ_MODE, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_ORDER_HINT, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_OBMC, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_WARPED_MOTION, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_GLOBAL_MOTION, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_REF_FRAME_MVS, 0); + + CALL_AOM_CONTROL(AV1E_SET_ENABLE_CFL_INTRA, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_SMOOTH_INTRA, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_ANGLE_DELTA, 0); + CALL_AOM_CONTROL(AV1E_SET_ENABLE_FILTER_INTRA, 0); + CALL_AOM_CONTROL(AV1E_SET_INTRA_DEFAULT_TX_ONLY, 1); + + if (config_.rc_end_usage == AOM_CBR) + CALL_AOM_CONTROL(AV1E_SET_AQ_MODE, 3); + + CALL_AOM_CONTROL(AV1E_SET_TILE_COLUMNS, + static_cast<int>(std::log2(config_.g_threads))); + + // AOME_SET_CPUUSED determines tradeoff between video quality and compression + // time. Valid range: 0..10. 0 runs the slowest, and 10 runs the fastest. + // Values 6 to 9 are usually used for realtime applications. Here we choose + // two sides of realtime range for our 'realtime' and 'quality' modes + // because we don't want encoding speed to drop into single digit fps + // even in quality mode. + const int cpu_speed = + (options.latency_mode == VideoEncoder::LatencyMode::Realtime) ? 9 : 7; + CALL_AOM_CONTROL(AOME_SET_CPUUSED, cpu_speed); +#undef CALL_AOM_CONTROL + + options_ = options; + originally_configured_size_ = options.frame_size; + output_cb_ = BindToCurrentLoop(std::move(output_cb)); + codec_ = std::move(codec); + std::move(done_cb).Run(OkStatus()); +} + +void Av1VideoEncoder::Encode(scoped_refptr<VideoFrame> frame, + bool key_frame, + StatusCB done_cb) { + done_cb = BindToCurrentLoop(std::move(done_cb)); + if (!codec_) { + std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + return; + } + + if (!frame) { + std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, + "No frame provided for encoding.")); + return; + } + + bool supported_format = frame->format() == PIXEL_FORMAT_NV12 || + frame->format() == PIXEL_FORMAT_I420 || + frame->format() == PIXEL_FORMAT_XBGR || + frame->format() == PIXEL_FORMAT_XRGB || + frame->format() == PIXEL_FORMAT_ABGR || + frame->format() == PIXEL_FORMAT_ARGB; + if ((!frame->IsMappable() && !frame->HasGpuMemoryBuffer()) || + !supported_format) { + Status status = + Status(StatusCode::kEncoderFailedEncode, "Unexpected frame format.") + .WithData("IsMappable", frame->IsMappable()) + .WithData("HasGpuMemoryBuffer", frame->HasGpuMemoryBuffer()) + .WithData("format", frame->format()); + std::move(done_cb).Run(std::move(status)); + return; + } + + if (frame->HasGpuMemoryBuffer()) { + frame = ConvertToMemoryMappedFrame(frame); + if (!frame) { + std::move(done_cb).Run( + Status(StatusCode::kEncoderFailedEncode, + "Convert GMB frame to MemoryMappedFrame failed.")); + return; + } + } + + const bool is_yuv = IsYuvPlanar(frame->format()); + if (frame->visible_rect().size() != options_.frame_size || !is_yuv) { + auto resized_frame = frame_pool_.CreateFrame( + is_yuv ? frame->format() : PIXEL_FORMAT_I420, options_.frame_size, + gfx::Rect(options_.frame_size), options_.frame_size, + frame->timestamp()); + Status status; + if (resized_frame) { + status = ConvertAndScaleFrame(*frame, *resized_frame, resize_buf_); + } else { + status = Status(StatusCode::kEncoderFailedEncode, + "Can't allocate a resized frame."); + } + if (!status.is_ok()) { + std::move(done_cb).Run(std::move(status)); + return; + } + frame = std::move(resized_frame); + } + + aom_image_t* image = aom_img_wrap( + &image_, AOM_IMG_FMT_I420, options_.frame_size.width(), + options_.frame_size.height(), 1, frame->data(VideoFrame::kYPlane)); + DCHECK_EQ(image, &image_); + + image->planes[AOM_PLANE_Y] = frame->visible_data(VideoFrame::kYPlane); + image->planes[AOM_PLANE_U] = frame->visible_data(VideoFrame::kUPlane); + image->planes[AOM_PLANE_V] = frame->visible_data(VideoFrame::kVPlane); + image->stride[AOM_PLANE_Y] = frame->stride(VideoFrame::kYPlane); + image->stride[AOM_PLANE_U] = frame->stride(VideoFrame::kUPlane); + image->stride[AOM_PLANE_V] = frame->stride(VideoFrame::kVPlane); + + auto duration_us = GetFrameDuration(*frame).InMicroseconds(); + last_frame_timestamp_ = frame->timestamp(); + if (last_frame_color_space_ != frame->ColorSpace()) { + last_frame_color_space_ = frame->ColorSpace(); + key_frame = true; + } + + TRACE_EVENT0("media", "aom_codec_encode"); + // Use artificial timestamps, so the encoder will not be misled by frame's + // fickle timestamps when doing rate control. + auto error = + aom_codec_encode(codec_.get(), image, artificial_timestamp_, duration_us, + key_frame ? AOM_EFLAG_FORCE_KF : 0); + artificial_timestamp_ += duration_us; + + if (error != AOM_CODEC_OK) { + auto msg = + base::StringPrintf("AOM encoding error: %s (%d)", + aom_codec_error_detail(codec_.get()), codec_->err); + DLOG(ERROR) << msg; + std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, msg)); + return; + } + DrainOutputs(frame->timestamp(), frame->ColorSpace()); + std::move(done_cb).Run(OkStatus()); +} + +void Av1VideoEncoder::ChangeOptions(const Options& options, + OutputCB output_cb, + StatusCB done_cb) { + done_cb = BindToCurrentLoop(std::move(done_cb)); + if (!codec_) { + std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + return; + } + // TODO(crbug.com/1208280) Try to actually adjust setting instead of + // immediately dismissing configuration change. + std::move(done_cb).Run(StatusCode::kEncoderUnsupportedConfig); +} + +base::TimeDelta Av1VideoEncoder::GetFrameDuration(const VideoFrame& frame) { + // Frame has duration in metadata, use it. + if (frame.metadata().frame_duration.has_value()) + return frame.metadata().frame_duration.value(); + + // Options have framerate specified, use it. + if (options_.framerate.has_value()) + return base::Seconds(1.0 / options_.framerate.value()); + + // No real way to figure out duration, use time passed since the last frame + // as an educated guess, but clamp it within reasonable limits. + constexpr auto min_duration = base::Seconds(1.0 / 60.0); + constexpr auto max_duration = base::Seconds(1.0 / 24.0); + auto duration = frame.timestamp() - last_frame_timestamp_; + return base::clamp(duration, min_duration, max_duration); +} + +void Av1VideoEncoder::DrainOutputs(base::TimeDelta ts, + gfx::ColorSpace color_space) { + const aom_codec_cx_pkt_t* pkt = nullptr; + aom_codec_iter_t iter = nullptr; + while ((pkt = aom_codec_get_cx_data(codec_.get(), &iter)) != nullptr) { + if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) + continue; + + VideoEncoderOutput result; + result.key_frame = (pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0; + result.timestamp = ts; + result.color_space = color_space; + result.size = pkt->data.frame.sz; + result.data.reset(new uint8_t[result.size]); + memcpy(result.data.get(), pkt->data.frame.buf, result.size); + output_cb_.Run(std::move(result), {}); + } +} + +Av1VideoEncoder::~Av1VideoEncoder() = default; + +void Av1VideoEncoder::Flush(StatusCB done_cb) { + done_cb = BindToCurrentLoop(std::move(done_cb)); + if (!codec_) { + std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + return; + } + + auto error = aom_codec_encode(codec_.get(), nullptr, 0, 0, 0); + + if (error != AOM_CODEC_OK) { + auto msg = + base::StringPrintf("AOM encoding error: %s (%d)", + aom_codec_error_detail(codec_.get()), codec_->err); + DLOG(ERROR) << msg; + std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, msg)); + return; + } + DrainOutputs(base::TimeDelta(), gfx::ColorSpace()); + std::move(done_cb).Run(OkStatus()); +} + +} // namespace media
diff --git a/media/video/av1_video_encoder.h b/media/video/av1_video_encoder.h new file mode 100644 index 0000000..3474ecc --- /dev/null +++ b/media/video/av1_video_encoder.h
@@ -0,0 +1,67 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_VIDEO_AV1_VIDEO_ENCODER_H_ +#define MEDIA_VIDEO_AV1_VIDEO_ENCODER_H_ + +#include <memory> +#include <vector> + +#include "base/time/time.h" +#include "media/base/media_export.h" +#include "media/base/video_encoder.h" +#include "media/base/video_frame_pool.h" +#include "third_party/libaom/source/libaom/aom/aom_encoder.h" +#include "ui/gfx/color_space.h" +#include "ui/gfx/geometry/size.h" + +namespace media { + +class MEDIA_EXPORT Av1VideoEncoder : public VideoEncoder { + public: + Av1VideoEncoder(); + ~Av1VideoEncoder() override; + + // VideoDecoder implementation. + void Initialize(VideoCodecProfile profile, + const Options& options, + OutputCB output_cb, + StatusCB done_cb) override; + void Encode(scoped_refptr<VideoFrame> frame, + bool key_frame, + StatusCB done_cb) override; + void ChangeOptions(const Options& options, + OutputCB output_cb, + StatusCB done_cb) override; + void Flush(StatusCB done_cb) override; + + private: + base::TimeDelta GetFrameDuration(const VideoFrame& frame); + void DrainOutputs(base::TimeDelta ts, gfx::ColorSpace color_space); + + using aom_codec_unique_ptr = + std::unique_ptr<aom_codec_ctx_t, void (*)(aom_codec_ctx_t*)>; + + aom_codec_unique_ptr codec_; + aom_codec_enc_cfg_t config_; + aom_image_t image_ = {}; + + // This is a timestamp that is always increasing by frame's duration. + // It's used only for rate control and has nothing to do with timestamps + // coming from real frames. + aom_codec_pts_t artificial_timestamp_ = 0; + + gfx::Size originally_configured_size_; + base::TimeDelta last_frame_timestamp_; + gfx::ColorSpace last_frame_color_space_; + + VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN; + VideoFramePool frame_pool_; + std::vector<uint8_t> resize_buf_; + Options options_; + OutputCB output_cb_; +}; + +} // namespace media +#endif // MEDIA_VIDEO_AV1_VIDEO_ENCODER_H_
diff --git a/media/video/software_video_encoder_test.cc b/media/video/software_video_encoder_test.cc index 8e4ed08..70c9155 100644 --- a/media/video/software_video_encoder_test.cc +++ b/media/video/software_video_encoder_test.cc
@@ -39,6 +39,14 @@ #include "media/video/vpx_video_encoder.h" #endif +#if BUILDFLAG(ENABLE_LIBAOM) +#include "media/video/av1_video_encoder.h" +#endif + +#if BUILDFLAG(ENABLE_DAV1D_DECODER) +#include "media/filters/dav1d_video_decoder.h" +#endif + namespace media { struct SwVideoTestParams { @@ -85,6 +93,10 @@ #if BUILDFLAG(ENABLE_LIBVPX) decoder_ = std::make_unique<VpxVideoDecoder>(); #endif + } else if (codec_ == VideoCodec::kAV1) { +#if BUILDFLAG(ENABLE_DAV1D_DECODER) + decoder_ = std::make_unique<Dav1dVideoDecoder>(&media_log_); +#endif } EXPECT_NE(decoder_, nullptr); @@ -151,6 +163,12 @@ std::unique_ptr<VideoEncoder> CreateEncoder(VideoCodec codec) { switch (codec) { + case media::VideoCodec::kAV1: +#if BUILDFLAG(ENABLE_LIBAOM) + return std::make_unique<media::Av1VideoEncoder>(); +#else + return nullptr; +#endif case media::VideoCodec::kVP8: case media::VideoCodec::kVP9: #if BUILDFLAG(ENABLE_LIBVPX) @@ -844,6 +862,17 @@ PrintTestParams); #endif // ENABLE_LIBVPX +#if BUILDFLAG(ENABLE_LIBAOM) +SwVideoTestParams kAv1Params[] = { + {VideoCodec::kAV1, AV1PROFILE_PROFILE_MAIN, PIXEL_FORMAT_I420}, + {VideoCodec::kAV1, AV1PROFILE_PROFILE_MAIN, PIXEL_FORMAT_XRGB}}; + +INSTANTIATE_TEST_SUITE_P(Av1Generic, + SoftwareVideoEncoderTest, + ::testing::ValuesIn(kAv1Params), + PrintTestParams); +#endif // ENABLE_LIBAOM + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(H264VideoEncoderTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SVCVideoEncoderTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoftwareVideoEncoderTest);
diff --git a/services/network/public/cpp/corb/corb_impl.h b/services/network/public/cpp/corb/corb_impl.h index ea518d26..c9b4a5f4 100644 --- a/services/network/public/cpp/corb/corb_impl.h +++ b/services/network/public/cpp/corb/corb_impl.h
@@ -119,6 +119,25 @@ Decision HandleEndOfSniffableResponseBody() override; bool ShouldReportBlockedResponse() const override; + class ConfirmationSniffer; + class SimpleConfirmationSniffer; + + // Returns true if the response has a nosniff header. + static bool HasNoSniff(const network::mojom::URLResponseHead& response); + + private: + FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, + SeemsSensitiveFromCORSHeuristic); + FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, + SeemsSensitiveFromCacheHeuristic); + FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, + SeemsSensitiveWithBothHeuristics); + FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, + SupportsRangeRequests); + FRIEND_TEST_ALL_PREFIXES(content::CrossSiteDocumentResourceHandlerTest, + CORBProtectionLogging); + FRIEND_TEST_ALL_PREFIXES(ResponseAnalyzerTest, CORBProtectionLogging); + // true if either 1) ShouldBlockBasedOnHeaders decided to allow the response // based on headers alone or 2) ShouldBlockBasedOnHeaders decided to sniff // the response body and SniffResponseBody decided to allow the response @@ -142,31 +161,6 @@ corb_protection_logging_needs_sniffing_; } - // The MIME type determined by ShouldBlockBasedOnHeaders. - const CrossOriginReadBlocking::MimeType& canonical_mime_type_for_testing() - const { - return canonical_mime_type_; - } - - class ConfirmationSniffer; - class SimpleConfirmationSniffer; - - // Returns true if the response has a nosniff header. - static bool HasNoSniff(const network::mojom::URLResponseHead& response); - - private: - FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, - SeemsSensitiveFromCORSHeuristic); - FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, - SeemsSensitiveFromCacheHeuristic); - FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, - SeemsSensitiveWithBothHeuristics); - FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, - SupportsRangeRequests); - FRIEND_TEST_ALL_PREFIXES(content::CrossSiteDocumentResourceHandlerTest, - CORBProtectionLogging); - FRIEND_TEST_ALL_PREFIXES(ResponseAnalyzerTest, CORBProtectionLogging); - // Helper for translating ShouldAllow(), ShouldBlock() and needs_sniffing() // into corb::Decision. Decision GetCorbDecision();
diff --git a/services/network/public/cpp/corb/corb_impl_unittest.cc b/services/network/public/cpp/corb/corb_impl_unittest.cc index 99faf46e..b06100af 100644 --- a/services/network/public/cpp/corb/corb_impl_unittest.cc +++ b/services/network/public/cpp/corb/corb_impl_unittest.cc
@@ -170,6 +170,7 @@ } return os << "\n description = " << scenario.description + << "\n source_line = " << scenario.source_line << "\n target_url = " << scenario.target_url << "\n initiator_origin = " << scenario.initiator_origin << "\n response_headers = " << response_headers_formatted @@ -1885,10 +1886,11 @@ return response; } - // Instantiate and run CORB analyzer on the current scenario. Allow the - // analyzer to sniff the response body if needed and confirm it correctly - // decides to block or allow. - void RunAnalyzerOnScenario(const mojom::URLResponseHead& response) { + // Take and run ResponseAnalyzer on the current scenario. Allow the analyzer + // to sniff the response body if needed and confirm it correctly decides to + // block or allow. + void RunAnalyzerOnScenario(const mojom::URLResponseHead& response, + std::unique_ptr<ResponseAnalyzer> analyzer) { TestScenario scenario = GetParam(); // Initialize |request| from the parameters. std::unique_ptr<net::URLRequest> request = @@ -1904,23 +1906,13 @@ auto request_mode = cors_header_value == "" ? mojom::RequestMode::kNoCors : mojom::RequestMode::kCors; - // Create a ResponseAnalyzer to test. + // Initialize the `analyzer`. // - // The ResponseAnalyzer will be destructed when `analyzer` goes out of scope - // (the destructor triggers logging of UMAs that some callers of + // Note that the `analyzer` will be destructed when `analyzer` goes out of + // scope (the destructor may trigger logging of UMAs that some callers of // RunAnalyzerOnScenario attempt to verify). - auto analyzer = std::make_unique<CorbResponseAnalyzer>(); - analyzer->Init(request->url(), request->initiator(), request_mode, - response); - - // Verify MIME type was classified correctly. - EXPECT_EQ(scenario.canonical_mime_type, - analyzer->canonical_mime_type_for_testing()); - - // Verify that the verdict packet is >= 0 if CORB expects to sniff. - bool expected_to_sniff = - scenario.verdict_packet != kVerdictPacketForHeadersBasedVerdict; - ASSERT_EQ(expected_to_sniff, analyzer->needs_sniffing()); + ResponseAnalyzer::Decision decision = analyzer->Init( + request->url(), request->initiator(), request_mode, response); // This vector holds the packets to be delivered. std::vector<const char*> packets_vector(scenario.packets); @@ -1931,84 +1923,78 @@ // then the sniffing loop below will be skipped. EXPECT_LT(scenario.verdict_packet, static_cast<int>(packets_vector.size())); - // If we don't expect to sniff then CORB should have already made a blockng - // decision based on the headers. - if (!expected_to_sniff) { - EXPECT_FALSE(analyzer->needs_sniffing()); + // Verify that the ResponseAnalyzer asks for sniffing if this is what the + // testcase expects. + bool expected_to_sniff = + scenario.verdict_packet != kVerdictPacketForHeadersBasedVerdict; + if (expected_to_sniff) { + EXPECT_EQ(decision, ResponseAnalyzer::Decision::kSniffMore); + } else { + // If we don't expect to sniff then ResponseAnalyzer should have already + // made a blockng decision based on the headers. if (scenario.verdict == Verdict::kBlock) { - ASSERT_FALSE(analyzer->ShouldAllow()); - ASSERT_TRUE(analyzer->ShouldBlock()); + EXPECT_EQ(decision, ResponseAnalyzer::Decision::kBlock); } else { - ASSERT_FALSE(analyzer->ShouldBlock()); - ASSERT_TRUE(analyzer->ShouldAllow()); + EXPECT_EQ(decision, ResponseAnalyzer::Decision::kAllow); } - return; } // Simulate the behaviour of the URLLoader by appending the packets into // |data_buffer| and feeding this to |analyzer|. - std::string data_buffer; - size_t data_offset = 0; - bool reached_final_packet = false; - for (int packet_index = 0; packet_index <= scenario.verdict_packet; - packet_index++) { - SCOPED_TRACE(testing::Message() - << "While delivering packet #" << packet_index); + bool run_out_of_data_to_sniff = false; + if (decision == ResponseAnalyzer::Decision::kSniffMore) { + std::string data_buffer; + size_t data_offset = 0; + for (int packet_index = 0; packet_index <= scenario.verdict_packet; + packet_index++) { + SCOPED_TRACE(testing::Message() + << "While delivering packet #" << packet_index); - // At each iteration of the loop we feed a new packet to |analyzer|, - // breaking at the |verdict_packet|. Since we haven't given the next - // packet to |analyzer| yet at this point in the loop, it shouldn't have - // made a decision yet. - EXPECT_TRUE(analyzer->needs_sniffing()); - EXPECT_FALSE(analyzer->ShouldBlock()); - EXPECT_FALSE(analyzer->ShouldAllow()); + // At each iteration of the loop we feed a new packet to |analyzer|, + // breaking at the |verdict_packet|. Since we haven't given the next + // packet to |analyzer| yet at this point in the loop, it shouldn't have + // made a decision yet. + EXPECT_EQ(decision, ResponseAnalyzer::Decision::kSniffMore); - // Append the next packet of the response body. If appending the entire - // packet would exceed net::kMaxBytesToSniff we truncate the data. - size_t bytes_to_append = strlen(packets_vector[packet_index]); - if (data_offset + bytes_to_append > net::kMaxBytesToSniff) - bytes_to_append = net::kMaxBytesToSniff - data_offset; - data_buffer.append(packets_vector[packet_index], bytes_to_append); + // Append the next packet of the response body. If appending the entire + // packet would exceed net::kMaxBytesToSniff we truncate the data. + size_t bytes_to_append = strlen(packets_vector[packet_index]); + if (data_offset + bytes_to_append > net::kMaxBytesToSniff) + bytes_to_append = net::kMaxBytesToSniff - data_offset; + data_buffer.append(packets_vector[packet_index], bytes_to_append); - // Hand |analyzer_| the data to sniff. - analyzer->Sniff(data_buffer); - data_offset += bytes_to_append; - - // If the latest packet was empty, or we reached net::kMaxBytesToSniff - // then sniffing should be over. Furthermore, if the |analyzer| hasn't - // decided to block or allow, then (in the real implementation) URLLoader - // will default to allowing. We check here that this occurs only when it - // is supposed to. - if ((bytes_to_append == 0 || data_offset == net::kMaxBytesToSniff)) { - reached_final_packet = true; - // Sanity check sniffing is over. - EXPECT_EQ(packet_index, scenario.verdict_packet); - // Check we have run out of data if and only if we expected to. - bool expected_to_run_out_of_data = - scenario.verdict == Verdict::kAllowBecauseOutOfData; - bool did_run_out_of_data = - !analyzer->ShouldAllow() && !analyzer->ShouldBlock(); - EXPECT_EQ(expected_to_run_out_of_data, did_run_out_of_data); + // Hand |analyzer_| the data to sniff. + decision = analyzer->Sniff(data_buffer); + data_offset += bytes_to_append; + if (decision != ResponseAnalyzer::Decision::kSniffMore) + break; } } + // Handle scenarios where no decision can be made before running out of data + // to sniff. + if (decision == ResponseAnalyzer::Decision::kSniffMore) { + run_out_of_data_to_sniff = true; + decision = analyzer->HandleEndOfSniffableResponseBody(); + + // HandleEndOfSniffableResponseBody should never return kSniffMore. + EXPECT_NE(decision, ResponseAnalyzer::Decision::kSniffMore); + } + // Confirm the analyzer is blocking or allowing correctly (now that we have // performed any needed sniffing). if (scenario.verdict == Verdict::kBlock) { - ASSERT_FALSE(analyzer->ShouldAllow()); - ASSERT_TRUE(analyzer->ShouldBlock()); + EXPECT_EQ(decision, ResponseAnalyzer::Decision::kBlock); } else { + EXPECT_EQ(decision, ResponseAnalyzer::Decision::kAllow); + // In this case either the |analyzer| has decided to allow the response, // or run out of data and so the response will be allowed by default. - ASSERT_FALSE(analyzer->ShouldBlock()); if (scenario.verdict == Verdict::kAllow) { - ASSERT_TRUE(analyzer->ShouldAllow()); + EXPECT_FALSE(run_out_of_data_to_sniff); } else { - // In this case |scenario.verdict| == Verdict::kAllowBecauseOutOfData, - // so double-check that sniffing actually occurred and failed. EXPECT_EQ(Verdict::kAllowBecauseOutOfData, scenario.verdict); - ASSERT_FALSE(analyzer->ShouldAllow()); - EXPECT_TRUE(reached_final_packet); + EXPECT_TRUE(run_out_of_data_to_sniff); } } } @@ -2039,7 +2025,7 @@ scenario.initiator_origin); // Run the analyzer and confirm it allows/blocks correctly. - RunAnalyzerOnScenario(*response); + RunAnalyzerOnScenario(*response, std::make_unique<CorbResponseAnalyzer>()); // Verify that histograms are correctly incremented. base::HistogramTester::CountsMap expected_counts; @@ -2125,7 +2111,7 @@ const bool expect_nosniff = CorbResponseAnalyzer::HasNoSniff(*response); // Run the analyzer and confirm it allows/blocks correctly. - RunAnalyzerOnScenario(*response); + RunAnalyzerOnScenario(*response, std::make_unique<CorbResponseAnalyzer>()); base::HistogramTester::CountsMap expected_counts; expected_counts["SiteIsolation.CORBProtection.SensitiveResource"] = 1;
diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc index 9c49ef60..4f69404 100644 --- a/services/network/public/cpp/simple_url_loader.cc +++ b/services/network/public/cpp/simple_url_loader.cc
@@ -140,7 +140,7 @@ std::min(static_cast<size_t>(32 * 1024), upload_string_.length() - write_position_)); if (write_size == 0) { - // Upload is done. Close the uplaod body pipe and wait for another call + // Upload is done. Close the upload body pipe and wait for another call // to Read(). ResetBodyPipe(); return; @@ -253,7 +253,7 @@ // Called by BodyHandler when the BodyHandler body handler is done. If |error| // is not net::OK, some error occurred reading or consuming the body. If it is // net::OK, the pipe was closed and all data received was successfully - // handled. This could indicate an error, concellation, or completion. To + // handled. This could indicate an error, cancellation, or completion. To // determine which case this is, the size will also be compared to the size // reported in URLLoaderCompletionStatus(), if // URLLoaderCompletionStatus indicates a success. @@ -1031,7 +1031,7 @@ } } - // These are set on cosntruction and accessed on both task runners. + // These are set on construction and accessed on both task runners. const scoped_refptr<base::SequencedTaskRunner> body_handler_task_runner_; const scoped_refptr<base::SequencedTaskRunner> file_writer_task_runner_;
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index 84031f6..47048e650 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -1967,29 +1967,6 @@ "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test:chrome_sizes/" - }, - { - "isolate_name": "variations_smoke_tests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "variations_smoke_tests", - "resultdb": { - "enable": true, - "result_format": "single" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-18.04", - "pool": "chrome.tests" - } - ], - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://chrome/test:variations_smoke_tests/" } ] }, @@ -3854,30 +3831,6 @@ "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test:chrome_sizes/" - }, - { - "isolate_name": "variations_smoke_tests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "variations_smoke_tests", - "resultdb": { - "enable": true, - "result_format": "single" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-10.15", - "pool": "chrome.tests" - } - ], - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://chrome/test:variations_smoke_tests/" } ] }, @@ -3928,29 +3881,6 @@ "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test:chrome_sizes/" - }, - { - "isolate_name": "variations_smoke_tests", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "variations_smoke_tests", - "resultdb": { - "enable": true, - "result_format": "single" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Windows-10-19042", - "pool": "chrome.tests" - } - ], - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://chrome/test:variations_smoke_tests/" } ] },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index c7452515..bef73cc 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -546,13 +546,6 @@ 'has_native_resultdb_integration', ], }, - 'variations_smoke_tests': { - 'isolate_name': 'variations_smoke_tests', - 'resultdb': { - 'enable': True, - 'result_format': 'single' - }, - }, }, 'chrome_public_tests': { @@ -5308,16 +5301,6 @@ 'upload_trace_processor': {}, }, - 'variations_smoke_tests': { - 'variations_smoke_tests': { - 'isolate_name': 'variations_smoke_tests', - 'resultdb': { - 'enable': True, - 'result_format': 'single' - }, - }, - }, - # Not applicable for android x86 & x64 since the targets here assert # "enable_vr" in GN which is only true for android arm & arm64. # For details, see the following files:
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn index ad62a459..9474fb6 100644 --- a/third_party/android_deps/BUILD.gn +++ b/third_party/android_deps/BUILD.gn
@@ -382,7 +382,7 @@ # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. java_prebuilt("org_jetbrains_kotlin_kotlin_stdlib_java") { - jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib/kotlin-stdlib-1.6.0.jar" + jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib/kotlin-stdlib-1.6.10.jar" output_name = "org_jetbrains_kotlin_kotlin_stdlib" supports_android = true deps = [ @@ -702,7 +702,7 @@ # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. java_prebuilt("org_jetbrains_kotlin_kotlin_stdlib_common_java") { - jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib_common/kotlin-stdlib-common-1.6.0.jar" + jar_path = "libs/org_jetbrains_kotlin_kotlin_stdlib_common/kotlin-stdlib-common-1.6.10.jar" output_name = "org_jetbrains_kotlin_kotlin_stdlib_common" supports_android = true
diff --git a/third_party/arcore-android-sdk-client/OWNERS b/third_party/arcore-android-sdk-client/OWNERS index 8f984dc5..d95d28c 100644 --- a/third_party/arcore-android-sdk-client/OWNERS +++ b/third_party/arcore-android-sdk-client/OWNERS
@@ -1,2 +1 @@ -bialpio@chromium.org -klausw@chromium.org +file://components/webxr/OWNERS
diff --git a/third_party/arcore-android-sdk/OWNERS b/third_party/arcore-android-sdk/OWNERS index 8f984dc5..d95d28c 100644 --- a/third_party/arcore-android-sdk/OWNERS +++ b/third_party/arcore-android-sdk/OWNERS
@@ -1,2 +1 @@ -bialpio@chromium.org -klausw@chromium.org +file://components/webxr/OWNERS
diff --git a/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc b/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc index a69bb9e..6a3fb44 100644 --- a/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc +++ b/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc
@@ -483,19 +483,19 @@ UpdateAllLifecyclePhasesForTest(); EXPECT_TRUE( GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_FALSE(GetElementById("div2") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); + EXPECT_TRUE(GetElementById("div2") + ->GetComputedStyle() + ->AncestorsAffectedByHoverInHas()); EXPECT_FALSE( GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_FALSE(GetElementById("div3") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); + EXPECT_TRUE(GetElementById("div3") + ->GetComputedStyle() + ->AncestorsAffectedByHoverInHas()); EXPECT_FALSE( GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_FALSE(GetElementById("div4") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); + EXPECT_TRUE(GetElementById("div4") + ->GetComputedStyle() + ->AncestorsAffectedByHoverInHas()); EXPECT_TRUE( GetElementById("div5")->GetComputedStyle()->AffectedByPseudoInHas()); EXPECT_TRUE(GetElementById("div5") @@ -547,7 +547,7 @@ UpdateAllLifecyclePhasesForTest(); unsigned element_count = GetStyleEngine().StyleForElementCount() - start_count; - ASSERT_EQ(0U, element_count); + ASSERT_EQ(1U, element_count); GetElementById("div3")->SetHovered(false); UpdateAllLifecyclePhasesForTest(); @@ -555,7 +555,7 @@ GetElementById("div4")->SetHovered(true); UpdateAllLifecyclePhasesForTest(); element_count = GetStyleEngine().StyleForElementCount() - start_count; - ASSERT_EQ(0U, element_count); + ASSERT_EQ(1U, element_count); GetElementById("div4")->SetHovered(false); UpdateAllLifecyclePhasesForTest(); @@ -563,28 +563,6 @@ GetElementById("div4")->setAttribute(html_names::kClassAttr, "b"); UpdateAllLifecyclePhasesForTest(); element_count = GetStyleEngine().StyleForElementCount() - start_count; - ASSERT_EQ(3U, element_count); - - EXPECT_TRUE( - GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_TRUE(GetElementById("div2") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - EXPECT_FALSE( - GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_TRUE(GetElementById("div3") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - EXPECT_FALSE( - GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_TRUE(GetElementById("div4") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - - start_count = GetStyleEngine().StyleForElementCount(); - GetElementById("div3")->setAttribute(html_names::kClassAttr, "b"); - UpdateAllLifecyclePhasesForTest(); - element_count = GetStyleEngine().StyleForElementCount() - start_count; ASSERT_EQ(1U, element_count); EXPECT_TRUE( @@ -604,66 +582,6 @@ ->AncestorsAffectedByHoverInHas()); start_count = GetStyleEngine().StyleForElementCount(); - GetElementById("div3")->SetHovered(true); - UpdateAllLifecyclePhasesForTest(); - element_count = GetStyleEngine().StyleForElementCount() - start_count; - ASSERT_EQ(1U, element_count); - GetElementById("div3")->SetHovered(false); - UpdateAllLifecyclePhasesForTest(); - - start_count = GetStyleEngine().StyleForElementCount(); - GetElementById("div4")->SetHovered(true); - UpdateAllLifecyclePhasesForTest(); - element_count = GetStyleEngine().StyleForElementCount() - start_count; - ASSERT_EQ(1U, element_count); - GetElementById("div4")->SetHovered(false); - UpdateAllLifecyclePhasesForTest(); - - start_count = GetStyleEngine().StyleForElementCount(); - GetElementById("div3")->setAttribute(html_names::kClassAttr, ""); - UpdateAllLifecyclePhasesForTest(); - element_count = GetStyleEngine().StyleForElementCount() - start_count; - ASSERT_EQ(1U, element_count); - - EXPECT_TRUE( - GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_TRUE(GetElementById("div2") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - EXPECT_FALSE( - GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_TRUE(GetElementById("div3") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - EXPECT_FALSE( - GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_TRUE(GetElementById("div4") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - - start_count = GetStyleEngine().StyleForElementCount(); - GetElementById("div4")->setAttribute(html_names::kClassAttr, ""); - UpdateAllLifecyclePhasesForTest(); - element_count = GetStyleEngine().StyleForElementCount() - start_count; - ASSERT_EQ(3U, element_count); - - EXPECT_TRUE( - GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_FALSE(GetElementById("div2") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - EXPECT_FALSE( - GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_FALSE(GetElementById("div3") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - EXPECT_FALSE( - GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas()); - EXPECT_FALSE(GetElementById("div4") - ->GetComputedStyle() - ->AncestorsAffectedByHoverInHas()); - - start_count = GetStyleEngine().StyleForElementCount(); GetElementById("div6")->SetHovered(true); UpdateAllLifecyclePhasesForTest(); element_count = GetStyleEngine().StyleForElementCount() - start_count;
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc index 1321970..2ceb47e 100644 --- a/third_party/blink/renderer/core/css/css_selector.cc +++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -1058,11 +1058,6 @@ data_.rare_data_->selector_list_ = std::move(selector_list); } -void CSSSelector::SetContainsPseudoInsideHasPseudoClass() { - CreateRareData(); - data_.rare_data_->contains_pseudo_inside_has_pseudo_class_ = true; -} - static bool ValidateSubSelector(const CSSSelector* selector) { switch (selector->Match()) { case CSSSelector::kTag: @@ -1263,8 +1258,7 @@ serializing_value_(value), bits_(), attribute_(AnyQName()), - argument_(g_null_atom), - contains_pseudo_inside_has_pseudo_class_(false) {} + argument_(g_null_atom) {} CSSSelector::RareData::~RareData() = default;
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h index 85c7d64b..027a42e 100644 --- a/third_party/blink/renderer/core/css/css_selector.h +++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -354,11 +354,6 @@ const Vector<AtomicString>* PartNames() const { return has_rare_data_ ? data_.rare_data_->part_names_.get() : nullptr; } - bool ContainsPseudoInsideHasPseudoClass() const { - return has_rare_data_ - ? data_.rare_data_->contains_pseudo_inside_has_pseudo_class_ - : false; - } #ifndef NDEBUG void Show() const; @@ -371,7 +366,6 @@ void SetArgument(const AtomicString&); void SetSelectorList(std::unique_ptr<CSSSelectorList>); void SetPartNames(std::unique_ptr<Vector<AtomicString>>); - void SetContainsPseudoInsideHasPseudoClass(); void SetNth(int a, int b); bool MatchNth(unsigned count) const; @@ -492,7 +486,6 @@ selector_list_; // Used for :-webkit-any and :not std::unique_ptr<Vector<AtomicString>> part_names_; // Used for ::part() selectors. - bool contains_pseudo_inside_has_pseudo_class_; // Used for :has() selectors private: RareData(const AtomicString& value);
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_selector.cc b/third_party/blink/renderer/core/css/parser/css_parser_selector.cc index 737a646..362d4fa 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_selector.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
@@ -58,10 +58,6 @@ selector_->SetSelectorList(std::move(selector_list)); } -void CSSParserSelector::SetContainsPseudoInsideHasPseudoClass() { - selector_->SetContainsPseudoInsideHasPseudoClass(); -} - void CSSParserSelector::AppendTagHistory( CSSSelector::RelationType relation, std::unique_ptr<CSSParserSelector> selector) {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_selector.h b/third_party/blink/renderer/core/css/parser/css_parser_selector.h index 2e244c65..fff17e1 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_selector.h +++ b/third_party/blink/renderer/core/css/parser/css_parser_selector.h
@@ -79,7 +79,6 @@ Vector<std::unique_ptr<CSSParserSelector>>& selector_vector); void SetSelectorList(std::unique_ptr<CSSSelectorList>); void SetAtomics(std::unique_ptr<CSSSelectorList>); - void SetContainsPseudoInsideHasPseudoClass(); bool IsHostPseudoSelector() const;
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc index 8c2f145..8f8074b 100644 --- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc +++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -784,9 +784,6 @@ bool has_arguments = token.GetType() == kFunctionToken; selector->UpdatePseudoType(value, *context_, has_arguments, context_->Mode()); - if (UNLIKELY(is_inside_has_argument_)) - found_pseudo_in_has_argument_ = true; - if (selector->Match() == CSSSelector::kPseudoElement) { switch (selector->GetPseudoType()) { case CSSSelector::kPseudoBefore: @@ -880,11 +877,6 @@ DisallowPseudoElementsScope scope(this); base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true); - base::AutoReset<bool> is_inside_has_argument(&is_inside_has_argument_, - true); - base::AutoReset<bool> found_pseudo_in_has_argument( - &found_pseudo_in_has_argument_, false); - std::unique_ptr<CSSSelectorList> selector_list = std::make_unique<CSSSelectorList>(); *selector_list = ConsumeRelativeSelectorList(block); @@ -892,8 +884,6 @@ return nullptr; selector->SetSelectorList(std::move(selector_list)); - if (UNLIKELY(found_pseudo_in_has_argument_)) - selector->SetContainsPseudoInsideHasPseudoClass(); return selector; } case CSSSelector::kPseudoNot: {
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.h b/third_party/blink/renderer/core/css/parser/css_selector_parser.h index b227d97..b2047bd 100644 --- a/third_party/blink/renderer/core/css/parser/css_selector_parser.h +++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.h
@@ -150,11 +150,6 @@ // the default namespace is '*' while this flag is true. bool ignore_default_namespace_ = false; - // The 'found_pseudo_in_has_argument flag is true when we found any pseudo in - // ':has()' argument while parsing. - bool found_pseudo_in_has_argument_ = false; - bool is_inside_has_argument_ = false; - class DisallowPseudoElementsScope { STACK_ALLOCATED();
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index 03f8dd08..fc69f68 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -874,14 +874,6 @@ style.OverflowY() != EOverflow::kVisible) AdjustOverflow(style, element); - // overflow-clip-margin only applies if 'overflow: clip' is set along both - // axis or 'contain: paint'. - if (!style.ContainsPaint() && !(style.OverflowX() == EOverflow::kClip && - style.OverflowY() == EOverflow::kClip)) { - style.SetOverflowClipMargin( - ComputedStyleInitialValues::InitialOverflowClipMargin()); - } - if (StopPropagateTextDecorations(style, element)) style.ClearAppliedTextDecorations(); else
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc index 10bb5dd..0783d5c0 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster_test.cc
@@ -110,77 +110,6 @@ target->GetComputedStyle()->GetEffectiveTouchAction()); } -TEST_F(StyleAdjusterTest, AdjustOverflow) { - ScopedOverflowClipForTest overflow_clip_feature_enabler(true); - GetDocument().SetBaseURLOverride(KURL("http://test.com")); - SetBodyInnerHTML(R"HTML( - <div id='clipauto' style='overflow-x: clip; overflow-y: auto; - overflow-clip-margin: 1px;'> - <div id='autoclip' style='overflow-x: auto; overflow-y: clip; - overflow-clip-margin: 1px;'> - <div id='clipclip' style='overflow-x: clip; overflow-y: clip; - overflow-clip-margin: 1px;'> - <div id='visclip' style='overflow-x: visible; overflow-y: clip; - overflow-clip-margin: 1px;'> - <div id='clipvis' style='overflow-x: clip; overflow-y: visible; - overflow-clip-margin: 1px;'> - <div id='hiddenvis' style='overflow-x: hidden; overflow-y: visible; - overflow-clip-margin: 1px;'> - <div id='vishidden' style='overflow-x: visible; overflow-y: hidden; - overflow-clip-margin: 1px;'> - <div id='containpaint' style='contain: paint; overflow-clip-margin: 1px;'> - </div> - )HTML"); - UpdateAllLifecyclePhasesForTest(); - - Element* target = GetDocument().getElementById("clipauto"); - ASSERT_TRUE(target); - EXPECT_EQ(EOverflow::kHidden, target->GetComputedStyle()->OverflowX()); - EXPECT_EQ(EOverflow::kAuto, target->GetComputedStyle()->OverflowY()); - EXPECT_EQ(LayoutUnit(), target->GetComputedStyle()->OverflowClipMargin()); - - target = GetDocument().getElementById("autoclip"); - ASSERT_TRUE(target); - EXPECT_EQ(EOverflow::kAuto, target->GetComputedStyle()->OverflowX()); - EXPECT_EQ(EOverflow::kHidden, target->GetComputedStyle()->OverflowY()); - EXPECT_EQ(LayoutUnit(), target->GetComputedStyle()->OverflowClipMargin()); - - target = GetDocument().getElementById("clipclip"); - ASSERT_TRUE(target); - EXPECT_EQ(EOverflow::kClip, target->GetComputedStyle()->OverflowX()); - EXPECT_EQ(EOverflow::kClip, target->GetComputedStyle()->OverflowY()); - EXPECT_EQ(LayoutUnit(1), target->GetComputedStyle()->OverflowClipMargin()); - - target = GetDocument().getElementById("visclip"); - ASSERT_TRUE(target); - EXPECT_EQ(EOverflow::kVisible, target->GetComputedStyle()->OverflowX()); - EXPECT_EQ(EOverflow::kClip, target->GetComputedStyle()->OverflowY()); - EXPECT_EQ(LayoutUnit(), target->GetComputedStyle()->OverflowClipMargin()); - - target = GetDocument().getElementById("clipvis"); - ASSERT_TRUE(target); - EXPECT_EQ(EOverflow::kClip, target->GetComputedStyle()->OverflowX()); - EXPECT_EQ(EOverflow::kVisible, target->GetComputedStyle()->OverflowY()); - EXPECT_EQ(LayoutUnit(), target->GetComputedStyle()->OverflowClipMargin()); - - target = GetDocument().getElementById("vishidden"); - ASSERT_TRUE(target); - EXPECT_EQ(EOverflow::kAuto, target->GetComputedStyle()->OverflowX()); - EXPECT_EQ(EOverflow::kHidden, target->GetComputedStyle()->OverflowY()); - EXPECT_EQ(LayoutUnit(), target->GetComputedStyle()->OverflowClipMargin()); - - target = GetDocument().getElementById("hiddenvis"); - ASSERT_TRUE(target); - EXPECT_EQ(EOverflow::kHidden, target->GetComputedStyle()->OverflowX()); - EXPECT_EQ(EOverflow::kAuto, target->GetComputedStyle()->OverflowY()); - EXPECT_EQ(LayoutUnit(), target->GetComputedStyle()->OverflowClipMargin()); - - target = GetDocument().getElementById("containpaint"); - ASSERT_TRUE(target); - EXPECT_TRUE(target->GetComputedStyle()->ContainsPaint()); - EXPECT_EQ(LayoutUnit(1), target->GetComputedStyle()->OverflowClipMargin()); -} - TEST_F(StyleAdjusterTest, TouchActionContentEditableArea) { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeatures({::features::kSwipeToMoveCursor}, {});
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc index 145ee2d..da5378a 100644 --- a/third_party/blink/renderer/core/css/selector_checker.cc +++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -664,8 +664,6 @@ sub_context.scope = context.scope; // sub_context.is_inside_visited_link is false (by default) to disable // :visited matching when it is in the :has argument - sub_context.is_inside_has_pseudo_class = true; - sub_context.pseudo_has_in_rightmost_compound = context.in_rightmost_compound; DCHECK(context.selector->SelectorList()); for (const CSSSelector* selector = context.selector->SelectorList()->First(); @@ -817,6 +815,69 @@ return false; } +namespace { + +struct HasPseudoClassArgumentInfo { + bool contains_pseudo = false; + bool contains_hover = false; + bool contains_active = false; + bool contains_focus = false; + bool contains_focus_visible = false; + + explicit HasPseudoClassArgumentInfo(const CSSSelectorList* selector_list) { + DCHECK(selector_list); + + for (const CSSSelector* relative_selector = selector_list->First(); + relative_selector; + relative_selector = CSSSelectorList::Next(*relative_selector)) { + DCHECK(relative_selector); + + for (const CSSSelector* simple = relative_selector; + simple && + simple->GetPseudoType() != CSSSelector::kPseudoRelativeLeftmost; + simple = simple->TagHistory()) { + switch (simple->GetPseudoType()) { + case CSSSelector::kPseudoUnknown: + break; + case CSSSelector::kPseudoHover: + contains_pseudo = true; + contains_hover = true; + break; + case CSSSelector::kPseudoActive: + contains_pseudo = true; + contains_active = true; + break; + case CSSSelector::kPseudoFocus: + case CSSSelector::kPseudoFocusWithin: + contains_pseudo = true; + contains_focus = true; + break; + case CSSSelector::kPseudoFocusVisible: + contains_pseudo = true; + contains_focus_visible = true; + break; + default: + contains_pseudo = true; + break; + } + } + } + } + + void SetDynamicRestyleFlagsForHas(ComputedStyle* style) { + if (contains_hover) + style->SetAncestorsAffectedByHoverInHas(); + if (contains_active) + style->SetAncestorsAffectedByActiveInHas(); + if (contains_focus) + style->SetAncestorsAffectedByFocusInHas(); + if (contains_focus_visible) + style->SetAncestorsAffectedByFocusVisibleInHas(); + } +}; + +} // namespace + bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context, MatchResult& result) const { Element& element = *context.element; @@ -1012,38 +1073,19 @@ } return element.IsDragged(); case CSSSelector::kPseudoFocus: - if (mode_ == kResolvingStyle) { - if (UNLIKELY(context.is_inside_has_pseudo_class)) { - if (context.pseudo_has_in_rightmost_compound) - element_style_->SetAncestorsAffectedByFocusInHas(); - } else { - if (!context.in_rightmost_compound) - element.SetChildrenOrSiblingsAffectedByFocus(); - } - } + if (mode_ == kResolvingStyle && !context.in_rightmost_compound) + element.SetChildrenOrSiblingsAffectedByFocus(); return MatchesFocusPseudoClass(element); case CSSSelector::kPseudoFocusVisible: - if (mode_ == kResolvingStyle) { - if (UNLIKELY(context.is_inside_has_pseudo_class)) { - if (context.pseudo_has_in_rightmost_compound) - element_style_->SetAncestorsAffectedByFocusVisibleInHas(); - } else { - if (!context.in_rightmost_compound) - element.SetChildrenOrSiblingsAffectedByFocusVisible(); - } - } + if (mode_ == kResolvingStyle && !context.in_rightmost_compound) + element.SetChildrenOrSiblingsAffectedByFocusVisible(); return MatchesFocusVisiblePseudoClass(element); case CSSSelector::kPseudoFocusWithin: if (mode_ == kResolvingStyle) { - if (UNLIKELY(context.is_inside_has_pseudo_class)) { - if (context.pseudo_has_in_rightmost_compound) - element_style_->SetAncestorsAffectedByFocusInHas(); - } else { - if (context.in_rightmost_compound) - element_style_->SetAffectedByFocusWithin(); - else - element.SetChildrenOrSiblingsAffectedByFocusWithin(); - } + if (context.in_rightmost_compound) + element_style_->SetAffectedByFocusWithin(); + else + element.SetChildrenOrSiblingsAffectedByFocusWithin(); } probe::ForcePseudoState(&element, CSSSelector::kPseudoFocusWithin, &force_pseudo_state); @@ -1052,15 +1094,10 @@ return element.HasFocusWithin(); case CSSSelector::kPseudoHover: if (mode_ == kResolvingStyle) { - if (UNLIKELY(context.is_inside_has_pseudo_class)) { - if (context.pseudo_has_in_rightmost_compound) - element_style_->SetAncestorsAffectedByHoverInHas(); - } else { - if (context.in_rightmost_compound) - element_style_->SetAffectedByHover(); - else - element.SetChildrenOrSiblingsAffectedByHover(); - } + if (context.in_rightmost_compound) + element_style_->SetAffectedByHover(); + else + element.SetChildrenOrSiblingsAffectedByHover(); } if (!ShouldMatchHoverOrActive(context)) return false; @@ -1071,15 +1108,10 @@ return element.IsHovered(); case CSSSelector::kPseudoActive: if (mode_ == kResolvingStyle) { - if (UNLIKELY(context.is_inside_has_pseudo_class)) { - if (context.pseudo_has_in_rightmost_compound) - element_style_->SetAncestorsAffectedByActiveInHas(); - } else { - if (context.in_rightmost_compound) - element_style_->SetAffectedByActive(); - else - element.SetChildrenOrSiblingsAffectedByActive(); - } + if (context.in_rightmost_compound) + element_style_->SetAffectedByActive(); + else + element.SetChildrenOrSiblingsAffectedByActive(); } if (!ShouldMatchHoverOrActive(context)) return false; @@ -1289,8 +1321,14 @@ // ':has()' selector. element_style_->SetAffectedByHas(); element_style_->SetAncestorsAffectedByHas(); - if (selector.ContainsPseudoInsideHasPseudoClass()) + + // TODO(blee@igalia.com) Move the logic in HasPseudoClassArgumentInfo + // to HasArgumentMatchContext + HasPseudoClassArgumentInfo argument(selector.SelectorList()); + if (argument.contains_pseudo) element_style_->SetAffectedByPseudoInHas(); + if (context.in_rightmost_compound) + argument.SetDynamicRestyleFlagsForHas(element_style_); } // TODO(blee@igalia.com) non-terminal ':has() is not supported yet }
diff --git a/third_party/blink/renderer/core/css/selector_checker.h b/third_party/blink/renderer/core/css/selector_checker.h index 038dc688..1b9deca 100644 --- a/third_party/blink/renderer/core/css/selector_checker.h +++ b/third_party/blink/renderer/core/css/selector_checker.h
@@ -122,8 +122,6 @@ bool in_nested_complex_selector = false; bool is_inside_visited_link = false; const ContainerNode* relative_leftmost_element = nullptr; - bool is_inside_has_pseudo_class = false; - bool pseudo_has_in_rightmost_compound = true; }; struct MatchResult {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 3f1e732..6974ba2 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3740,9 +3740,6 @@ void Document::DispatchUnloadEvents( SecurityOrigin* committing_origin, absl::optional<Document::UnloadEventTiming>* unload_timing) { - // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done. - VLOG(1) << "Document::DispatchUnloadEvents() URL = " << Url(); - PluginScriptForbiddenScope forbid_plugin_destructor_scripting; PageDismissalScope in_page_dismissal; if (parser_) @@ -3818,9 +3815,6 @@ GetFrame()->Loader().SaveScrollAnchor(); - // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done. - VLOG(1) << "Actually dispatching an UnloadEvent: URL = " << Url(); - load_event_progress_ = kUnloadEventInProgress; Event& unload_event = *Event::Create(event_type_names::kUnload); const base::TimeTicks unload_event_start = base::TimeTicks::Now();
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc index 9c780940..2736937 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -1109,9 +1109,6 @@ mojom::blink::LocalMainFrame::ClosePageCallback completion_callback) { SECURITY_CHECK(frame_->IsMainFrame()); - // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done. - VLOG(1) << "LocalFrame::ClosePage() URL = " << frame_->GetDocument()->Url(); - // There are two ways to close a page: // // 1/ Via webview()->Close() that currently sets the WebView's delegate_ to
diff --git a/third_party/blink/renderer/core/layout/layout_inline_test.cc b/third_party/blink/renderer/core/layout/layout_inline_test.cc index 1000e0c..df1490cf 100644 --- a/third_party/blink/renderer/core/layout/layout_inline_test.cc +++ b/third_party/blink/renderer/core/layout/layout_inline_test.cc
@@ -719,7 +719,9 @@ GetLayoutObjectByElementId("target5") ->AbsoluteBoundingBoxRectHandlingEmptyInline()); // This rect covers the overflowing images and continuations. - EXPECT_EQ(PhysicalRect(390, 70, 160, 100), + const int height = + RuntimeEnabledFeatures::LayoutNGBlockInInlineEnabled() ? 400 : 100; + EXPECT_EQ(PhysicalRect(390, 70, 160, height), GetLayoutObjectByElementId("target6") ->AbsoluteBoundingBoxRectHandlingEmptyInline()); }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc index 83d0d6b..c48f09394 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -3433,7 +3433,7 @@ wtf_size_t breakpoint_row_set_index; bool has_subsequent_children; - const LayoutUnit fragmentainer_space = + LayoutUnit fragmentainer_space = FragmentainerSpaceAtBfcStart(ConstraintSpace()); const LayoutUnit previous_consumed_block_size = BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit(); @@ -3633,12 +3633,20 @@ auto ShiftBreakpointIntoNextFragmentainer = [&]() -> bool { if (breakpoint_row_set_index == kNotFound) return false; - DCHECK_NE(fragmentainer_space, kIndefiniteSize); const LayoutUnit fragment_relative_row_offset = grid_geometry->row_geometry.sets[breakpoint_row_set_index].offset + (*row_offset_adjustments)[breakpoint_row_set_index] - previous_consumed_block_size; + + // We may be within the initial column-balancing pass (where we have an + // indefinite fragmentainer size). If we have a forced break, re-run + // |PlaceItems()| assuming the breakpoint offset is the fragmentainer size. + if (fragmentainer_space == kIndefiniteSize) { + fragmentainer_space = fragment_relative_row_offset; + return true; + } + const LayoutUnit row_offset_delta = fragmentainer_space - fragment_relative_row_offset;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc index f5372fc..18794b8 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -646,10 +646,35 @@ // block-start border/padding), or in the outer fragmentation context), it may // be better to push some of the content to the next outer fragmentainer and // retry there. - bool may_have_more_space_in_next_outer_fragmentainer = - may_resume_in_next_outer_fragmentainer && - (intrinsic_block_size_ || - ConstraintSpace().FragmentainerOffsetAtBfc() > LayoutUnit()); + bool may_have_more_space_in_next_outer_fragmentainer = false; + if (may_resume_in_next_outer_fragmentainer) { + if (intrinsic_block_size_) { + may_have_more_space_in_next_outer_fragmentainer = true; + } else { + if (ConstraintSpace().FragmentainerOffsetAtBfc() > LayoutUnit()) { + if (!BreakToken()) { + may_have_more_space_in_next_outer_fragmentainer = true; + } else { + // We have already added a break for this multicol container, but we + // think that we're not at the start of the fragmentainer. This may be + // the case if we have a nested floated multicol container with a + // non-zero block-start margin. Float margins are unbreakable and are + // never truncated. So we may have broken before it, and kept the + // margin for the next fragmentainer (as we should), but since a + // fragmentainer offset is a border-box offset, we'll now think that + // we're past the fragmentainer start (the margin edge is at the + // start, but the border edge isn't). This is not ideal, but for now + // just avoid breaking before *again*, which would cause an infinite + // loop with no content progress. DCHECK that this is the situation. + // TODO(mstensho): Find a solution to this. We may have added an + // unnecessary break now. Pushing the float to the next fragmentainer + // may not have solved anything. + DCHECK(Node().IsFloating()); + DCHECK(BreakToken()->IsBreakBefore()); + } + } + } + } scoped_refptr<const NGLayoutResult> result; absl::optional<NGBreakAppeal> min_break_appeal;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index ad8c08a..4d6f909d 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -713,9 +713,6 @@ return self_rect; const OverflowClipAxes overflow_clip_axes = GetOverflowClipAxes(); - // overflow_clip_margin should only be set if we clip both axes. - DCHECK(overflow_clip_axes == kOverflowClipBothAxis || - !style.OverflowClipMargin()); if (overflow_clip_axes == kNoOverflowClip) { return UnionRect(self_rect, ink_overflow_.Contents(InkOverflowType(), Size()));
diff --git a/third_party/blink/renderer/modules/beacon/navigator_beacon.cc b/third_party/blink/renderer/modules/beacon/navigator_beacon.cc index f2e4e23..003327e 100644 --- a/third_party/blink/renderer/modules/beacon/navigator_beacon.cc +++ b/third_party/blink/renderer/modules/beacon/navigator_beacon.cc
@@ -78,16 +78,9 @@ ExecutionContext* execution_context = ExecutionContext::From(script_state); KURL url = execution_context->CompleteURL(url_string); if (!CanSendBeacon(execution_context, url, exception_state)) { - // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done. - VLOG(1) << "Cannot send a beacon to " << url.ElidedString() - << ", initiator = " << execution_context->Url(); return false; } - // TODO(crbug.com/1161996): Remove this VLOG once the investigation is done. - VLOG(1) << "Send a beacon to " << url.ElidedString() - << ", initiator = " << execution_context->Url(); - bool allowed; LocalFrame* frame = GetSupplementable()->DomWindow()->GetFrame(); if (data) {
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc index a8d1bd2..27c0367 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -69,6 +69,10 @@ #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" +#if BUILDFLAG(ENABLE_LIBAOM) +#include "media/video/av1_video_encoder.h" +#endif + #if BUILDFLAG(ENABLE_OPENH264) #include "media/video/openh264_video_encoder.h" #endif @@ -287,9 +291,41 @@ return result; } +const base::Feature kWebCodecsAv1Encoding{"WebCodecsAv1Encoding", + base::FEATURE_DISABLED_BY_DEFAULT}; + bool VerifyCodecSupportStatic(VideoEncoderTraits::ParsedConfig* config, ExceptionState* exception_state) { switch (config->codec) { + case media::VideoCodec::kAV1: + if (!base::FeatureList::IsEnabled(kWebCodecsAv1Encoding)) { + if (exception_state) { + exception_state->ThrowDOMException( + DOMExceptionCode::kNotSupportedError, + "AV1 encoding is not supported yet."); + } + return false; + } + + if (config->options.scalability_mode.has_value()) { + if (exception_state) { + exception_state->ThrowDOMException( + DOMExceptionCode::kNotSupportedError, + "SVC encoding is not supported for AV1 yet."); + } + return false; + } + if (config->profile != + media::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN) { + if (exception_state) { + exception_state->ThrowDOMException( + DOMExceptionCode::kNotSupportedError, "Unsupported av1 profile."); + } + return false; + } + // TODO(crbug.com/1208280): Check for supported AV1 levels + break; + case media::VideoCodec::kVP8: break; @@ -455,6 +491,14 @@ callback_runner_)); } +std::unique_ptr<media::VideoEncoder> CreateAv1VideoEncoder() { +#if BUILDFLAG(ENABLE_LIBAOM) + return std::make_unique<media::Av1VideoEncoder>(); +#else + return nullptr; +#endif // BUILDFLAG(ENABLE_LIBAOM) +} + std::unique_ptr<media::VideoEncoder> CreateVpxVideoEncoder() { #if BUILDFLAG(ENABLE_LIBVPX) return std::make_unique<media::VpxVideoEncoder>(); @@ -480,6 +524,10 @@ return nullptr; std::unique_ptr<media::VideoEncoder> result; switch (codec) { + case media::VideoCodec::kAV1: + result = CreateAv1VideoEncoder(); + self->UpdateEncoderLog("Av1VideoEncoder", false); + break; case media::VideoCodec::kVP8: case media::VideoCodec::kVP9: result = CreateVpxVideoEncoder();
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc index 43cfde6..b6a44f9 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc +++ b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
@@ -299,6 +299,9 @@ if (webgpu_enum == "depth24plus-stencil8") { return WGPUTextureFormat_Depth24PlusStencil8; } + if (webgpu_enum == "depth16unorm") { + return WGPUTextureFormat_Depth16Unorm; + } // Block Compression (BC) formats if (webgpu_enum == "bc1-rgba-unorm") {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl index 7fcb5bedc..c560a7c 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
@@ -66,6 +66,7 @@ "depth32float", "depth24plus", "depth24plus-stencil8", + "depth16unorm", /* Block Compression (BC) formats */ "bc1-rgba-unorm", "bc1-rgba-unorm-srgb",
diff --git a/third_party/blink/renderer/modules/xr/OWNERS b/third_party/blink/renderer/modules/xr/OWNERS index 9b95aec..d95d28c 100644 --- a/third_party/blink/renderer/modules/xr/OWNERS +++ b/third_party/blink/renderer/modules/xr/OWNERS
@@ -1,3 +1 @@ -alcooper@chromium.org -bajones@chromium.org -klausw@chromium.org +file://components/webxr/OWNERS
diff --git a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc index 58ab5185..7de6466 100644 --- a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.cc
@@ -47,7 +47,7 @@ XRBoundedReferenceSpace::~XRBoundedReferenceSpace() = default; -void XRBoundedReferenceSpace::EnsureUpdated() { +void XRBoundedReferenceSpace::EnsureUpdated() const { // Check first to see if the stage parameters have updated since the last // call. We only need to update the transform and bounds if it has. if (stage_parameters_id_ == session()->StageParametersId()) @@ -89,10 +89,15 @@ offset_bounds_geometry_.clear(); } - DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this)); + // DispatchEvent inherited from core/dom/events/event_target.h isn't const. + XRBoundedReferenceSpace* mutable_this = + const_cast<XRBoundedReferenceSpace*>(this); + mutable_this->DispatchEvent( + *XRReferenceSpaceEvent::Create(event_type_names::kReset, mutable_this)); } -absl::optional<TransformationMatrix> XRBoundedReferenceSpace::MojoFromNative() { +absl::optional<TransformationMatrix> XRBoundedReferenceSpace::MojoFromNative() + const { EnsureUpdated(); if (!mojo_from_bounded_native_) @@ -118,7 +123,7 @@ } XRBoundedReferenceSpace* XRBoundedReferenceSpace::cloneWithOriginOffset( - XRRigidTransform* origin_offset) { + XRRigidTransform* origin_offset) const { return MakeGarbageCollected<XRBoundedReferenceSpace>(this->session(), origin_offset); }
diff --git a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h index 006d723..055509a2 100644 --- a/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h +++ b/third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h
@@ -22,7 +22,7 @@ XRBoundedReferenceSpace(XRSession*, XRRigidTransform*); ~XRBoundedReferenceSpace() override; - absl::optional<TransformationMatrix> MojoFromNative() override; + absl::optional<TransformationMatrix> MojoFromNative() const override; HeapVector<Member<DOMPointReadOnly>> boundsGeometry(); @@ -32,13 +32,13 @@ private: XRBoundedReferenceSpace* cloneWithOriginOffset( - XRRigidTransform* origin_offset) override; + XRRigidTransform* origin_offset) const override; - void EnsureUpdated(); + void EnsureUpdated() const; - HeapVector<Member<DOMPointReadOnly>> offset_bounds_geometry_; - std::unique_ptr<TransformationMatrix> mojo_from_bounded_native_; - uint32_t stage_parameters_id_ = 0; + mutable HeapVector<Member<DOMPointReadOnly>> offset_bounds_geometry_; + mutable std::unique_ptr<TransformationMatrix> mojo_from_bounded_native_; + mutable uint32_t stage_parameters_id_ = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_grip_space.cc b/third_party/blink/renderer/modules/xr/xr_grip_space.cc index 8b79d29..7153a0e 100644 --- a/third_party/blink/renderer/modules/xr/xr_grip_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_grip_space.cc
@@ -14,7 +14,7 @@ XRGripSpace::XRGripSpace(XRSession* session, XRInputSource* source) : XRSpace(session), input_source_(source) {} -absl::optional<TransformationMatrix> XRGripSpace::MojoFromNative() { +absl::optional<TransformationMatrix> XRGripSpace::MojoFromNative() const { // Grip is only available when using tracked pointer for input. if (input_source_->TargetRayMode() != device::mojom::XRTargetRayMode::POINTING) {
diff --git a/third_party/blink/renderer/modules/xr/xr_grip_space.h b/third_party/blink/renderer/modules/xr/xr_grip_space.h index e81b3f8..297f7b9 100644 --- a/third_party/blink/renderer/modules/xr/xr_grip_space.h +++ b/third_party/blink/renderer/modules/xr/xr_grip_space.h
@@ -16,7 +16,7 @@ public: XRGripSpace(XRSession* session, XRInputSource* input_source); - absl::optional<TransformationMatrix> MojoFromNative() override; + absl::optional<TransformationMatrix> MojoFromNative() const override; bool EmulatedPosition() const override; device::mojom::blink::XRNativeOriginInformationPtr NativeOrigin()
diff --git a/third_party/blink/renderer/modules/xr/xr_joint_space.cc b/third_party/blink/renderer/modules/xr/xr_joint_space.cc index 24cb004..4a910e7 100644 --- a/third_party/blink/renderer/modules/xr/xr_joint_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_joint_space.cc
@@ -27,7 +27,7 @@ radius_(radius), handedness_(handedness) {} -absl::optional<TransformationMatrix> XRJointSpace::MojoFromNative() { +absl::optional<TransformationMatrix> XRJointSpace::MojoFromNative() const { return *mojo_from_joint_space_.get(); } @@ -45,7 +45,7 @@ return false; } -XRPose* XRJointSpace::getPose(XRSpace* other_space) { +XRPose* XRJointSpace::getPose(const XRSpace* other_space) const { // If any of the spaces belonging to the same XRHand return null when // populating the pose, all the spaces of that XRHand must also return // null when populating the pose.
diff --git a/third_party/blink/renderer/modules/xr/xr_joint_space.h b/third_party/blink/renderer/modules/xr/xr_joint_space.h index f14c756..cf5d71f 100644 --- a/third_party/blink/renderer/modules/xr/xr_joint_space.h +++ b/third_party/blink/renderer/modules/xr/xr_joint_space.h
@@ -34,11 +34,11 @@ const String jointName() const; device::mojom::XRHandedness handedness() const { return handedness_; } - absl::optional<TransformationMatrix> MojoFromNative() override; + absl::optional<TransformationMatrix> MojoFromNative() const override; device::mojom::blink::XRNativeOriginInformationPtr NativeOrigin() const override; bool EmulatedPosition() const override; - XRPose* getPose(XRSpace* other_space) override; + XRPose* getPose(const XRSpace* other_space) const override; void UpdateTracking(std::unique_ptr<TransformationMatrix> mojo_from_joint, float radius);
diff --git a/third_party/blink/renderer/modules/xr/xr_object_space.h b/third_party/blink/renderer/modules/xr/xr_object_space.h index d537dc4..10813a9 100644 --- a/third_party/blink/renderer/modules/xr/xr_object_space.h +++ b/third_party/blink/renderer/modules/xr/xr_object_space.h
@@ -36,7 +36,7 @@ object_(object), is_stationary_(object->IsStationary()) {} - absl::optional<TransformationMatrix> MojoFromNative() override { + absl::optional<TransformationMatrix> MojoFromNative() const override { return object_->MojoFromObject(); }
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_reference_space.cc index 1eaf218..8bc4885c 100644 --- a/third_party/blink/renderer/modules/xr/xr_reference_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.cc
@@ -51,7 +51,7 @@ XRReferenceSpace::~XRReferenceSpace() = default; -XRPose* XRReferenceSpace::getPose(XRSpace* other_space) { +XRPose* XRReferenceSpace::getPose(const XRSpace* other_space) const { if (type_ == ReferenceSpaceType::kViewer) { absl::optional<TransformationMatrix> other_offset_from_viewer = other_space->OffsetFromViewer(); @@ -71,7 +71,7 @@ } } -void XRReferenceSpace::SetMojoFromFloor() { +void XRReferenceSpace::SetMojoFromFloor() const { const device::mojom::blink::VRStageParametersPtr& stage_parameters = session()->GetStageParameters(); @@ -86,7 +86,7 @@ stage_parameters_id_ = session()->StageParametersId(); } -absl::optional<TransformationMatrix> XRReferenceSpace::MojoFromNative() { +absl::optional<TransformationMatrix> XRReferenceSpace::MojoFromNative() const { DVLOG(3) << __func__ << ": type_=" << type_; switch (type_) { @@ -139,7 +139,7 @@ } absl::optional<TransformationMatrix> XRReferenceSpace::NativeFromViewer( - const absl::optional<TransformationMatrix>& mojo_from_viewer) { + const absl::optional<TransformationMatrix>& mojo_from_viewer) const { if (type_ == ReferenceSpaceType::kViewer) { // Special case for viewer space, always return an identity matrix // explicitly. In theory the default behavior of multiplying NativeFromMojo @@ -159,11 +159,11 @@ return native_from_viewer; } -TransformationMatrix XRReferenceSpace::NativeFromOffsetMatrix() { +TransformationMatrix XRReferenceSpace::NativeFromOffsetMatrix() const { return origin_offset_->TransformMatrix(); } -TransformationMatrix XRReferenceSpace::OffsetFromNativeMatrix() { +TransformationMatrix XRReferenceSpace::OffsetFromNativeMatrix() const { return origin_offset_->InverseTransformMatrix(); } @@ -184,7 +184,7 @@ } XRReferenceSpace* XRReferenceSpace::getOffsetReferenceSpace( - XRRigidTransform* additional_offset) { + XRRigidTransform* additional_offset) const { auto matrix = NativeFromOffsetMatrix().Multiply(additional_offset->TransformMatrix()); @@ -193,7 +193,7 @@ } XRReferenceSpace* XRReferenceSpace::cloneWithOriginOffset( - XRRigidTransform* origin_offset) { + XRRigidTransform* origin_offset) const { return MakeGarbageCollected<XRReferenceSpace>(this->session(), origin_offset, type_); } @@ -219,8 +219,10 @@ void XRReferenceSpace::OnReset() { if (type_ != ReferenceSpaceType::kViewer) { - DispatchEvent( - *XRReferenceSpaceEvent::Create(event_type_names::kReset, this)); + // DispatchEvent inherited from core/dom/events/event_target.h isn't const. + XRReferenceSpace* mutable_this = const_cast<XRReferenceSpace*>(this); + mutable_this->DispatchEvent( + *XRReferenceSpaceEvent::Create(event_type_names::kReset, mutable_this)); } }
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.h b/third_party/blink/renderer/modules/xr/xr_reference_space.h index 42bd15f..4b5ba73 100644 --- a/third_party/blink/renderer/modules/xr/xr_reference_space.h +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.h
@@ -31,22 +31,23 @@ ~XRReferenceSpace() override; absl::optional<TransformationMatrix> NativeFromViewer( - const absl::optional<TransformationMatrix>& mojo_from_viewer) override; + const absl::optional<TransformationMatrix>& mojo_from_viewer) + const override; - absl::optional<TransformationMatrix> MojoFromNative() override; + absl::optional<TransformationMatrix> MojoFromNative() const override; bool IsStationary() const override; - TransformationMatrix NativeFromOffsetMatrix() override; - TransformationMatrix OffsetFromNativeMatrix() override; + TransformationMatrix NativeFromOffsetMatrix() const override; + TransformationMatrix OffsetFromNativeMatrix() const override; // We override getPose to ensure that the viewer pose in viewer space returns // the identity pose instead of the result of multiplying inverse matrices. - XRPose* getPose(XRSpace* other_space) override; + XRPose* getPose(const XRSpace* other_space) const override; device::mojom::blink::XRReferenceSpaceType GetType() const; - XRReferenceSpace* getOffsetReferenceSpace(XRRigidTransform* transform); + XRReferenceSpace* getOffsetReferenceSpace(XRRigidTransform* transform) const; DEFINE_ATTRIBUTE_EVENT_LISTENER(reset, kReset) @@ -60,16 +61,16 @@ private: virtual XRReferenceSpace* cloneWithOriginOffset( - XRRigidTransform* origin_offset); + XRRigidTransform* origin_offset) const; // Updates the mojo_from_floor_ transform to match the one present in the // latest display parameters of a session. - void SetMojoFromFloor(); + void SetMojoFromFloor() const; - uint32_t stage_parameters_id_ = 0; + mutable uint32_t stage_parameters_id_ = 0; // Floor from mojo (aka local-floor_from_mojo) transform. - std::unique_ptr<TransformationMatrix> mojo_from_floor_; + mutable std::unique_ptr<TransformationMatrix> mojo_from_floor_; Member<XRRigidTransform> origin_offset_; device::mojom::blink::XRReferenceSpaceType type_; };
diff --git a/third_party/blink/renderer/modules/xr/xr_space.cc b/third_party/blink/renderer/modules/xr/xr_space.cc index a740dfe..8f0732f1 100644 --- a/third_party/blink/renderer/modules/xr/xr_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_space.cc
@@ -17,7 +17,7 @@ XRSpace::~XRSpace() = default; absl::optional<TransformationMatrix> XRSpace::NativeFromViewer( - const absl::optional<TransformationMatrix>& mojo_from_viewer) { + const absl::optional<TransformationMatrix>& mojo_from_viewer) const { if (!mojo_from_viewer) return absl::nullopt; @@ -31,17 +31,17 @@ return native_from_mojo; } -TransformationMatrix XRSpace::NativeFromOffsetMatrix() { +TransformationMatrix XRSpace::NativeFromOffsetMatrix() const { TransformationMatrix identity; return identity; } -TransformationMatrix XRSpace::OffsetFromNativeMatrix() { +TransformationMatrix XRSpace::OffsetFromNativeMatrix() const { TransformationMatrix identity; return identity; } -absl::optional<TransformationMatrix> XRSpace::MojoFromOffsetMatrix() { +absl::optional<TransformationMatrix> XRSpace::MojoFromOffsetMatrix() const { auto maybe_mojo_from_native = MojoFromNative(); if (!maybe_mojo_from_native) { return absl::nullopt; @@ -53,7 +53,7 @@ return maybe_mojo_from_native; } -absl::optional<TransformationMatrix> XRSpace::NativeFromMojo() { +absl::optional<TransformationMatrix> XRSpace::NativeFromMojo() const { absl::optional<TransformationMatrix> mojo_from_native = MojoFromNative(); if (!mojo_from_native) return absl::nullopt; @@ -66,7 +66,7 @@ return session()->EmulatedPosition(); } -XRPose* XRSpace::getPose(XRSpace* other_space) { +XRPose* XRSpace::getPose(const XRSpace* other_space) const { DVLOG(2) << __func__ << ": ToString()=" << ToString() << ", other_space->ToString()=" << other_space->ToString(); @@ -102,7 +102,7 @@ EmulatedPosition() || other_space->EmulatedPosition()); } -absl::optional<TransformationMatrix> XRSpace::OffsetFromViewer() { +absl::optional<TransformationMatrix> XRSpace::OffsetFromViewer() const { absl::optional<TransformationMatrix> native_from_viewer = NativeFromViewer(session()->GetMojoFrom( device::mojom::blink::XRReferenceSpaceType::kViewer));
diff --git a/third_party/blink/renderer/modules/xr/xr_space.h b/third_party/blink/renderer/modules/xr/xr_space.h index bf3bc1814..d7a642b 100644 --- a/third_party/blink/renderer/modules/xr/xr_space.h +++ b/third_party/blink/renderer/modules/xr/xr_space.h
@@ -38,12 +38,12 @@ // Unless noted otherwise, all data returned over vr_service.mojom interfaces // is expressed in mojo space coordinates. // Returns nullopt if computing a transform is not possible. - virtual absl::optional<TransformationMatrix> MojoFromNative() = 0; + virtual absl::optional<TransformationMatrix> MojoFromNative() const = 0; // Convenience method to try to get the inverse of the above. This will return // the pose of the mojo origin in this space's native origin. // Returns nullopt if computing a transform is not possible. - absl::optional<TransformationMatrix> NativeFromMojo(); + absl::optional<TransformationMatrix> NativeFromMojo() const; // Gets the viewer pose in the native coordinates of this space, corresponding // to a transform from viewer coordinates to this space's native coordinates. @@ -54,22 +54,22 @@ // instead of something near to, but not quite, identity. // Returns nullopt if computing a transform is not possible. virtual absl::optional<TransformationMatrix> NativeFromViewer( - const absl::optional<TransformationMatrix>& mojo_from_viewer); + const absl::optional<TransformationMatrix>& mojo_from_viewer) const; // Convenience method for calling NativeFromViewer with the current // MojoFromViewer of the session associated with this space. This also handles // the multiplication of OffsetFromNative onto the result of NativeFromViewer. // Returns nullopt if computing a transform is not possible. - absl::optional<TransformationMatrix> OffsetFromViewer(); + absl::optional<TransformationMatrix> OffsetFromViewer() const; // Return origin offset matrix, aka native_origin_from_offset_space. - virtual TransformationMatrix NativeFromOffsetMatrix(); - virtual TransformationMatrix OffsetFromNativeMatrix(); + virtual TransformationMatrix NativeFromOffsetMatrix() const; + virtual TransformationMatrix OffsetFromNativeMatrix() const; // Returns transformation from offset space to mojo space. Convenience method, // returns MojoFromNative() * NativeFromOffsetMatrix() or nullopt if computing // a transform is not possible. - absl::optional<TransformationMatrix> MojoFromOffsetMatrix(); + absl::optional<TransformationMatrix> MojoFromOffsetMatrix() const; // Returns true when invoked on a space that is deemed stationary, false // otherwise (this means that the space is considered dynamic). Stationary @@ -87,7 +87,7 @@ // Gets the pose of this space's origin in |other_space|. This is a transform // that maps from this space to the other's space, or in other words: // other_from_this. - virtual XRPose* getPose(XRSpace* other_space); + virtual XRPose* getPose(const XRSpace* other_space) const; XRSession* session() const { return session_; }
diff --git a/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc b/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc index 372cff7..ccac469 100644 --- a/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_target_ray_space.cc
@@ -16,7 +16,7 @@ XRTargetRaySpace::XRTargetRaySpace(XRSession* session, XRInputSource* source) : XRSpace(session), input_source_(source) {} -absl::optional<TransformationMatrix> XRTargetRaySpace::MojoFromNative() { +absl::optional<TransformationMatrix> XRTargetRaySpace::MojoFromNative() const { auto mojo_from_viewer = session()->GetMojoFrom( device::mojom::blink::XRReferenceSpaceType::kViewer); switch (input_source_->TargetRayMode()) {
diff --git a/third_party/blink/renderer/modules/xr/xr_target_ray_space.h b/third_party/blink/renderer/modules/xr/xr_target_ray_space.h index 5a212fa..c8553c1a 100644 --- a/third_party/blink/renderer/modules/xr/xr_target_ray_space.h +++ b/third_party/blink/renderer/modules/xr/xr_target_ray_space.h
@@ -16,7 +16,7 @@ public: XRTargetRaySpace(XRSession* session, XRInputSource* input_space); - absl::optional<TransformationMatrix> MojoFromNative() override; + absl::optional<TransformationMatrix> MojoFromNative() const override; bool EmulatedPosition() const override; device::mojom::blink::XRNativeOriginInformationPtr NativeOrigin()
diff --git a/third_party/blink/renderer/platform/graphics/gpu/OWNERS b/third_party/blink/renderer/platform/graphics/gpu/OWNERS index 1bac549..7f3941f 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/OWNERS +++ b/third_party/blink/renderer/platform/graphics/gpu/OWNERS
@@ -10,6 +10,7 @@ # WebXR bajones@chromium.org klausw@chromium.org +per-file xr_*=file://components/webxr/OWNERS # SharedGpuContext, ImageLayerBridge, etc. sunnyps@chromium.org
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index 0bdb559c..a892500 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -13,6 +13,7 @@ # Tests that fail in legacy but pass in NG # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/inline-box-orthogonal-child-with-margins.html [ Failure ] crbug.com/626703 virtual/system-color-compute/external/wpt/css/css-color/oklch-008.html [ Failure ] crbug.com/626703 external/wpt/selection/textcontrols/onselectionchange-content-attribute.html [ Timeout ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials index 87cb0563..1eb709b 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials +++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -52,4 +52,3 @@ crbug.com/626703 external/wpt/infrastructure/channels/test_serialize.html [ Timeout ] crbug.com/626703 external/wpt/resource-timing/entries-for-network-errors.sub.https.html [ Timeout ] crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/resource-timing/entries-for-network-errors.sub.https.html [ Timeout ] -crbug.com/626703 wpt_internal/webid/get-argument-validation.https.html [ Timeout ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 2cffe2e..cd4f632 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2812,6 +2812,40 @@ crbug.com/626703 [ Fuchsia ] external/wpt/dom/historical.html [ Skip ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac11-arm64 ] external/wpt/content-security-policy/inside-worker/dedicatedworker-script-src.html [ Timeout ] +crbug.com/626703 external/wpt/css/css-color/color-mix-percents-01.html [ Failure ] +crbug.com/626703 external/wpt/css/css-color/color-mix-percents-02.html [ Failure ] +crbug.com/626703 [ Mac10.14 ] external/wpt/css/css-overflow/scrollbar-gutter-002.html [ Failure ] +crbug.com/626703 [ Mac10.15 ] external/wpt/css/css-overflow/scrollbar-gutter-002.html [ Failure ] +crbug.com/626703 [ Mac11 ] external/wpt/css/css-overflow/scrollbar-gutter-002.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-overflow/scrollbar-gutter-002.html [ Failure ] +crbug.com/626703 [ Mac10.14 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html [ Failure ] +crbug.com/626703 [ Mac10.15 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html [ Failure ] +crbug.com/626703 [ Mac11 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html [ Failure ] +crbug.com/626703 [ Mac11 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html [ Failure Crash ] +crbug.com/626703 [ Mac10.14 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html [ Failure ] +crbug.com/626703 [ Mac10.15 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-fallback-props-revert-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-background-color-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-background-position-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-block-start-color-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-bottom-left-radius-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-bottom-width-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-end-start-radius-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-image-source-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-inline-end-width-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-inline-start-style-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-left-style-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-top-right-radius-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-top-style-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-top-width-001.html [ Failure ] +crbug.com/626703 [ Mac11-arm64 ] virtual/no-auto-wpt-origin-isolation/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-no-subdomain-child2-yes-subdomainport.sub.https.html [ Failure Crash ] +crbug.com/626703 [ Mac11-arm64 ] virtual/no-auto-wpt-origin-isolation/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-subdomain.sub.https.html [ Failure Crash ] +crbug.com/626703 [ Mac11-arm64 ] virtual/plz-dedicated-worker/external/wpt/content-security-policy/inside-worker/serviceworker-report-only.https.sub.html [ Timeout ] +crbug.com/626703 virtual/system-color-compute/external/wpt/css/css-color/color-mix-percents-01.html [ Failure ] +crbug.com/626703 virtual/system-color-compute/external/wpt/css/css-color/color-mix-percents-02.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/css-ui/compute-kind-widget-fallback-props-revert-001.html [ Failure ] crbug.com/626703 [ Mac10.12 ] external/wpt/css/css-ui/compute-kind-widget-fallback-props-revert-001.html [ Failure ] crbug.com/626703 [ Mac10.13 ] external/wpt/css/css-ui/compute-kind-widget-fallback-props-revert-001.html [ Failure ] @@ -2931,7 +2965,7 @@ crbug.com/626703 [ Mac10.15 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-start-start-radius-001.html [ Failure ] crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-start-start-radius-001.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-start-start-radius-001.html [ Failure ] -crbug.com/626703 [ Mac11 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-start-start-radius-001.html [ Timeout Failure ] +crbug.com/626703 [ Mac11 ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-start-start-radius-001.html [ Failure Timeout ] crbug.com/626703 external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-top-color-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-top-left-radius-001.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-border-top-right-radius-001.html [ Failure ] @@ -4904,6 +4938,7 @@ crbug.com/614667 external/wpt/css/css-break/grid/grid-item-fragmentation-034.html [ Failure ] crbug.com/614667 external/wpt/css/css-break/grid/grid-item-fragmentation-037.html [ Failure ] crbug.com/614667 external/wpt/css/css-break/grid/grid-item-fragmentation-038.html [ Failure ] +crbug.com/614667 external/wpt/css/css-break/grid/grid-item-fragmentation-039.html [ Failure ] crbug.com/1066629 external/wpt/css/css-break/hit-test-transformed.html [ Failure ] crbug.com/1058792 external/wpt/css/css-break/transform-007.html [ Failure ] crbug.com/1224888 external/wpt/css/css-break/transform-009.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index e62a6f1..30b7bbc 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -978,11 +978,6 @@ "args": ["--enable-fake-no-alloc-direct-call-for-testing"] }, { - "prefix": "webid", - "bases": ["wpt_internal/webid"], - "args": ["--enable-features=WebID"] - }, - { "prefix": "document-transition", "bases": ["wpt_internal/document-transition"], "args": ["--enable-blink-features=DocumentTransition",
diff --git a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations index fa5feb01..c33e20cc 100644 --- a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations +++ b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
@@ -396,7 +396,7 @@ crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/device-with-name.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/optional-services-present.https.window.html [ Failure ] -crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.html [ Failure ] +crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-optionalServices.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/canonicalizeFilter/device-name-longer-than-29-bytes.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/canonicalizeFilter/empty-filter.https.window.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations index 7e3e98dd..6516bbfe 100644 --- a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations +++ b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
@@ -457,7 +457,7 @@ crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/device-with-name.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/optional-services-present.https.window.html [ Failure ] -crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.html [ Failure ] +crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-optionalServices.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/canonicalizeFilter/data-prefix-and-mask-size.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/canonicalizeFilter/dataPrefix-buffer-is-detached.https.window.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/WebviewWPTExpectations b/third_party/blink/web_tests/android/WebviewWPTExpectations index 56fe9fa..070b3ab 100644 --- a/third_party/blink/web_tests/android/WebviewWPTExpectations +++ b/third_party/blink/web_tests/android/WebviewWPTExpectations
@@ -355,7 +355,7 @@ crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/device-with-name.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/optional-services-missing.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/acceptAllDevices/optional-services-present.https.window.html [ Failure ] -crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.html [ Failure ] +crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/blocklisted-service-in-optionalServices.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/canonicalizeFilter/device-name-longer-than-29-bytes.https.window.html [ Failure ] crbug.com/1050754 external/wpt/bluetooth/requestDevice/canonicalizeFilter/empty-filter.https.window.html [ Failure ]
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 87d65c7..ab6a072 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
@@ -1685,6 +1685,13 @@ {} ] ], + "preserve3d-svg-foreign-object-hit-test.svg": [ + "14c772cb2d24ae89cc2bce0e2ed2dad83d3ae6d9", + [ + null, + {} + ] + ], "transform-marquee-resize-div-image-001.html": [ "8bdbb984f3a1cb8a500a93faa4efa4a633b81826", [ @@ -82565,6 +82572,32 @@ {} ] ], + "color-mix-percents-01.html": [ + "425ef9a63621ef635fc3e800ee92a59dd32978d0", + [ + null, + [ + [ + "/css/css-color/color-mix-percents-01-ref.html", + "==" + ] + ], + {} + ] + ], + "color-mix-percents-02.html": [ + "5b1a4cfd9d92f311b7a6619017f29fb42c62f269", + [ + null, + [ + [ + "/css/css-color/color-mix-percents-01-ref.html", + "==" + ] + ], + {} + ] + ], "composited-filters-under-opacity.html": [ "f613748af3ac5bb59c9fa207937ae6207d71062e", [ @@ -135907,6 +135940,19 @@ {} ] ], + "overflow-clip-margin-008.html": [ + "fabe669a49c69319c9fc689cc9f22af6b6fe41f9", + [ + null, + [ + [ + "/css/css-overflow/overflow-clip-margin-008-ref.html", + "==" + ] + ], + {} + ] + ], "overflow-clip-margin-invalidation.html": [ "d9c87a34a53f17451b0d3ae8c2071971d1df3a94", [ @@ -136089,6 +136135,71 @@ {} ] ], + "scrollbar-gutter-002.html": [ + "129eb2c08590c98505e36f63da173d1c8a4bf98d", + [ + null, + [ + [ + "/css/css-overflow/scrollbar-gutter-002-ref.html", + "==" + ] + ], + {} + ] + ], + "scrollbar-gutter-dynamic-001.html": [ + "3dcb32048cd7a1b94eb7cd30be4a381a5f168eab", + [ + null, + [ + [ + "/css/css-overflow/scrollbar-gutter-dynamic-001-ref.html", + "==" + ] + ], + {} + ] + ], + "scrollbar-gutter-rtl-002.html": [ + "8d0376defdfc69ecb44fc2134c81573e553db2bb", + [ + null, + [ + [ + "/css/css-overflow/scrollbar-gutter-rtl-002-ref.html", + "==" + ] + ], + {} + ] + ], + "scrollbar-gutter-vertical-lr-002.html": [ + "9e5dcd299eba99e4ab6f077149a841011805c0a5", + [ + null, + [ + [ + "/css/css-overflow/scrollbar-gutter-vertical-lr-002-ref.html", + "==" + ] + ], + {} + ] + ], + "scrollbar-gutter-vertical-rl-002.html": [ + "d68d4e5d3cba0353da274f9c75c558c0a8324092", + [ + null, + [ + [ + "/css/css-overflow/scrollbar-gutter-vertical-rl-002-ref.html", + "==" + ] + ], + {} + ] + ], "text-overflow-ellipsis-001.html": [ "41c11d581e982c7de2d51d38b18decd99e8a60b3", [ @@ -231585,7 +231696,7 @@ [] ], "fedcm-mock.js": [ - "2fa351446c2601580c525f4ef75b01f2ba2a19c8", + "407ca8d7702adbf6d7dbc100323eb46267048631", [] ], "federatedcredential-get.html": [ @@ -241348,6 +241459,10 @@ "77ccec0d3adfc6bb9840f529ad5e574792c96cef", [] ], + "color-mix-percents-01-ref.html": [ + "2d9a1380b3889a446356725b75db485e55992cc1", + [] + ], "color-resolving-hwb-expected.txt": [ "4c702545c17052ddbdda669b4a8191116b9306f8", [] @@ -258742,6 +258857,10 @@ "9f562d67fe4249d09c98062a74dcb2b656123056", [] ], + "overflow-clip-margin-008-ref.html": [ + "3af9e4e951d9d35eafc72fd7593be20a7c94dbde", + [] + ], "overflow-clip-margin-invalidation-ref.html": [ "1ec2a5ce0a21c8dd578b3fcfde702307e4e2a9a8", [] @@ -258986,10 +259105,26 @@ "782ffab9da1c1cb55b4488e7fc8f913dd18857f3", [] ], + "scrollbar-gutter-002-ref.html": [ + "ae51682c75920743d4ae69fffe8b566a3758c7a4", + [] + ], "scrollbar-gutter-dynamic-001-ref.html": [ "5f2f7bff26420e949093a822d8995d9fcc3f1f51", [] ], + "scrollbar-gutter-rtl-002-ref.html": [ + "e6510a081353db996c4ead14ad6a167b90d48297", + [] + ], + "scrollbar-gutter-vertical-lr-002-ref.html": [ + "cb7c647da43c842e68c9ca8e9ca24cd9708324dd", + [] + ], + "scrollbar-gutter-vertical-rl-002-ref.html": [ + "7dbadf995ed89bc3032c4ca1b53e1cebecd6237e", + [] + ], "text-overflow-ellipsis-editing-input-ref.html": [ "3902072bc58b7bf62290edafbce1b735288af716", [] @@ -354116,6 +354251,13 @@ {} ] ], + "fedcm-logout.https.html": [ + "e4f83b0f90e1a684c254235e6222b299b8647cbc", + [ + null, + {} + ] + ], "fedcm-revoke.https.html": [ "c014724b8173e47e9d9ffb00a08537055c3f8003", [ @@ -354124,7 +354266,7 @@ ] ], "fedcm.https.html": [ - "71ff0ab70f49258f5e6d701b8e7034933ae1ae42", + "618f0ec3c24e5cca8512748d972357e03590d77e", [ null, {} @@ -559606,15 +559748,6 @@ ] ] }, - "css-overflow": { - "scrollbar-gutter-dynamic-001.html": [ - "d6451ff995f5b522626e8e05eaed33d3e49e5f9b", - [ - null, - {} - ] - ] - }, "css-ruby": { "rbc-rtc-basic-001.html": [ "e086181ab938b54ff40d2363d801380d1b9ada9b",
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.html b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.html deleted file mode 100644 index cb2f989..0000000 --- a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!DOCTYPE html> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/testdriver.js"></script> -<script src="/resources/testdriver-vendor.js"></script> -<script src="/bluetooth/resources/bluetooth-test.js"></script> -<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script> -<script> -'use strict'; -const test_desc = 'Reject with SecurityError if requesting a blocklisted ' + - 'service.'; -const expected = new DOMException( - 'requestDevice() called with a filter containing a blocklisted UUID. ' + - 'https://goo.gl/4NeimX', - 'SecurityError'); - -bluetooth_test( - () => - setUpPreconnectedDevice({knownServiceUUIDs: ['human_interface_device']}) - .then( - () => assert_promise_rejects_with_message( - requestDeviceWithTrustedClick( - {filters: [{services: ['human_interface_device']}]}), - expected, 'Requesting blocklisted service rejects.')), - test_desc); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.window.js b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.window.js new file mode 100644 index 0000000..48f3d13 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/blocklisted-service-in-filter.https.window.js
@@ -0,0 +1,23 @@ +// META: script=/resources/testharness.js +// META: script=/resources/testharnessreport.js +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Reject with SecurityError if requesting a blocklisted ' + + 'service.'; +const expected = new DOMException( + 'requestDevice() called with a filter containing a blocklisted UUID. ' + + 'https://goo.gl/4NeimX', + 'SecurityError'); + +bluetooth_test(async () => { + await assert_promise_rejects_with_message( + setUpPreconnectedFakeDevice({ + fakeDeviceOptions: {knownServiceUUIDs: ['human_interface_device']}, + requestDeviceOptions: + {filters: [{services: ['human_interface_device']}]} + }), + expected, 'Requesting blocklisted service rejects.'); +}, test_desc);
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/support/README.md b/third_party/blink/web_tests/external/wpt/credential-management/support/README.md index f58d4cd0..886faa8 100644 --- a/third_party/blink/web_tests/external/wpt/credential-management/support/README.md +++ b/third_party/blink/web_tests/external/wpt/credential-management/support/README.md
@@ -31,3 +31,24 @@ - function receive(): the main/only function that can be mocked - function expect(): the main/only function that enables us to mock it - enum State {kSuccess, kTimeout}: allows you to mock success/failures + +## FedCM Testing + +`fedcm-helper.js` exposes `fedcm_test` which is a specialized +`promise_test` which comes pre-setup with the appropriate mocking infrastructure +to emulate platform federated auth backend. The mock is passed to the test +function as the second parameter. + +Example usage: +``` +<script type="module"> + import {fedcm_test} from './support/fedcm-helper.js'; + + fedcm_test(async (t, mock) => { + mock.returnIdToken("a_token"); + assert_equals("a_token", await navigator.credentials.get(options)); + }, "Successfully obtaining a token using mock."); +</script> +``` + +The chromium implementation uses the MojoJS shim.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/grid/grid-item-fragmentation-039.html b/third_party/blink/web_tests/external/wpt/css/css-break/grid/grid-item-fragmentation-039.html new file mode 100644 index 0000000..5201c49 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/grid/grid-item-fragmentation-039.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#pagination"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="position: relative; width: 50px; columns: 1; column-gap: 0; background: red;"> + <div style="display: grid;"> + <div style="background: green; height: 100px; break-after: column;"></div> + <div style="background: green; height: 100px;"></div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-01-ref.html b/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-01-ref.html new file mode 100644 index 0000000..2d9a1380 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-01-ref.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Color 5: color-mix</title> +<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org"> +<style> + .test { background-color: rgb(68.4898% 36.015% 68.3102%); width: 14em; height: 14em; margin-top: 0; margin-bottom: 0;} +</style> +<body> + <p>Test passes if you see a purple square, and no red.</p> + <div class="test"></div> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-01.html b/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-01.html new file mode 100644 index 0000000..425ef9a6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-01.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Color 5: color-mix</title> +<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-color-5/#color-mix"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#interpolation-space"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#hue-interpolation"> +<link rel="match" href="./color-mix-percents-01-ref.html"> +<meta name="assert" content="missing percentages, percent normalization"> +<style> + .test { background-color: red; width: 14em; height: 2em; margin-top: 0; margin-bottom: 0;} + .t1 { background-color: rgb(68.4898% 36.015% 68.3102%); } + .t2 { background-color: color-mix(in lch, purple 50%, plum 50%);} + .t3 { background-color: color-mix(in lch, purple 50%, plum);} + .t4 { background-color: color-mix(in lch, purple, plum 50%); } + .t5 { background-color: color-mix(in lch, purple, plum);} + .t6 { background-color: color-mix(in lch, plum, purple);} + .t7 { background-color: color-mix(in lch, purple 80%, plum 80%);} +</style> +<body> + <p>Test passes if you see a purple square, and no red.</p> + <div class="test t1"></div> + <div class="test t2"></div> + <div class="test t3"></div> + <div class="test t4"></div> + <div class="test t5"></div> + <div class="test t6"></div> + <div class="test t7"></div> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-02.html b/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-02.html new file mode 100644 index 0000000..5b1a4cf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/color-mix-percents-02.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Color 5: color-mix</title> +<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-color-5/#color-mix"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#interpolation-space"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#hue-interpolation"> +<link rel="match" href="./color-mix-percents-01-ref.html"> +<meta name="assert" content="percent normalization for opaque mixes"> +<style> + .test { background-color: red; width: 14em; height: 2em; margin-top: 0; margin-bottom: 0;} + .t1 { background-color: rgb(68.4898% 36.015% 68.3102%); } + .t2 { background-color: color-mix(in lch, purple 50%, plum 50%);} + .t3 { background-color: color-mix(in lch, purple 55%, plum 55%);} + .t4 { background-color: color-mix(in lch, purple 70%, plum 70%); } + .t5 { background-color: color-mix(in lch, purple 95%, plum 95%);} + .t6 { background-color: color-mix(in lch, purple 125%, plum 125%);} + .t7 { background-color: color-mix(in lch, purple 9999%, plum 9999%);} +</style> +<body> + <p>Test passes if you see a purple square, and no red.</p> + <div class="test t1"></div> + <div class="test t2"></div> + <div class="test t3"></div> + <div class="test t4"></div> + <div class="test t5"></div> + <div class="test t6"></div> + <div class="test t7"></div> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/nested-floated-multicol-with-monolithic-child-crash.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/nested-floated-multicol-with-monolithic-child-crash.html new file mode 100644 index 0000000..f48ae9ff --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/nested-floated-multicol-with-monolithic-child-crash.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1280624"> +<p>PASS if no freeze or crash.</p> +<div style="columns:2; column-fill:auto; height:100px;"> + <div style="margin-top:10px; float:right; columns:2; column-fill:auto; width:100%;"> + <div style="height:100px; contain:size;"></div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-009-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-009-ref.html new file mode 100644 index 0000000..efbf8985 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-009-ref.html
@@ -0,0 +1,22 @@ +<!doctype html> +<html class="reftest"> +<meta charset="utf-8"> +<title>Overflow-clip-margin can be inherited even if it has no effect on specified element</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<style> +.container { + width: 100px; + height: 100px; + overflow-clip-margin: 20px; + overflow: clip; +} +.child { + width: 200px; + height: 200px; + background: lightblue; +} +</style> +<div class=container> + <div class=child></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-009.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-009.html new file mode 100644 index 0000000..6ba9a5a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-clip-margin-009.html
@@ -0,0 +1,28 @@ +<!doctype html> +<html class="reftest"> +<meta charset="utf-8"> +<title>Overflow-clip-margin can be inherited even if it has no effect on specified element</title> +<link rel="help" href="https://www.w3.org/TR/css-overflow-3/#propdef-overflow-clip-margin"> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="match" href="overflow-clip-margin-009-ref.html"> +<style> +.prop { + overflow-clip-margin: 20px; +} +.container { + width: 100px; + height: 100px; + overflow-clip-margin: inherit; + overflow: clip; +} +.child { + width: 200px; + height: 200px; + background: lightblue; +} +</style> +<div class=prop> + <div class=container> + <div class=child></div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-002-ref.html new file mode 100644 index 0000000..ae51682c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-002-ref.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow Reference: test scrollbar-gutter with horizontal left to right content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: horizontal-tb; + direction: ltr; + + box-sizing: border-box; + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-y: auto"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll" id="container_scroll_stable"> + <div class="content" id="content_scroll_stable"></div> + </div> + + <div class="container" style="overflow-y: hidden" id="container_hidden_stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-y: auto;" id="container_auto_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll" id="container_scroll_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: hidden;" id="container_hidden_stable_both_edges"> + <div class="content"></div> + </div> + </div> + + <script> + let container_scroll_stable = document.getElementById("container_scroll_stable"); + let content_scroll_stable = document.getElementById("content_scroll_stable"); + let vScrollbarWidth = (container_scroll_stable.offsetWidth - content_scroll_stable.offsetWidth); + let vScrollbarWidthStr = vScrollbarWidth + "px"; + + // Simulate scrollbar-gutter via padding on containers. + document.getElementById("container_hidden_stable").style.paddingInlineEnd = vScrollbarWidthStr; + document.getElementById("container_auto_stable_both_edges").style.paddingInlineStart = vScrollbarWidthStr; + document.getElementById("container_scroll_stable_both_edges").style.paddingInlineStart = vScrollbarWidthStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineStart = vScrollbarWidthStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineEnd = vScrollbarWidthStr; + </script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-002.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-002.html new file mode 100644 index 0000000..129eb2c0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-002.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow: test scrollbar-gutter with horizontal left to right content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property"> + <link rel="match" href="scrollbar-gutter-002-ref.html"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: horizontal-tb; + direction: ltr; + + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-y: auto; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: hidden; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-y: auto; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: hidden; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + </div> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-dynamic-001.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-dynamic-001.html index d6451ff..3dcb320 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-dynamic-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-dynamic-001.html
@@ -3,6 +3,8 @@ <title>CSS Overflow: scrollbar-gutter changing dynamically</title> <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property"> <link rel="stylesheet" href="/fonts/ahem.css"> +<link rel="match" href="scrollbar-gutter-dynamic-001-ref.html"> + <style> #scroller { font: 100px/1 Ahem;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-rtl-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-rtl-002-ref.html new file mode 100644 index 0000000..e6510a0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-rtl-002-ref.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow Reference: test scrollbar-gutter with horizontal right to left content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: horizontal-tb; + direction: rtl; + + box-sizing: border-box; + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-y: auto"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll" id="container_scroll_stable"> + <div class="content" id="content_scroll_stable"></div> + </div> + + <div class="container" style="overflow-y: hidden" id="container_hidden_stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-y: auto;" id="container_auto_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll" id="container_scroll_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: hidden;" id="container_hidden_stable_both_edges"> + <div class="content"></div> + </div> + </div> + + <script> + let container_scroll_stable = document.getElementById("container_scroll_stable"); + let content_scroll_stable = document.getElementById("content_scroll_stable"); + let vScrollbarWidth = (container_scroll_stable.offsetWidth - content_scroll_stable.offsetWidth); + let vScrollbarWidthStr = vScrollbarWidth + "px"; + + // Simulate scrollbar-gutter via padding on containers. + document.getElementById("container_hidden_stable").style.paddingInlineEnd = vScrollbarWidthStr; + document.getElementById("container_auto_stable_both_edges").style.paddingInlineStart = vScrollbarWidthStr; + document.getElementById("container_scroll_stable_both_edges").style.paddingInlineStart = vScrollbarWidthStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineStart = vScrollbarWidthStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineEnd = vScrollbarWidthStr; + </script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-rtl-002.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-rtl-002.html new file mode 100644 index 0000000..8d0376d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-rtl-002.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow: test scrollbar-gutter with horizontal right to left content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property"> + <link rel="match" href="scrollbar-gutter-rtl-002-ref.html"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: horizontal-tb; + direction: rtl; + + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-y: auto; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: hidden; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-y: auto; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: scroll; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-y: hidden; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + </div> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002-ref.html new file mode 100644 index 0000000..cb7c647 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002-ref.html
@@ -0,0 +1,72 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow Reference: test scrollbar-gutter with vertical left to right content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: vertical-lr; + + box-sizing: border-box; + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-x: auto"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll" id="container_scroll_stable"> + <div class="content" id="content_scroll_stable"></div> + </div> + + <div class="container" style="overflow-x: hidden" id="container_hidden_stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-x: auto;" id="container_auto_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll" id="container_scroll_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: hidden;" id="container_hidden_stable_both_edges"> + <div class="content"></div> + </div> + </div> + + <script> + let container_scroll_stable = document.getElementById("container_scroll_stable"); + let content_scroll_stable = document.getElementById("content_scroll_stable"); + let hScrollbarHeight = (container_scroll_stable.offsetHeight - content_scroll_stable.offsetHeight); + let hScrollbarHeightStr = hScrollbarHeight + "px"; + + // Simulate scrollbar-gutter via padding on containers. + document.getElementById("container_hidden_stable").style.paddingInlineEnd = hScrollbarHeightStr; + document.getElementById("container_auto_stable_both_edges").style.paddingInlineStart = hScrollbarHeightStr; + document.getElementById("container_scroll_stable_both_edges").style.paddingInlineStart = hScrollbarHeightStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineStart = hScrollbarHeightStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineEnd = hScrollbarHeightStr; + </script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html new file mode 100644 index 0000000..9e5dcd29 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-lr-002.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow: test scrollbar-gutter with vertical left to right content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property"> + <link rel="match" href="scrollbar-gutter-vertical-lr-002-ref.html"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: vertical-lr; + + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-x: auto; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: hidden; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-x: auto; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: hidden; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + </div> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002-ref.html new file mode 100644 index 0000000..7dbadf9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002-ref.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow Reference: test scrollbar-gutter with vertical right to left content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: vertical-rl; + direction: ltr; + + box-sizing: border-box; + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-x: auto"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll" id="container_scroll_stable"> + <div class="content" id="content_scroll_stable"></div> + </div> + + <div class="container" style="overflow-x: hidden" id="container_hidden_stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-x: auto;" id="container_auto_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll" id="container_scroll_stable_both_edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: hidden;" id="container_hidden_stable_both_edges"> + <div class="content"></div> + </div> + </div> + + <script> + let container_scroll_stable = document.getElementById("container_scroll_stable"); + let content_scroll_stable = document.getElementById("content_scroll_stable"); + let hScrollbarHeight = (container_scroll_stable.offsetHeight - content_scroll_stable.offsetHeight); + let hScrollbarHeightStr = hScrollbarHeight + "px"; + + // Simulate scrollbar-gutter via padding on containers. + document.getElementById("container_hidden_stable").style.paddingInlineEnd = hScrollbarHeightStr; + document.getElementById("container_auto_stable_both_edges").style.paddingInlineStart = hScrollbarHeightStr; + document.getElementById("container_scroll_stable_both_edges").style.paddingInlineStart = hScrollbarHeightStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineStart = hScrollbarHeightStr; + document.getElementById("container_hidden_stable_both_edges").style.paddingInlineEnd = hScrollbarHeightStr; + </script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html new file mode 100644 index 0000000..d68d4e5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollbar-gutter-vertical-rl-002.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html> + <meta charset="utf-8"> + <title>CSS Overflow: test scrollbar-gutter with vertical right to left content</title> + <link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> + <link rel="author" title="Mozilla" href="http://www.mozilla.org/"> + <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property"> + <link rel="match" href="scrollbar-gutter-vertical-rl-002-ref.html"> + + <style> + .line { + display: flex; + } + + .container { + writing-mode: vertical-rl; + + block-size: 200px; + inline-size: 200px; + margin: 10px; + background: deepskyblue; + resize: both; + } + + .content { + inline-size: 100%; + block-size: 200%; + background: lightsalmon; + } + </style> + + <div class="line"> + <div class="container" style="overflow-x: auto; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: hidden; scrollbar-gutter: stable"> + <div class="content"></div> + </div> + </div> + + <div class="line"> + <div class="container" style="overflow-x: auto; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: scroll; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + + <div class="container" style="overflow-x: hidden; scrollbar-gutter: stable both-edges"> + <div class="content"></div> + </div> + </div> +</html>
diff --git a/third_party/blink/web_tests/virtual/webid/README.md b/third_party/blink/web_tests/virtual/webid/README.md deleted file mode 100644 index 4731317..0000000 --- a/third_party/blink/web_tests/virtual/webid/README.md +++ /dev/null
@@ -1,3 +0,0 @@ -# Overview - -This suite runs the tests in wpt_internal/webid with `--enable-features=WebID`
diff --git a/third_party/blink/web_tests/wpt_internal/webid/README.md b/third_party/blink/web_tests/wpt_internal/webid/README.md deleted file mode 100644 index 9c8d6e62..0000000 --- a/third_party/blink/web_tests/wpt_internal/webid/README.md +++ /dev/null
@@ -1,29 +0,0 @@ -The `webid-helpers.js` exposes `webid_test` which is a specialized -`promise_test` which comes pre-setup with the appropriate mocking infrastructure -to emulate platform federated auth backend. The mock is passed to the test -function as the second parameter. - -Example usage: -``` -<script type="module"> - import {webid_test} from './resources/webid-helper.js'; - - webid_test(async (t, mock) => { - mock.returnIdToken("a_token"); - assert_equals("a_token", await navigator.id.get(options)); - }, "Successfully obtaining a token using mock."); -</script> -``` - -The mock interface, `MockFederatedAuthRequest`, is defined as: - -``` -class MockFederatedAuthRequest { - // Causes the subsequent `navigator.id.get()` to resolve with the token. - returnIdToken(string token); - // Causes the subsequent `navigator.id.get()` to reject with the error. - returnError(string error); -}; -``` - -The chromium implementation uses the MojoJS shim.
diff --git a/third_party/blink/web_tests/wpt_internal/webid/insecure-context.html b/third_party/blink/web_tests/wpt_internal/webid/insecure-context.html deleted file mode 100644 index cd07351..0000000 --- a/third_party/blink/web_tests/wpt_internal/webid/insecure-context.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>WebID requires secure context</title> -<link rel="author" title="Majid Valipour" href="mailto:majidvp@chromium.org"> -<link rel="help" href="https://wicg.github.io/WebID"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -test(t => { - assert_false(isSecureContext); - assert_false('id' in navigator); -}, "navigator.id requires secure context."); -</script>
diff --git a/third_party/blink/web_tests/wpt_internal/webid/resources/webid-helper.js b/third_party/blink/web_tests/wpt_internal/webid/resources/webid-helper.js deleted file mode 100644 index ecf6795..0000000 --- a/third_party/blink/web_tests/wpt_internal/webid/resources/webid-helper.js +++ /dev/null
@@ -1,18 +0,0 @@ -// The testing infra for WebID is loaded using mojo js shim. To enable these -// tests the browser must be run with these options: -// -// --enable-blink-features=MojoJS,MojoJSTest - -import { MockFederatedAuthRequest } from './webid-mock.js'; - -export function webid_test(test_func, name, properties) { - promise_test(async (t) => { - assert_implements(navigator.id, 'missing navigator.id'); - const mock = new MockFederatedAuthRequest(); - try { - await test_func(t, mock); - } finally { - await mock.reset(); - } - }, name, properties); -}
diff --git a/third_party/blink/web_tests/wpt_internal/webid/resources/webid-mock.js b/third_party/blink/web_tests/wpt_internal/webid/resources/webid-mock.js deleted file mode 100644 index 4aa9af4..0000000 --- a/third_party/blink/web_tests/wpt_internal/webid/resources/webid-mock.js +++ /dev/null
@@ -1,75 +0,0 @@ -import { RequestMode, RequestIdTokenStatus, LogoutStatus, RevokeStatus, FederatedAuthRequest, FederatedAuthRequestReceiver } from '/gen/third_party/blink/public/mojom/webid/federated_auth_request.mojom.m.js'; - -function toMojoIdTokenStatus(status) { - switch(status) { - case "Success": return RequestIdTokenStatus.kSuccess; - case "ApprovalDeclined": return RequestIdTokenStatus.kApprovalDeclined; - case "ErrorTooManyRequests": return RequestIdTokenStatus.kErrorTooManyRequests; - case "ErrorWebIdNotSupportedByProvider": return RequestIdTokenStatus.kErrorWebIdNotSupportedByProvider; - case "ErrorFetchingWellKnown": return RequestIdTokenStatus.kErrorFetchingWellKnown; - case "ErrorInvalidWellKnown": return RequestIdTokenStatus.kErrorInvalidWellKnown; - case "ErrorFetchingSignin": return RequestIdTokenStatus.kErrorFetchingSignin; - case "ErrorInvalidSigninResponse": return RequestIdTokenStatus.kErrorInvalidSigninResponse; - case "ErrorInvalidAccountsResponse": return RequestIdTokenStatus.kErrorInvalidAccountsResponse; - case "ErrorInvalidTokenResponse": return RequestIdTokenStatus.kErrorInvalidTokenResponse; - case "Error": return RequestIdTokenStatus.kError; - default: throw new Error(`Invalid status: ${status}`); - } -} - -// A mock service for responding to federated auth requests. -export class MockFederatedAuthRequest { - constructor() { - this.receiver_ = new FederatedAuthRequestReceiver(this); - this.interceptor_ = new MojoInterfaceInterceptor(FederatedAuthRequest.$interfaceName); - this.interceptor_.oninterfacerequest = e => { - this.receiver_.$.bindHandle(e.handle); - } - this.interceptor_.start(); - this.idToken_ = null; - this.status_ = RequestIdTokenStatus.kError; - this.logoutStatus_ = LogoutStatus.kError; - } - - // Causes the subsequent `navigator.id.get()` to resolve with the token. - returnIdToken(token) { - this.status_ = RequestIdTokenStatus.kSuccess; - this.idToken_ = token; - } - - // Causes the subsequent `navigator.id.get()` to reject with the error. - returnError(error) { - if (error == "Success") - throw new Error("Success is not a valid error"); - this.status_ = toMojoIdTokenStatus(error); - this.idToken_ = null; - } - - // Implements - // RequestIdToken(url.mojom.Url provider, string id_request, RequestMode mode) => (RequestIdTokenStatus status, string? id_token); - async requestIdToken(provider, idRequest, mode) { - return Promise.resolve({ - status: this.status_, - idToken: this.idToken_ - }); - } - - async logout(logout_endpoints) { - return Promise.resolve({ - status: this.logoutStatus_ - }); - } - - async reset() { - this.idToken_ = null; - this.status_ = RequestIdTokenStatus.kError; - this.logoutStatus_ = LogoutStatus.kError; - this.receiver_.$.close(); - this.interceptor_.stop(); - - // Clean up and reset mock stubs asynchronously, so that the blink side - // closes its proxies and notifies JS sensor objects before new test is - // started. - await new Promise(resolve => { setTimeout(resolve, 0); }); - } -}
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 2cf1f73..fe056c5 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: 3b8a7cf594da2e3454fb230f98a60808837da217 +Revision: 5cc0d543d0e5dadba03a6bf7dd8161fb78ab07b5 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes @@ -36,6 +36,7 @@ Local Modifications: - codereview.settings has been excluded. + - infra/ has been excluded. - MultiprocessExec.MultiprocessExec is disabled when OS_POSIX and BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) are defined. crbug.com/1153544 (crashpad/test/BUILD.gn, crashpad/test/multiprocess_exec_test.cc)
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index c1edb80c..e13bea8 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -33,13 +33,13 @@ }, 'crashpad/third_party/googletest/googletest': Var('chromium_git') + '/external/github.com/google/googletest@' + - '11da093e0477185dbd78abaaa9f99db15be498d0', + '5bcd8e3bb929714e031a542d303f818e5a5af45d', 'crashpad/third_party/lss/lss': Var('chromium_git') + '/linux-syscall-support.git@' + '7bde79cc274d06451bf65ae82c012a5d3e476b5a', 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - '0e22eed71eec97dacbe80822a14c5cd0b580d793', + '502930381b23c5fa3911c8b82ec3e4ba6ceb3658', 'crashpad/third_party/libfuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' + 'fda403cf93ecb8792cb1d061564d89a6553ca020', @@ -106,7 +106,7 @@ 'packages': [ { 'package': 'chrome_internal/third_party/sdk/windows', - 'version': 'uploaded:2018-06-13' + 'version': 'uploaded:2021-04-28' }, ], 'condition': 'checkout_win and pull_win_toolchain',
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc index a3ddc31..ddf15390 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc
@@ -26,6 +26,7 @@ #include "client/annotation.h" #include "client/annotation_list.h" #include "client/crash_report_database.h" +#include "client/crashpad_info.h" #include "client/simulate_crash.h" #include "gtest/gtest.h" #include "snapshot/annotation_snapshot.h" @@ -73,12 +74,13 @@ bool set_first_chance_handler; bool crash_non_main_thread; bool client_uses_signals; + bool gather_indirectly_referenced_memory; CrashType crash_type; }; class StartHandlerForSelfTest : public testing::TestWithParam< - std::tuple<bool, bool, bool, bool, CrashType>> { + std::tuple<bool, bool, bool, bool, bool, CrashType>> { public: StartHandlerForSelfTest() = default; @@ -92,6 +94,7 @@ options_.set_first_chance_handler, options_.crash_non_main_thread, options_.client_uses_signals, + options_.gather_indirectly_referenced_memory, options_.crash_type) = GetParam(); } @@ -147,7 +150,8 @@ 0); } -void ValidateExtraMemory(const ProcessSnapshotMinidump& minidump) { +void ValidateExtraMemory(const StartHandlerForSelfTestOptions& options, + const ProcessSnapshotMinidump& minidump) { // Verify that if we have an exception, then the code around the instruction // pointer is included in the extra memory. const ExceptionSnapshot* exception = minidump.Exception(); @@ -164,10 +168,11 @@ break; } } - EXPECT_TRUE(pc_found); + EXPECT_EQ(pc_found, options.gather_indirectly_referenced_memory); } -void ValidateDump(const CrashReportDatabase::UploadReport* report) { +void ValidateDump(const StartHandlerForSelfTestOptions& options, + const CrashReportDatabase::UploadReport* report) { ProcessSnapshotMinidump minidump_snapshot; ASSERT_TRUE(minidump_snapshot.Initialize(report->Reader())); @@ -184,7 +189,7 @@ #endif ValidateAttachment(report); - ValidateExtraMemory(minidump_snapshot); + ValidateExtraMemory(options, minidump_snapshot); for (const ModuleSnapshot* module : minidump_snapshot.Modules()) { for (const AnnotationSnapshot& annotation : module->AnnotationObjects()) { @@ -330,6 +335,11 @@ client_handler, SA_ONSTACK, &old_actions)); } + if (options.gather_indirectly_referenced_memory) { + CrashpadInfo::GetCrashpadInfo()->set_gather_indirectly_referenced_memory( + TriState::kEnabled, 1024 * 1024 * 4); + } + base::FilePath handler_path = TestPaths::Executable().DirName().Append( FILE_PATH_LITERAL("crashpad_handler")); @@ -442,7 +452,7 @@ std::unique_ptr<const CrashReportDatabase::UploadReport> report; ASSERT_EQ(database->GetReportForUploading(reports[0].uuid, &report), CrashReportDatabase::kNoError); - ValidateDump(report.get()); + ValidateDump(options_, report.get()); } StartHandlerForSelfTestOptions options_; @@ -471,6 +481,7 @@ testing::Bool(), testing::Bool(), testing::Bool(), + testing::Bool(), testing::Values(CrashType::kSimulated, CrashType::kBuiltinTrap, CrashType::kInfiniteRecursion)));
diff --git a/third_party/crashpad/crashpad/client/crashpad_info_note.S b/third_party/crashpad/crashpad/client/crashpad_info_note.S index b13d864..ef3d68c 100644 --- a/third_party/crashpad/crashpad/client/crashpad_info_note.S +++ b/third_party/crashpad/crashpad/client/crashpad_info_note.S
@@ -17,6 +17,7 @@ // that symbol to be in the dynamic symbol table. #include "util/misc/elf_note_types.h" +#include "util/misc/arm64_bti_note.S" // namespace crashpad { // CrashpadInfo g_crashpad_info;
diff --git a/third_party/crashpad/crashpad/infra/config/PRESUBMIT.py b/third_party/crashpad/crashpad/infra/config/PRESUBMIT.py deleted file mode 100644 index 3961942..0000000 --- a/third_party/crashpad/crashpad/infra/config/PRESUBMIT.py +++ /dev/null
@@ -1,28 +0,0 @@ -# Copyright 2018 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. - - -USE_PYTHON3 = True -PRESUBMIT_VERSION = '2.0.0' - - -def CheckChangedLUCIConfigs(input_api, output_api): - return input_api.canned_checks.CheckChangedLUCIConfigs( - input_api, output_api) - - -def CheckLucicfgGenOutputMain(input_api, output_api): - return input_api.RunTests( - input_api.canned_checks.CheckLucicfgGenOutput(input_api, output_api, - 'main.star'))
diff --git a/third_party/crashpad/crashpad/infra/config/generated/commit-queue.cfg b/third_party/crashpad/crashpad/infra/config/generated/commit-queue.cfg deleted file mode 100644 index 95b31824..0000000 --- a/third_party/crashpad/crashpad/infra/config/generated/commit-queue.cfg +++ /dev/null
@@ -1,80 +0,0 @@ -# Auto-generated by lucicfg. -# Do not modify manually. -# -# For the schema of this file, see Config message: -# https://luci-config.appspot.com/schemas/projects:commit-queue.cfg - -cq_status_host: "chromium-cq-status.appspot.com" -submit_options { - max_burst: 4 - burst_delay { - seconds: 480 - } -} -config_groups { - name: "crashpad" - gerrit { - url: "https://chromium-review.googlesource.com" - projects { - name: "crashpad/crashpad" - ref_regexp: "refs/heads/.+" - } - } - verifiers { - gerrit_cq_ability { - committer_list: "project-crashpad-tryjob-access" - dry_run_access_list: "project-crashpad-tryjob-access" - } - tryjob { - builders { - name: "crashpad/try/crashpad_fuchsia_arm64_dbg" - } - builders { - name: "crashpad/try/crashpad_fuchsia_arm64_rel" - } - builders { - name: "crashpad/try/crashpad_fuchsia_x64_dbg" - } - builders { - name: "crashpad/try/crashpad_fuchsia_x64_rel" - } - builders { - name: "crashpad/try/crashpad_ios_arm64_dbg" - } - builders { - name: "crashpad/try/crashpad_ios_arm64_rel" - } - builders { - name: "crashpad/try/crashpad_ios_x64_dbg" - } - builders { - name: "crashpad/try/crashpad_ios_x64_rel" - } - builders { - name: "crashpad/try/crashpad_linux_x64_dbg" - } - builders { - name: "crashpad/try/crashpad_linux_x64_rel" - } - builders { - name: "crashpad/try/crashpad_mac_x64_dbg" - } - builders { - name: "crashpad/try/crashpad_mac_x64_rel" - } - builders { - name: "crashpad/try/crashpad_win_x64_dbg" - } - builders { - name: "crashpad/try/crashpad_win_x64_rel" - } - retry_config { - single_quota: 1 - global_quota: 2 - failure_weight: 1 - transient_failure_weight: 1 - timeout_weight: 2 - } - } - } -}
diff --git a/third_party/crashpad/crashpad/infra/config/generated/cr-buildbucket.cfg b/third_party/crashpad/crashpad/infra/config/generated/cr-buildbucket.cfg deleted file mode 100644 index d34621c..0000000 --- a/third_party/crashpad/crashpad/infra/config/generated/cr-buildbucket.cfg +++ /dev/null
@@ -1,972 +0,0 @@ -# Auto-generated by lucicfg. -# Do not modify manually. -# -# For the schema of this file, see BuildbucketCfg message: -# https://luci-config.appspot.com/schemas/projects:buildbucket.cfg - -buckets { - name: "ci" - acls { - role: WRITER - group: "project-crashpad-admins" - } - acls { - group: "all" - } - acls { - role: SCHEDULER - identity: "user:luci-scheduler@appspot.gserviceaccount.com" - } - swarming { - builders { - name: "crashpad_fuchsia_arm64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_fuchsia_arm64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_fuchsia_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_fuchsia_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_arm64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_arm64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_linux_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "linux"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_linux_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "linux"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_mac_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "mac"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_mac" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_mac_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "mac"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_mac" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_win_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-10" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "win"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_win_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-10" - dimensions: "pool:luci.flex.ci" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$gatekeeper": {' - ' "group": "client.crashpad"' - ' },' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "win"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - } -} -buckets { - name: "try" - acls { - role: WRITER - group: "project-crashpad-admins" - } - acls { - role: WRITER - group: "service-account-crashpad-cq" - } - acls { - group: "all" - } - acls { - role: SCHEDULER - group: "project-crashpad-tryjob-access" - } - acls { - role: SCHEDULER - group: "service-account-cq" - } - swarming { - builders { - name: "crashpad_fuchsia_arm64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_fuchsia_arm64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_fuchsia_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_fuchsia_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "fuchsia"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_arm64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_arm64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_cpu": "arm64",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_ios_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "ios"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_ios" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_linux_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "linux"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_linux_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-16.04" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "linux"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_mac_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "mac"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_mac" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_mac_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.15" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "mac"' - '}' - execution_timeout_secs: 10800 - caches { - name: "osx_sdk_mac" - path: "osx_sdk" - } - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_win_x64_dbg" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-10" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Debug",' - ' "recipe": "crashpad/build",' - ' "target_os": "win"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - builders { - name: "crashpad_win_x64_rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Windows-10" - dimensions: "pool:luci.flex.try" - exe { - cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" - cipd_version: "refs/heads/main" - cmd: "luciexe" - } - properties: - '{' - ' "$kitchen": {' - ' "devshell": true,' - ' "git_auth": true' - ' },' - ' "config": "Release",' - ' "recipe": "crashpad/build",' - ' "target_os": "win"' - '}' - execution_timeout_secs: 10800 - build_numbers: YES - service_account: "crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - } - } -}
diff --git a/third_party/crashpad/crashpad/infra/config/generated/luci-logdog.cfg b/third_party/crashpad/crashpad/infra/config/generated/luci-logdog.cfg deleted file mode 100644 index adc75be..0000000 --- a/third_party/crashpad/crashpad/infra/config/generated/luci-logdog.cfg +++ /dev/null
@@ -1,9 +0,0 @@ -# Auto-generated by lucicfg. -# Do not modify manually. -# -# For the schema of this file, see ProjectConfig message: -# https://luci-config.appspot.com/schemas/projects:luci-logdog.cfg - -reader_auth_groups: "all" -writer_auth_groups: "luci-logdog-chromium-writers" -archive_gs_bucket: "chromium-luci-logdog"
diff --git a/third_party/crashpad/crashpad/infra/config/generated/luci-milo.cfg b/third_party/crashpad/crashpad/infra/config/generated/luci-milo.cfg deleted file mode 100644 index 6c891b1..0000000 --- a/third_party/crashpad/crashpad/infra/config/generated/luci-milo.cfg +++ /dev/null
@@ -1,131 +0,0 @@ -# Auto-generated by lucicfg. -# Do not modify manually. -# -# For the schema of this file, see Project message: -# https://luci-config.appspot.com/schemas/projects:luci-milo.cfg - -consoles { - id: "main" - name: "Crashpad Main Console" - repo_url: "https://chromium.googlesource.com/crashpad/crashpad" - refs: "regexp:refs/heads/main" - manifest_name: "REVISION" - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_fuchsia_arm64_dbg" - category: "fuchsia|arm64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_fuchsia_arm64_rel" - category: "fuchsia|arm64" - short_name: "rel" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_fuchsia_x64_dbg" - category: "fuchsia|x64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_fuchsia_x64_rel" - category: "fuchsia|x64" - short_name: "rel" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_ios_arm64_dbg" - category: "ios|arm64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_ios_arm64_rel" - category: "ios|arm64" - short_name: "rel" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_ios_x64_dbg" - category: "ios|x64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_ios_x64_rel" - category: "ios|x64" - short_name: "rel" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_linux_x64_dbg" - category: "linux|x64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_linux_x64_rel" - category: "linux|x64" - short_name: "rel" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_mac_x64_dbg" - category: "mac|x64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_mac_x64_rel" - category: "mac|x64" - short_name: "rel" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_win_x64_dbg" - category: "win|x64" - short_name: "dbg" - } - builders { - name: "buildbucket/luci.crashpad.ci/crashpad_win_x64_rel" - category: "win|x64" - short_name: "rel" - } -} -consoles { - id: "try" - name: "Crashpad Try Builders" - builders { - name: "buildbucket/luci.crashpad.try/crashpad_fuchsia_arm64_dbg" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_fuchsia_arm64_rel" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_fuchsia_x64_dbg" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_fuchsia_x64_rel" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_ios_arm64_dbg" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_ios_arm64_rel" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_ios_x64_dbg" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_ios_x64_rel" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_linux_x64_dbg" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_linux_x64_rel" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_mac_x64_dbg" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_mac_x64_rel" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_win_x64_dbg" - } - builders { - name: "buildbucket/luci.crashpad.try/crashpad_win_x64_rel" - } - builder_view_only: true -} -logo_url: "https://storage.googleapis.com/chrome-infra-public/logo/crashpad-logo.svg"
diff --git a/third_party/crashpad/crashpad/infra/config/generated/luci-scheduler.cfg b/third_party/crashpad/crashpad/infra/config/generated/luci-scheduler.cfg deleted file mode 100644 index 6b3d04d1..0000000 --- a/third_party/crashpad/crashpad/infra/config/generated/luci-scheduler.cfg +++ /dev/null
@@ -1,179 +0,0 @@ -# Auto-generated by lucicfg. -# Do not modify manually. -# -# For the schema of this file, see ProjectConfig message: -# https://luci-config.appspot.com/schemas/projects:luci-scheduler.cfg - -job { - id: "crashpad_fuchsia_arm64_dbg" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_fuchsia_arm64_dbg" - } -} -job { - id: "crashpad_fuchsia_arm64_rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_fuchsia_arm64_rel" - } -} -job { - id: "crashpad_fuchsia_x64_dbg" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_fuchsia_x64_dbg" - } -} -job { - id: "crashpad_fuchsia_x64_rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_fuchsia_x64_rel" - } -} -job { - id: "crashpad_ios_arm64_dbg" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_ios_arm64_dbg" - } -} -job { - id: "crashpad_ios_arm64_rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_ios_arm64_rel" - } -} -job { - id: "crashpad_ios_x64_dbg" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_ios_x64_dbg" - } -} -job { - id: "crashpad_ios_x64_rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_ios_x64_rel" - } -} -job { - id: "crashpad_linux_x64_dbg" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_linux_x64_dbg" - } -} -job { - id: "crashpad_linux_x64_rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_linux_x64_rel" - } -} -job { - id: "crashpad_mac_x64_dbg" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_mac_x64_dbg" - } -} -job { - id: "crashpad_mac_x64_rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_mac_x64_rel" - } -} -job { - id: "crashpad_win_x64_dbg" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_win_x64_dbg" - } -} -job { - id: "crashpad_win_x64_rel" - realm: "ci" - acl_sets: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "luci.crashpad.ci" - builder: "crashpad_win_x64_rel" - } -} -trigger { - id: "master-gitiles-trigger" - realm: "ci" - acl_sets: "ci" - triggers: "crashpad_fuchsia_arm64_dbg" - triggers: "crashpad_fuchsia_arm64_rel" - triggers: "crashpad_fuchsia_x64_dbg" - triggers: "crashpad_fuchsia_x64_rel" - triggers: "crashpad_ios_arm64_dbg" - triggers: "crashpad_ios_arm64_rel" - triggers: "crashpad_ios_x64_dbg" - triggers: "crashpad_ios_x64_rel" - triggers: "crashpad_linux_x64_dbg" - triggers: "crashpad_linux_x64_rel" - triggers: "crashpad_mac_x64_dbg" - triggers: "crashpad_mac_x64_rel" - triggers: "crashpad_win_x64_dbg" - triggers: "crashpad_win_x64_rel" - gitiles { - repo: "https://chromium.googlesource.com/crashpad/crashpad" - refs: "regexp:refs/heads/main" - } -} -acl_sets { - name: "ci" - acls { - role: OWNER - granted_to: "group:project-crashpad-admins" - } - acls { - granted_to: "group:all" - } -}
diff --git a/third_party/crashpad/crashpad/infra/config/generated/project.cfg b/third_party/crashpad/crashpad/infra/config/generated/project.cfg deleted file mode 100644 index 9dcccbfa..0000000 --- a/third_party/crashpad/crashpad/infra/config/generated/project.cfg +++ /dev/null
@@ -1,14 +0,0 @@ -# Auto-generated by lucicfg. -# Do not modify manually. -# -# For the schema of this file, see ProjectCfg message: -# https://luci-config.appspot.com/schemas/projects:project.cfg - -name: "crashpad" -access: "group:all" -lucicfg { - version: "1.30.1" - package_dir: ".." - config_dir: "generated" - entry_point: "main.star" -}
diff --git a/third_party/crashpad/crashpad/infra/config/generated/realms.cfg b/third_party/crashpad/crashpad/infra/config/generated/realms.cfg deleted file mode 100644 index 8dc05f6b..0000000 --- a/third_party/crashpad/crashpad/infra/config/generated/realms.cfg +++ /dev/null
@@ -1,65 +0,0 @@ -# Auto-generated by lucicfg. -# Do not modify manually. -# -# For the schema of this file, see RealmsCfg message: -# https://luci-config.appspot.com/schemas/projects:realms.cfg - -realms { - name: "@root" - bindings { - role: "role/buildbucket.reader" - principals: "group:all" - } - bindings { - role: "role/configs.reader" - principals: "group:all" - } - bindings { - role: "role/logdog.reader" - principals: "group:all" - } - bindings { - role: "role/logdog.writer" - principals: "group:luci-logdog-chromium-writers" - } - bindings { - role: "role/scheduler.owner" - principals: "group:project-crashpad-admins" - } - bindings { - role: "role/scheduler.reader" - principals: "group:all" - } -} -realms { - name: "ci" - bindings { - role: "role/buildbucket.builderServiceAccount" - principals: "user:crashpad-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - } - bindings { - role: "role/buildbucket.owner" - principals: "group:project-crashpad-admins" - } - bindings { - role: "role/buildbucket.triggerer" - principals: "user:luci-scheduler@appspot.gserviceaccount.com" - } -} -realms { - name: "try" - bindings { - role: "role/buildbucket.builderServiceAccount" - principals: "user:crashpad-try-builder@chops-service-accounts.iam.gserviceaccount.com" - } - bindings { - role: "role/buildbucket.owner" - principals: "group:project-crashpad-admins" - principals: "group:service-account-crashpad-cq" - } - bindings { - role: "role/buildbucket.triggerer" - principals: "group:project-crashpad-tryjob-access" - principals: "group:service-account-cq" - } -}
diff --git a/third_party/crashpad/crashpad/infra/config/main.star b/third_party/crashpad/crashpad/infra/config/main.star deleted file mode 100755 index f51ef23..0000000 --- a/third_party/crashpad/crashpad/infra/config/main.star +++ /dev/null
@@ -1,261 +0,0 @@ -#!/usr/bin/env lucicfg -# Copyright 2021 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. - -lucicfg.check_version("1.28.0", "Please update depot_tools") - -# Enable LUCI Realms support and Launch 100% of Swarming tasks for builds in -# "realms-aware mode". -lucicfg.enable_experiment("crbug.com/1085650") - -REPO_URL = "https://chromium.googlesource.com/crashpad/crashpad" -REVIEW_URL = "https://chromium-review.googlesource.com/crashpad/crashpad" - -luci.project( - name = "crashpad", - buildbucket = "cr-buildbucket.appspot.com", - swarming = "chromium-swarm.appspot.com", - acls = [ - acl.entry( - roles = [ - acl.LOGDOG_READER, - acl.PROJECT_CONFIGS_READER, - acl.SCHEDULER_READER, - acl.BUILDBUCKET_READER, - ], - groups = "all", - ), - acl.entry( - roles = acl.LOGDOG_WRITER, - groups = "luci-logdog-chromium-writers", - ), - acl.entry( - roles = acl.SCHEDULER_OWNER, - groups = "project-crashpad-admins", - ), - ], - logdog = "luci-logdog.appspot.com", - milo = "luci-milo.appspot.com", - scheduler = "luci-scheduler.appspot.com", -) - -luci.cq( - status_host = "chromium-cq-status.appspot.com", - submit_max_burst = 4, - submit_burst_delay = 8 * time.minute, -) - -luci.cq_group( - name = "crashpad", - watch = cq.refset(repo = REVIEW_URL, refs = ["refs/heads/.+"]), - retry_config = cq.retry_config( - single_quota = 1, - global_quota = 2, - failure_weight = 1, - transient_failure_weight = 1, - timeout_weight = 2, - ), - acls = [ - acl.entry( - roles = acl.CQ_COMMITTER, - groups = "project-crashpad-tryjob-access", - ), - acl.entry( - roles = acl.CQ_DRY_RUNNER, - groups = "project-crashpad-tryjob-access", - ), - ], -) - -luci.gitiles_poller( - name = "master-gitiles-trigger", - bucket = "ci", - repo = REPO_URL, -) - -luci.logdog( - gs_bucket = "chromium-luci-logdog", -) - -luci.milo( - logo = "https://storage.googleapis.com/chrome-infra-public/logo/crashpad-logo.svg", -) - -luci.console_view( - name = "main", - repo = REPO_URL, - title = "Crashpad Main Console", -) - -luci.list_view( - name = "try", - title = "Crashpad Try Builders", -) - -luci.bucket( - name = "ci", - acls = [ - acl.entry( - acl.BUILDBUCKET_OWNER, - groups = "project-crashpad-admins", - ), - acl.entry( - acl.BUILDBUCKET_TRIGGERER, - users = "luci-scheduler@appspot.gserviceaccount.com", - ), - ], -) - -luci.bucket( - name = "try", - acls = [ - acl.entry( - acl.BUILDBUCKET_OWNER, - groups = [ - "service-account-crashpad-cq", - "project-crashpad-admins", - ], - ), - acl.entry( - acl.BUILDBUCKET_TRIGGERER, - groups = "service-account-cq", - ), - acl.entry( - acl.BUILDBUCKET_TRIGGERER, - groups = "project-crashpad-tryjob-access", - ), - ], -) - -def crashpad_recipe(): - return luci.recipe( - name = "crashpad/build", - cipd_package = "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build", - use_python3=True, - ) - -def crashpad_caches(platform): - if platform == "ios": - return [swarming.cache("osx_sdk", name = "osx_sdk_ios")] - elif platform == "mac": - return [swarming.cache("osx_sdk", name = "osx_sdk_mac")] - -def crashpad_dimensions(platform, bucket): - dimensions = {} - dimensions["cpu"] = "x86-64" - dimensions["pool"] = "luci.flex." + bucket - - if platform == "fuchsia": - dimensions["os"] = "Ubuntu-16.04" - elif platform == "ios": - dimensions["os"] = "Mac-10.15" - elif platform == "linux": - dimensions["os"] = "Ubuntu-16.04" - elif platform == "mac": - dimensions["os"] = "Mac-10.15" - elif platform == "win": - dimensions["os"] = "Windows-10" - - if platform == "fuchsia" or platform == "linux" or platform == "win": - dimensions["cores"] = "8" - - return dimensions - -def crashpad_properties(platform, cpu, config, bucket): - properties = {} - properties["target_os"] = platform - properties["$kitchen"] = { - "devshell": True, - "git_auth": True, - } - - if cpu != "x64": - properties["target_cpu"] = cpu - - if bucket == "ci": - properties["$gatekeeper"] = { - "group": "client.crashpad", - } - - if config == "dbg": - properties["config"] = "Debug" - elif config == "rel": - properties["config"] = "Release" - - return properties - -def crashpad_builder(platform, cpu, config, bucket): - name = "_".join(["crashpad", platform, cpu, config]) - triggered_by = None - - if bucket == "ci": - luci.console_view_entry( - builder = "ci/" + name, - console_view = "main", - short_name = config, - category = platform + "|" + cpu, - ) - triggered_by = ["master-gitiles-trigger"] - elif bucket == "try": - luci.list_view_entry( - builder = "try/" + name, - list_view = "try", - ) - luci.cq_tryjob_verifier( - "try/" + name, - cq_group = "crashpad", - ) - - return luci.builder( - name = name, - bucket = bucket, - executable = crashpad_recipe(), - build_numbers = True, - caches = crashpad_caches(platform), - dimensions = crashpad_dimensions(platform, bucket), - execution_timeout = 3 * time.hour, - properties = crashpad_properties(platform, cpu, config, bucket), - service_account = "crashpad-" + bucket + "-builder@chops-service-accounts.iam.gserviceaccount.com", - triggered_by = triggered_by, - ) - -crashpad_builder("fuchsia", "arm64", "dbg", "ci") -crashpad_builder("fuchsia", "arm64", "rel", "ci") -crashpad_builder("fuchsia", "x64", "dbg", "ci") -crashpad_builder("fuchsia", "x64", "rel", "ci") -crashpad_builder("ios", "arm64", "dbg", "ci") -crashpad_builder("ios", "arm64", "rel", "ci") -crashpad_builder("ios", "x64", "dbg", "ci") -crashpad_builder("ios", "x64", "rel", "ci") -crashpad_builder("linux", "x64", "dbg", "ci") -crashpad_builder("linux", "x64", "rel", "ci") -crashpad_builder("mac", "x64", "dbg", "ci") -crashpad_builder("mac", "x64", "rel", "ci") -crashpad_builder("win", "x64", "dbg", "ci") -crashpad_builder("win", "x64", "rel", "ci") - -crashpad_builder("fuchsia", "arm64", "dbg", "try") -crashpad_builder("fuchsia", "arm64", "rel", "try") -crashpad_builder("fuchsia", "x64", "dbg", "try") -crashpad_builder("fuchsia", "x64", "rel", "try") -crashpad_builder("ios", "arm64", "dbg", "try") -crashpad_builder("ios", "arm64", "rel", "try") -crashpad_builder("ios", "x64", "dbg", "try") -crashpad_builder("ios", "x64", "rel", "try") -crashpad_builder("linux", "x64", "dbg", "try") -crashpad_builder("linux", "x64", "rel", "try") -crashpad_builder("mac", "x64", "dbg", "try") -crashpad_builder("mac", "x64", "rel", "try") -crashpad_builder("win", "x64", "dbg", "try") -crashpad_builder("win", "x64", "rel", "try")
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc b/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc index f5baa5bc..4476e21 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc
@@ -144,7 +144,7 @@ EXPECT_EQ(options.crashpad_handler_behavior, TriState::kUnset); EXPECT_EQ(options.system_crash_reporter_forwarding, TriState::kUnset); EXPECT_EQ(options.gather_indirectly_referenced_memory, TriState::kEnabled); - EXPECT_EQ(options.indirectly_referenced_memory_cap, 1234u); + EXPECT_LE(options.indirectly_referenced_memory_cap, 1234u); } }
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S index 16b5d49..8b1a0bd 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S +++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S
@@ -17,6 +17,7 @@ // that symbol to be in the dynamic symbol table. #include "util/misc/elf_note_types.h" +#include "util/misc/arm64_bti_note.S" // namespace crashpad { // CrashpadInfo g_test_crashpad_info;
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S index 9ab0338..08f1829 100644 --- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S +++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S
@@ -13,6 +13,7 @@ // limitations under the License. #include "util/misc/elf_note_types.h" +#include "util/misc/arm64_bti_note.S" #define NOTE_ALIGN 4 .section .note.crashpad.test,"a",%note
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc index 496d97a8..9389868 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia_test.cc
@@ -56,7 +56,7 @@ // correctly. for (const auto& t : kTestMappingPermAndSizes) { zx_handle_t vmo = ZX_HANDLE_INVALID; - const size_t size = t.pages * PAGE_SIZE; + const size_t size = t.pages * zx_system_get_page_size(); zx_status_t status = zx_vmo_create(size, 0, &vmo); ZX_CHECK(status == ZX_OK, status) << "zx_vmo_create"; status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo); @@ -126,7 +126,7 @@ const auto& t = kTestMappingPermAndSizes[i]; EXPECT_TRUE(HasSingleMatchingMapping(process_snapshot.MemoryMap(), test_addresses[i], - t.pages * PAGE_SIZE, + t.pages * zx_system_get_page_size(), t.minidump_perm)) << base::StringPrintf( "index %zu, zircon_perm 0x%x, minidump_perm 0x%x",
diff --git a/third_party/crashpad/crashpad/snapshot/linux/capture_memory_delegate_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/capture_memory_delegate_linux.cc index 4f15874..918e572 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/capture_memory_delegate_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/capture_memory_delegate_linux.cc
@@ -57,19 +57,17 @@ return; if (range.size() == 0) return; - if (budget_remaining_ && *budget_remaining_ == 0) + if (!budget_remaining_ || *budget_remaining_ == 0) return; snapshots_->push_back(std::make_unique<internal::MemorySnapshotGeneric>()); internal::MemorySnapshotGeneric* snapshot = snapshots_->back().get(); snapshot->Initialize(process_reader_->Memory(), range.base(), range.size()); - if (budget_remaining_) { - if (!base::IsValueInRangeForNumericType<int64_t>(range.size())) { - *budget_remaining_ = 0; - } else { - int64_t temp = *budget_remaining_; - temp -= range.size(); - *budget_remaining_ = base::saturated_cast<uint32_t>(temp); - } + if (!base::IsValueInRangeForNumericType<int64_t>(range.size())) { + *budget_remaining_ = 0; + } else { + int64_t temp = *budget_remaining_; + temp -= range.size(); + *budget_remaining_ = base::saturated_cast<uint32_t>(temp); } }
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc index 42d0eb0..6726d048 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
@@ -326,10 +326,12 @@ #endif // ARCH_CPU_X86_FAMILY -bool ExceptionSnapshotLinux::Initialize(ProcessReaderLinux* process_reader, - LinuxVMAddress siginfo_address, - LinuxVMAddress context_address, - pid_t thread_id) { +bool ExceptionSnapshotLinux::Initialize( + ProcessReaderLinux* process_reader, + LinuxVMAddress siginfo_address, + LinuxVMAddress context_address, + pid_t thread_id, + uint32_t* gather_indirectly_referenced_memory_cap) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); thread_id_ = thread_id; @@ -359,7 +361,10 @@ } CaptureMemoryDelegateLinux capture_memory_delegate( - process_reader, thread, &extra_memory_, nullptr); + process_reader, + thread, + &extra_memory_, + gather_indirectly_referenced_memory_cap); CaptureMemory::PointedToByContext(context_, &capture_memory_delegate); INITIALIZATION_STATE_SET_VALID(initialized_);
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h index 1719f0b..05f6004 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h +++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
@@ -59,7 +59,8 @@ bool Initialize(ProcessReaderLinux* process_reader, LinuxVMAddress siginfo_address, LinuxVMAddress context_address, - pid_t thread_id); + pid_t thread_id, + uint32_t* gather_indirectly_referenced_memory_cap); // ExceptionSnapshot:
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc index 51d3fd3..91be497 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
@@ -320,7 +320,8 @@ ASSERT_TRUE(exception.Initialize(&process_reader, FromPointerCast<LinuxVMAddress>(&siginfo), FromPointerCast<LinuxVMAddress>(&context), - gettid())); + gettid(), + nullptr)); EXPECT_EQ(exception.Exception(), static_cast<uint32_t>(siginfo.si_signo)); EXPECT_EQ(exception.ExceptionInfo(), static_cast<uint32_t>(siginfo.si_code)); EXPECT_EQ(exception.ExceptionAddress(), @@ -393,7 +394,8 @@ ASSERT_TRUE(exception.Initialize(&process_reader, FromPointerCast<LinuxVMAddress>(siginfo), FromPointerCast<LinuxVMAddress>(context), - gettid())); + gettid(), + nullptr)); EXPECT_EQ(exception.Exception(), static_cast<uint32_t>(kSigno)); @@ -464,7 +466,8 @@ ASSERT_TRUE(exception.Initialize(&process_reader, FromPointerCast<LinuxVMAddress>(siginfo), FromPointerCast<LinuxVMAddress>(context), - gettid())); + gettid(), + nullptr)); EXPECT_EQ(exception.Exception(), static_cast<uint32_t>(kSigno));
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc index 62331347..a730b29 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc
@@ -42,10 +42,9 @@ client_id_.InitializeToZero(); system_.Initialize(&process_reader_, &snapshot_time_); - GetCrashpadOptionsInternal((&options_)); - - InitializeThreads(); InitializeModules(); + GetCrashpadOptionsInternal((&options_)); + InitializeThreads(); InitializeAnnotations(); INITIALIZATION_STATE_SET_VALID(initialized_); @@ -83,11 +82,17 @@ info.thread_id = exception_thread_id; } + uint32_t* budget_remaining_pointer = + options_.gather_indirectly_referenced_memory == TriState::kEnabled + ? &options_.indirectly_referenced_memory_cap + : nullptr; + exception_.reset(new internal::ExceptionSnapshotLinux()); if (!exception_->Initialize(&process_reader_, info.siginfo_address, info.context_address, - info.thread_id)) { + info.thread_id, + budget_remaining_pointer)) { exception_.reset(); return false; } @@ -269,11 +274,11 @@ void ProcessSnapshotLinux::InitializeThreads() { const std::vector<ProcessReaderLinux::Thread>& process_reader_threads = process_reader_.Threads(); - uint32_t* budget_remaining_pointer = nullptr; - uint32_t budget_remaining = options_.indirectly_referenced_memory_cap; - if (options_.gather_indirectly_referenced_memory == TriState::kEnabled) { - budget_remaining_pointer = &budget_remaining; - } + uint32_t* budget_remaining_pointer = + options_.gather_indirectly_referenced_memory == TriState::kEnabled + ? &options_.indirectly_referenced_memory_cap + : nullptr; + for (const ProcessReaderLinux::Thread& process_reader_thread : process_reader_threads) { auto thread = std::make_unique<internal::ThreadSnapshotLinux>();
diff --git a/third_party/crashpad/crashpad/snapshot/win/capture_memory_delegate_win.cc b/third_party/crashpad/crashpad/snapshot/win/capture_memory_delegate_win.cc index ee5e5d64..43067ca 100644 --- a/third_party/crashpad/crashpad/snapshot/win/capture_memory_delegate_win.cc +++ b/third_party/crashpad/crashpad/snapshot/win/capture_memory_delegate_win.cc
@@ -55,19 +55,17 @@ return; if (range.size() == 0) return; - if (budget_remaining_ && *budget_remaining_ == 0) + if (!budget_remaining_ || *budget_remaining_ == 0) return; snapshots_->push_back(std::make_unique<internal::MemorySnapshotGeneric>()); internal::MemorySnapshotGeneric* snapshot = snapshots_->back().get(); snapshot->Initialize(process_reader_->Memory(), range.base(), range.size()); - if (budget_remaining_) { - if (!base::IsValueInRangeForNumericType<int64_t>(range.size())) { - *budget_remaining_ = 0; - } else { - int64_t temp = *budget_remaining_; - temp -= range.size(); - *budget_remaining_ = base::saturated_cast<uint32_t>(temp); - } + if (!base::IsValueInRangeForNumericType<int64_t>(range.size())) { + *budget_remaining_ = 0; + } else { + int64_t temp = *budget_remaining_; + temp -= range.size(); + *budget_remaining_ = base::saturated_cast<uint32_t>(temp); } }
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc index 5759652..5b306cd 100644 --- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc +++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc
@@ -84,7 +84,8 @@ bool ExceptionSnapshotWin::Initialize( ProcessReaderWin* process_reader, DWORD thread_id, - WinVMAddress exception_pointers_address) { + WinVMAddress exception_pointers_address, + uint32_t* gather_indirectly_referenced_memory_cap) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); const ProcessReaderWin::Thread* thread = nullptr; @@ -132,7 +133,10 @@ #endif CaptureMemoryDelegateWin capture_memory_delegate( - process_reader, *thread, &extra_memory_, nullptr); + process_reader, + *thread, + &extra_memory_, + gather_indirectly_referenced_memory_cap); CaptureMemory::PointedToByContext(context_, &capture_memory_delegate); INITIALIZATION_STATE_SET_VALID(initialized_);
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h index 9167a9ef..b8fa735 100644 --- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h +++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h
@@ -72,7 +72,8 @@ //! an appropriate message logged. bool Initialize(ProcessReaderWin* process_reader, DWORD thread_id, - WinVMAddress exception_pointers); + WinVMAddress exception_pointers, + uint32_t* gather_indirectly_referenced_memory_cap); // ExceptionSnapshot:
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc index b60ea38..fee843c 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc +++ b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.cc
@@ -63,24 +63,6 @@ if (!process_reader_.Initialize(process, suspension_state)) return false; - if (exception_information_address != 0) { - ExceptionInformation exception_information = {}; - if (!process_reader_.Memory()->Read(exception_information_address, - sizeof(exception_information), - &exception_information)) { - LOG(WARNING) << "ReadMemory ExceptionInformation failed"; - return false; - } - - exception_.reset(new internal::ExceptionSnapshotWin()); - if (!exception_->Initialize(&process_reader_, - exception_information.thread_id, - exception_information.exception_pointers)) { - exception_.reset(); - return false; - } - } - client_id_.InitializeToZero(); system_.Initialize(&process_reader_); @@ -96,10 +78,31 @@ InitializeUnloadedModules(); GetCrashpadOptionsInternal(&options_); + uint32_t* budget_remaining_pointer = + options_.gather_indirectly_referenced_memory == TriState::kEnabled + ? &options_.indirectly_referenced_memory_cap + : nullptr; - InitializeThreads( - options_.gather_indirectly_referenced_memory == TriState::kEnabled, - options_.indirectly_referenced_memory_cap); + if (exception_information_address != 0) { + ExceptionInformation exception_information = {}; + if (!process_reader_.Memory()->Read(exception_information_address, + sizeof(exception_information), + &exception_information)) { + LOG(WARNING) << "ReadMemory ExceptionInformation failed"; + return false; + } + + exception_.reset(new internal::ExceptionSnapshotWin()); + if (!exception_->Initialize(&process_reader_, + exception_information.thread_id, + exception_information.exception_pointers, + budget_remaining_pointer)) { + exception_.reset(); + return false; + } + } + + InitializeThreads(budget_remaining_pointer); for (const MEMORY_BASIC_INFORMATION64& mbi : process_reader_.GetProcessInfo().MemoryInfo()) { @@ -239,15 +242,9 @@ return process_reader_.Memory(); } -void ProcessSnapshotWin::InitializeThreads( - bool gather_indirectly_referenced_memory, - uint32_t indirectly_referenced_memory_cap) { +void ProcessSnapshotWin::InitializeThreads(uint32_t* budget_remaining_pointer) { const std::vector<ProcessReaderWin::Thread>& process_reader_threads = process_reader_.Threads(); - uint32_t* budget_remaining_pointer = nullptr; - uint32_t budget_remaining = indirectly_referenced_memory_cap; - if (gather_indirectly_referenced_memory) - budget_remaining_pointer = &budget_remaining; for (const ProcessReaderWin::Thread& process_reader_thread : process_reader_threads) { auto thread = std::make_unique<internal::ThreadSnapshotWin>();
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h index 7a8ae2fd..0021070 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h +++ b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win.h
@@ -137,8 +137,7 @@ private: // Initializes threads_ on behalf of Initialize(). - void InitializeThreads(bool gather_indirectly_referenced_memory, - uint32_t indirectly_referenced_memory_cap); + void InitializeThreads(uint32_t* indirectly_referenced_memory_cap); // Initializes modules_ on behalf of Initialize(). void InitializeModules();
diff --git a/third_party/crashpad/crashpad/util/misc/arm64_bti_note.S b/third_party/crashpad/crashpad/util/misc/arm64_bti_note.S new file mode 100644 index 0000000..987493b --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/arm64_bti_note.S
@@ -0,0 +1,46 @@ +// Copyright 2021 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. + +#ifndef CRASHPAD_UTIL_MISC_ARM64_BTI_NOTE_S +#define CRASHPAD_UTIL_MISC_ARM64_BTI_NOTE_S + +/* Support macros for the Armv8.5-A Branch Target Identification feature which + * requires emitting a .note.gnu.property section with the appropriate + * architecture-dependent feature bits set. + * Read more: "ELF for the Arm® 64-bit Architecture" + */ +#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) +#define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has BTI + .pushsection .note.gnu.property, "a" + .balign 4 + .long 0x4 /* size of field "GNU" */ + .long 0x10 /* note descriptor size */ + .long 0x5 /* type of note descriptor: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" + .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 0x4 + .long GNU_PROPERTY_AARCH64_BTI + .long 0x0 + .popsection +#define CRASHPAD_AARCH64_VALID_JUMP_CALL_TARGET bti jc +#define CRASHPAD_AARCH64_VALID_CALL_TARGET bti c +#define CRASHPAD_AARCH64_VALID_JUMP_TARGET bti j +#undef GNU_PROPERTY_AARCH64_BTI +#else +#define CRASHPAD_AARCH64_VALID_JUMP_CALL_TARGET +#define CRASHPAD_AARCH64_VALID_CALL_TARGET +#define CRASHPAD_AARCH64_VALID_JUMP_TARGET +#endif + +#endif /* CRASHPAD_UTIL_MISC_ARM64_BTI_NOTE_S */
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_linux.S b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S index 52215ee..0ee561f 100644 --- a/third_party/crashpad/crashpad/util/misc/capture_context_linux.S +++ b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S
@@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "util/misc/arm64_bti_note.S" + // namespace crashpad { // void CaptureContext(ucontext_t* context); // } // namespace crashpad @@ -38,6 +40,7 @@ CAPTURECONTEXT_SYMBOL: CAPTURECONTEXT_SYMBOL2: + CRASHPAD_AARCH64_VALID_CALL_TARGET #if defined(__i386__)
diff --git a/third_party/crashpad/update.py b/third_party/crashpad/update.py index f99640f8c..6758d6b9 100755 --- a/third_party/crashpad/update.py +++ b/third_party/crashpad/update.py
@@ -76,7 +76,7 @@ dest='readme_path') parser.add_argument( '--exclude', - default=['codereview.settings'], + default=['codereview.settings', 'infra'], action='append', help='Files to exclude from the imported copy', metavar='PATH') @@ -137,7 +137,7 @@ 'filter-branch', '--force', '--index-filter', - 'git rm --cached --ignore-unmatch ' + + 'git rm -r --cached --ignore-unmatch ' + ' '.join(pipes.quote(path) for path in parsed.exclude), revision_old + '..UPDATE_TO'], cwd=toplevel,
diff --git a/third_party/distributed_point_functions/DEPS b/third_party/distributed_point_functions/DEPS index fa43b60..fa1f248 100644 --- a/third_party/distributed_point_functions/DEPS +++ b/third_party/distributed_point_functions/DEPS
@@ -1,7 +1,6 @@ include_rules = [ "+absl", "+benchmark", - "+dcf", "+dpf", "+google/protobuf", ]
diff --git a/third_party/distributed_point_functions/README.chromium b/third_party/distributed_point_functions/README.chromium index e1212d0..3fced6a 100644 --- a/third_party/distributed_point_functions/README.chromium +++ b/third_party/distributed_point_functions/README.chromium
@@ -14,10 +14,11 @@ functions, based on the paper by Boneh et al. Local Modifications: -The directory code/ is an unchanged copy of the source code other than the -addition of a .clang-format file to disable automatic code formatting. Parts of -code/dpf/distributed_point_function_test.cc are also adapted for fuzzing in -fuzz/dpf_fuzzer.cc. +The directory code/ is a copy of the source code, modified in two ways. First, +all top-level directories other than dpf/ have been removed as they are unused. +Second, a .clang-format file has been added to disable automatic code +formatting. Parts of code/dpf/distributed_point_function_test.cc are also +adapted for fuzzing in fuzz/dpf_fuzzer.cc. The source code pulled in depends on "glog/logging.h" which is not accessible from chromium. As a workaround, we create a simple glog/logging.h that includes
diff --git a/third_party/distributed_point_functions/code/.bazelci/presubmit.yml b/third_party/distributed_point_functions/code/.bazelci/presubmit.yml deleted file mode 100644 index 02fccaf..0000000 --- a/third_party/distributed_point_functions/code/.bazelci/presubmit.yml +++ /dev/null
@@ -1,22 +0,0 @@ -# Copyright 2021 Google LLC -# -# 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. - -tasks: - ubuntu2004: - build_targets: - - "//..." - test_flags: - - "--test_tag_filters=-benchmark" - test_targets: - - "//..."
diff --git a/third_party/distributed_point_functions/code/dcf/BUILD b/third_party/distributed_point_functions/code/dcf/BUILD deleted file mode 100644 index a62f03f..0000000 --- a/third_party/distributed_point_functions/code/dcf/BUILD +++ /dev/null
@@ -1,48 +0,0 @@ -load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") -load("@rules_cc//cc:defs.bzl", "cc_library") -load("@rules_proto//proto:defs.bzl", "proto_library") - -package( - default_visibility = ["//visibility:public"], -) - -licenses(["notice"]) - -cc_library( - name = "distributed_comparison_function", - srcs = ["distributed_comparison_function.cc"], - hdrs = ["distributed_comparison_function.h"], - deps = [ - ":distributed_comparison_function_cc_proto", - "//dpf:distributed_point_function", - "//dpf:distributed_point_function_cc_proto", - "//dpf:status_macros", - "@com_google_absl//absl/meta:type_traits", - "@com_google_absl//absl/status:statusor", - ], -) - -proto_library( - name = "distributed_comparison_function_proto", - srcs = ["distributed_comparison_function.proto"], - deps = [ - "//dpf:distributed_point_function_proto", - ], -) - -cc_proto_library( - name = "distributed_comparison_function_cc_proto", - deps = [":distributed_comparison_function_proto"], -) - -cc_test( - name = "distributed_comparison_function_test", - srcs = ["distributed_comparison_function_test.cc"], - deps = [ - ":distributed_comparison_function", - "//dpf/internal:status_matchers", - "@com_github_google_googletest//:gtest_main", - "@com_google_absl//absl/random", - "@com_google_absl//absl/utility", - ], -)
diff --git a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.cc b/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.cc deleted file mode 100644 index 20db2bb..0000000 --- a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.cc +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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 "dcf/distributed_comparison_function.h" - -#include "dpf/status_macros.h" - -namespace distributed_point_functions { - -namespace { - -void SetToZero(Value& value) { - if (value.value_case() == Value::kInteger) { - value.mutable_integer()->set_value_uint64(0); - } else if (value.value_case() == Value::kIntModN) { - value.mutable_int_mod_n()->set_value_uint64(0); - } else if (value.value_case() == Value::kTuple) { - for (int i = 0; i < value.tuple().elements_size(); ++i) { - SetToZero(*(value.mutable_tuple()->mutable_elements(i))); - } - } -} - -} // namespace - -DistributedComparisonFunction::DistributedComparisonFunction( - DcfParameters parameters, std::unique_ptr<DistributedPointFunction> dpf) - : parameters_(std::move(parameters)), dpf_(std::move(dpf)) {} - -absl::StatusOr<std::unique_ptr<DistributedComparisonFunction>> -DistributedComparisonFunction::Create(const DcfParameters& parameters) { - // A DCF with a single-element domain doesn't make sense. - if (parameters.parameters().log_domain_size() < 1) { - return absl::InvalidArgumentError("A DCF must have log_domain_size >= 1"); - } - - // We don't support the legacy element_bitsize field in DCFs. - if (!parameters.parameters().has_value_type()) { - return absl::InvalidArgumentError( - "parameters.value_type must be set for " - "DistributedComparisonFunction::Create"); - } - - // Create parameter vector for the incremental DPF. - std::vector<DpfParameters> dpf_parameters( - parameters.parameters().log_domain_size()); - for (int i = 0; i < static_cast<int>(dpf_parameters.size()); ++i) { - dpf_parameters[i].set_log_domain_size(i); - *(dpf_parameters[i].mutable_value_type()) = - parameters.parameters().value_type(); - } - - // Check that parameters are valid. We can use the DPF proto validator - // directly. - DPF_RETURN_IF_ERROR( - dpf_internal::ProtoValidator::ValidateParameters(dpf_parameters)); - - // Create incremental DPF. - DPF_ASSIGN_OR_RETURN( - std::unique_ptr<DistributedPointFunction> dpf, - DistributedPointFunction::CreateIncremental(dpf_parameters)); - - return absl::WrapUnique( - new DistributedComparisonFunction(parameters, std::move(dpf))); -} - -absl::StatusOr<std::pair<DcfKey, DcfKey>> -DistributedComparisonFunction::GenerateKeys(absl::uint128 alpha, - const Value& beta) { - const int log_domain_size = parameters_.parameters().log_domain_size(); - std::vector<Value> dpf_values(log_domain_size, beta); - for (int i = 0; i < log_domain_size; ++i) { - // beta_i = 0 if alpha_i == 0, and beta otherwise. - bool current_bit = - (alpha & (absl::uint128{1} << (log_domain_size - i - 1))) != 0; - if (!current_bit) { - SetToZero(dpf_values[i]); - } - } - - std::pair<DcfKey, DcfKey> result; - DPF_ASSIGN_OR_RETURN( - std::tie(*(result.first.mutable_key()), *(result.second.mutable_key())), - dpf_->GenerateKeysIncremental( - alpha >> 1, // We can ignore the last bit of alpha, since it is - // encoded in dpf_values.back(). - dpf_values)); - return result; -} - -} // namespace distributed_point_functions
diff --git a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.h b/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.h deleted file mode 100644 index 36527e3..0000000 --- a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.h +++ /dev/null
@@ -1,125 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * 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. - */ - -#ifndef DISTRIBUTED_POINT_FUNCTIONS_DCF_DISTRIBUTED_COMPARISON_FUNCTION_H_ -#define DISTRIBUTED_POINT_FUNCTIONS_DCF_DISTRIBUTED_COMPARISON_FUNCTION_H_ - -#include <memory> - -#include "absl/meta/type_traits.h" -#include "absl/status/statusor.h" -#include "dcf/distributed_comparison_function.pb.h" -#include "dpf/distributed_point_function.h" -#include "dpf/distributed_point_function.pb.h" - -namespace distributed_point_functions { - -class DistributedComparisonFunction { - public: - static absl::StatusOr<std::unique_ptr<DistributedComparisonFunction>> Create( - const DcfParameters& parameters); - - // Creates keys for a DCF that evaluates to shares of `beta` on any input x < - // `alpha`, and shares of 0 otherwise. - // - // Returns INVALID_ARGUMENT if `alpha` or `beta` do not match the - // DcfParameters passed at construction. - // - // Overload for explicit Value proto. - absl::StatusOr<std::pair<DcfKey, DcfKey>> GenerateKeys(absl::uint128 alpha, - const Value& beta); - - // Template for automatic conversion to Value proto. Disabled if the argument - // is convertible to `absl::uint128` or `Value` to make overloading - // unambiguous. - template <typename T, typename = absl::enable_if_t< - !std::is_convertible<T, Value>::value && - is_supported_type_v<T>>> - absl::StatusOr<std::pair<DcfKey, DcfKey>> GenerateKeys(absl::uint128 alpha, - const T& beta) { - absl::StatusOr<Value> value = dpf_->ToValue(beta); - if (!value.ok()) { - return value.status(); - } - return GenerateKeys(alpha, *value); - } - - // Evaluates a DcfKey at the given point `x`. - // - // Returns INVALID_ARGUMENT if `key` or `x` do not match the parameters passed - // at construction. - template <typename T> - absl::StatusOr<T> Evaluate(const DcfKey& key, absl::uint128 x); - - // DistributedComparisonFunction is neither copyable nor movable. - DistributedComparisonFunction(const DistributedComparisonFunction&) = delete; - DistributedComparisonFunction& operator=( - const DistributedComparisonFunction&) = delete; - - private: - DistributedComparisonFunction(DcfParameters parameters, - std::unique_ptr<DistributedPointFunction> dpf); - - const DcfParameters parameters_; - const std::unique_ptr<DistributedPointFunction> dpf_; -}; - -// Implementation details. - -template <typename T> -absl::StatusOr<T> DistributedComparisonFunction::Evaluate(const DcfKey& key, - absl::uint128 x) { - const int log_domain_size = parameters_.parameters().log_domain_size(); - T result{}; - - absl::StatusOr<EvaluationContext> ctx = - dpf_->CreateEvaluationContext(key.key()); - if (!ctx.ok()) { - return ctx.status(); - } - - int previous_bit = 0; - for (int i = 0; i < log_domain_size; ++i) { - absl::StatusOr<std::vector<T>> expansion_i; - if (i == 0) { - expansion_i = dpf_->EvaluateNext<T>({}, *ctx); - } else { - absl::uint128 prefix = 0; - if (log_domain_size < 128) { - prefix = x >> (log_domain_size - i + 1); - } - expansion_i = - dpf_->EvaluateNext<T>(absl::MakeConstSpan(&prefix, 1), *ctx); - } - if (!expansion_i.ok()) { - return expansion_i.status(); - } - - int current_bit = static_cast<int>( - (x & (absl::uint128{1} << (log_domain_size - i - 1))) != 0); - // We only add the current value along the path if the current bit of x is - // 0. - if (current_bit == 0) { - result += (*expansion_i)[previous_bit]; - } - previous_bit = current_bit; - } - return result; -} - -} // namespace distributed_point_functions - -#endif // DISTRIBUTED_POINT_FUNCTIONS_DCF_DISTRIBUTED_COMPARISON_FUNCTION_H_
diff --git a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.proto b/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.proto deleted file mode 100644 index dd69043..0000000 --- a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function.proto +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. - -syntax = "proto3"; - -package distributed_point_functions; - -import "dpf/distributed_point_function.proto"; - -// For faster allocations of sub-messages. -option cc_enable_arenas = true; - -// The parameters for a DCF have the same form as for a DPF. -message DcfParameters { - DpfParameters parameters = 1; -} - -// A DCF key is just a special DpfKey. -message DcfKey { - DpfKey key = 1; -} \ No newline at end of file
diff --git a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function_test.cc b/third_party/distributed_point_functions/code/dcf/distributed_comparison_function_test.cc deleted file mode 100644 index 7d12894cb..0000000 --- a/third_party/distributed_point_functions/code/dcf/distributed_comparison_function_test.cc +++ /dev/null
@@ -1,180 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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 "dcf/distributed_comparison_function.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "absl/random/random.h" -#include "absl/utility/utility.h" -#include "dpf/internal/status_matchers.h" - -namespace distributed_point_functions { - -namespace { - -// Helper function that recursively sets all elements of a tuple to 42. -template <typename T0> -static void SetTo42(T0& x) { - x = T0(42); -} -template <typename T0, typename... Tn> -static void SetTo42(T0& x0, Tn&... xn) { - SetTo42(x0); - SetTo42(xn...); -} -template <typename... Tn> -static void SetTo42(Tuple<Tn...>& x) { - absl::apply([](auto&... in) { SetTo42(in...); }, x.value()); -} - -TEST(DcfTest, CreateFailsWithZeroLogDomainSize) { - DcfParameters parameters; - parameters.mutable_parameters() - ->mutable_value_type() - ->mutable_integer() - ->set_bitsize(32); - - parameters.mutable_parameters()->set_log_domain_size(0); - - EXPECT_THAT(DistributedComparisonFunction::Create(parameters), - dpf_internal::StatusIs(absl::StatusCode::kInvalidArgument, - "A DCF must have log_domain_size >= 1")); -} - -template <typename T, int log_domain_size> -class DcfTestParameters { - public: - using ValueType = T; - static constexpr int kLogDomainSize = log_domain_size; -}; - -template <typename T> -struct DcfTest : public testing::Test { - void SetUp() { - DcfParameters parameters; - parameters.mutable_parameters()->set_log_domain_size(T::kLogDomainSize); - *(parameters.mutable_parameters()->mutable_value_type()) = - ToValueType<typename T::ValueType>(); - - DPF_ASSERT_OK_AND_ASSIGN(dcf_, - DistributedComparisonFunction::Create(parameters)); - } - - std::unique_ptr<DistributedComparisonFunction> dcf_; -}; - -using MyIntModN = IntModN<uint32_t, 4294967291u>; // 2**32 - 5. -using DcfTestTypes = ::testing::Types< - DcfTestParameters<uint32_t, 1>, DcfTestParameters<uint32_t, 2>, - DcfTestParameters<uint32_t, 5>, DcfTestParameters<absl::uint128, 5>, - DcfTestParameters<Tuple<uint32_t, uint32_t>, 5>, - DcfTestParameters<Tuple<uint32_t, absl::uint128>, 5>, - DcfTestParameters<Tuple<MyIntModN, MyIntModN>, 5> >; - -TYPED_TEST_SUITE(DcfTest, DcfTestTypes); - -TYPED_TEST(DcfTest, CreateWorks) { - EXPECT_THAT(this->dcf_, testing::Ne(nullptr)); -} - -TYPED_TEST(DcfTest, GenEval) { - using ValueType = typename TypeParam::ValueType; - const absl::uint128 domain_size = absl::uint128{1} - << TypeParam::kLogDomainSize; - ValueType beta; - SetTo42(beta); - for (absl::uint128 alpha = 0; alpha < domain_size; ++alpha) { - // Generate keys. - DcfKey key_0, key_1; - DPF_ASSERT_OK_AND_ASSIGN(std::tie(key_0, key_1), - this->dcf_->GenerateKeys(alpha, beta)); - - // Evaluate on every point in the domain. - for (absl::uint128 x = 0; x < domain_size; ++x) { - DPF_ASSERT_OK_AND_ASSIGN( - ValueType result_0, - this->dcf_->template Evaluate<ValueType>(key_0, x)); - DPF_ASSERT_OK_AND_ASSIGN( - ValueType result_1, - this->dcf_->template Evaluate<ValueType>(key_1, x)); - if (x < alpha) { - EXPECT_EQ(ValueType(result_0 + result_1), beta) - << "x=" << x << ", alpha=" << alpha; - } else { - EXPECT_EQ(ValueType(result_0 + result_1), ValueType{}) - << "x=" << x << ", alpha=" << alpha; - } - } - } -} - -TEST(DcfTest, WorksCorrectlyOnUint64TWithLargeDomain) { - using ValueType = uint64_t; - const absl::uint128 domain_size = absl::uint128{1} << 64; - ValueType beta; - SetTo42(beta); - absl::uint128 alpha = 50; - - DcfParameters parameters; - parameters.mutable_parameters()->set_log_domain_size(64); - *(parameters.mutable_parameters()->mutable_value_type()) = - ToValueType<uint64_t>(); - - DPF_ASSERT_OK_AND_ASSIGN(auto dcf, - DistributedComparisonFunction::Create(parameters)); - - // Generate keys. - DcfKey key_0, key_1; - DPF_ASSERT_OK_AND_ASSIGN(std::tie(key_0, key_1), - dcf->GenerateKeys(alpha, beta)); - - // Evaluate on every point in the domain smaller than alpha. - for (absl::uint128 x = 0; x < alpha; ++x) { - DPF_ASSERT_OK_AND_ASSIGN(ValueType result_0, - dcf->template Evaluate<ValueType>(key_0, x)); - DPF_ASSERT_OK_AND_ASSIGN(ValueType result_1, - dcf->template Evaluate<ValueType>(key_1, x)); - EXPECT_EQ(ValueType(result_0 + result_1), beta) - << "x=" << x << ", alpha=" << alpha; - } - - // Evaluate on 100 random points in the domain. - absl::BitGen rng; - absl::uniform_int_distribution<uint64_t> dist; - const int kNumEvaluationPoints = 100; - std::vector<absl::uint128> evaluation_points(kNumEvaluationPoints); - for (int i = 0; i < kNumEvaluationPoints - 1; ++i) { - evaluation_points[i] = - absl::MakeUint128(dist(rng), dist(rng)) % domain_size; - DPF_ASSERT_OK_AND_ASSIGN( - uint64_t result_0, - dcf->template Evaluate<ValueType>(key_0, evaluation_points[i])); - DPF_ASSERT_OK_AND_ASSIGN( - ValueType result_1, - dcf->template Evaluate<ValueType>(key_1, evaluation_points[i])); - if (evaluation_points[i] < alpha) { - EXPECT_EQ(ValueType(result_0 + result_1), beta) - << "x=" << evaluation_points[i] << ", alpha=" << alpha; - } else { - EXPECT_EQ(ValueType(result_0 + result_1), ValueType{}) - << "x=" << evaluation_points[i] << ", alpha=" << alpha; - } - } -} - -} // namespace - -} // namespace distributed_point_functions
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/BUILD b/third_party/distributed_point_functions/code/dcf/fss_gates/BUILD deleted file mode 100644 index b62be84b..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/BUILD +++ /dev/null
@@ -1,62 +0,0 @@ -# This package contains implementation of various Function Secret Sharing (FSS) -# gates as specified in https://eprint.iacr.org/2020/1392. The implementation -# uses the Distributed Comparison Function (as implemented in -# distributed_comparison_function.cc) as a central component. - -load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") -load("@rules_cc//cc:defs.bzl", "cc_library") -load("@rules_proto//proto:defs.bzl", "proto_library") - -package( - default_visibility = ["//visibility:public"], -) - -licenses(["notice"]) - -# Multiple Interval Containment - -cc_library( - name = "multiple_interval_containment", - srcs = ["multiple_interval_containment.cc"], - hdrs = ["multiple_interval_containment.h"], - deps = [ - ":multiple_interval_containment_cc_proto", - "//dcf:distributed_comparison_function", - "//dcf/fss_gates/prng:basic_rng", - "//dpf:distributed_point_function_cc_proto", - "//dpf:status_macros", - "@com_google_absl//absl/numeric:int128", - "@com_google_absl//absl/status", - "@com_google_absl//absl/status:statusor", - ], -) - -proto_library( - name = "multiple_interval_containment_proto", - srcs = ["multiple_interval_containment.proto"], - deps = [ - "//dcf:distributed_comparison_function_proto", - "//dpf:distributed_point_function_proto", - ], -) - -cc_proto_library( - name = "multiple_interval_containment_cc_proto", - deps = [":multiple_interval_containment_proto"], -) - -cc_test( - name = "multiple_interval_containment_test", - srcs = ["multiple_interval_containment_test.cc"], - deps = [ - ":multiple_interval_containment", - ":multiple_interval_containment_cc_proto", - "//dcf/fss_gates/prng:basic_rng", - "//dpf:distributed_point_function_cc_proto", - "//dpf:status_macros", - "//dpf/internal:status_matchers", - "//dpf/internal:value_type_helpers", - "@com_github_google_googletest//:gtest_main", - "@com_google_absl//absl/numeric:int128", - ], -)
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.cc b/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.cc deleted file mode 100644 index e47b436a..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.cc +++ /dev/null
@@ -1,278 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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 "dcf/fss_gates/multiple_interval_containment.h" - -#include <utility> - -#include "absl/numeric/int128.h" -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "dcf/distributed_comparison_function.h" -#include "dcf/fss_gates/multiple_interval_containment.pb.h" -#include "dcf/fss_gates/prng/basic_rng.h" -#include "dpf/distributed_point_function.pb.h" -#include "dpf/status_macros.h" - -namespace distributed_point_functions { -namespace fss_gates { - -absl::StatusOr<std::unique_ptr<MultipleIntervalContainmentGate>> -MultipleIntervalContainmentGate::Create(const MicParameters& mic_parameters) { - // Declaring the parameters for a Distributed Comparison Function (DCF). - DcfParameters dcf_parameters; - - // Return error if log_group_size is not between 0 and 127. - if (mic_parameters.log_group_size() < 0 || - mic_parameters.log_group_size() > 127) { - return absl::InvalidArgumentError( - "log_group_size should be in > 0 and < 128"); - } - - // Setting N = 2 ^ log_group_size. - absl::uint128 N = absl::uint128(1) << mic_parameters.log_group_size(); - - for (int i = 0; i < mic_parameters.intervals_size(); i++) { - // Return error if some interval is empty. - if (!mic_parameters.intervals(i).has_lower_bound() || - !mic_parameters.intervals(i).has_upper_bound()) { - return absl::InvalidArgumentError("Intervals should be non-empty"); - } - - absl::uint128 p = absl::MakeUint128( - mic_parameters.intervals(i).lower_bound().value_uint128().high(), - mic_parameters.intervals(i).lower_bound().value_uint128().low()); - - absl::uint128 q = absl::MakeUint128( - mic_parameters.intervals(i).upper_bound().value_uint128().high(), - mic_parameters.intervals(i).upper_bound().value_uint128().low()); - - // Return error if the intervals are not valid group elements. - if (p < 0 || p >= N) { - return absl::InvalidArgumentError( - "Interval bounds should be between 0 and 2^log_group_size"); - } - - // Return error if the intervals are not valid group elements. - if (q < 0 || q >= N) { - return absl::InvalidArgumentError( - "Interval bounds should be between 0 and 2^log_group_size"); - } - - // Return error if lower bound of an interval is less that its - // upper bound. - if (p > q) { - return absl::InvalidArgumentError( - "Interval upper bounds should be >= lower bound"); - } - } - - // Setting the `log_domain_size` of the DCF to be same as the - // `log_group_size` of the Multiple Interval Containment Gate. - dcf_parameters.mutable_parameters()->set_log_domain_size( - mic_parameters.log_group_size()); - - // Setting the output ValueType of the DCF so that it can store 128 bit - // integers. - *(dcf_parameters.mutable_parameters()->mutable_value_type()) = - ToValueType<absl::uint128>(); - - // Creating a DCF with appropriate parameters. - DPF_ASSIGN_OR_RETURN(std::unique_ptr<DistributedComparisonFunction> dcf, - DistributedComparisonFunction::Create(dcf_parameters)); - - return absl::WrapUnique( - new MultipleIntervalContainmentGate(mic_parameters, std::move(dcf))); -} - -MultipleIntervalContainmentGate::MultipleIntervalContainmentGate( - MicParameters mic_parameters, - std::unique_ptr<DistributedComparisonFunction> dcf) - : mic_parameters_(std::move(mic_parameters)), dcf_(std::move(dcf)) {} - -absl::StatusOr<std::pair<MicKey, MicKey>> MultipleIntervalContainmentGate::Gen( - absl::uint128 r_in, std::vector<absl::uint128> r_out) { - if (r_out.size() != mic_parameters_.intervals_size()) { - return absl::InvalidArgumentError( - "Count of output masks should be equal to the number of intervals"); - } - - // Setting N = 2 ^ log_group_size. - absl::uint128 N = absl::uint128(1) << mic_parameters_.log_group_size(); - - // Checking whether r_in is a group element. - if (r_in < 0 || r_in >= N) { - return absl::InvalidArgumentError( - "Input mask should be between 0 and 2^log_group_size"); - } - - // Checking whether each element of r_out is a group element. - for (int i = 0; i < r_out.size(); i++) { - if (r_out[i] < 0 || r_out[i] >= N) { - return absl::InvalidArgumentError( - "Output mask should be between 0 and 2^log_group_size"); - } - } - - // The following code is commented using their Line numbering in - // https://eprint.iacr.org/2020/1392 Fig. 14 Gen procedure. - - // Line 1 - absl::uint128 gamma = (N - 1 + r_in) % N; - - // Line 2 - - DcfKey key_0, key_1; - - absl::uint128 alpha = gamma; - absl::uint128 beta = 1; - - DPF_ASSIGN_OR_RETURN(std::tie(key_0, key_1), - this->dcf_->GenerateKeys(alpha, beta)); - - MicKey k0, k1; - - // Part of Line 7 - *(k0.mutable_dcfkey()) = key_0; - *(k1.mutable_dcfkey()) = key_1; - - // Line 3 - for (int i = 0; i < mic_parameters_.intervals_size(); i++) { - absl::uint128 p = absl::MakeUint128( - mic_parameters_.intervals(i).lower_bound().value_uint128().high(), - mic_parameters_.intervals(i).lower_bound().value_uint128().low()); - - absl::uint128 q = absl::MakeUint128( - mic_parameters_.intervals(i).upper_bound().value_uint128().high(), - mic_parameters_.intervals(i).upper_bound().value_uint128().low()); - - // Line 4 - absl::uint128 q_prime = (q + 1) % N; - - absl::uint128 alpha_p = (p + r_in) % N; - - absl::uint128 alpha_q = (q + r_in) % N; - - absl::uint128 alpha_q_prime = (q + 1 + r_in) % N; - - // Line 5 - This computes the correction term for the output of the gate, - // and the logic and proof of its correctness is described in - // https://eprint.iacr.org/2020/1392 Lemma 1, Lemma 2 and Theorem 3. - absl::uint128 z = - r_out[i] + (alpha_p > alpha_q ? 1 : 0) + (alpha_p > p ? -1 : 0) + - (alpha_q_prime > q_prime ? 1 : 0) + (alpha_q == (N - 1) ? 1 : 0); - z = z % N; - - const absl::string_view kSampleSeed = absl::string_view(); - DPF_ASSIGN_OR_RETURN( - auto rng, distributed_point_functions::BasicRng::Create(kSampleSeed)); - DPF_ASSIGN_OR_RETURN(absl::uint128 z_0, rng->Rand128()); - - z_0 = z_0 % N; - - absl::uint128 z_1 = (z - z_0) % N; - - // Part of Line 7 - Value_Integer* k0_output_mask_share = k0.add_output_mask_share(); - - k0_output_mask_share->mutable_value_uint128()->set_high( - absl::Uint128High64(z_0)); - k0_output_mask_share->mutable_value_uint128()->set_low( - absl::Uint128Low64(z_0)); - - Value_Integer* k1_output_mask_share = k1.add_output_mask_share(); - - k1_output_mask_share->mutable_value_uint128()->set_high( - absl::Uint128High64(z_1)); - k1_output_mask_share->mutable_value_uint128()->set_low( - absl::Uint128Low64(z_1)); - } - - // Line 8 - return std::pair<MicKey, MicKey>(k0, k1); -} - -absl::StatusOr<std::vector<absl::uint128>> -MultipleIntervalContainmentGate::Eval(MicKey k, absl::uint128 x) { - // Setting N = 2 ^ log_group_size - absl::uint128 N = absl::uint128(1) << mic_parameters_.log_group_size(); - - // Checking whether x is a group element - if (x < 0 || x >= N) { - return absl::InvalidArgumentError( - "Masked input should be between 0 and 2^log_group_size"); - } - - std::vector<absl::uint128> res; - - // The following code is commented using their Line numbering in - // https://eprint.iacr.org/2020/1392 Fig. 14 Eval procedure. - - // Line 2 - for (int i = 0; i < mic_parameters_.intervals_size(); i++) { - absl::uint128 p = absl::MakeUint128( - mic_parameters_.intervals(i).lower_bound().value_uint128().high(), - mic_parameters_.intervals(i).lower_bound().value_uint128().low()); - - absl::uint128 q = absl::MakeUint128( - mic_parameters_.intervals(i).upper_bound().value_uint128().high(), - mic_parameters_.intervals(i).upper_bound().value_uint128().low()); - - // Line 3 - - absl::uint128 q_prime = (q + 1) % N; - - // Line 4 - absl::uint128 x_p = (x + N - 1 - p) % N; - - absl::uint128 x_q_prime = (x + N - 1 - q_prime) % N; - - // Line 5 - - absl::uint128 s_p; - - DPF_ASSIGN_OR_RETURN(s_p, dcf_->Evaluate<absl::uint128>(k.dcfkey(), x_p)); - - s_p = s_p % N; - - // Line 6 - - absl::uint128 s_q_prime; - - DPF_ASSIGN_OR_RETURN(s_q_prime, - dcf_->Evaluate<absl::uint128>(k.dcfkey(), x_q_prime)); - - s_q_prime = s_q_prime % N; - - // Line 7 - - absl::uint128 y; - - absl::uint128 z = - absl::MakeUint128(k.output_mask_share(i).value_uint128().high(), - k.output_mask_share(i).value_uint128().low()); - - y = (k.dcfkey().key().party() ? ((x > p ? 1 : 0) - (x > q_prime ? 1 : 0)) - : 0) - - s_p + s_q_prime + z; - - res.push_back(y % N); - } - - // Line 9 - return res; -} - -} // namespace fss_gates -} // namespace distributed_point_functions
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.h b/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.h deleted file mode 100644 index cb8c203..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.h +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. - -#ifndef DISTRIBUTED_POINT_FUNCTIONS_DCF_FSS_GATES_MULTIPLE_INTERVAL_CONTAINMENT_H_ -#define DISTRIBUTED_POINT_FUNCTIONS_DCF_FSS_GATES_MULTIPLE_INTERVAL_CONTAINMENT_H_ -#include <vector> - -#include "absl/numeric/int128.h" -#include "absl/status/statusor.h" -#include "dcf/distributed_comparison_function.h" -#include "dcf/fss_gates/multiple_interval_containment.pb.h" -#include "dpf/status_macros.h" - -namespace distributed_point_functions { -namespace fss_gates { - -// Implements the Multiple Interval Containment gate as specified in -// https://eprint.iacr.org/2020/1392 (Fig. 14). Such a gate is specified by -// input and output group Z_{2 ^ n} where n is the bit length and a sequence -// of `m` public intervals {p_i, q_i}_{i \in [m]}. The Key generation procedure -// produces two keys, k_0 and k_1, corresponding to Party 0 and Party 1 -// respectively. Evaluating each key on any point `x` in the input group results -// in an additive secret share of m values {y_i}_{i \in [m]} where y_i = `1`, if -// `p_i <= x <= q_i`, and 0 otherwise. - -class MultipleIntervalContainmentGate { - public: - // Factory method : creates and returns a MultipleIntervalContainmentGate - // initialized with appropriate parameters. - static absl::StatusOr<std::unique_ptr<MultipleIntervalContainmentGate>> - Create(const MicParameters& mic_parameters); - - // MultipleIntervalContainmentGate is neither copyable nor movable. - MultipleIntervalContainmentGate(const MultipleIntervalContainmentGate&) = - delete; - MultipleIntervalContainmentGate& operator=( - const MultipleIntervalContainmentGate&) = delete; - - // This method generates Multiple Interval Containment Gate a pair of keys - // using `r_in` and `r_out` as the input mask and output masks respectively. - // The implementation of this method is identical to Gen procedure specified - // in https://eprint.iacr.org/2020/1392 (Fig. 14). Note that although the - // datatype of r_in and r_out is absl::uint128, but they will be interpreted - // as an element in the input and output group Z_{2 ^ n} respectively. This - // reinterpretion in the group is achieved simply by taking mod of r_in and - // r_out with the size of group i.e. 2^{log_group_size}. - - // This method expects that the size of r_out vector be exactly same as the - // number of public intervals in the MicParameters. This is because for - // each interval in MIC, we will need an independent output mask to hide - // the actual cleartext output of the MIC on that interval. This method - // will return InvalidArgumentError. - - // Returns INVALID_ARGUMENT if the size of r_out vector does not match the - // number of intervals specified during construction. - absl::StatusOr<std::pair<MicKey, MicKey>> Gen( - absl::uint128 r_in, std::vector<absl::uint128> r_out); - - // This method evaluates the Multiple Interval Containment Gate key k - // on input domain point `x`. The output is returned as a 128 bit string - // and needs to be interpreted as an element in the output group Z_{2 ^ n}. - absl::StatusOr<std::vector<absl::uint128>> Eval(MicKey k, absl::uint128 x); - - private: - // Parameters needed for specifying a Multiple Interval Containment Gate. - const MicParameters mic_parameters_; - - // Private constructor, called by `Create` - MultipleIntervalContainmentGate( - MicParameters mic_parameters, - std::unique_ptr<DistributedComparisonFunction> dcf); - - // Pointer to a Distributed Comparison Function which will be internally - // invoked by Gen and Eval. - std::unique_ptr<DistributedComparisonFunction> dcf_; -}; - -} // namespace fss_gates -} // namespace distributed_point_functions - -#endif // DISTRIBUTED_POINT_FUNCTIONS_DCF_FSS_GATES_MULTIPLE_INTERVAL_CONTAINMENT_H_
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.proto b/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.proto deleted file mode 100644 index 54551fd..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment.proto +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. - -syntax = "proto3"; - -package distributed_point_functions.fss_gates; - -import "dcf/distributed_comparison_function.proto"; -import "dpf/distributed_point_function.proto"; - -// Represents an interval on the group G = Z_N. -message Interval { - // Represents the lower limit of the interval. This corresponds to `p_i` - // used in https://eprint.iacr.org/2020/1392 (Fig. 14). - Value.Integer lower_bound = 1; - - // Represents the upper limit of the interval. This corresponds to `q_i` - // used in https://eprint.iacr.org/2020/1392 (Fig. 14). - Value.Integer upper_bound = 2; -} - -message MicParameters { - // Represents the bit length of the input to the Multiple Interval Containment - // gate. This corresponds to `n` used in https://eprint.iacr.org/2020/1392 - // (Fig. 14). Here we assume that if `n` is the input bit-length, then the - // input and output group of the gate is implicitly Z_N where N = 2^n, and - // hence the variable name "log_group_size". Maximum allowed log_group_size - // is 127 and minimum value should be at least the number of bits required to - // store each interval boundary. - int32 log_group_size = 1; - - // Represents a sequence of public intervals. This corresponds to `{p_i, q_i}` - // used in https://eprint.iacr.org/2020/1392 (Fig. 14). - repeated Interval intervals = 2; -} - -// Represents a key for Multiple Interval Containment gate. This corresponds to -//`k_b` used in https://eprint.iacr.org/2020/1392 (Fig. 14). The key implicitly -// corresponds to the MicParameters used to generate this key. -message MicKey { - // Represents a Distributed Comparison Function Key. This corresponds to - //`k_b^(N - 1)` used in https://eprint.iacr.org/2020/1392 (Fig. 14). - DcfKey dcfkey = 1; - - // Represents output mask shares corresponding to each of the m different - // intervals. This corresponds to `{z_i,b}_i` used in - // https://eprint.iacr.org/2020/1392 (Fig. 14). - repeated Value.Integer output_mask_share = 2; -}
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment_test.cc b/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment_test.cc deleted file mode 100644 index b24904a..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/multiple_interval_containment_test.cc +++ /dev/null
@@ -1,543 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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 "dcf/fss_gates/multiple_interval_containment.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <cstdint> -#include <vector> - -#include "absl/numeric/int128.h" -#include "dcf/fss_gates/multiple_interval_containment.pb.h" -#include "dcf/fss_gates/prng/basic_rng.h" -#include "dpf/distributed_point_function.pb.h" -#include "dpf/internal/status_matchers.h" -#include "dpf/internal/value_type_helpers.h" -#include "dpf/status_macros.h" - -namespace distributed_point_functions { -namespace fss_gates { -namespace { - -using ::testing::Test; - -TEST(MICTest, GenAndEvalSucceedsForSmallGroup) { - MicParameters mic_parameters; - const int group_size = 64; - const uint64_t interval_count = 5; - - // Setting input and output group to be Z_{2^64} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{10, 23, 45, 66, 15}; - std::vector<absl::uint128> qs{45, 30, 100, 250, 15}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - // Creating a MIC gate - DPF_ASSERT_OK_AND_ASSIGN( - std::unique_ptr<MultipleIntervalContainmentGate> MicGate, - MultipleIntervalContainmentGate::Create(mic_parameters)); - - MicKey key_0, key_1; - - // Initializing the input and output masks uniformly at random; - const absl::string_view kSampleSeed = absl::string_view(); - DPF_ASSERT_OK_AND_ASSIGN( - auto rng, distributed_point_functions::BasicRng::Create(kSampleSeed)); - - absl::uint128 N = absl::uint128(1) << mic_parameters.log_group_size(); - - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_in, rng->Rand64()); - r_in = r_in % N; - - std::vector<absl::uint128> r_outs; - - for (int i = 0; i < interval_count; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_out, rng->Rand64()); - r_out = r_out % N; - r_outs.push_back(r_out); - } - - // Generating MIC gate keys - DPF_ASSERT_OK_AND_ASSIGN(std::tie(key_0, key_1), MicGate->Gen(r_in, r_outs)); - - // Inside this loop we will test the Evaluation of the MIC gate on - // input values ranging between [0, 400) - for (uint64_t i = 0; i < 400; i++) { - std::vector<absl::uint128> res_0, res_1; - - // Evaluating MIC gate key_0 on masked input i + r_in - DPF_ASSERT_OK_AND_ASSIGN(res_0, MicGate->Eval(key_0, (i + r_in) % N)); - - // Evaluating MIC gate key_1 on masked input i + r_in - DPF_ASSERT_OK_AND_ASSIGN(res_1, MicGate->Eval(key_1, (i + r_in) % N)); - - // Reconstructing the actual output of the MIC gate by adding together - // the secret shared output res_0 and res_1, and then subtracting out - // the output mask r_out - for (int j = 0; j < interval_count; j++) { - absl::uint128 result = (res_0[j] + res_1[j] - r_outs[j]) % N; - - // If the input i lies inside the j^th interval, then the expected - // output of MIC gate is 1, and 0 otherwise - if (i >= ps[j] && i <= qs[j]) { - EXPECT_EQ(result, 1); - } else { - EXPECT_EQ(result, 0); - } - } - } -} - -TEST(MICTest, GenAndEvalSucceedsForLargeGroup) { - MicParameters mic_parameters; - const int group_size = 127; - const uint64_t interval_count = 3; - const absl::uint128 two_power_127 = absl::uint128(1) << 127; - const absl::uint128 two_power_126 = absl::uint128(1) << 126; - - // Setting input and output group to be Z_{2^127} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - - std::vector<absl::uint128> ps{two_power_126, two_power_127 - 1, - two_power_127 - 3}; - std::vector<absl::uint128> qs{two_power_126 + 3, two_power_127 - 1, - two_power_127 - 2}; - - std::vector<absl::uint128> x{two_power_126 - 1, two_power_126, - two_power_126 + 1, two_power_126 + 2, - two_power_126 + 3, two_power_126 + 4, - two_power_127 - 4, two_power_127 - 3, - two_power_127 - 2, two_power_127 - 1}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_high( - absl::Uint128High64(ps[i])); - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_high( - absl::Uint128High64(qs[i])); - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - // Creating a MIC gate - DPF_ASSERT_OK_AND_ASSIGN( - std::unique_ptr<MultipleIntervalContainmentGate> MicGate, - MultipleIntervalContainmentGate::Create(mic_parameters)); - - MicKey key_0, key_1; - - absl::uint128 N = absl::uint128(1) << mic_parameters.log_group_size(); - - // Initializing the input and output masks uniformly at random; - const absl::string_view kSampleSeed = absl::string_view(); - DPF_ASSERT_OK_AND_ASSIGN( - auto rng, distributed_point_functions::BasicRng::Create(kSampleSeed)); - - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_in, rng->Rand128()); - - r_in = r_in % N; - - std::vector<absl::uint128> r_outs; - - for (int i = 0; i < interval_count; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_out, rng->Rand128()); - r_out = r_out % N; - r_outs.push_back(r_out); - } - - // Generating MIC gate keys - DPF_ASSERT_OK_AND_ASSIGN(std::tie(key_0, key_1), MicGate->Gen(r_in, r_outs)); - - // Inside this loop we will test the Evaluation of the MIC gate on - // input values in the vicinity of interval boundaries which are hardcoded - // in the vector x. - for (uint64_t i = 0; i < x.size(); i++) { - std::vector<absl::uint128> res_0, res_1; - - // Evaluating MIC gate key_0 on masked input - DPF_ASSERT_OK_AND_ASSIGN(res_0, MicGate->Eval(key_0, (x[i] + r_in) % N)); - - // Evaluating MIC gate key_1 on masked input - DPF_ASSERT_OK_AND_ASSIGN(res_1, MicGate->Eval(key_1, (x[i] + r_in) % N)); - - // Reconstructing the actual output of the MIC gate by adding together - // the secret shared output res_0 and res_1, and then subtracting out - // the output mask r_out - for (int j = 0; j < interval_count; j++) { - absl::uint128 result = (res_0[j] + res_1[j] - r_outs[j]) % N; - - // If the input lies inside the j^th interval, then the expected - // output of MIC gate is 1, and 0 otherwise - if (x[i] >= ps[j] && x[i] <= qs[j]) { - EXPECT_EQ(result, 1); - } else { - EXPECT_EQ(result, 0); - } - } - } -} - -TEST(MICTest, CreateFailsWith128bitGroup) { - MicParameters mic_parameters; - const int group_size = 128; - const uint64_t interval_count = 5; - - // Setting input and output group to be Z_{2^128} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{10, 23, 45, 66, 15}; - std::vector<absl::uint128> qs{45, 30, 100, 250, 15}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - EXPECT_THAT( - MultipleIntervalContainmentGate::Create(mic_parameters), - dpf_internal::StatusIs(absl::StatusCode::kInvalidArgument, - "log_group_size should be in > 0 and < 128")); -} - -TEST(MICTest, CreateFailsForIntervalBoundariesOutsideGroup) { - MicParameters mic_parameters; - const int group_size = 20; - const uint64_t interval_count = 1; - const absl::uint128 two_power_20 = absl::uint128(1) << 20; - - // Setting input and output group to be Z_{2^20} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{4}; - std::vector<absl::uint128> qs{two_power_20}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - EXPECT_THAT(MultipleIntervalContainmentGate::Create(mic_parameters), - dpf_internal::StatusIs( - absl::StatusCode::kInvalidArgument, - "Interval bounds should be between 0 and 2^log_group_size")); -} - -TEST(MICTest, CreateFailsForInvalidIntervalBoundaries) { - MicParameters mic_parameters; - const int group_size = 20; - const uint64_t interval_count = 1; - - // Setting input and output group to be Z_{2^20} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{4}; - std::vector<absl::uint128> qs{3}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - EXPECT_THAT( - MultipleIntervalContainmentGate::Create(mic_parameters), - dpf_internal::StatusIs(absl::StatusCode::kInvalidArgument, - "Interval upper bounds should be >= lower bound")); -} - -TEST(MICTest, CreateFailsForEmptyInterval) { - MicParameters mic_parameters; - const int group_size = 20; - const uint64_t interval_count = 1; - - // Setting input and output group to be Z_{2^20} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{}; - std::vector<absl::uint128> qs{3}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - // Only setting upper bound (and skipping lower bound) - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - EXPECT_THAT(MultipleIntervalContainmentGate::Create(mic_parameters), - dpf_internal::StatusIs(absl::StatusCode::kInvalidArgument, - "Intervals should be non-empty")); -} - -TEST(MICTest, GenFailsForIncorrectNumberOfOutputMasks) { - MicParameters mic_parameters; - const int group_size = 64; - const uint64_t interval_count = 5; - - // Setting input and output group to be Z_{2^64} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{10, 23, 45, 66, 15}; - std::vector<absl::uint128> qs{45, 30, 100, 250, 15}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - // Creating a MIC gate - DPF_ASSERT_OK_AND_ASSIGN( - std::unique_ptr<MultipleIntervalContainmentGate> MicGate, - MultipleIntervalContainmentGate::Create(mic_parameters)); - - MicKey key_0, key_1; - - absl::uint128 N = absl::uint128(1) << mic_parameters.log_group_size(); - - // Initializing the input and output masks uniformly at random; - const absl::string_view kSampleSeed = absl::string_view(); - DPF_ASSERT_OK_AND_ASSIGN( - auto rng, distributed_point_functions::BasicRng::Create(kSampleSeed)); - - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_in, rng->Rand64()); - r_in = r_in % N; - - std::vector<absl::uint128> r_outs; - - // Setting only (interval_count - 1) many output masks - for (int i = 0; i < interval_count - 1; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_out, rng->Rand64()); - r_out = r_out % N; - r_outs.push_back(r_out); - } - - // Generating MIC gate keys - EXPECT_THAT( - MicGate->Gen(r_in, r_outs), - dpf_internal::StatusIs( - absl::StatusCode::kInvalidArgument, - "Count of output masks should be equal to the number of intervals")); -} - -TEST(MICTest, GenFailsForInputMaskOutsideGroup) { - MicParameters mic_parameters; - const int group_size = 10; - const uint64_t interval_count = 1; - - // Setting input and output group to be Z_{2^10} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{10}; - std::vector<absl::uint128> qs{45}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - // Creating a MIC gate - DPF_ASSERT_OK_AND_ASSIGN( - std::unique_ptr<MultipleIntervalContainmentGate> MicGate, - MultipleIntervalContainmentGate::Create(mic_parameters)); - - MicKey key_0, key_1; - - absl::uint128 N = absl::uint128(1) << mic_parameters.log_group_size(); - - const absl::string_view kSampleSeed = absl::string_view(); - DPF_ASSERT_OK_AND_ASSIGN( - auto rng, distributed_point_functions::BasicRng::Create(kSampleSeed)); - - // Fixing r_in to be an element outside group - absl::uint128 r_in = 2048; - - std::vector<absl::uint128> r_outs; - - // Initializing the output masks uniformly at random; - for (int i = 0; i < interval_count; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_out, rng->Rand64()); - r_out = r_out % N; - r_outs.push_back(r_out); - } - - // Generating MIC gate keys - EXPECT_THAT(MicGate->Gen(r_in, r_outs), - dpf_internal::StatusIs( - absl::StatusCode::kInvalidArgument, - "Input mask should be between 0 and 2^log_group_size")); -} - -TEST(MICTest, GenFailsForOutputMaskOutsideGroup) { - MicParameters mic_parameters; - const int group_size = 10; - const uint64_t interval_count = 1; - - // Setting input and output group to be Z_{2^10} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{10}; - std::vector<absl::uint128> qs{45}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - // Creating a MIC gate - DPF_ASSERT_OK_AND_ASSIGN( - std::unique_ptr<MultipleIntervalContainmentGate> MicGate, - MultipleIntervalContainmentGate::Create(mic_parameters)); - - MicKey key_0, key_1; - - absl::uint128 N = absl::uint128(1) << mic_parameters.log_group_size(); - - const absl::string_view kSampleSeed = absl::string_view(); - DPF_ASSERT_OK_AND_ASSIGN( - auto rng, distributed_point_functions::BasicRng::Create(kSampleSeed)); - - // Initializing the input masks uniformly at random; - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_in, rng->Rand64()); - r_in = r_in % N; - - std::vector<absl::uint128> r_outs; - - // Fixing the output masks to be elements outside group; - for (int i = 0; i < interval_count; ++i) { - absl::uint128 r_out = 2048; - r_outs.push_back(r_out); - } - - // Generating MIC gate keys - EXPECT_THAT(MicGate->Gen(r_in, r_outs), - dpf_internal::StatusIs( - absl::StatusCode::kInvalidArgument, - "Output mask should be between 0 and 2^log_group_size")); -} - -TEST(MICTest, EvalFailsForMaskedInputOutsideGroup) { - MicParameters mic_parameters; - const int group_size = 64; - const uint64_t interval_count = 1; - - // Setting input and output group to be Z_{2^64} - mic_parameters.set_log_group_size(group_size); - - // Setting up the lower bound and upper bounds for intervals - std::vector<absl::uint128> ps{10}; - std::vector<absl::uint128> qs{45}; - - for (int i = 0; i < interval_count; ++i) { - Interval* interval = mic_parameters.add_intervals(); - - interval->mutable_lower_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(ps[i])); - - interval->mutable_upper_bound()->mutable_value_uint128()->set_low( - absl::Uint128Low64(qs[i])); - } - - // Creating a MIC gate - DPF_ASSERT_OK_AND_ASSIGN( - std::unique_ptr<MultipleIntervalContainmentGate> MicGate, - MultipleIntervalContainmentGate::Create(mic_parameters)); - - MicKey key_0, key_1; - - // Initializing the input and output masks uniformly at random; - const absl::string_view kSampleSeed = absl::string_view(); - DPF_ASSERT_OK_AND_ASSIGN( - auto rng, distributed_point_functions::BasicRng::Create(kSampleSeed)); - - absl::uint128 N = absl::uint128(1) << mic_parameters.log_group_size(); - - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_in, rng->Rand64()); - r_in = r_in % N; - - std::vector<absl::uint128> r_outs; - - for (int i = 0; i < interval_count; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r_out, rng->Rand64()); - r_out = r_out % N; - r_outs.push_back(r_out); - } - - // Generating MIC gate keys - DPF_ASSERT_OK_AND_ASSIGN(std::tie(key_0, key_1), MicGate->Gen(r_in, r_outs)); - - // Calling Eval on a masked input which is not a group element - EXPECT_THAT(MicGate->Eval(key_0, absl::uint128(1) << 72), - dpf_internal::StatusIs( - absl::StatusCode::kInvalidArgument, - "Masked input should be between 0 and 2^log_group_size")); -} - -} // namespace -} // namespace fss_gates -} // namespace distributed_point_functions
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/BUILD b/third_party/distributed_point_functions/code/dcf/fss_gates/prng/BUILD deleted file mode 100644 index 160fa9a9..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/BUILD +++ /dev/null
@@ -1,42 +0,0 @@ -load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") - -package( - default_visibility = ["//:__subpackages__"], -) - -licenses(["notice"]) - -cc_library( - name = "prng", - hdrs = ["prng.h"], - deps = [ - "//dpf:status_macros", - "@com_google_absl//absl/numeric:int128", - "@com_google_absl//absl/status:statusor", - "@com_google_absl//absl/strings", - ], -) - -cc_library( - name = "basic_rng", - hdrs = ["basic_rng.h"], - deps = [ - ":prng", - "@boringssl//:crypto", - "@com_google_absl//absl/base", - "@com_google_absl//absl/memory", - "@com_google_absl//absl/numeric:int128", - "@com_google_absl//absl/strings", - ], -) - -cc_test( - name = "basic_rng_test", - srcs = ["basic_rng_test.cc"], - deps = [ - ":basic_rng", - "//dpf/internal:status_matchers", - "@com_github_google_googletest//:gtest_main", - "@com_google_absl//absl/numeric:int128", - ], -)
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/basic_rng.h b/third_party/distributed_point_functions/code/dcf/fss_gates/prng/basic_rng.h deleted file mode 100644 index 13b0da8b..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/basic_rng.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. - -#ifndef DISTRIBUTED_POINT_FUNCTIONS_PRNG_BASIC_RNG_H_ -#define DISTRIBUTED_POINT_FUNCTIONS_PRNG_BASIC_RNG_H_ - -#include <openssl/rand.h> - -#include "absl/base/casts.h" -#include "absl/memory/memory.h" -#include "absl/numeric/int128.h" -#include "absl/strings/string_view.h" -#include "dcf/fss_gates/prng/prng.h" - -namespace distributed_point_functions { - -// Basic RNG class that uses RAND_bytes from OpenSSL to sample randomness. -// BasicRng does not require a seed internally. -class BasicRng : public SecurePrng { - public: - // Create a BasicRng object. - // Returns an INTERNAL error code if the creation fails. - static absl::StatusOr<std::unique_ptr<BasicRng>> Create( - absl::string_view seed) { - return absl::make_unique<BasicRng>(); - } - - // Sample 8 bits of randomness using OpenSSL RAND_bytes. - // Returns an INTERNAL error code if the sampling fails. - inline absl::StatusOr<uint8_t> Rand8() override { return Rand<uint8_t>(); } - - // Sample 64 bits of randomness using OPENSSL RAND_bytes. - // Returns an INTERNAL error code if the sampling fails. - inline absl::StatusOr<uint64_t> Rand64() override { return Rand<uint64_t>(); } - - // Sample 128 bits of randomness using OPENSSL RAND_bytes. - // Returns an INTERNAL error code if the sampling fails. - inline absl::StatusOr<absl::uint128> Rand128() override { - return Rand<absl::uint128>(); - } - - // BasicRng does not use seeds. - static absl::StatusOr<std::string> GenerateSeed() { return std::string(); } - static int SeedLength() { return 0; } - - private: - template <typename T> - absl::StatusOr<T> Rand() { - std::array<uint8_t, sizeof(T)> rand; - int success = RAND_bytes(rand.data(), rand.size()); - if (!success) { - return absl::InternalError( - "BasicRng::Rand - Failed to create randomness"); - } - return absl::bit_cast<T>(rand); - } -}; - -} // namespace distributed_point_functions - -#endif // DISTRIBUTED_POINT_FUNCTIONS_PRNG_BASIC_RNG_H_
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/basic_rng_test.cc b/third_party/distributed_point_functions/code/dcf/fss_gates/prng/basic_rng_test.cc deleted file mode 100644 index 5d955210..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/basic_rng_test.cc +++ /dev/null
@@ -1,106 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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 "dcf/fss_gates/prng/basic_rng.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include "absl/numeric/int128.h" -#include "dpf/internal/status_matchers.h" - -namespace distributed_point_functions { -namespace { - -using ::testing::Test; - -const absl::string_view kSampleSeed = absl::string_view(); -constexpr int kNumSamples = 10; - -class BasicRngTest : public Test { - protected: - void SetUp() { - DPF_ASSERT_OK_AND_ASSIGN(rng_, BasicRng::Create(kSampleSeed)); - } - - std::unique_ptr<BasicRng> rng_; -}; - -TEST_F(BasicRngTest, Test8BitRand) { - // Two random 8 bit strings have 1/256 probability of being equal. Instead, - // we check that 8 consecutively generated strings are not all equal. - bool equal = true; - DPF_ASSERT_OK_AND_ASSIGN(uint8_t prev, rng_->Rand8()); - for (int i = 0; i < 8; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(uint8_t next, rng_->Rand8()); - if (next != prev) { - equal = false; - } - prev = next; - } - EXPECT_FALSE(equal); -} - -TEST_F(BasicRngTest, Test64BitRand) { - DPF_ASSERT_OK_AND_ASSIGN(uint64_t r1, rng_->Rand64()); - DPF_ASSERT_OK_AND_ASSIGN(uint64_t r2, rng_->Rand64()); - EXPECT_NE(r1, r2); -} - -TEST_F(BasicRngTest, Test128BitRand) { - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r1, rng_->Rand128()); - DPF_ASSERT_OK_AND_ASSIGN(absl::uint128 r2, rng_->Rand128()); - EXPECT_NE(r1, r2); -} - -TEST_F(BasicRngTest, BytesAreDifferent64) { - std::vector<uint64_t> rand(kNumSamples); - for (size_t i = 0; i < kNumSamples; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(rand[i], rng_->Rand64()); - } - - for (int i = 0; i < sizeof(uint64_t); ++i) { - bool not_all_equal = false; - for (int j = 1; j < kNumSamples; ++j) { - auto byte1 = static_cast<uint8_t>(rand[j - 1] >> (8 * i)); - auto byte2 = static_cast<uint8_t>(rand[j] >> (8 * i)); - if (byte1 != byte2) { - not_all_equal = true; - } - } - EXPECT_TRUE(not_all_equal); - } -} - -TEST_F(BasicRngTest, BytesAreDifferent128) { - std::vector<absl::uint128> rand(kNumSamples); - for (int i = 0; i < kNumSamples; ++i) { - DPF_ASSERT_OK_AND_ASSIGN(rand[i], rng_->Rand128()); - } - - for (size_t i = 0; i < sizeof(absl::uint128); ++i) { - bool not_all_equal = false; - for (int j = 1; j < kNumSamples; ++j) { - auto byte1 = static_cast<uint8_t>(rand[j - 1] >> (8 * i)); - auto byte2 = static_cast<uint8_t>(rand[j] >> (8 * i)); - if (byte1 != byte2) { - not_all_equal = true; - } - } - EXPECT_TRUE(not_all_equal); - } -} - -} // namespace -} // namespace distributed_point_functions
diff --git a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/prng.h b/third_party/distributed_point_functions/code/dcf/fss_gates/prng/prng.h deleted file mode 100644 index 1920deb..0000000 --- a/third_party/distributed_point_functions/code/dcf/fss_gates/prng/prng.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2021 Google LLC -// -// 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. - -#ifndef DISTRIBUTED_POINT_FUNCTIONS_PRNG_PRNG_H_ -#define DISTRIBUTED_POINT_FUNCTIONS_PRNG_PRNG_H_ - -#include "absl/numeric/int128.h" -#include "absl/status/statusor.h" -#include "absl/strings/string_view.h" -#include "dpf/status_macros.h" - -namespace distributed_point_functions { - -// An interface for a secure pseudo-random number generator. -class SecurePrng { - public: - virtual absl::StatusOr<uint8_t> Rand8() = 0; - virtual absl::StatusOr<uint64_t> Rand64() = 0; - virtual absl::StatusOr<absl::uint128> Rand128() = 0; - virtual ~SecurePrng() = default; - static absl::StatusOr<std::unique_ptr<SecurePrng>> Create( - absl::string_view seed); - static absl::StatusOr<std::string> GenerateSeed(); - static int SeedLength(); -}; - -} // namespace distributed_point_functions - -#endif // DISTRIBUTED_POINT_FUNCTIONS_PRNG_PRNG_H_
diff --git a/third_party/gvr-android-sdk/OWNERS b/third_party/gvr-android-sdk/OWNERS index 019bb305..cdc8cf48 100644 --- a/third_party/gvr-android-sdk/OWNERS +++ b/third_party/gvr-android-sdk/OWNERS
@@ -1,5 +1,3 @@ -alcooper@chromium.org -bajones@chromium.org -bialpio@chromium.org +file://components/webxr/OWNERS mthiesse@chromium.org vollick@chromium.org
diff --git a/third_party/openxr/OWNERS b/third_party/openxr/OWNERS index fa80476..0b752de 100644 --- a/third_party/openxr/OWNERS +++ b/third_party/openxr/OWNERS
@@ -1,2 +1,2 @@ -alcooper@chromium.org +file://components/webxr/OWNERS rafael.cintron@microsoft.com
diff --git a/third_party/webxr_test_pages/OWNERS b/third_party/webxr_test_pages/OWNERS index e01af6d..d95d28c 100644 --- a/third_party/webxr_test_pages/OWNERS +++ b/third_party/webxr_test_pages/OWNERS
@@ -1,4 +1 @@ -alcooper@chromium.org -bajones@chromium.org -bialpio@chromium.org -klausw@chromium.org +file://components/webxr/OWNERS
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 5eb9ffc..b75dda82 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -65035,6 +65035,10 @@ <int value="4" label="responses loaded from HTTP cache"> Subset of Suggest responses that were loaded from the HTTP cache. </int> + <int value="5" label="out-of-date responses loaded from HTTP cache"> + Subset of Suggest responses that were loaded from the HTTP cache and were + out-of-date. + </int> </enum> <enum name="OnServiceConnectedTimedOutResult"> @@ -73902,6 +73906,7 @@ <int value="6" label="Thanks"/> <int value="7" label="Unsure"/> <int value="8" label="Heart"/> + <int value="9" label="Laugh Cry"/> </enum> <enum name="ReadDynamicRulesJSONStatus">
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml index fa298ae..dc74ed9 100644 --- a/tools/metrics/histograms/metadata/optimization/histograms.xml +++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -393,6 +393,17 @@ </summary> </histogram> +<histogram name="OptimizationGuide.HintsManager.ConcurrentBatchUpdateFetches" + units="counts" expires_after="M106"> + <owner>sophiechang@chromium.org</owner> + <owner>mcrouse@chromium.org</owner> + <summary> + The number of active batch update hints fetches initiated by the hints + manager. Recorded when a fetch is initiated to the remote Optimization Guide + Service for a batch update context (i.e. on SRP, other UI surfaces, etc.). + </summary> +</histogram> + <histogram name="OptimizationGuide.HintsManager.ConcurrentPageNavigationFetches" units="counts" expires_after="M106">
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml index 800d567b..55402512 100644 --- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml +++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -54,7 +54,8 @@ summary="ESB enabled duration was between 1 hour and 24 hours"/> <variant name="NeverEnabled" summary="There is no enabled duration because ESB wasn't manually - enabled"/> + enabled, or it has been longer than kEventMaxDurationDay days + since the latest enabled event."/> <variant name="ShortEnabled" summary="ESB enabled duration was less than 1 hour"/> </variants>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index e56ee27..8bb4d07 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -9,16 +9,16 @@ "remote_path": "perfetto_binaries/trace_processor_shell/win/9c674c8ed6844fb88b545a8df9282a9405f8a072/trace_processor_shell.exe" }, "mac": { - "hash": "0b89b9b7de51b70e2218120061b62f9011bfcd08", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/15e3467297c3877d090e92940a04b085318ab933/trace_processor_shell" + "hash": "83a92c4b88f963f5606a1e3c953d2051b0cb1958", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/9c674c8ed6844fb88b545a8df9282a9405f8a072/trace_processor_shell" }, "linux_arm64": { "hash": "5074025a2898ec41a872e70a5719e417acb0a380", "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "linux": { - "hash": "46bd1cb0b881714948a74f091500c22f241fea08", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/15e3467297c3877d090e92940a04b085318ab933/trace_processor_shell" + "hash": "9e5e4909b2b6a6f4e1aeb2b5bc081567935aeea0", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/cefb3e0ec3a0580c996f801e854fe02963c03d5c/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 37151bc..acfc3ff 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -670,7 +670,10 @@ if (is_win) { data += [ "//tools/skia_goldctl/win/goldctl.exe" ] } else if (is_mac) { - data += [ "//tools/skia_goldctl/mac/goldctl" ] + data += [ + "//tools/skia_goldctl/mac_amd64/goldctl", + "//tools/skia_goldctl/mac_arm64/goldctl", + ] } else { data += [ "//tools/skia_goldctl/linux/goldctl" ] }
diff --git a/ui/base/test/skia_gold_pixel_diff.cc b/ui/base/test/skia_gold_pixel_diff.cc index a754f6c0..2f6c231 100644 --- a/ui/base/test/skia_gold_pixel_diff.cc +++ b/ui/base/test/skia_gold_pixel_diff.cc
@@ -40,7 +40,11 @@ #if defined(OS_WIN) const wchar_t* kSkiaGoldCtl = L"tools/skia_goldctl/win/goldctl.exe"; #elif defined(OS_APPLE) -const char* kSkiaGoldCtl = "tools/skia_goldctl/mac/goldctl"; +#if defined(ARCH_CPU_ARM64) +const char* kSkiaGoldCtl = "tools/skia_goldctl/mac_arm64/goldctl"; +#else +const char* kSkiaGoldCtl = "tools/skia_goldctl/mac_amd64/goldctl"; +#endif // defined(ARCH_CPU_ARM64) #else const char* kSkiaGoldCtl = "tools/skia_goldctl/linux/goldctl"; #endif
diff --git a/ui/events/keycodes/dom/dom_code_data.inc b/ui/events/keycodes/dom/dom_code_data.inc index c96987d..dd8ac49 100644 --- a/ui/events/keycodes/dom/dom_code_data.inc +++ b/ui/events/keycodes/dom/dom_code_data.inc
@@ -76,6 +76,13 @@ // Apple keyboards with USB 0x070049 [Insert] labelled "Help" have not // been made since 2007. +// ChromeOS notes: +// +// Any keys that are added or updated specifically for use in the ChromeOS +// top-row should also be updated in sections of Input Diagnostics: +// ash/webui/diagnostics_ui/mojom/input_data_provider.mojom: enum TopRowKey +// ash/webui/diagnostics_ui/backend/input_data_provider_keyboard.cc: kScancodeMapping + DOM_CODE_DECLARATION { // USB evdev XKB Win Mac Code
diff --git a/ui/gtk/window_frame_provider_gtk.cc b/ui/gtk/window_frame_provider_gtk.cc index 4c7773f..e9b7a98 100644 --- a/ui/gtk/window_frame_provider_gtk.cc +++ b/ui/gtk/window_frame_provider_gtk.cc
@@ -8,6 +8,7 @@ #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/skia_conversions.h" #include "ui/gfx/scoped_canvas.h" #include "ui/gtk/gtk_compat.h" #include "ui/gtk/gtk_util.h" @@ -47,7 +48,9 @@ GtkCssContext DecorationContext(bool solid_frame, bool focused) { auto context = WindowContext(solid_frame, focused); - context = AppendCssNodeToStyleContext(context, "#decoration"); + // GTK4 renders the decoration directly on the window. + if (!GtkCheckVersion(4)) + context = AppendCssNodeToStyleContext(context, "#decoration"); if (!focused) gtk_style_context_set_state(context, GTK_STATE_FLAG_BACKDROP); @@ -105,8 +108,11 @@ int ComputeTopCornerRadius() { // In GTK4, there's no way to directly obtain CSS values for a context, so we // need to experimentally determine the corner radius by rendering a sample. - auto context = HeaderContext(false, false); - ApplyCssToContext(context, R"(headerbar { + // Additionally, in GTK4, the headerbar corners get clipped by the window + // rather than the headerbar having its own rounded corners. + auto context = GtkCheckVersion(4) ? DecorationContext(false, false) + : HeaderContext(false, false); + ApplyCssToContext(context, R"(window, headerbar { background-image: none; background-color: black; box-shadow: none; @@ -115,8 +121,10 @@ border-bottom-right-radius: 0; border-top-right-radius: 0; })"); - auto bitmap = - PaintHeaderbar({kMaxCornerRadiusDip, kMaxCornerRadiusDip}, context, 1); + gfx::Size size_dip{kMaxCornerRadiusDip, kMaxCornerRadiusDip}; + auto bitmap = GtkCheckVersion(4) + ? PaintBitmap(size_dip, {{0, 0}, size_dip}, context, 1) + : PaintHeaderbar(size_dip, context, 1); DCHECK_EQ(bitmap.width(), bitmap.height()); for (int i = 0; i < bitmap.width(); ++i) { if (SkColorGetA(bitmap.getColor(0, i)) == 255 && @@ -258,6 +266,17 @@ auto header = PaintHeaderbar({client_bounds_px.width(), top_area_height_px}, HeaderContext(solid_frame_, focused), scale); image = gfx::ImageSkia::CreateFrom1xBitmap(header); + // In GTK4, the headerbar gets clipped by the window. + if (GtkCheckVersion(4)) { + gfx::RectF bounds_px = + gfx::RectF(client_bounds_px.x(), client_bounds_px.y(), header.width(), + header.height()); + float radius_px = scale * top_corner_radius_dip_; + SkVector radii[4]{{radius_px, radius_px}, {radius_px, radius_px}, {}, {}}; + SkRRect clip; + clip.setRectRadii(gfx::RectFToSkRect(bounds_px), radii); + canvas->sk_canvas()->clipRRect(clip, SkClipOp::kIntersect, true); + } draw_image(0, 0, header.width(), header.height(), client_bounds_px.x(), client_bounds_px.y(), header.width(), header.height()); }
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index 830ee0f..9d9dcab5 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn
@@ -215,6 +215,7 @@ "cr_elements/mwb_shared_style.ts", "cr_elements/mwb_shared_vars.ts", "cr_elements/search_highlight_style_css.ts", + "js/custom_element.ts", "js/i18n_mixin.ts", "js/list_property_update_mixin.ts", "js/web_ui_listener_mixin.ts", @@ -260,7 +261,6 @@ "$root_dir/js/cr/ui/focus_outline_manager.m.d.ts", "$root_dir/js/cr/ui/focus_row.m.d.ts", "$root_dir/js/cr/ui/keyboard_shortcut_list.m.d.ts", - "$root_dir/js/custom_element.d.ts", "$root_dir/js/event_tracker.m.d.ts", "$root_dir/js/load_time_data.m.d.ts", "$root_dir/js/plural_string_proxy.d.ts", @@ -323,7 +323,6 @@ "js/cr/ui/focus_row.m.js", "js/cr/ui/keyboard_shortcut_list.m.js", "js/cr/ui/store.js", - "js/custom_element.js", "js/event_tracker.m.js", "js/icon.js", "js/load_time_data.m.js",
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn index c2fefdb..c66ad39 100644 --- a/ui/webui/resources/cr_components/BUILD.gn +++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -12,6 +12,7 @@ "$root_gen_dir/ui/webui/resources/preprocessed/cr_components" preprocess_gen_manifest = "preprocessed_gen_manifest.json" preprocess_mojom_manifest = "preprocessed_mojom_manifest.json" +preprocess_external_mojo_manifest = "preprocessed_external_mojo_manifest.json" if (is_chromeos_ash) { preprocess_polymer2_manifest = "preprocessed_polymer2_manifest.json" } @@ -20,7 +21,10 @@ generate_grd("build_grdp") { grd_prefix = "cr_components" out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp" - deps = [ ":preprocess" ] + deps = [ + ":preprocess", + ":preprocess_external_mojo", + ] if (is_chromeos_ash) { input_files_base_dir = rebase_path(".", "//") input_files = [ @@ -64,6 +68,7 @@ "$target_gen_dir/$preprocess_gen_manifest", "$target_gen_dir/$preprocess_mojom_manifest", "$target_gen_dir/$preprocess_src_manifest", + "$target_gen_dir/$preprocess_external_mojo_manifest", ] # TODO(crbug.com/1184053): Fully remove once no longer used by CrOS. @@ -72,6 +77,13 @@ } resource_path_prefix = "cr_components" + + resource_path_rewrites = [ + "mojo/public/mojom/base/file_path.mojom-lite.js|app_management/file_path.mojom-lite.js", + "mojo/public/mojom/base/safe_base_name.mojom-lite.js|app_management/safe_base_name.mojom-lite.js", + "ui/gfx/image/mojom/image.mojom-lite.js|app_management/image.mojom-lite.js", + "components/services/app_service/public/mojom/types.mojom-lite.js|app_management/types.mojom-lite.js", + ] } group("preprocess") { @@ -103,6 +115,12 @@ "most_visited/window_proxy.js", "color_change_listener/browser_proxy.js", "color_change_listener/colors_css_updater.js", + "app_management/permission_constants.js", + "app_management/permission_util.js", + "app_management/browser_proxy.js", + "app_management/constants.js", + "app_management/types.js", + "app_management/util.js", ] } @@ -121,7 +139,10 @@ } preprocess_if_expr("preprocess_generated") { - deps = [ ":polymer3_elements" ] + deps = [ + ":polymer3_elements", + "//ui/webui/resources/cr_components/app_management:mojo_bindings_js__generator", + ] in_folder = target_gen_dir out_folder = preprocess_folder out_manifest = "$target_gen_dir/$preprocess_gen_manifest" @@ -131,6 +152,11 @@ "managed_dialog/managed_dialog.js", "managed_footnote/managed_footnote.js", "omnibox/cr_autocomplete_match_list.js", + "app_management/permission_item.js", + "app_management/shared_style.js", + "app_management/shared_vars.js", + "app_management/toggle_row.js", + "app_management/app_management.mojom-lite.js", ] if (is_chromeos_ash) { @@ -402,6 +428,7 @@ group("closure_compile") { deps = [ + "app_management:closure_compile", "color_change_listener:closure_compile", "managed_dialog:closure_compile", "managed_footnote:closure_compile", @@ -416,6 +443,7 @@ group("polymer3_elements") { public_deps = [ + "app_management:web_components", "customize_themes:web_components", "iph_bubble:web_components", "managed_dialog:web_components", @@ -428,3 +456,25 @@ public_deps += [ "chromeos:polymer3_elements" ] } } + +preprocess_if_expr("preprocess_external_mojo") { + deps = [ + "//components/services/app_service/public/mojom:mojom_js", + "//mojo/public/js:bindings_lite", + "//mojo/public/mojom/base", + "//ui/gfx/image/mojom:mojom_js", + ] + in_folder = "$root_gen_dir" + + # It does not matter which preprocess folder these files are pasted into, as + # they are not used for bundling; the purpose of this build rule is to + # include them in the generated grd file. + out_folder = "$preprocess_folder" + out_manifest = "$target_gen_dir/$preprocess_external_mojo_manifest" + in_files = [ + "mojo/public/mojom/base/file_path.mojom-lite.js", + "mojo/public/mojom/base/safe_base_name.mojom-lite.js", + "ui/gfx/image/mojom/image.mojom-lite.js", + "components/services/app_service/public/mojom/types.mojom-lite.js", + ] +}
diff --git a/ui/webui/resources/cr_components/app_management/BUILD.gn b/ui/webui/resources/cr_components/app_management/BUILD.gn new file mode 100644 index 0000000..e6bd6b82 --- /dev/null +++ b/ui/webui/resources/cr_components/app_management/BUILD.gn
@@ -0,0 +1,97 @@ +# 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. + +import("//mojo/public/tools/bindings/mojom.gni") +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ + ":browser_proxy", + ":constants", + ":permission_constants", + ":permission_item", + ":permission_util", + ":shared_style", + ":shared_vars", + ":toggle_row", + ":types", + ":util", + ] +} + +js_library("permission_item") { + deps = [ + ":browser_proxy", + ":permission_constants", + ":toggle_row", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + +js_library("shared_style") { + deps = [] +} + +js_library("shared_vars") { + deps = [] +} + +js_library("permission_constants") { + deps = [ ":mojo_bindings_js_library_for_compile" ] +} + +js_library("permission_util") { + deps = [ + ":permission_constants", + "//ui/webui/resources/js:assert.m", + ] +} + +js_library("browser_proxy") { + deps = [ + ":mojo_bindings_js_library_for_compile", + "//ui/webui/resources/js:cr.m", + ] +} + +js_library("toggle_row") { + deps = [ + ":types", + "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle.m", + "//ui/webui/resources/cr_elements/policy:cr_policy_indicator.m", + ] +} + +js_library("constants") { + deps = [ ":mojo_bindings_js_library_for_compile" ] +} + +js_library("types") { + deps = [] +} + +js_library("util") { + deps = [ ":permission_constants" ] + externs_list = [ "//third_party/closure_compiler/externs/metrics_private.js" ] +} + +html_to_js("web_components") { + js_files = [ + "permission_item.js", + "shared_style.js", + "shared_vars.js", + "toggle_row.js", + ] +} + +mojom("mojo_bindings") { + sources = [ "app_management.mojom" ] + + public_deps = [ + "//components/services/app_service/public/mojom", + "//mojo/public/mojom/base", + ] +}
diff --git a/ui/webui/resources/cr_components/app_management/OWNERS b/ui/webui/resources/cr_components/app_management/OWNERS new file mode 100644 index 0000000..d3f5d59 --- /dev/null +++ b/ui/webui/resources/cr_components/app_management/OWNERS
@@ -0,0 +1,4 @@ +file://chrome/browser/resources/settings/chromeos/os_apps_page/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/app_management/app_management.mojom b/ui/webui/resources/cr_components/app_management/app_management.mojom similarity index 100% rename from chrome/browser/ui/webui/app_management/app_management.mojom rename to ui/webui/resources/cr_components/app_management/app_management.mojom
diff --git a/ui/webui/resources/cr_components/app_management/browser_proxy.js b/ui/webui/resources/cr_components/app_management/browser_proxy.js new file mode 100644 index 0000000..983f19a --- /dev/null +++ b/ui/webui/resources/cr_components/app_management/browser_proxy.js
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; +import 'chrome://resources/mojo/skia/public/mojom/image_info.mojom-lite.js'; +import 'chrome://resources/mojo/skia/public/mojom/bitmap.mojom-lite.js'; +import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js'; +import './file_path.mojom-lite.js'; +import './image.mojom-lite.js'; +import './types.mojom-lite.js'; +import './app_management.mojom-lite.js'; + +import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; + +export class BrowserProxy { + constructor() { + /** @type {appManagement.mojom.PageCallbackRouter} */ + this.callbackRouter = new appManagement.mojom.PageCallbackRouter(); + + /** @type {appManagement.mojom.PageHandlerRemote} */ + this.handler = new appManagement.mojom.PageHandlerRemote(); + const factory = appManagement.mojom.PageHandlerFactory.getRemote(); + factory.createPageHandler( + this.callbackRouter.$.bindNewPipeAndPassRemote(), + this.handler.$.bindNewPipeAndPassReceiver()); + } +} + +addSingletonGetter(BrowserProxy);
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/constants.js b/ui/webui/resources/cr_components/app_management/constants.js similarity index 90% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/constants.js rename to ui/webui/resources/cr_components/app_management/constants.js index 6a95b0f..6130d23 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/constants.js +++ b/ui/webui/resources/cr_components/app_management/constants.js
@@ -7,11 +7,11 @@ import 'chrome://resources/mojo/skia/public/mojom/image_info.mojom-lite.js'; import 'chrome://resources/mojo/skia/public/mojom/bitmap.mojom-lite.js'; import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js'; -import '/app-management/file_path.mojom-lite.js'; -import '/app-management/image.mojom-lite.js'; -import '/app-management/safe_base_name.mojom-lite.js'; -import '/app-management/types.mojom-lite.js'; -import '/app-management/app_management.mojom-lite.js'; +import './file_path.mojom-lite.js'; +import './image.mojom-lite.js'; +import './safe_base_name.mojom-lite.js'; +import './types.mojom-lite.js'; +import './app_management.mojom-lite.js'; /** * The number of apps displayed in app list in the main view before expanding.
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/permission_constants.js b/ui/webui/resources/cr_components/app_management/permission_constants.js similarity index 66% rename from chrome/browser/resources/settings/chromeos/os_apps_page/permission_constants.js rename to ui/webui/resources/cr_components/app_management/permission_constants.js index 37e2e580..26d8bd84 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/permission_constants.js +++ b/ui/webui/resources/cr_components/app_management/permission_constants.js
@@ -4,10 +4,10 @@ import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; -import '/app-management/file_path.mojom-lite.js'; -import '/app-management/image.mojom-lite.js'; -import '/app-management/safe_base_name.mojom-lite.js'; -import '/app-management/types.mojom-lite.js'; +import './file_path.mojom-lite.js'; +import './image.mojom-lite.js'; +import './safe_base_name.mojom-lite.js'; +import './types.mojom-lite.js'; export const TriState = apps.mojom.TriState;
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.html b/ui/webui/resources/cr_components/app_management/permission_item.html similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.html rename to ui/webui/resources/cr_components/app_management/permission_item.html
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.js b/ui/webui/resources/cr_components/app_management/permission_item.js similarity index 93% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.js rename to ui/webui/resources/cr_components/app_management/permission_item.js index ac3489d..4bfade1 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/permission_item.js +++ b/ui/webui/resources/cr_components/app_management/permission_item.js
@@ -7,22 +7,16 @@ import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {recordClick, recordNavigation, recordPageBlur, recordPageFocus, recordSearch, recordSettingChange, setUserActionRecorderForTesting} from '../../metrics_recorder.m.js'; -import {PermissionType, PermissionValue, TriState} from '../permission_constants.js'; -import {createBoolPermission, createTriStatePermission, getBoolPermissionValue, getTriStatePermissionValue, isBoolValue, isTriStateValue} from '../permission_util.js'; - import {BrowserProxy} from './browser_proxy.js'; import {AppManagementUserAction} from './constants.js'; -import {AppManagementStoreClient} from './store_client.js'; +import {PermissionType, PermissionValue, TriState} from './permission_constants.js'; +import {createBoolPermission, createTriStatePermission, getBoolPermissionValue, getTriStatePermissionValue, isBoolValue, isTriStateValue} from './permission_util.js'; import {getPermission, getPermissionValueBool, getSelectedApp, recordAppManagementUserAction} from './util.js'; Polymer({ _template: html`{__html_template__}`, is: 'app-management-permission-item', - behaviors: [ - AppManagementStoreClient, - ], properties: { /** @@ -82,11 +76,6 @@ listeners: {click: 'onClick_', change: 'togglePermission_'}, - attached() { - this.watch('app_', state => getSelectedApp(state)); - this.updateFromStore(); - }, - /** * Returns true if the permission type is available for the app. * @@ -186,7 +175,6 @@ BrowserProxy.getInstance().handler.setPermission( this.app_.id, newPermission); - recordSettingChange(); recordAppManagementUserAction( this.app_.type, this.getUserMetricActionForPermission_(
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/permission_util.js b/ui/webui/resources/cr_components/app_management/permission_util.js similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/permission_util.js rename to ui/webui/resources/cr_components/app_management/permission_util.js
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.html b/ui/webui/resources/cr_components/app_management/shared_style.html similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.html rename to ui/webui/resources/cr_components/app_management/shared_style.html
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.js b/ui/webui/resources/cr_components/app_management/shared_style.js similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.js rename to ui/webui/resources/cr_components/app_management/shared_style.js
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.html b/ui/webui/resources/cr_components/app_management/shared_vars.html similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.html rename to ui/webui/resources/cr_components/app_management/shared_vars.html
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.js b/ui/webui/resources/cr_components/app_management/shared_vars.js similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.js rename to ui/webui/resources/cr_components/app_management/shared_vars.js
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/toggle_row.html b/ui/webui/resources/cr_components/app_management/toggle_row.html similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/toggle_row.html rename to ui/webui/resources/cr_components/app_management/toggle_row.html
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/toggle_row.js b/ui/webui/resources/cr_components/app_management/toggle_row.js similarity index 92% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/toggle_row.js rename to ui/webui/resources/cr_components/app_management/toggle_row.js index 54f4457..6bc6fd00 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/toggle_row.js +++ b/ui/webui/resources/cr_components/app_management/toggle_row.js
@@ -7,9 +7,6 @@ import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {BrowserProxy} from './browser_proxy.js'; -import {AppManagementStoreClient} from './store_client.js'; - Polymer({ _template: html`{__html_template__}`, is: 'app-management-toggle-row',
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js b/ui/webui/resources/cr_components/app_management/types.js similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js rename to ui/webui/resources/cr_components/app_management/types.js
diff --git a/ui/webui/resources/cr_components/app_management/util.js b/ui/webui/resources/cr_components/app_management/util.js new file mode 100644 index 0000000..2f23b5f --- /dev/null +++ b/ui/webui/resources/cr_components/app_management/util.js
@@ -0,0 +1,190 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert} from 'chrome://resources/js/assert.m.js'; +import {assertNotReached} from 'chrome://resources/js/assert.m.js'; + +import {AppManagementUserAction, AppType, OptionalBool} from './constants.js'; +import {PermissionType} from './permission_constants.js'; +import {isPermissionEnabled} from './permission_util.js'; + + +/** + * @fileoverview Utility functions for the App Management page. + */ + +/** + * @return {!AppManagementPageState} + */ +export function createEmptyState() { + return { + apps: {}, + selectedAppId: null, + }; +} + +/** + * @param {!Array<App>} apps + * @return {!AppManagementPageState} + */ +export function createInitialState(apps) { + const initialState = createEmptyState(); + + for (const app of apps) { + initialState.apps[app.id] = app; + } + + return initialState; +} + +/** + * @param {App} app + * @return {string} + */ +export function getAppIcon(app) { + return `chrome://app-icon/${app.id}/64`; +} + +/** + * If the given value is not in the set, returns a new set with the value + * added, otherwise returns the old set. + * @template T + * @param {!Set<T>} set + * @param {T} value + * @return {!Set<T>} + */ +export function addIfNeeded(set, value) { + if (!set.has(value)) { + set = new Set(set); + set.add(value); + } + return set; +} + +/** + * If the given value is in the set, returns a new set without the value, + * otherwise returns the old set. + * @template T + * @param {!Set<T>} set + * @param {T} value + * @return {!Set<T>} + */ +export function removeIfNeeded(set, value) { + if (set.has(value)) { + set = new Set(set); + set.delete(value); + } + return set; +} + +/** + * @param {App} app + * @param {string} permissionType + * @return {boolean} + */ +export function getPermissionValueBool(app, permissionType) { + const permission = getPermission(app, permissionType); + assert(permission); + + return isPermissionEnabled(permission.value); +} + +/** + * Undefined is returned when the app does not request a permission. + * + * @param {App} app + * @param {string} permissionType + * @return {Permission|undefined} + */ +export function getPermission(app, permissionType) { + return app.permissions[PermissionType[permissionType]]; +} + +/** + * @param {AppManagementPageState} state + * @return {?App} + */ +export function getSelectedApp(state) { + const selectedAppId = state.selectedAppId; + return selectedAppId ? state.apps[selectedAppId] : null; +} + +/** + * A comparator function to sort strings alphabetically. + * + * @param {string} a + * @param {string} b + */ +export function alphabeticalSort(a, b) { + return a.localeCompare(b); +} + +/** + * Toggles an OptionalBool + * + * @param {OptionalBool} bool + * @return {OptionalBool} + */ +export function toggleOptionalBool(bool) { + switch (bool) { + case OptionalBool.kFalse: + return OptionalBool.kTrue; + case OptionalBool.kTrue: + return OptionalBool.kFalse; + default: + assertNotReached(); + } +} + +/** + * @param {OptionalBool} optionalBool + * @returns {boolean} + */ +export function convertOptionalBoolToBool(optionalBool) { + switch (optionalBool) { + case OptionalBool.kTrue: + return true; + case OptionalBool.kFalse: + return false; + default: + assertNotReached(); + } +} + +/** + * @param {AppType} appType + * @return {string} + * @private + */ +export function getUserActionHistogramNameForAppType_(appType) { + switch (appType) { + case AppType.kArc: + return 'AppManagement.AppDetailViews.ArcApp'; + case AppType.kChromeApp: + case AppType.kStandaloneBrowser: + case AppType.kStandaloneBrowserChromeApp: + // TODO(https://crbug.com/1225848): Figure out appropriate behavior for + // Lacros-hosted chrome-apps. + return 'AppManagement.AppDetailViews.ChromeApp'; + case AppType.kWeb: + return 'AppManagement.AppDetailViews.WebApp'; + case AppType.kPluginVm: + return 'AppManagement.AppDetailViews.PluginVmApp'; + case AppType.kBorealis: + return 'AppManagement.AppDetailViews.BorealisApp'; + default: + assertNotReached(); + } +} + +/** + * @param {AppType} appType + * @param {AppManagementUserAction} userAction + */ +export function recordAppManagementUserAction(appType, userAction) { + const histogram = getUserActionHistogramNameForAppType_(appType); + const enumLength = Object.keys(AppManagementUserAction).length; + chrome.metricsPrivate.recordEnumerationValue( + histogram, userAction, enumLength); +}
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index 8bb2f10..29fe466 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -47,6 +47,7 @@ in_folder = "./" out_folder = "$preprocess_folder" in_files = [ + "custom_element.ts", "i18n_mixin.ts", "list_property_update_mixin.ts", "web_ui_listener_mixin.ts", @@ -62,7 +63,6 @@ "assert.js", "color_utils.js", "cr.m.js", - "custom_element.js", "i18n_template_no_process.js", "icon.js", "load_time_data.m.js", @@ -292,7 +292,6 @@ deps = [ ":assert.m", ":cr.m", - ":custom_element", ":event_tracker.m", ":i18n_behavior.m", ":icon", @@ -328,9 +327,6 @@ externs_list = [ "$externs_path/chrome_send.js" ] } -js_library("custom_element") { -} - js_library("event_tracker.m") { sources = [ "$root_gen_dir/ui/webui/resources/js/event_tracker.m.js" ] extra_deps = [ ":modulize_local" ]
diff --git a/ui/webui/resources/js/custom_element.js b/ui/webui/resources/js/custom_element.js deleted file mode 100644 index 9d74568..0000000 --- a/ui/webui/resources/js/custom_element.js +++ /dev/null
@@ -1,35 +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. - -/** - * @fileoverview Base class for Web Components that don't use Polymer. - * See the following file for usage: - * chrome/test/data/webui/js/custom_element_test.js - */ -export class CustomElement extends HTMLElement { - constructor() { - super(); - - this.attachShadow({mode: 'open'}); - const template = document.createElement('template'); - template.innerHTML = this.constructor.template || ''; - this.shadowRoot.appendChild(template.content.cloneNode(true)); - } - - /** - * @param {string} query - * @return {?Element} - */ - $(query) { - return this.shadowRoot.querySelector(query); - } - - /** - * @param {string} query - * @return {!NodeList<!Element>} - */ - $all(query) { - return this.shadowRoot.querySelectorAll(query); - } -}
diff --git a/ui/webui/resources/js/custom_element.ts b/ui/webui/resources/js/custom_element.ts new file mode 100644 index 0000000..b2f0f1a2 --- /dev/null +++ b/ui/webui/resources/js/custom_element.ts
@@ -0,0 +1,33 @@ +// 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. + +/** + * @fileoverview Base class for Web Components that don't use Polymer. + * See the following file for usage: + * chrome/test/data/webui/js/custom_element_test.js + */ + +export class CustomElement extends HTMLElement { + static get template(): string { + return ''; + } + + constructor() { + super(); + + this.attachShadow({mode: 'open'}); + const template = document.createElement('template'); + template.innerHTML = + (this.constructor as typeof CustomElement).template || ''; + this.shadowRoot!.appendChild(template.content.cloneNode(true)); + } + + $<E extends Element = Element>(query: string): E|null { + return this.shadowRoot!.querySelector<E>(query); + } + + $all<E extends Element = Element>(query: string): NodeListOf<E> { + return this.shadowRoot!.querySelectorAll<E>(query); + } +}
diff --git a/weblayer/browser/android/javatests/skew/expectations.txt b/weblayer/browser/android/javatests/skew/expectations.txt index ba796a08f..d73b58c 100644 --- a/weblayer/browser/android/javatests/skew/expectations.txt +++ b/weblayer/browser/android/javatests/skew/expectations.txt
@@ -5,7 +5,7 @@ # with versions less than or equal to $VERSION of the implementation. # # These lines are not comments! They define the set of known tags and other information. -# tags: [ client_lte_91 client_lte_94 client_lte_95 impl_lte_95 ] +# tags: [ client_lte_91 client_lte_94 client_lte_95 impl_lte_95 client_lte_98 impl_lte_98 ] # 'all' disables the test from any skew test. # tags: [ all ] # results: [ Skip ] @@ -95,3 +95,19 @@ # fail in this case. Unfortunately there is no way to skip tests based on # the impl being >= a given version. crbug.com/1233480 [ all ] org.chromium.weblayer.test.NavigationTest#testInitialRendererInitiatedNavigationToAboutBlankFails [ Skip ] + +# In 99 we added logic to avoid the disambiguation dialog and a test for it. +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentAfterRedirectInBackgroundTabLaunchedWhenBackgroundLaunchesAllowed [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentAfterRedirectLaunched [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentInNewTabLaunchedOnLinkClick [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentInSameTabLaunchedOnLinkClick [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentNavigationParamSetOnIntentLaunchViaLinkClick [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentNavigationParamSetOnNavigationsToIntents [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentViaOnLoadLaunched [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentWithFallbackUrlAfterRedirectLaunched [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentWithNoRedirectInBackgroundTabLaunchedWhenBackgroundLaunchesAllowed [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentWithNoRedirectInBrowserStartupLaunchedWhenBackgroundLaunchesAllowed [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentWithNoRedirectLaunched [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testUserClicksLinkToPageWithExternalIntentLaunchedViaOnLoad [ Skip ] +crbug.com/1278017 [ client_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testAvoidDisambiguationDialog [ Skip ] +crbug.com/1278017 [ impl_lte_98 ] org.chromium.weblayer.test.ExternalNavigationTest#testAvoidDisambiguationDialog [ Skip ]