diff --git a/DEPS b/DEPS index 67970e9..3d173db 100644 --- a/DEPS +++ b/DEPS
@@ -231,7 +231,7 @@ # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:df39938896c4603fb2a214a2430450a85d9cca81', + 'luci_go': 'git_revision:5d9b6ecf87cdfb928e1112d2838d26bc7ede2b48', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -280,11 +280,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'c1373396b85792ee6cf7fcc16870bd3d7e9d0c93', + 'skia_revision': 'c37b3868863bc9881ce14b33125900749a673f52', # 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': '15d9040b367b37cc643215aa9913d989c5bf115e', + 'v8_revision': 'ff099f3e0d371eccaa535e6438bd9ed7ac2eb549', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -292,11 +292,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'e78a7dd5ec0b9acad25c9b7c4656cee935c8149c', + 'swiftshader_revision': '5cb6a639d49457b258f9777b9bc180d67e5b7e4e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '057b3d331dbf564f59bdbf24b2c9407f00d3fd47', + 'pdfium_revision': 'ce72527c01dc086acf407b82d0a69874ea426711', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -395,7 +395,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': '79e90e5f3b35be7b654fc717ff8ef3a02ab004b4', + 'dawn_revision': '9be6b99a4b9c13c8d48691e3bf04ea09b736c03d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -760,12 +760,12 @@ }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'a800009e44fe22dd527c36462cef25962ef3b6a6', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '2163a71a16632abd953b055cf391d66eb410a16d', 'condition': 'checkout_ios', }, 'src/ios/third_party/edo/src': { - 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '3e49e0e9664d7af8268eee9db7ab0a05671643e2', + 'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'f35669ab28e912551f12891673b11c7d1b0c1688', 'condition': 'checkout_ios', }, @@ -1145,7 +1145,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9a3c4bc67c6ee06993e295d957681452f829577d', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '39e4055004da058d34682e11ffb1f0a035289149', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1542,7 +1542,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '3d3f58658fdecc553543e801076e44febf5490b5', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '2b0a2135f09e99334d902dee6052569bfc26d212', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1709,10 +1709,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'e58ed2132aa47ac110a4cce1763abfa34f4fa34e', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'f8000b0ea82de00b3cc7d337e7521d1e94fed587', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'ca9a3bc65360a04399c2403d140b6680d74e021d', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '7edbf237004164bb1ba38638fc2f055a57953b02', + Var('webrtc_git') + '/src.git' + '@' + 'e3342ef27f747463c741ff109fee70b7ddc0eb0e', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1742,7 +1742,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'OvVEMsHSDcQwu44X8cgC96F-XVZFYKyLTAnIhU4YgRMC', + 'version': 'LOLBT9fx6Zp6tPJMXhgMoDZcTPCk-VSNk5gHIOchhIMC', }, ], 'dep_type': 'cipd', @@ -1752,7 +1752,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'zaA5e-0b_opOOKLYTWgORdrhX4IWX6NGw1cn6f6gBCsC', + 'version': '0JoR2aK22wezglgiEZQathxIbpRDITqBt6h9rwFMU7QC', }, ], 'dep_type': 'cipd', @@ -1763,7 +1763,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'R3UJ_6wcxlpRWvd-qYlFbqJMdonTU0oOwXbwEeGdXKkC', + 'version': 'u6SVSv19aduMZOLqGYkCHbjhnJWwm0WimUYQs4q9mDgC', }, ], 'dep_type': 'cipd', @@ -1774,7 +1774,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': '0Q-N1gY2crCQYdezvnNMBarAkwPnVs8ftHgHXBdunhMC', + 'version': '1aHoSQfZbmKtsxSSw_7SIfNuMapnLQb_uHdo237FM88C', }, ], 'dep_type': 'cipd', @@ -1785,7 +1785,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b502c2cb1ea4a926ac1e9cf33a78fb4e6fe0f08c', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7ff2a183cb21394d43e4526a1b11c50423807a13', 'condition': 'checkout_src_internal', }, @@ -1826,7 +1826,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'KI3SsVX28-gopSf-SYwZpYxFhkIy_dakHV0gG2o30REC', + 'version': 'a6KSLbsYoaubZsrOcT_IRNMy6dOcrre1XrEzxWKMA1YC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
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 3d71f00c..a63bcdd 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
@@ -18,8 +18,6 @@ import android.webkit.WebStorage; import android.webkit.WebViewDatabase; -import androidx.annotation.IntDef; - import org.chromium.android_webview.AwBrowserContext; import org.chromium.android_webview.AwBrowserProcess; import org.chromium.android_webview.AwContents; @@ -101,17 +99,6 @@ private final WebViewChromiumFactoryProvider mFactory; - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - @IntDef({WebViewInitType.SYNC, WebViewInitType.ASYNC, WebViewInitType.BOTH}) - private @interface WebViewInitType { - int SYNC = 0; - int ASYNC = 1; - int BOTH = 2; - int COUNT = 3; - } - - private boolean mIsInitializedFromUIThread; private boolean mIsPostedFromBackgroundThread; WebViewChromiumAwInit(WebViewChromiumFactoryProvider factory) { @@ -160,17 +147,6 @@ return; } - @WebViewInitType - int type; - if (mIsPostedFromBackgroundThread) { - type = mIsInitializedFromUIThread ? WebViewInitType.BOTH : WebViewInitType.ASYNC; - } else { - type = WebViewInitType.SYNC; - } - - RecordHistogram.recordEnumeratedHistogram( - "Android.WebView.Startup.InitType", type, WebViewInitType.COUNT); - final Context context = ContextUtils.getApplicationContext(); JNIUtils.setClassLoader(WebViewChromiumAwInit.class.getClassLoader()); @@ -343,7 +319,6 @@ // If we are currently running on the UI thread then we must do init now. If there was // already a task posted to the UI thread from another thread to do it, it will just // no-op when it runs. - mIsInitializedFromUIThread = true; startChromiumLocked(); return; }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java index 06db715..e68dec17 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewContentsClientAdapter.java
@@ -1079,7 +1079,7 @@ result |= Resource.AUDIO_CAPTURE; } else if (resource.equals(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID)) { result |= Resource.PROTECTED_MEDIA_ID; - } else if (resource.equals(AwPermissionRequest.RESOURCE_MIDI_SYSEX)) { + } else if (resource.equals(PermissionRequest.RESOURCE_MIDI_SYSEX)) { result |= Resource.MIDI_SYSEX; } } @@ -1098,7 +1098,7 @@ result.add(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID); } if ((resources & Resource.MIDI_SYSEX) != 0) { - result.add(AwPermissionRequest.RESOURCE_MIDI_SYSEX); + result.add(PermissionRequest.RESOURCE_MIDI_SYSEX); } String[] resource_array = new String[result.size()]; return result.toArray(resource_array);
diff --git a/android_webview/java/src/org/chromium/android_webview/permission/AwPermissionRequest.java b/android_webview/java/src/org/chromium/android_webview/permission/AwPermissionRequest.java index 1903b2ab..074c0da 100644 --- a/android_webview/java/src/org/chromium/android_webview/permission/AwPermissionRequest.java +++ b/android_webview/java/src/org/chromium/android_webview/permission/AwPermissionRequest.java
@@ -28,13 +28,6 @@ // Responsible for deleting native peer. private CleanupReference mCleanupReference; - // This should be same as corresponding definition in PermissionRequest. - // We duplicate definition because it is used in Android L and afterwards, but is only - // defined in M. - // TODO(michaelbai) : Replace "android.webkit.resource.MIDI_SYSEX" with - // PermissionRequest.RESOURCE_MIDI_SYSEX once Android M SDK is used. - public static final String RESOURCE_MIDI_SYSEX = "android.webkit.resource.MIDI_SYSEX"; - private static final class DestroyRunnable implements Runnable { private final long mNativeAwPermissionRequest;
diff --git a/ash/app_list/BUILD.gn b/ash/app_list/BUILD.gn index ad97eab0..969530c 100644 --- a/ash/app_list/BUILD.gn +++ b/ash/app_list/BUILD.gn
@@ -125,8 +125,6 @@ "views/recent_apps_view.h", "views/remove_query_confirmation_dialog.cc", "views/remove_query_confirmation_dialog.h", - "views/remove_task_feedback_dialog.cc", - "views/remove_task_feedback_dialog.h", "views/result_selection_controller.cc", "views/result_selection_controller.h", "views/scrollable_apps_grid_view.cc",
diff --git a/ash/app_list/views/app_list_bubble_apps_page.cc b/ash/app_list/views/app_list_bubble_apps_page.cc index d45409a6..abab120 100644 --- a/ash/app_list/views/app_list_bubble_apps_page.cc +++ b/ash/app_list/views/app_list_bubble_apps_page.cc
@@ -21,7 +21,6 @@ #include "ash/app_list/views/recent_apps_view.h" #include "ash/app_list/views/scrollable_apps_grid_view.h" #include "ash/app_list/views/search_box_view.h" -#include "ash/app_list/views/search_result_page_dialog_controller.h" #include "ash/bubble/bubble_utils.h" #include "ash/constants/ash_features.h" #include "ash/controls/rounded_scroll_bar.h" @@ -117,13 +116,11 @@ ApplicationDragAndDropHost* drag_and_drop_host, AppListConfig* app_list_config, AppListA11yAnnouncer* a11y_announcer, - SearchResultPageDialogController* dialog_controller, AppListFolderController* folder_controller, SearchBoxView* search_box) : view_delegate_(view_delegate), search_box_(search_box), - app_list_nudge_controller_(std::make_unique<AppListNudgeController>()), - dialog_controller_(dialog_controller) { + app_list_nudge_controller_(std::make_unique<AppListNudgeController>()) { DCHECK(view_delegate); DCHECK(drag_and_drop_host); DCHECK(a11y_announcer); @@ -171,10 +168,9 @@ InitContinueLabelContainer(scroll_contents.get()); // Continue section row. - continue_section_ = - scroll_contents->AddChildView(std::make_unique<ContinueSectionView>( - view_delegate, dialog_controller_, kContinueColumnCount, - /*tablet_mode=*/false)); + continue_section_ = scroll_contents->AddChildView( + std::make_unique<ContinueSectionView>(view_delegate, kContinueColumnCount, + /*tablet_mode=*/false)); continue_section_->SetBorder( views::CreateEmptyBorder(kContinueSectionInsets)); continue_section_->SetNudgeController(app_list_nudge_controller_.get());
diff --git a/ash/app_list/views/app_list_bubble_apps_page.h b/ash/app_list/views/app_list_bubble_apps_page.h index 5798457..aaf2e85 100644 --- a/ash/app_list/views/app_list_bubble_apps_page.h +++ b/ash/app_list/views/app_list_bubble_apps_page.h
@@ -44,7 +44,6 @@ class IconButton; class RecentAppsView; class RoundedScrollBar; -class SearchResultPageDialogController; class SearchBoxView; class ScrollableAppsGridView; class ScrollViewGradientHelper; @@ -68,7 +67,6 @@ ApplicationDragAndDropHost* drag_and_drop_host, AppListConfig* app_list_config, AppListA11yAnnouncer* a11y_announcer, - SearchResultPageDialogController* dialog_controller, AppListFolderController* folder_controller, SearchBoxView* search_box); AppListBubbleAppsPage(const AppListBubbleAppsPage&) = delete; @@ -242,9 +240,6 @@ std::unique_ptr<AppListNudgeController> app_list_nudge_controller_; - // Controller for showing a modal dialog in the continue section. - SearchResultPageDialogController* const dialog_controller_; - // Adds fade in/out gradients to `scroll_view_`. std::unique_ptr<ScrollViewGradientHelper> gradient_helper_;
diff --git a/ash/app_list/views/app_list_bubble_view.cc b/ash/app_list/views/app_list_bubble_view.cc index c9f5e59..6a96008 100644 --- a/ash/app_list/views/app_list_bubble_view.cc +++ b/ash/app_list/views/app_list_bubble_view.cc
@@ -275,8 +275,8 @@ apps_page_ = pages_container->AddChildView(std::make_unique<AppListBubbleAppsPage>( view_delegate_, drag_and_drop_host, GetAppListConfig(), - a11y_announcer_.get(), search_page_dialog_controller_.get(), - /*folder_controller=*/this, /*search_box=*/search_box_view_)); + a11y_announcer_.get(), /*folder_controller=*/this, + /*search_box=*/search_box_view_)); search_page_ = pages_container->AddChildView(std::make_unique<AppListBubbleSearchPage>(
diff --git a/ash/app_list/views/apps_container_view.cc b/ash/app_list/views/apps_container_view.cc index b5e58557..10eb785 100644 --- a/ash/app_list/views/apps_container_view.cc +++ b/ash/app_list/views/apps_container_view.cc
@@ -164,8 +164,7 @@ class AppsContainerView::ContinueContainer : public views::View { public: ContinueContainer(AppsContainerView* apps_container, - AppListViewDelegate* view_delegate, - SearchResultPageDialogController* dialog_controller) + AppListViewDelegate* view_delegate) : view_delegate_(view_delegate), separator_(apps_container->separator()) { DCHECK(view_delegate_); DCHECK(separator_); @@ -175,7 +174,7 @@ ->SetOrientation(views::LayoutOrientation::kVertical); continue_section_ = AddChildView(std::make_unique<ContinueSectionView>( - view_delegate, dialog_controller, kContinueColumnCount, + view_delegate, kContinueColumnCount, /*tablet_mode=*/true)); continue_section_->SetPaintToLayer(); continue_section_->layer()->SetFillsBoundsOpaquely(false); @@ -272,9 +271,8 @@ dialog_controller_ = std::make_unique<SearchResultPageDialogController>( contents_view_->GetSearchBoxView()); - continue_container_ = - scrollable_container_->AddChildView(std::make_unique<ContinueContainer>( - this, view_delegate, dialog_controller_.get())); + continue_container_ = scrollable_container_->AddChildView( + std::make_unique<ContinueContainer>(this, view_delegate)); continue_container_->continue_section()->SetNudgeController( app_list_nudge_controller_.get()); // Update the suggestion tasks after the app list nudge controller is set in
diff --git a/ash/app_list/views/apps_grid_context_menu.cc b/ash/app_list/views/apps_grid_context_menu.cc index b7e0b5c..10df2c2 100644 --- a/ash/app_list/views/apps_grid_context_menu.cc +++ b/ash/app_list/views/apps_grid_context_menu.cc
@@ -79,18 +79,28 @@ context_menu_model_->AddTitle(l10n_util::GetStringUTF16( IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_TITLE)); + // Add an empty icon to the title for it to be aligned with the other menu + // item elements. See crbug/1117650. + context_menu_model_->SetIcon( + 0, ui::ImageModel::FromImageGenerator( + base::BindRepeating([](const ui::ColorProvider* color_provider) { + return gfx::ImageSkia(); + }), + gfx::Size(kAppContextMenuIconSize, kAppContextMenuIconSize))); context_menu_model_->AddItemWithIcon( REORDER_BY_NAME_ALPHABETICAL, l10n_util::GetStringUTF16( IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_BY_NAME), ui::ImageModel::FromVectorIcon(kSortAlphabeticalIcon, - ui::kColorAshSystemUIMenuIcon)); + ui::kColorAshSystemUIMenuIcon, + kAppContextMenuIconSize)); context_menu_model_->AddItemWithIcon( REORDER_BY_COLOR, l10n_util::GetStringUTF16( IDS_ASH_LAUNCHER_APPS_GRID_CONTEXT_MENU_REORDER_BY_COLOR), ui::ImageModel::FromVectorIcon(kSortColorIcon, - ui::kColorAshSystemUIMenuIcon)); + ui::kColorAshSystemUIMenuIcon, + kAppContextMenuIconSize)); } void AppsGridContextMenu::OnMenuClosed() {
diff --git a/ash/app_list/views/continue_section_view.cc b/ash/app_list/views/continue_section_view.cc index 5de317c..628ffa31 100644 --- a/ash/app_list/views/continue_section_view.cc +++ b/ash/app_list/views/continue_section_view.cc
@@ -19,7 +19,6 @@ #include "ash/app_list/views/app_list_toast_view.h" #include "ash/app_list/views/app_list_view_util.h" #include "ash/app_list/views/continue_task_view.h" -#include "ash/app_list/views/search_result_page_dialog_controller.h" #include "ash/bubble/bubble_utils.h" #include "ash/constants/ash_features.h" #include "ash/public/cpp/app_list/app_list_config.h" @@ -85,14 +84,10 @@ } // namespace -ContinueSectionView::ContinueSectionView( - AppListViewDelegate* view_delegate, - SearchResultPageDialogController* dialog_controller, - int columns, - bool tablet_mode) - : view_delegate_(view_delegate), - dialog_controller_(dialog_controller), - tablet_mode_(tablet_mode) { +ContinueSectionView::ContinueSectionView(AppListViewDelegate* view_delegate, + int columns, + bool tablet_mode) + : view_delegate_(view_delegate), tablet_mode_(tablet_mode) { DCHECK(view_delegate_); AppListModelProvider::Get()->AddObserver(this); @@ -124,7 +119,7 @@ base::BindRepeating( &ContinueSectionView::OnSearchResultContainerResultsChanged, base::Unretained(this)), - dialog_controller_, tablet_mode)); + tablet_mode)); suggestions_container_->SetVisible(false); }
diff --git a/ash/app_list/views/continue_section_view.h b/ash/app_list/views/continue_section_view.h index 95c1ddb6..2cf0bd1 100644 --- a/ash/app_list/views/continue_section_view.h +++ b/ash/app_list/views/continue_section_view.h
@@ -24,7 +24,6 @@ class AppListToastView; class ContinueTaskContainerView; class ContinueTaskView; -class SearchResultPageDialogController; // The "Continue" section of the bubble launcher. This view wraps around // suggestions with tasks to continue. @@ -36,7 +35,6 @@ METADATA_HEADER(ContinueSectionView); ContinueSectionView(AppListViewDelegate* view_delegate, - SearchResultPageDialogController* dialog_controller, int columns, bool tablet_mode); ContinueSectionView(const ContinueSectionView&) = delete; @@ -143,9 +141,6 @@ AppListViewDelegate* const view_delegate_; - // Controller for showing a modal dialog in the continue section. - SearchResultPageDialogController* const dialog_controller_; - bool tablet_mode_ = false; // Timer for marking the privacy notice as shown.
diff --git a/ash/app_list/views/continue_section_view_unittest.cc b/ash/app_list/views/continue_section_view_unittest.cc index 5bc19f3..b7479c7 100644 --- a/ash/app_list/views/continue_section_view_unittest.cc +++ b/ash/app_list/views/continue_section_view_unittest.cc
@@ -23,11 +23,8 @@ #include "ash/app_list/views/apps_grid_view_test_api.h" #include "ash/app_list/views/continue_task_view.h" #include "ash/app_list/views/recent_apps_view.h" -#include "ash/app_list/views/remove_task_feedback_dialog.h" #include "ash/app_list/views/scrollable_apps_grid_view.h" #include "ash/app_list/views/search_box_view.h" -#include "ash/app_list/views/search_result_page_anchored_dialog.h" -#include "ash/app_list/views/search_result_page_dialog_controller.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/app_list/app_list_features.h" @@ -99,9 +96,7 @@ : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME), tablet_mode_(tablet_mode) { scoped_feature_list_.InitWithFeatures( - {features::kLauncherAppSort, features::kProductivityLauncher, - app_list_features::kFeedbackOnContinueSectionRemove}, - {}); + {features::kLauncherAppSort, features::kProductivityLauncher}, {}); } ~ContinueSectionViewTestBase() override = default; @@ -298,27 +293,10 @@ GetContinueSectionView()->GetWidget()->LayoutRootViewIfNecessary(); SimulateRightClickOrLongPressOn(continue_task_view); - EXPECT_TRUE(continue_task_view->IsMenuShowing()); + EXPECT_TRUE(continue_task_view->IsMenuShowing()) << index; continue_task_view->ExecuteCommand(ContinueTaskCommandId::kRemoveResult, ui::EF_NONE); - } - - SearchResultPageAnchoredDialog* GetSearchViewAnchoredDialog() { - if (Shell::Get()->tablet_mode_controller()->InTabletMode()) - return GetAppListTestHelper()->GetFullscreenSearchPageDialog(); - return GetAppListTestHelper()->GetBubbleSearchPageDialog(); - } - - bool IsSearchViewAnchoredDialogOpen() { - SearchResultPageAnchoredDialog* dialog = GetSearchViewAnchoredDialog(); - return (dialog && !dialog->widget()->IsClosed()); - } - - RemoveTaskFeedbackDialog* GetFeedbackDialog() { - SearchResultPageAnchoredDialog* dialog = GetSearchViewAnchoredDialog(); - return dialog ? static_cast<RemoveTaskFeedbackDialog*>( - dialog->widget()->widget_delegate()) - : nullptr; + EXPECT_FALSE(continue_task_view->IsMenuShowing()); } test::AppsGridViewTestApi* test_api() { return test_api_.get(); } @@ -789,257 +767,6 @@ EXPECT_EQ("id1", client->last_opened_search_result()); } -TEST_P(ContinueSectionViewTest, SelectCancelOptionCloseDialogNoRemove) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); - RemoveSearchResultWithContextMenuAt(0); - - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - ASSERT_TRUE(GetFeedbackDialog()); - GestureTapOn(GetFeedbackDialog()->cancel_button_for_test()); - - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - - TestAppListClient* client = GetAppListTestHelper()->app_list_client(); - std::vector<TestAppListClient::SearchResultActionId> invoked_actions = - client->GetAndClearInvokedResultActions(); - EXPECT_TRUE(invoked_actions.empty()); -} - -TEST_P(ContinueSectionViewTest, SelectRemoveOptionCloseDialogAndRemove) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); - RemoveSearchResultWithContextMenuAt(0); - - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - ASSERT_TRUE(GetFeedbackDialog()); - GestureTapOn(GetFeedbackDialog()->remove_button_for_test()); - - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - - TestAppListClient* client = GetAppListTestHelper()->app_list_client(); - std::vector<TestAppListClient::SearchResultActionId> expected_actions = { - {"id1", SearchResultActionType::kRemove}}; - std::vector<TestAppListClient::SearchResultActionId> invoked_actions = - client->GetAndClearInvokedResultActions(); - EXPECT_EQ(expected_actions, invoked_actions); -} - -TEST_P(ContinueSectionViewTest, RemoveResultShowsFeedbackDialogOnce) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id4", AppListSearchResultType::kZeroStateFile); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2"); - RemoveSearchResultWithContextMenuAt(1); - - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog(); - ASSERT_TRUE(dialog); - GestureTapOn(dialog->all_suggestions_option_for_test()); - GestureTapOn(dialog->remove_button_for_test()); - - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - - VerifyResultViewsUpdated(); - - // Click on another result and remove it. - EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); - RemoveSearchResultWithContextMenuAt(0); - - // Feedback Dialog should not show the second time. - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - - // Both items were removed. - TestAppListClient* client = GetAppListTestHelper()->app_list_client(); - std::vector<TestAppListClient::SearchResultActionId> expected_actions = { - {"id2", SearchResultActionType::kRemove}, - {"id1", SearchResultActionType::kRemove}}; - std::vector<TestAppListClient::SearchResultActionId> invoked_actions = - client->GetAndClearInvokedResultActions(); - EXPECT_EQ(expected_actions, invoked_actions); -} - -TEST_P(ContinueSectionViewTest, RemoveResultShowsFeedbackUntilFeedbackSent) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id4", AppListSearchResultType::kZeroStateFile); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2"); - RemoveSearchResultWithContextMenuAt(1); - - // Feedback dialog should show. Confirm without sending feedback. - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog(); - ASSERT_TRUE(dialog); - GestureTapOn(dialog->remove_button_for_test()); - - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - - VerifyResultViewsUpdated(); - - // Click on another result and remove it. - EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); - RemoveSearchResultWithContextMenuAt(0); - - // Feedback Dialog should show a second time. Send feedback. - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - dialog = GetFeedbackDialog(); - ASSERT_TRUE(dialog); - GestureTapOn(dialog->all_suggestions_option_for_test()); - GestureTapOn(dialog->remove_button_for_test()); - - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - - VerifyResultViewsUpdated(); - - // Click on another result and remove it. - EXPECT_EQ(GetResultViewAt(2)->result()->id(), "id3"); - RemoveSearchResultWithContextMenuAt(2); - - // Feedback Dialog should not show. - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - - // Both items were removed. - TestAppListClient* client = GetAppListTestHelper()->app_list_client(); - std::vector<TestAppListClient::SearchResultActionId> expected_actions = { - {"id2", SearchResultActionType::kRemove}, - {"id1", SearchResultActionType::kRemove}, - {"id3", SearchResultActionType::kRemove}}; - std::vector<TestAppListClient::SearchResultActionId> invoked_actions = - client->GetAndClearInvokedResultActions(); - EXPECT_EQ(expected_actions, invoked_actions); -} - -TEST_P(ContinueSectionViewTest, - RemoveResultShowsFeedbackDialogAgainIfCancelled) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id4", AppListSearchResultType::kZeroStateFile); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2"); - RemoveSearchResultWithContextMenuAt(1); - - // Cancel the Feedback Dialog, result should not have been removed. - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - ASSERT_TRUE(GetFeedbackDialog()); - GestureTapOn(GetFeedbackDialog()->cancel_button_for_test()); - - EXPECT_FALSE(IsSearchViewAnchoredDialogOpen()); - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2"); - RemoveSearchResultWithContextMenuAt(1); - - // Feedback Dialog should show again. - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - ASSERT_TRUE(GetFeedbackDialog()); - GestureTapOn(GetFeedbackDialog()->remove_button_for_test()); - - // Items was removed. - TestAppListClient* client = GetAppListTestHelper()->app_list_client(); - std::vector<TestAppListClient::SearchResultActionId> expected_actions = { - {"id2", SearchResultActionType::kRemove}}; - std::vector<TestAppListClient::SearchResultActionId> invoked_actions = - client->GetAndClearInvokedResultActions(); - EXPECT_EQ(expected_actions, invoked_actions); -} - -TEST_P(ContinueSectionViewTest, SecondaryPanelOnFeedbackDialogStartsHidden) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); - RemoveSearchResultWithContextMenuAt(0); - - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog(); - ASSERT_TRUE(dialog); - EXPECT_FALSE(dialog->secondary_options_panel_for_test()->GetVisible()); -} - -TEST_P(ContinueSectionViewTest, - SingleSuggestionOnFeedbackDialogShowsSecondaryPanel) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); - RemoveSearchResultWithContextMenuAt(0); - - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog(); - ASSERT_TRUE(dialog); - - // Click on single suggestion option. Panel should show. - GestureTapOn(dialog->single_suggestion_option_for_test()); - EXPECT_TRUE(dialog->secondary_options_panel_for_test()->GetVisible()); -} - -TEST_P(ContinueSectionViewTest, - AllSuggestionsOnFeedbackDialogHidesSecondaryPanel) { - AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); - AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); - AddSearchResult("id3", AppListSearchResultType::kZeroStateDrive); - - EnsureLauncherShown(); - - VerifyResultViewsUpdated(); - - EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); - RemoveSearchResultWithContextMenuAt(0); - - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog(); - ASSERT_TRUE(dialog); - - // Show the secondary options panel by clicking on single suggestion option. - GestureTapOn(dialog->single_suggestion_option_for_test()); - EXPECT_TRUE(dialog->secondary_options_panel_for_test()->GetVisible()); - - // Click on all suggestions option. Panel should hide. - GestureTapOn(dialog->all_suggestions_option_for_test()); - EXPECT_FALSE(dialog->secondary_options_panel_for_test()->GetVisible()); -} - TEST_P(ContinueSectionViewTest, RemoveWithContextMenuOption) { AddSearchResult("id1", AppListSearchResultType::kZeroStateFile); AddSearchResult("id2", AppListSearchResultType::kZeroStateDrive); @@ -1052,10 +779,6 @@ EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); RemoveSearchResultWithContextMenuAt(0); - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - ASSERT_TRUE(GetFeedbackDialog()); - GestureTapOn(GetFeedbackDialog()->remove_button_for_test()); - TestAppListClient* client = GetAppListTestHelper()->app_list_client(); std::vector<TestAppListClient::SearchResultActionId> expected_actions = { {"id1", SearchResultActionType::kRemove}}; @@ -1079,17 +802,9 @@ EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1"); RemoveSearchResultWithContextMenuAt(0); - ASSERT_TRUE(IsSearchViewAnchoredDialogOpen()); - RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog(); - ASSERT_TRUE(dialog); - GestureTapOn(dialog->all_suggestions_option_for_test()); - GestureTapOn(dialog->remove_button_for_test()); - EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2"); RemoveSearchResultWithContextMenuAt(1); - ASSERT_FALSE(IsSearchViewAnchoredDialogOpen()); - TestAppListClient* client = GetAppListTestHelper()->app_list_client(); std::vector<TestAppListClient::SearchResultActionId> expected_actions = { {"id1", SearchResultActionType::kRemove},
diff --git a/ash/app_list/views/continue_task_container_view.cc b/ash/app_list/views/continue_task_container_view.cc index 54030f4..61f69ae 100644 --- a/ash/app_list/views/continue_task_container_view.cc +++ b/ash/app_list/views/continue_task_container_view.cc
@@ -12,7 +12,6 @@ #include "ash/app_list/app_list_view_delegate.h" #include "ash/app_list/model/search/search_model.h" #include "ash/app_list/views/continue_task_view.h" -#include "ash/app_list/views/search_result_page_dialog_controller.h" #include "ash/public/cpp/app_list/app_list_notifier.h" #include "ash/strings/grit/ash_strings.h" #include "base/check.h" @@ -129,11 +128,9 @@ AppListViewDelegate* view_delegate, int columns, OnResultsChanged update_callback, - SearchResultPageDialogController* dialog_controller, bool tablet_mode) : view_delegate_(view_delegate), update_callback_(update_callback), - dialog_controller_(dialog_controller), tablet_mode_(tablet_mode) { DCHECK(!update_callback_.is_null()); @@ -292,8 +289,8 @@ // Create new result views. for (size_t i = 0; i < num_results_; ++i) { - auto task = std::make_unique<ContinueTaskView>( - view_delegate_, dialog_controller_, tablet_mode_); + auto task = + std::make_unique<ContinueTaskView>(view_delegate_, tablet_mode_); if (i == 0) task->SetProperty(views::kMarginsKey, gfx::Insets()); task->set_index_in_container(i);
diff --git a/ash/app_list/views/continue_task_container_view.h b/ash/app_list/views/continue_task_container_view.h index b572346..e521ab5 100644 --- a/ash/app_list/views/continue_task_container_view.h +++ b/ash/app_list/views/continue_task_container_view.h
@@ -29,7 +29,6 @@ class AppListViewDelegate; class ContinueTaskView; -class SearchResultPageDialogController; // The container for the Continue Tasks results view. The view contains a preset // number of ContinueTaskViews that get populated based on the list of results @@ -46,7 +45,6 @@ ContinueTaskContainerView(AppListViewDelegate* view_delegate, int columns, OnResultsChanged update_callback, - SearchResultPageDialogController* dialog_controller, bool tablet_mode); ContinueTaskContainerView(const ContinueTaskContainerView&) = delete; ContinueTaskContainerView& operator=(const ContinueTaskContainerView&) = @@ -169,8 +167,6 @@ OnResultsChanged update_callback_; SearchModel::SearchResults* results_ = nullptr; // Owned by SearchModel. - SearchResultPageDialogController* const dialog_controller_; - // Only one of the layouts is to be set. // `flex_layout_` aligns the views as a single row centered in the container. // Used in tablet mode.
diff --git a/ash/app_list/views/continue_task_view.cc b/ash/app_list/views/continue_task_view.cc index 096fa8bd..34786df 100644 --- a/ash/app_list/views/continue_task_view.cc +++ b/ash/app_list/views/continue_task_view.cc
@@ -12,11 +12,8 @@ #include "ash/app_list/app_list_util.h" #include "ash/app_list/app_list_view_delegate.h" #include "ash/app_list/model/search/search_result.h" -#include "ash/app_list/views/remove_task_feedback_dialog.h" -#include "ash/app_list/views/search_result_page_dialog_controller.h" #include "ash/bubble/bubble_utils.h" #include "ash/constants/ash_features.h" -#include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/style/color_provider.h" #include "ash/resources/vector_icons/vector_icons.h" @@ -26,8 +23,6 @@ #include "ash/style/style_util.h" #include "base/bind.h" #include "base/strings/string_util.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" #include "extensions/common/constants.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" @@ -76,24 +71,11 @@ return tablet_mode ? kViewCornerRadiusTablet : kViewCornerRadiusClamshell; } -PrefService* GetActiveUserPrefService() { - DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted()); - - auto* pref_service = - Shell::Get()->session_controller()->GetActivePrefService(); - DCHECK(pref_service); - return pref_service; -} - } // namespace -ContinueTaskView::ContinueTaskView( - AppListViewDelegate* view_delegate, - SearchResultPageDialogController* dialog_controller, - bool tablet_mode) - : view_delegate_(view_delegate), - dialog_controller_(dialog_controller), - is_tablet_mode_(tablet_mode) { +ContinueTaskView::ContinueTaskView(AppListViewDelegate* view_delegate, + bool tablet_mode) + : view_delegate_(view_delegate), is_tablet_mode_(tablet_mode) { SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); @@ -269,22 +251,14 @@ views::InkDropState::ACTIVATED); } -bool ContinueTaskView::ShouldShowFeedbackDialog() { - return app_list_features::IsFeedbackOnContinueSectionRemoveEnabled() && - !GetActiveUserPrefService()->GetBoolean( - prefs::kLauncherFeedbackOnContinueSectionSent); -} - void ContinueTaskView::ExecuteCommand(int command_id, int event_flags) { + CloseContextMenu(); switch (command_id) { case ContinueTaskCommandId::kOpenResult: OpenResult(event_flags); break; case ContinueTaskCommandId::kRemoveResult: - if (ShouldShowFeedbackDialog()) - ShowFeedbackDialog(); - else - RemoveResult(); + RemoveResult(); break; case ContinueTaskCommandId::kHideContinueSection: view_delegate_->SetHideContinueSection(true); @@ -352,22 +326,6 @@ return TaskResultType::kUnknown; } -void ContinueTaskView::ShowFeedbackDialog() { - dialog_controller_->Show(std::make_unique<RemoveTaskFeedbackDialog>( - base::BindOnce(&ContinueTaskView::RemoveResultAndMaybeUpdateFeedbackPref, - weak_ptr_factory_.GetWeakPtr()), - GetTaskResultType())); -} - -void ContinueTaskView::RemoveResultAndMaybeUpdateFeedbackPref( - bool has_feedback) { - if (has_feedback) { - GetActiveUserPrefService()->SetBoolean( - prefs::kLauncherFeedbackOnContinueSectionSent, true); - } - RemoveResult(); -} - void ContinueTaskView::RemoveResult() { // May be null if the result got reset, and the task view is animating out. if (!result())
diff --git a/ash/app_list/views/continue_task_view.h b/ash/app_list/views/continue_task_view.h index 8271dfe..c1bc1b4 100644 --- a/ash/app_list/views/continue_task_view.h +++ b/ash/app_list/views/continue_task_view.h
@@ -22,7 +22,6 @@ namespace ash { class AppListViewDelegate; -class SearchResultPageDialogController; enum ContinueTaskCommandId { // Context Menu option to open the selected suggestion. @@ -50,9 +49,7 @@ METADATA_HEADER(ContinueTaskView); - ContinueTaskView(AppListViewDelegate* view_delegate, - SearchResultPageDialogController* dialog_controller, - bool tablet_mode); + ContinueTaskView(AppListViewDelegate* view_delegate, bool tablet_mode); ContinueTaskView(const ContinueTaskView&) = delete; ContinueTaskView& operator=(const ContinueTaskView&) = delete; ~ContinueTaskView() override; @@ -101,9 +98,6 @@ // Removes the search result related to the view. void RemoveResult(); - // Displays a dialog requesting for continue section feedback. - void ShowFeedbackDialog(); - // Builds and returns a raw pointer to `context_menu_model_`. ui::SimpleMenuModel* BuildMenuModel(); @@ -117,14 +111,6 @@ // Record metrics at the moment when the ContinueTaskView result is removed. void LogMetricsOnResultRemoved(); - // Returns true if the feedback dialog should be shown on task removal. - bool ShouldShowFeedbackDialog(); - - // Invoked when the remove feedback dialog for the task has been closed by the - // usser confirming the removal. This function handles removing the result and - // updating the remove feedback dialog pref if |has_feedback| is true. - void RemoveResultAndMaybeUpdateFeedbackPref(bool has_feedback); - // The index of this view within a |SearchResultContainerView| that holds it. absl::optional<int> index_in_container_; @@ -134,9 +120,6 @@ views::ImageView* icon_ = nullptr; SearchResult* result_ = nullptr; // Owned by SearchModel::SearchResults. - // Controller for displaying a searchbox anchored dialog. - SearchResultPageDialogController* const dialog_controller_; - const bool is_tablet_mode_; std::unique_ptr<ui::SimpleMenuModel> context_menu_model_;
diff --git a/ash/app_list/views/remove_task_feedback_dialog.cc b/ash/app_list/views/remove_task_feedback_dialog.cc deleted file mode 100644 index 834f7e1..0000000 --- a/ash/app_list/views/remove_task_feedback_dialog.cc +++ /dev/null
@@ -1,251 +0,0 @@ -// Copyright (c) 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/app_list/views/remove_task_feedback_dialog.h" - -#include <memory> -#include <utility> - -#include "ash/public/cpp/ash_typography.h" -#include "ash/public/cpp/view_shadow.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/style/ash_color_provider.h" -#include "ash/style/pill_button.h" -#include "base/bind.h" -#include "base/metrics/histogram_functions.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/geometry/insets.h" -#include "ui/strings/grit/ui_strings.h" -#include "ui/views/background.h" -#include "ui/views/controls/button/checkbox.h" -#include "ui/views/controls/button/radio_button.h" -#include "ui/views/controls/label.h" -#include "ui/views/highlight_border.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/layout/box_layout_view.h" -#include "ui/views/style/typography.h" -#include "ui/views/view_class_properties.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { - -constexpr int kDialogWidth = 360; -constexpr gfx::Insets kDialogContentInsets = gfx::Insets::VH(20, 24); -constexpr float kDialogRoundedCornerRadius = 16.0f; -constexpr int kDialogShadowElevation = 3; -constexpr int kMarginBetweenTitleAndBody = 8; -constexpr int kMarginBetweenBodyAndOptions = 8; -constexpr int kMarginBetweenOptionsAndButtons = 20; -constexpr int kMarginBetweenBorderAndCheckboxes = 20; -constexpr int kMarginBetweenButtons = 8; - -} // namespace - -RemoveTaskFeedbackDialog::RemoveTaskFeedbackDialog( - ConfirmDialogCallback confirm_callback, - ContinueTaskView::TaskResultType task_type) - : confirm_callback_(std::move(confirm_callback)), task_type_(task_type) { - views::View* button_row; - views::Builder<RemoveTaskFeedbackDialog>(this) - .SetModalType(ui::MODAL_TYPE_WINDOW) - .SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical, kDialogContentInsets)) - .SetPaintToLayer() - .AddChildren( - views::Builder<views::Label>() - .CopyAddressTo(&title_) - .SetText(l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_TITLE)) - .SetTextContext(views::style::CONTEXT_DIALOG_TITLE) - .SetTextStyle(ash::STYLE_EMPHASIZED) - .SetHorizontalAlignment(gfx::ALIGN_LEFT) - .SetAutoColorReadabilityEnabled(false) - .SetPaintToLayer(), - views::Builder<views::Label>() - .CopyAddressTo(&feedback_text_) - .SetText(l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_FEEDBACK_TEXT)) - .SetProperty(views::kMarginsKey, - gfx::Insets::TLBR(kMarginBetweenTitleAndBody, 0, - kMarginBetweenBodyAndOptions, 0)) - .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT) - .SetHorizontalAlignment(gfx::ALIGN_LEFT) - .SetAutoColorReadabilityEnabled(false) - .SetPaintToLayer(), - views::Builder<views::View>() - .SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)) - .AddChildren( - views::Builder<views::RadioButton>() - .SetText(l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_ANY_SUGGESTIONS_OPTION)) - .CopyAddressTo(&all_suggestions_option_), - views::Builder<views::RadioButton>() - .SetText(l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_THIS_SUGGESTION_OPTION)) - .CopyAddressTo(&single_suggestion_option_), - views::Builder<views::View>() - .CopyAddressTo(&secondary_options_panel_) - .SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)) - .SetProperty( - views::kMarginsKey, - gfx::Insets::TLBR(kMarginBetweenBodyAndOptions, - kMarginBetweenBorderAndCheckboxes, - kMarginBetweenOptionsAndButtons, 0)) - .SetVisible(false) - .AddChildren( - views::Builder<views::Checkbox>() - .SetText(l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_FILE_DONE_OPTION)) - .CopyAddressTo(&done_using_option_), - views::Builder<views::Checkbox>() - .SetText(l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_DO_NOT_SHOW_FILE_OPTION)) - .CopyAddressTo(¬_show_option_))), - views::Builder<views::BoxLayoutView>() - .SetOrientation(views::BoxLayout::Orientation::kHorizontal) - .SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd) - .SetBetweenChildSpacing(kMarginBetweenButtons) - .CopyAddressTo(&button_row)) - .BuildChildren(); - - layer()->SetFillsBoundsOpaquely(false); - title_->layer()->SetFillsBoundsOpaquely(false); - feedback_text_->layer()->SetFillsBoundsOpaquely(false); - - cancel_button_ = button_row->AddChildView(std::make_unique<ash::PillButton>( - views::Button::PressedCallback(base::BindRepeating( - &RemoveTaskFeedbackDialog::Cancel, base::Unretained(this))), - l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_CANCEL_BUTTON_LABEL), - PillButton::Type::kIconless, nullptr)); - remove_button_ = button_row->AddChildView(std::make_unique<ash::PillButton>( - views::Button::PressedCallback(base::BindRepeating( - &RemoveTaskFeedbackDialog::Remove, base::Unretained(this))), - l10n_util::GetStringUTF16( - IDS_ASH_LAUNCHER_CONTINUE_SECTION_REMOVE_DIALOG_REMOVE_BUTTON_LABEL), - PillButton::Type::kIconlessProminent, nullptr)); - - single_suggestion_option_subscription_ = - single_suggestion_option_->AddCheckedChangedCallback(base::BindRepeating( - &RemoveTaskFeedbackDialog::ToggleSecondaryOptionsPanel, - base::Unretained(this))); - - view_shadow_ = std::make_unique<ViewShadow>(this, kDialogShadowElevation); - view_shadow_->SetRoundedCornerRadius(kDialogRoundedCornerRadius); - - layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma); - layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality); -} - -RemoveTaskFeedbackDialog::~RemoveTaskFeedbackDialog() = default; - -gfx::Size RemoveTaskFeedbackDialog::CalculatePreferredSize() const { - return gfx::Size(kDialogWidth, GetHeightForWidth(kDialogWidth)); -} - -void RemoveTaskFeedbackDialog::OnThemeChanged() { - views::WidgetDelegateView::OnThemeChanged(); - - title_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); - feedback_text_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); - - auto set_checkbox_text_color = [](views::Checkbox* view) { - view->SetEnabledTextColors(AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); - }; - set_checkbox_text_color(all_suggestions_option_); - set_checkbox_text_color(single_suggestion_option_); - set_checkbox_text_color(done_using_option_); - set_checkbox_text_color(not_show_option_); - - SetBackground(views::CreateRoundedRectBackground( - AshColorProvider::Get()->GetBaseLayerColor( - AshColorProvider::BaseLayerType::kTransparent80), - kDialogRoundedCornerRadius)); - SetBorder(std::make_unique<views::HighlightBorder>( - kDialogRoundedCornerRadius, - views::HighlightBorder::Type::kHighlightBorder1, - /*use_light_colors=*/false)); -} - -void RemoveTaskFeedbackDialog::Remove() { - const bool has_feedback = all_suggestions_option_->GetChecked() || - single_suggestion_option_->GetChecked(); - - if (has_feedback) - LogMetricsOnFeedbackSubmitted(); - - if (confirm_callback_) - std::move(confirm_callback_).Run(has_feedback); - - GetWidget()->CloseWithReason( - views::Widget::ClosedReason::kAcceptButtonClicked); -} - -void RemoveTaskFeedbackDialog::Cancel() { - confirm_callback_.Reset(); - GetWidget()->CloseWithReason( - views::Widget::ClosedReason::kCancelButtonClicked); -} - -void RemoveTaskFeedbackDialog::ToggleSecondaryOptionsPanel() { - secondary_options_panel_->SetVisible(single_suggestion_option_->GetChecked()); - PreferredSizeChanged(); -} - -RemoveTaskFeedbackDialog::FeedbackBuckets -RemoveTaskFeedbackDialog::GetFeedbackBucketValue() { - DCHECK_NE(task_type_, ContinueTaskView::TaskResultType::kUnknown); - - const bool is_local_file = - task_type_ == ContinueTaskView::TaskResultType::kLocalFile; - - if (all_suggestions_option_->GetChecked()) { - return is_local_file ? FeedbackBuckets::kLocalFileDontWantAny - : FeedbackBuckets::kDriveFileDontWantAny; - } - - if (single_suggestion_option_->GetChecked()) { - const bool done_using_checked = done_using_option_->GetChecked(); - const bool not_show_checked = not_show_option_->GetChecked(); - if (done_using_checked && not_show_checked) { - return is_local_file ? FeedbackBuckets::kLocalFileDontNeedDontSee - : FeedbackBuckets::kDriveFileDontNeedDontSee; - } - - if (done_using_checked) { - return is_local_file ? FeedbackBuckets::kLocalFileDontNeed - : FeedbackBuckets::kDriveFileDontNeed; - } - - if (not_show_checked) { - return is_local_file ? FeedbackBuckets::kLocalFileDontSee - : FeedbackBuckets::kDriveFileDontSee; - } - - return is_local_file ? FeedbackBuckets::kLocalFileDontWantThis - : FeedbackBuckets::kDriveFileDontWantThis; - } - NOTREACHED(); - return FeedbackBuckets::kInvalidFeedback; -} - -void RemoveTaskFeedbackDialog::LogMetricsOnFeedbackSubmitted() { - base::UmaHistogramEnumeration( - "Apps.AppList.Search.ContinueResultRemovalReason", - GetFeedbackBucketValue(), FeedbackBuckets::kMaxValue); -} - -BEGIN_METADATA(RemoveTaskFeedbackDialog, views::WidgetDelegateView) -END_METADATA - -} // namespace ash
diff --git a/ash/app_list/views/remove_task_feedback_dialog.h b/ash/app_list/views/remove_task_feedback_dialog.h deleted file mode 100644 index e478176..0000000 --- a/ash/app_list/views/remove_task_feedback_dialog.h +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright (c) 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_APP_LIST_VIEWS_REMOVE_TASK_FEEDBACK_DIALOG_H_ -#define ASH_APP_LIST_VIEWS_REMOVE_TASK_FEEDBACK_DIALOG_H_ - -#include <memory> - -#include "ash/app_list/views/continue_task_view.h" -#include "base/scoped_multi_source_observation.h" -#include "ui/views/view_observer.h" -#include "ui/views/widget/widget_delegate.h" -#include "ui/views/widget/widget_observer.h" - -namespace views { -class Button; -class Checkbox; -class RadioButton; -} // namespace views - -namespace ash { -class ContinueTaskView; -class ViewShadow; - -// RemoveTaskFeedbackDialog displays a dialog for collecting feedback on users' -// reasons to remove an element from the continue section. -class RemoveTaskFeedbackDialog : public views::WidgetDelegateView { - public: - // The different combinations of feedback that could be given on this dialog. - // These values are used for metrics and should not be changed. - enum class FeedbackBuckets { - // This bucket reflects that there was an error with the feedback provided. - kInvalidFeedback = 0, - kLocalFileDontWantAny = 1, - kLocalFileDontWantThis = 2, - kLocalFileDontNeed = 3, - kLocalFileDontSee = 4, - kLocalFileDontNeedDontSee = 5, - kDriveFileDontWantAny = 6, - kDriveFileDontWantThis = 7, - kDriveFileDontNeed = 8, - kDriveFileDontSee = 9, - kDriveFileDontNeedDontSee = 10, - kMaxValue = kDriveFileDontNeedDontSee, - }; - - using ConfirmDialogCallback = base::OnceCallback<void(bool)>; - - METADATA_HEADER(RemoveTaskFeedbackDialog); - - // Receives a callback to notify user's confirmation for removing the task - // suggestion. Invoked only after the user confirms removing the suggestion by - // clicking the Remove button. If the user cancels the dialog, callback will - // not run. - RemoveTaskFeedbackDialog(ConfirmDialogCallback callback, - ContinueTaskView::TaskResultType type); - - RemoveTaskFeedbackDialog(const RemoveTaskFeedbackDialog&) = delete; - RemoveTaskFeedbackDialog& operator=(const RemoveTaskFeedbackDialog&) = delete; - - ~RemoveTaskFeedbackDialog() override; - - // views::View: - gfx::Size CalculatePreferredSize() const override; - void OnThemeChanged() override; - - views::Button* cancel_button_for_test() { return cancel_button_; } - views::Button* remove_button_for_test() { return remove_button_; } - views::RadioButton* all_suggestions_option_for_test() { - return all_suggestions_option_; - } - views::RadioButton* single_suggestion_option_for_test() { - return single_suggestion_option_; - } - views::View* secondary_options_panel_for_test() { - return secondary_options_panel_; - } - - private: - // Callbacks for dialog buttons. - void Remove(); - void Cancel(); - - // Invoked when `primary_options_second_` changes checked state. - void ToggleSecondaryOptionsPanel(); - - // Helpers to record the UMA for the dialog resuslts. - RemoveTaskFeedbackDialog::FeedbackBuckets GetFeedbackBucketValue(); - void LogMetricsOnFeedbackSubmitted(); - - views::Label* title_ = nullptr; - views::Label* feedback_text_ = nullptr; - - // Primary feedback options. Indicates user preference regarding what - // suggestions they would not have shown. Detailed feedback may be given as - // selected. - views::RadioButton* all_suggestions_option_ = nullptr; - views::RadioButton* single_suggestion_option_ = nullptr; - - // View with detailed feedback options. Shown when user checks - // `this_suggestion_option_`. - views::View* secondary_options_panel_ = nullptr; - // Detailed feedback options. - views::Checkbox* done_using_option_ = nullptr; - views::Checkbox* not_show_option_ = nullptr; - - views::Button* cancel_button_ = nullptr; - views::Button* remove_button_ = nullptr; - std::unique_ptr<ViewShadow> view_shadow_; - - ConfirmDialogCallback confirm_callback_; - const ContinueTaskView::TaskResultType task_type_; - - base::CallbackListSubscription single_suggestion_option_subscription_; -}; - -BEGIN_VIEW_BUILDER(, RemoveTaskFeedbackDialog, views::WidgetDelegateView) -VIEW_BUILDER_OVERLOAD_METHOD_CLASS(views::WidgetDelegate, - SetModalType, - ui::ModalType) -END_VIEW_BUILDER - -} // namespace ash - -DEFINE_VIEW_BUILDER(, ash::RemoveTaskFeedbackDialog) - -#endif // ASH_APP_LIST_VIEWS_REMOVE_TASK_FEEDBACK_DIALOG_H_
diff --git a/ash/components/audio/BUILD.gn b/ash/components/audio/BUILD.gn index 5ebb795..4733eb2 100644 --- a/ash/components/audio/BUILD.gn +++ b/ash/components/audio/BUILD.gn
@@ -10,12 +10,14 @@ component("audio") { defines = [ "IS_ASH_COMPONENTS_AUDIO_IMPL" ] deps = [ + "//ash/components/audio/public/mojom", "//ash/constants", "//base", "//chromeos/dbus/audio", "//components/prefs", "//device/bluetooth", "//media/base:video_facing", + "//mojo/public/cpp/bindings", "//services/media_session/public/mojom", "//ui/events/devices", ] @@ -30,6 +32,10 @@ "audio_pref_observer.h", "cras_audio_handler.cc", "cras_audio_handler.h", + "cros_audio_config.cc", + "cros_audio_config.h", + "cros_audio_config_impl.cc", + "cros_audio_config_impl.h", "sounds.h", ] } @@ -38,12 +44,14 @@ testonly = true deps = [ ":audio", + "//ash/components/audio/public/mojom", "//ash/constants", "//base/test:test_support", "//chromeos/dbus/audio", "//components/prefs:test_support", "//device/bluetooth", "//media/base:video_facing", + "//mojo/public/cpp/bindings", "//services/media_session/public/mojom", "//testing/gmock", "//testing/gtest", @@ -51,5 +59,6 @@ sources = [ "audio_devices_pref_handler_impl_unittest.cc", "cras_audio_handler_unittest.cc", + "cros_audio_config_impl_unittest.cc", ] }
diff --git a/ash/components/audio/cros_audio_config.cc b/ash/components/audio/cros_audio_config.cc new file mode 100644 index 0000000..6377fd2 --- /dev/null +++ b/ash/components/audio/cros_audio_config.cc
@@ -0,0 +1,40 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/components/audio/cros_audio_config.h" + +#include <utility> + +namespace ash::audio_config { + +CrosAudioConfig::CrosAudioConfig() { + DCHECK(features::IsAudioSettingsPageEnabled()); +} + +CrosAudioConfig::~CrosAudioConfig() = default; + +void CrosAudioConfig::ObserveAudioSystemProperties( + mojo::PendingRemote<mojom::AudioSystemPropertiesObserver> observer) { + const mojo::RemoteSetElementId id = observers_.Add(std::move(observer)); + observers_.Get(id)->OnPropertiesUpdated(GetAudioSystemProperties()); +} + +mojom::AudioSystemPropertiesPtr CrosAudioConfig::GetAudioSystemProperties() { + auto properties = mojom::AudioSystemProperties::New(); + properties->output_volume_percent = GetOutputVolumePercent(); + return properties; +} + +void CrosAudioConfig::BindPendingReceiver( + mojo::PendingReceiver<mojom::CrosAudioConfig> pending_receiver) { + receivers_.Add(this, std::move(pending_receiver)); +} + +void CrosAudioConfig::NotifyObserversAudioSystemPropertiesChanged() { + for (const auto& observer : observers_) { + observer->OnPropertiesUpdated(GetAudioSystemProperties()); + } +} + +} // namespace ash::audio_config
diff --git a/ash/components/audio/cros_audio_config.h b/ash/components/audio/cros_audio_config.h new file mode 100644 index 0000000..50bd1f9 --- /dev/null +++ b/ash/components/audio/cros_audio_config.h
@@ -0,0 +1,50 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_COMPONENTS_AUDIO_CROS_AUDIO_CONFIG_H_ +#define ASH_COMPONENTS_AUDIO_CROS_AUDIO_CONFIG_H_ + +#include "ash/components/audio/public/mojom/cros_audio_config.mojom.h" +#include "ash/constants/ash_features.h" +#include "base/component_export.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "mojo/public/cpp/bindings/remote_set.h" + +namespace ash::audio_config { + +// Implements the CrosAudioConfig API, which will support Audio system UI on +// Chrome OS, providing and allowing configuration of system audio settings. +class COMPONENT_EXPORT(ASH_COMPONENTS_AUDIO) CrosAudioConfig + : public mojom::CrosAudioConfig { + public: + CrosAudioConfig(const CrosAudioConfig&) = delete; + CrosAudioConfig& operator=(const CrosAudioConfig&) = delete; + ~CrosAudioConfig() override; + + void BindPendingReceiver( + mojo::PendingReceiver<mojom::CrosAudioConfig> pending_receiver); + + protected: + CrosAudioConfig(); + + void NotifyObserversAudioSystemPropertiesChanged(); + + virtual uint8_t GetOutputVolumePercent() = 0; + + private: + // mojom::CrosAudioConfig: + void ObserveAudioSystemProperties( + mojo::PendingRemote<mojom::AudioSystemPropertiesObserver> observer) + override; + + mojom::AudioSystemPropertiesPtr GetAudioSystemProperties(); + + mojo::ReceiverSet<mojom::CrosAudioConfig> receivers_; + mojo::RemoteSet<mojom::AudioSystemPropertiesObserver> observers_; +}; + +} // namespace ash::audio_config + +#endif // ASH_COMPONENTS_AUDIO_CROS_AUDIO_CONFIG_H_
diff --git a/ash/components/audio/cros_audio_config_impl.cc b/ash/components/audio/cros_audio_config_impl.cc new file mode 100644 index 0000000..5658355c --- /dev/null +++ b/ash/components/audio/cros_audio_config_impl.cc
@@ -0,0 +1,30 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/components/audio/cros_audio_config_impl.h" + +#include "ash/components/audio/cras_audio_handler.h" + +namespace ash::audio_config { + +CrosAudioConfigImpl::CrosAudioConfigImpl() { + CrasAudioHandler::Get()->AddAudioObserver(this); +} + +CrosAudioConfigImpl::~CrosAudioConfigImpl() { + if (CrasAudioHandler::Get()) { + CrasAudioHandler::Get()->RemoveAudioObserver(this); + } +} + +uint8_t CrosAudioConfigImpl::GetOutputVolumePercent() { + return CrasAudioHandler::Get()->GetOutputVolumePercent(); +}; + +void CrosAudioConfigImpl::OnOutputNodeVolumeChanged(uint64_t node_id, + int volume) { + NotifyObserversAudioSystemPropertiesChanged(); +}; + +} // namespace ash::audio_config \ No newline at end of file
diff --git a/ash/components/audio/cros_audio_config_impl.h b/ash/components/audio/cros_audio_config_impl.h new file mode 100644 index 0000000..e5c795ee --- /dev/null +++ b/ash/components/audio/cros_audio_config_impl.h
@@ -0,0 +1,31 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_COMPONENTS_AUDIO_CROS_AUDIO_CONFIG_IMPL_H_ +#define ASH_COMPONENTS_AUDIO_CROS_AUDIO_CONFIG_IMPL_H_ + +#include "ash/components/audio/cras_audio_handler.h" +#include "ash/components/audio/cros_audio_config.h" +#include "base/component_export.h" + +namespace ash::audio_config { + +class COMPONENT_EXPORT(ASH_COMPONENTS_AUDIO) CrosAudioConfigImpl + : public CrosAudioConfig, + public CrasAudioHandler::AudioObserver { + public: + CrosAudioConfigImpl(); + ~CrosAudioConfigImpl() override; + + private: + // CrosAudioConfig: + uint8_t GetOutputVolumePercent() override; + + // CrasAudioHandler::AudioObserver: + void OnOutputNodeVolumeChanged(uint64_t node_id, int volume) override; +}; + +} // namespace ash::audio_config + +#endif // ASH_COMPONENTS_AUDIO_CROS_AUDIO_CONFIG_IMPL_H_ \ No newline at end of file
diff --git a/ash/components/audio/cros_audio_config_impl_unittest.cc b/ash/components/audio/cros_audio_config_impl_unittest.cc new file mode 100644 index 0000000..53cc1be --- /dev/null +++ b/ash/components/audio/cros_audio_config_impl_unittest.cc
@@ -0,0 +1,99 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/components/audio/cros_audio_config_impl.h" + +#include "ash/components/audio/audio_devices_pref_handler.h" +#include "ash/components/audio/cras_audio_handler.h" +#include "ash/components/audio/cros_audio_config.h" +#include "ash/components/audio/public/mojom/cros_audio_config.mojom.h" +#include "ash/constants/ash_features.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash::audio_config { + +const uint8_t kTestOutputVolumePercent = 80u; +const int8_t kDefaultOutputVolumePercent = + AudioDevicesPrefHandler::kDefaultOutputVolumePercent; + +class FakeAudioSystemPropertiesObserver + : public mojom::AudioSystemPropertiesObserver { + public: + FakeAudioSystemPropertiesObserver() = default; + ~FakeAudioSystemPropertiesObserver() override = default; + + mojo::PendingRemote<AudioSystemPropertiesObserver> GeneratePendingRemote() { + return receiver_.BindNewPipeAndPassRemote(); + } + + void OnPropertiesUpdated( + mojom::AudioSystemPropertiesPtr properties) override { + last_audio_system_properties_ = std::move(properties); + ++num_properties_updated_calls_; + }; + + absl::optional<mojom::AudioSystemPropertiesPtr> last_audio_system_properties_; + size_t num_properties_updated_calls_ = 0u; + mojo::Receiver<mojom::AudioSystemPropertiesObserver> receiver_{this}; +}; + +class CrosAudioConfigImplTest : public testing::Test { + public: + CrosAudioConfigImplTest() = default; + ~CrosAudioConfigImplTest() override = default; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + ash::features::kAudioSettingsPage); + CrasAudioHandler::InitializeForTesting(); + cras_audio_handler_ = CrasAudioHandler::Get(); + cros_audio_config_ = std::make_unique<CrosAudioConfigImpl>(); + } + + protected: + void SetOutputVolumePercent(uint8_t volume_percent) { + cras_audio_handler_->SetOutputVolumePercent(volume_percent); + base::RunLoop().RunUntilIdle(); + } + + std::unique_ptr<FakeAudioSystemPropertiesObserver> Observe() { + cros_audio_config_->BindPendingReceiver( + remote_.BindNewPipeAndPassReceiver()); + auto fake_observer = std::make_unique<FakeAudioSystemPropertiesObserver>(); + remote_->ObserveAudioSystemProperties( + fake_observer->GeneratePendingRemote()); + base::RunLoop().RunUntilIdle(); + return fake_observer; + } + + private: + base::test::TaskEnvironment task_environment_; + base::test::ScopedFeatureList scoped_feature_list_; + + CrasAudioHandler* cras_audio_handler_ = nullptr; // Not owned. + std::unique_ptr<CrosAudioConfigImpl> cros_audio_config_; + mojo::Remote<mojom::CrosAudioConfig> remote_; +}; + +TEST_F(CrosAudioConfigImplTest, GetOutputVolumePercent) { + std::unique_ptr<FakeAudioSystemPropertiesObserver> fake_observer = Observe(); + ASSERT_EQ(1u, fake_observer->num_properties_updated_calls_); + ASSERT_TRUE(fake_observer->last_audio_system_properties_.has_value()); + ASSERT_EQ(kDefaultOutputVolumePercent, + fake_observer->last_audio_system_properties_.value() + ->output_volume_percent); + + SetOutputVolumePercent(kTestOutputVolumePercent); + ASSERT_EQ(2u, fake_observer->num_properties_updated_calls_); + EXPECT_EQ(kTestOutputVolumePercent, + fake_observer->last_audio_system_properties_.value() + ->output_volume_percent); +} + +} // namespace ash::audio_config
diff --git a/ash/components/audio/public/mojom/BUILD.gn b/ash/components/audio/public/mojom/BUILD.gn new file mode 100644 index 0000000..a27a6b5 --- /dev/null +++ b/ash/components/audio/public/mojom/BUILD.gn
@@ -0,0 +1,12 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +assert(is_chromeos_ash, "Non-Chrome-OS builds must not depend on //ash") + +mojom("mojom") { + sources = [ "cros_audio_config.mojom" ] + public_deps = [ "//mojo/public/mojom/base" ] +}
diff --git a/ash/components/audio/public/mojom/OWNERS b/ash/components/audio/public/mojom/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/ash/components/audio/public/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/ash/components/audio/public/mojom/cros_audio_config.mojom b/ash/components/audio/public/mojom/cros_audio_config.mojom new file mode 100644 index 0000000..523d116c --- /dev/null +++ b/ash/components/audio/public/mojom/cros_audio_config.mojom
@@ -0,0 +1,31 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ash.audio_config.mojom; + +// Represents the audio state of the Audio system. +struct AudioSystemProperties { + // The volume of the active output device. + uint8 output_volume_percent; +}; + +// Observer for changes to audio system properties. +interface AudioSystemPropertiesObserver { + // Invoked whenever any property changes, including whenever a property of + // an audio device changes (e.g., from active to inactive). + OnPropertiesUpdated(AudioSystemProperties properties); +}; + +// Provides audio metadata and controls. Embedded in the browser process. +// +// Clients include: +// * WebUI such as chrome://os-settings, implemented in JS as part of renderer +// processes. +interface CrosAudioConfig { + // Invokes OnPropertiesUpdated() with initial set of properties when + // observer is first added, then again whenever properties are updated. + // To stop observing, disconnect |observer|. + ObserveAudioSystemProperties( + pending_remote<AudioSystemPropertiesObserver> observer); +};
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index d108753..415389b 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -1710,6 +1710,10 @@ return base::FeatureList::IsEnabled(kAssistMultiWord); } +bool IsAudioSettingsPageEnabled() { + return base::FeatureList::IsEnabled(kAudioSettingsPage); +} + bool IsAutoNightLightEnabled() { return base::FeatureList::IsEnabled(kAutoNightLight); }
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc index 91e12a0..28f9c52 100644 --- a/ash/public/cpp/app_list/app_list_features.cc +++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -45,8 +45,6 @@ "DynamicSearchUpdateAnimation", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kLauncherLacrosIntegration{ "LauncherLacrosIntegration", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kFeedbackOnContinueSectionRemove{ - "FeedbackOnContinueSectionRemove", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kCompactBubbleLauncher{"CompactBubbleLauncher", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kLauncherPlayStoreSearch{"LauncherPlayStoreSearch", @@ -145,11 +143,6 @@ return base::FeatureList::IsEnabled(kForceShowContinueSection); } -bool IsFeedbackOnContinueSectionRemoveEnabled() { - return ash::features::IsProductivityLauncherEnabled() && - base::FeatureList::IsEnabled(kFeedbackOnContinueSectionRemove); -} - bool IsCompactBubbleLauncherEnabled() { return base::FeatureList::IsEnabled(kCompactBubbleLauncher); }
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h index f9a753d2..cd3ffea 100644 --- a/ash/public/cpp/app_list/app_list_features.h +++ b/ash/public/cpp/app_list/app_list_features.h
@@ -78,9 +78,6 @@ // browser. If disabled, queries are sent to the ash browser. ASH_PUBLIC_EXPORT extern const base::Feature kLauncherLacrosIntegration; -// Shows a feedback dialog when removing a continue section suggestion. -ASH_PUBLIC_EXPORT extern const base::Feature kFeedbackOnContinueSectionRemove; - // Controls the bubble launcher (productivity launcher in clamshell) width. When // enabled, the bubble UI will be narrower. ASH_PUBLIC_EXPORT extern const base::Feature kCompactBubbleLauncher; @@ -107,7 +104,6 @@ ASH_PUBLIC_EXPORT bool IsDynamicSearchUpdateAnimationEnabled(); ASH_PUBLIC_EXPORT base::TimeDelta DynamicSearchUpdateAnimationDuration(); ASH_PUBLIC_EXPORT bool IsLauncherLacrosIntegrationEnabled(); -ASH_PUBLIC_EXPORT bool IsFeedbackOnContinueSectionRemoveEnabled(); ASH_PUBLIC_EXPORT bool IsCompactBubbleLauncherEnabled(); ASH_PUBLIC_EXPORT bool IsLauncherPlayStoreSearchEnabled();
diff --git a/ash/session/session_controller_impl.cc b/ash/session/session_controller_impl.cc index cd74dd374..a0e0f4a 100644 --- a/ash/session/session_controller_impl.cc +++ b/ash/session/session_controller_impl.cc
@@ -234,11 +234,6 @@ client_->ShowMultiProfileLogin(); } -void SessionControllerImpl::EmitAshInitialized() { - if (client_) - client_->EmitAshInitialized(); -} - PrefService* SessionControllerImpl::GetSigninScreenPrefService() const { return client_ ? client_->GetSigninScreenPrefService() : nullptr; }
diff --git a/ash/session/session_controller_impl.h b/ash/session/session_controller_impl.h index 17b6f6f..6685bd6 100644 --- a/ash/session/session_controller_impl.h +++ b/ash/session/session_controller_impl.h
@@ -159,9 +159,6 @@ // Show the multi-profile login UI to add another user to this session. void ShowMultiProfileLogin(); - // Forwards EmitAshInitialized to |client_|. - void EmitAshInitialized(); - // Returns the PrefService used at the signin screen, which is tied to an // incognito profile in chrome and is valid until the browser exits. PrefService* GetSigninScreenPrefService() const;
diff --git a/ash/shelf/kiosk_app_instruction_bubble.cc b/ash/shelf/kiosk_app_instruction_bubble.cc index c580ba2..be05174f 100644 --- a/ash/shelf/kiosk_app_instruction_bubble.cc +++ b/ash/shelf/kiosk_app_instruction_bubble.cc
@@ -6,6 +6,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/shell_window_ids.h" +#include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_provider.h" #include "ash/system/tray/tray_popup_utils.h" @@ -47,9 +48,8 @@ } // namespace KioskAppInstructionBubble::KioskAppInstructionBubble(views::View* anchor, - ShelfAlignment alignment, - SkColor background_color) - : ShelfBubble(anchor, alignment, background_color) { + ShelfAlignment alignment) + : views::BubbleDialogDelegateView(anchor, views::BubbleBorder::NONE) { set_close_on_deactivate(false); const int bubble_margin = views::LayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_DIALOG_CONTENT_MARGIN_TOP_CONTROL); @@ -67,15 +67,11 @@ title_->SetMultiLine(true); title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - // TODO(crbug.com/1334998): We should inherit directly from - // views::BubbleDialogDelegateView as ShelfBubble by default puts the bubble - // in the container of kShellWindowId_SettingBubbleContainer. - - set_parent_window( - anchor_widget()->GetNativeWindow()->GetRootWindow()->GetChildById( - kShellWindowId_LockScreenRelatedContainersContainer)); - - CreateBubble(); + views::DialogDelegate::CreateDialogWidget( + this, nullptr /* context */, + Shell::GetContainer( + anchor_widget()->GetNativeWindow()->GetRootWindow(), + kShellWindowId_LockScreenRelatedContainersContainer) /* parent */); auto bubble_border = std::make_unique<views::BubbleBorder>(arrow(), GetShadow()); @@ -90,7 +86,7 @@ KioskAppInstructionBubble::~KioskAppInstructionBubble() = default; void KioskAppInstructionBubble::OnThemeChanged() { - ShelfBubble::OnThemeChanged(); + BubbleDialogDelegateView::OnThemeChanged(); SkColor label_color = AshColorProvider::Get()->GetContentLayerColor( AshColorProvider::ContentLayerType::kTextColorPrimary); @@ -110,12 +106,4 @@ return gfx::Size(width, GetHeightForWidth(width)); } -bool KioskAppInstructionBubble::ShouldCloseOnPressDown() { - return false; -} - -bool KioskAppInstructionBubble::ShouldCloseOnMouseExit() { - return false; -} - } // namespace ash \ No newline at end of file
diff --git a/ash/shelf/kiosk_app_instruction_bubble.h b/ash/shelf/kiosk_app_instruction_bubble.h index 3431ebd..d375102 100644 --- a/ash/shelf/kiosk_app_instruction_bubble.h +++ b/ash/shelf/kiosk_app_instruction_bubble.h
@@ -7,8 +7,8 @@ #include "ash/ash_export.h" #include "ash/public/cpp/shelf_types.h" -#include "ash/shelf/shelf_bubble.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/views/bubble/bubble_dialog_delegate_view.h" namespace views { class Label; @@ -19,11 +19,10 @@ // A shelf bubble instructing kiosk users to interact with the kiosk app menu // button. -class ASH_EXPORT KioskAppInstructionBubble : public ShelfBubble { +class ASH_EXPORT KioskAppInstructionBubble + : public views::BubbleDialogDelegateView { public: - KioskAppInstructionBubble(views::View* anchor, - ShelfAlignment alignment, - SkColor background_color); + KioskAppInstructionBubble(views::View* anchor, ShelfAlignment alignment); KioskAppInstructionBubble(const KioskAppInstructionBubble&) = delete; KioskAppInstructionBubble& operator=(const KioskAppInstructionBubble&) = @@ -36,10 +35,6 @@ gfx::Size CalculatePreferredSize() const override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - // ShelfBubble: - bool ShouldCloseOnPressDown() override; - bool ShouldCloseOnMouseExit() override; - views::Label* title_ = nullptr; };
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index 1a3aa8b..d2fbed43 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -973,9 +973,8 @@ // Create the bubble once the login shelf view is available for anchoring. if (!kiosk_instruction_bubble_) { Shelf* shelf = Shelf::ForWindow(GetWidget()->GetNativeWindow()); - kiosk_instruction_bubble_ = new KioskAppInstructionBubble( - GetViewByID(kApps), shelf->alignment(), - shelf->shelf_widget()->GetShelfBackgroundColor()); + kiosk_instruction_bubble_ = + new KioskAppInstructionBubble(GetViewByID(kApps), shelf->alignment()); } if (kiosk_instruction_bubble_) { // Show kiosk instructions if the kiosk app button is visible and the menu
diff --git a/ash/shelf/shelf_application_menu_model.cc b/ash/shelf/shelf_application_menu_model.cc index 7634019..3e8de8d 100644 --- a/ash/shelf/shelf_application_menu_model.cc +++ b/ash/shelf/shelf_application_menu_model.cc
@@ -8,10 +8,12 @@ #include <limits> #include "ash/app_list/app_list_controller_impl.h" +#include "ash/public/cpp/app_menu_constants.h" #include "ash/shell.h" #include "base/metrics/histogram_macros.h" #include "ui/base/models/image_model.h" #include "ui/display/types/display_constants.h" +#include "ui/gfx/favicon_size.h" namespace ash { @@ -21,6 +23,15 @@ ShelfItemDelegate* delegate) : ui::SimpleMenuModel(this), delegate_(delegate) { AddTitle(title); + // Add an empty icon to the title for it to be aligned with the other menu + // item elements. See crbug/1117650. + SetIcon(0, + ui::ImageModel::FromImageGenerator( + base::BindRepeating([](const ui::ColorProvider* color_provider) { + return gfx::ImageSkia(); + }), + gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize))); + for (const auto& item : items) { enabled_commands_.emplace(item.command_id); AddItemWithIcon(item.command_id, item.title,
diff --git a/ash/shell.cc b/ash/shell.cc index 06cc01ba..733f067c 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -1443,10 +1443,6 @@ // Initialize the D-Bus bus and services for ash. dbus_bus_ = dbus_bus; ash_dbus_services_ = std::make_unique<AshDBusServices>(dbus_bus.get()); - - // By this point ash shell should have initialized its D-Bus signal - // listeners, so inform the session manager that Ash is initialized. - session_controller_->EmitAshInitialized(); } void Shell::InitializeDisplayManager() {
diff --git a/ash/system/time/calendar_month_view.cc b/ash/system/time/calendar_month_view.cc index e2dc4c5..90f4dc98 100644 --- a/ash/system/time/calendar_month_view.cc +++ b/ash/system/time/calendar_month_view.cc
@@ -423,8 +423,7 @@ if (updated_is_fetched != is_fetched) UpdateIsFetchedAndRepaint(updated_is_fetched); - if (calendar_utils::GetDayOfWeek(current_date) == - calendar_utils::kFirstDayOfWeekString) + if (calendar_utils::GetDayOfWeekInt(current_date) == 1) return; // Adds the first several days from the next month if the last day is not the
diff --git a/ash/system/time/calendar_utils.cc b/ash/system/time/calendar_utils.cc index 93fca4c..b4a6a51 100644 --- a/ash/system/time/calendar_utils.cc +++ b/ash/system/time/calendar_utils.cc
@@ -22,13 +22,6 @@ namespace ash { -namespace { -// Map of week index from string to number. -std::map<std::u16string, int> kDayOfWeekMap = {{u"1", 1}, {u"2", 2}, {u"3", 3}, - {u"4", 4}, {u"5", 5}, {u"6", 6}, - {u"7", 7}}; -} // namespace - namespace calendar_utils { bool IsToday(const base::Time selected_date) { @@ -252,10 +245,10 @@ } base::Time GetFirstDayOfWeekLocalMidnight(base::Time date) { - std::u16string day_of_week = GetDayOfWeek(date); + int day_of_week = calendar_utils::GetDayOfWeekInt(date); base::Time first_day_of_week = DateHelper::GetInstance()->GetLocalMidnight(date) - - base::Days(kDayOfWeekMap[day_of_week] - 1) + kDurationForAdjustingDST; + base::Days(day_of_week - 1) + kDurationForAdjustingDST; return DateHelper::GetInstance()->GetLocalMidnight(first_day_of_week); } @@ -270,6 +263,20 @@ return std::make_pair(start, end); } +int GetDayOfWeekInt(const base::Time date) { + int day_int; + if (base::StringToInt(GetDayOfWeek(date), &day_int)) + return day_int; + + // For a few special locales the day of week is not in a number. In these + // cases, use the default day of week from time exploded. For example: + // 'pa-PK', it returns '۰۳' for the fourth day of week. + base::Time date_local = date + GetTimeDifference(date); + base::Time::Exploded local_date_exploded = GetExplodedUTC(date_local); + // Time exploded uses 0-based day of week (0 = Sunday, etc.) + return local_date_exploded.day_of_week + 1; +} + } // namespace calendar_utils } // namespace ash
diff --git a/ash/system/time/calendar_utils.h b/ash/system/time/calendar_utils.h index 39c098f..0eaa88e 100644 --- a/ash/system/time/calendar_utils.h +++ b/ash/system/time/calendar_utils.h
@@ -26,10 +26,6 @@ // Number of days in one week. constexpr int kDateInOneWeek = 7; -// First day of the week index in string, which is returned from the -// `DateFormat`. -constexpr char16_t kFirstDayOfWeekString[] = u"1"; - // Milliseconds per minute. constexpr int kMillisecondsPerMinute = 60000; @@ -223,6 +219,11 @@ ASH_EXPORT const std::pair<base::Time, base::Time> GetFetchStartEndTimes( base::Time start_of_month_local_midnight); +// Gets the int index of this day in the week, starts from 1. This number is +// different for different languages. If cannot find this local's day in a week, +// returns its time exploded's `day_of_week`; +int GetDayOfWeekInt(const base::Time date); + } // namespace calendar_utils } // namespace ash
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc index d57787c..5da07b8e 100644 --- a/ash/system/time/calendar_view.cc +++ b/ash/system/time/calendar_view.cc
@@ -60,6 +60,8 @@ constexpr int kChevronPadding = calendar_utils::kColumnSetPadding - 1; constexpr int kEventListViewVerticalPadding = 6; constexpr int kEventListViewHorizontalOffset = 1; +constexpr int kMonthHeaderLabelTopPadding = 14; +constexpr int kMonthHeaderLabelBottomPadding = 2; // The offset for `month_label_` to make it align with `month_header`. constexpr int kMonthLabelPaddingOffset = -1; @@ -210,9 +212,9 @@ month_label_->SetText(month_name_); SetupLabel(month_label_); month_label_->SetBorder(views::CreateEmptyBorder( - gfx::Insets::TLBR(kLabelVerticalPadding, + gfx::Insets::TLBR(kMonthHeaderLabelTopPadding, kContentHorizontalPadding + kMonthLabelPaddingOffset, - kLabelVerticalPadding, 0))); + kMonthHeaderLabelBottomPadding, 0))); } MonthHeaderLabelView(const MonthHeaderLabelView&) = delete; MonthHeaderLabelView& operator=(const MonthHeaderLabelView&) = delete;
diff --git a/ash/system/time/date_helper.cc b/ash/system/time/date_helper.cc index 98ac0566..4d25ba5a 100644 --- a/ash/system/time/date_helper.cc +++ b/ash/system/time/date_helper.cc
@@ -181,16 +181,25 @@ start_date = GetLocalMidnight(start_date); std::u16string day_of_week = GetFormattedTime(&day_of_week_formatter_, start_date); - int safe_index = 0; + // For a few special locales the day of week is not in a number. In these + // cases, use the default week titles. + int day_int; + if (!base::StringToInt(day_of_week, &day_int)) { + week_titles_ = kDefaultWeekTitle; + return; + } + + int safe_index = 0; // Find a first day of a week. - while (day_of_week != calendar_utils::kFirstDayOfWeekString) { + while (day_int != 1) { start_date += base::Hours(25); day_of_week = GetFormattedTime(&day_of_week_formatter_, start_date); + DCHECK(base::StringToInt(day_of_week, &day_int)); ++safe_index; // Should already find the first day within 7 times, since there are only 7 // days in a week. - DCHECK_NE(safe_index, calendar_utils::kDateInOneWeek); + CHECK_NE(safe_index, calendar_utils::kDateInOneWeek); } int day_index = 0;
diff --git a/ash/system/time/date_helper.h b/ash/system/time/date_helper.h index cc1447a..dfd1c389 100644 --- a/ash/system/time/date_helper.h +++ b/ash/system/time/date_helper.h
@@ -20,6 +20,14 @@ namespace ash { +namespace { +// Default week title for a few special languages that cannot find the start of +// a week. So far the known languages that cannot return their day of week are: +// 'bn', 'fa', 'mr', 'pa-PK'. +std::vector<std::u16string> kDefaultWeekTitle = {u"S", u"M", u"T", u"W", + u"T", u"F", u"S"}; +} // namespace + // A singleton class used to create and cache `GregorianCalendar`, // `icu::SimpleDateFormat` and `icu::DateIntervalFormat` objects, so that they // don't have to be recreated each time when querying the time difference or
diff --git a/ash/system/time/date_helper_unittest.cc b/ash/system/time/date_helper_unittest.cc index 1a0aac3..55879c0 100644 --- a/ash/system/time/date_helper_unittest.cc +++ b/ash/system/time/date_helper_unittest.cc
@@ -9,6 +9,48 @@ namespace ash { +namespace { + +// These are from "third_party/fontconfig/include/fc-lang/fclang.h" data. +const char* kLocales[] = { + "aa", "ab", "af", "ak", "am", "an", "ar", + "as", "ast", "av", "ay", "az-az", "az-ir", "ba", + "be", "ber-dz", "ber-ma", "bg", "bh", "bho", "bi", + "bin", "bm", "bn", "bo", "br", "brx", "bs", + "bua", "byn", "ca", "ce", "ch", "chm", "chr", + "co", "crh", "cs", "csb", "cu", "cv", "cy", + "da", "de", "doi", "dv", "dz", "ee", "el", + "en", "eo", "es", "et", "eu", "fa", "fat", + "ff", "fi", "fil", "fj", "fo", "fr", "fur", + "fy", "ga", "gd", "gez", "gl", "gn", "gu", + "gv", "ha", "haw", "he", "hi", "hne", "ho", + "hr", "hsb", "ht", "hu", "hy", "hz", "ia", + "id", "ie", "ig", "ii", "ik", "io", "is", + "it", "iu", "ja", "jv", "ka", "kaa", "kab", + "ki", "kj", "kk", "kl", "km", "kn", "ko", + "kok", "kr", "ks", "ku-am", "ku-iq", "ku-ir", "ku-tr", + "kum", "kv", "kw", "kwm", "ky", "la", "lah", + "lb", "lez", "lg", "li", "ln", "lo", "lt", + "lv", "mai", "mg", "mh", "mi", "mk", "ml", + "mn-cn", "mn-mn", "mni", "mo", "mr", "ms", "mt", + "my", "na", "nb", "nds", "ne", "ng", "nl", + "nn", "no", "nqo", "nr", "nso", "nv", "ny", + "oc", "om", "or", "os", "ota", "pa", "pa-pk", + "pap-an", "pap-aw", "pl", "ps-af", "ps-pk", "pt", "qu", + "quz", "rm", "rn", "ro", "ru", "rw", "sa", + "sah", "sat", "sc", "sco", "sd", "se", "sel", + "sg", "sh", "shs", "si", "sid", "sk", "sl", + "sm", "sma", "smj", "smn", "sms", "sn", "so", + "sq", "sr", "ss", "st", "su", "sv", "sw", + "syr", "ta", "te", "tg", "th", "ti-er", "ti-et", + "tig", "tk", "tl", "tn", "to", "tr", "ts", + "tt", "tw", "ty", "tyv", "ug", "uk", "und-zmth", + "und-zsye", "ur", "uz", "ve", "vi", "vo", "vot", + "wa", "wal", "wen", "wo", "xh", "yap", "yi", + "yo", "za", "zh-cn", "zh-hk", "zh-mo", "zh-sg", "zh-tw", + "zu"}; +} // namespace + class DateHelperUnittest : public AshTestBase { public: DateHelperUnittest() = default; @@ -81,6 +123,14 @@ EXPECT_EQ(u"S", week_titles[6]); } +// Tests getting the calendar week titles in all languages. +TEST_F(DateHelperUnittest, GetWeekTitleForAllLocales) { + for (auto* local : kLocales) { + SetDefaultLocale(local); + DateHelper::GetInstance()->week_titles(); + } +} + // Formats the interval between two dates in different languages. TEST_F(DateHelperUnittest, GetFormattedInterval) { ash::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(u"GMT");
diff --git a/ash/system/time/time_view.cc b/ash/system/time/time_view.cc index 9d5df76..65016f9 100644 --- a/ash/system/time/time_view.cc +++ b/ash/system/time/time_view.cc
@@ -382,15 +382,15 @@ vertical_view_->AddChildView(std::make_unique<views::Label>()); SetupLabel(vertical_label_hours_); vertical_label_hours_->SetBorder(views::CreateEmptyBorder( - gfx::Insets::TLBR(0, 0, 0, kVerticalDateClockHorizontalPadding))); + gfx::Insets::VH(0, kVerticalDateClockHorizontalPadding))); vertical_label_minutes_ = vertical_view_->AddChildView(std::make_unique<views::Label>()); SetupLabel(vertical_label_minutes_); // Pull the minutes up closer to the hours by using a negative top border. - vertical_label_minutes_->SetBorder(views::CreateEmptyBorder( - gfx::Insets::TLBR(kVerticalClockMinutesTopOffset, 0, 0, - kVerticalDateClockHorizontalPadding))); + vertical_label_minutes_->SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR( + kVerticalClockMinutesTopOffset, kVerticalDateClockHorizontalPadding, 0, + kVerticalDateClockHorizontalPadding))); SetLayoutManager(std::make_unique<views::FillLayout>()); AddChildView(clock_layout == ClockLayout::HORIZONTAL_CLOCK
diff --git a/ash/webui/diagnostics_ui/resources/data_point.html b/ash/webui/diagnostics_ui/resources/data_point.html index 0ac1c13e..cbdaa62 100644 --- a/ash/webui/diagnostics_ui/resources/data_point.html +++ b/ash/webui/diagnostics_ui/resources/data_point.html
@@ -28,7 +28,7 @@ } :host([orientation=horizontal]) .header { - margin-right: 16px; + margin-inline-end: 16px; max-width: 96px; min-width: 90px; }
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html b/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html index 565a074..f609f3b 100644 --- a/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html +++ b/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html
@@ -49,11 +49,11 @@ } .data-point-margin-end { - margin-right: 20px; + margin-inline-end: 20px; } .data-point-margin-start { - margin-left: 20px; + margin-inline-start: 20px; } data-point[orientation=horizontal] { @@ -107,7 +107,7 @@ } .divider { - border-left: 1px solid var(--cros-separator-color); + border-inline-start: 1px solid var(--cros-separator-color); height: 32px; padding-inline: 16px; position: relative; @@ -116,7 +116,7 @@ .divider-horizontal { align-self: center; - border-left: 1px solid var(--cros-separator-color); + border-inline-start: 1px solid var(--cros-separator-color); height: var(--divider-horizontal-height, 94px); margin: 10px 20px; }
diff --git a/ash/webui/diagnostics_ui/resources/network_list.html b/ash/webui/diagnostics_ui/resources/network_list.html index ca364fc..b035d66d 100644 --- a/ash/webui/diagnostics_ui/resources/network_list.html +++ b/ash/webui/diagnostics_ui/resources/network_list.html
@@ -8,7 +8,7 @@ --iron-icon-height: 20px; --iron-icon-width: 20px; fill: var(--cros-icon-color-secondary); - margin-right: 6px; + margin-inline-end: 6px; top: 1px; }
diff --git a/ash/webui/diagnostics_ui/resources/overview_card.html b/ash/webui/diagnostics_ui/resources/overview_card.html index d3f527f..7b68ce9 100644 --- a/ash/webui/diagnostics_ui/resources/overview_card.html +++ b/ash/webui/diagnostics_ui/resources/overview_card.html
@@ -1,7 +1,7 @@ <style include="diagnostics-shared"> #marketingName { font-weight: 500; - margin-right: 4px; + margin-inline-end: 4px; } #overviewCardContainer {
diff --git a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html index e82d8fb..4c6eeec 100644 --- a/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html +++ b/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.html
@@ -57,8 +57,8 @@ font-family: var(--diagnostics-roboto-font-family); font-size: 12px; font-weight: var(--diagnostics-regular-font-weight); - padding-right: 5px; - text-align: right; + padding-inline-end: 5px; + text-align: end; } #chart-legend > .divider { @@ -71,13 +71,13 @@ div.legend-group { display: inline-block; padding: 0 20px 8px 0; - text-align: left; + text-align: start; } div.legend-group > span { display: inline-block; - padding-left: 8px; - text-align: right; + padding-inline-start: 8px; + text-align: end; width: 25px; }
diff --git a/ash/webui/diagnostics_ui/resources/routine_result_entry.html b/ash/webui/diagnostics_ui/resources/routine_result_entry.html index 4ad78286..dcf656c 100644 --- a/ash/webui/diagnostics_ui/resources/routine_result_entry.html +++ b/ash/webui/diagnostics_ui/resources/routine_result_entry.html
@@ -45,16 +45,16 @@ } .green { - border-left: 1px dashed var(--cros-color-positive); + border-inline-start: 1px dashed var(--cros-color-positive); } .red { - border-left: 1px dashed var(--cros-color-alert); + border-inline-start: 1px dashed var(--cros-color-alert); position: relative; } .yellow { - border-left: 1px dashed var(--cros-color-warning); + border-inline-start: 1px dashed var(--cros-color-warning); } #routine { @@ -67,7 +67,7 @@ } .failed-test-text-container { - margin-left: 8px; + margin-inline-start: 8px; } #status { @@ -76,7 +76,7 @@ #failed-test-text { color: var(--cros-text-color-secondary); - margin-left: 12px; + margin-inline-start: 12px; } @keyframes fadeInLine1 {
diff --git a/ash/webui/diagnostics_ui/resources/routine_section.html b/ash/webui/diagnostics_ui/resources/routine_section.html index 079d554..31f79222 100644 --- a/ash/webui/diagnostics_ui/resources/routine_section.html +++ b/ash/webui/diagnostics_ui/resources/routine_section.html
@@ -63,7 +63,7 @@ } #toggleReportButton { - margin-right: 8px; + margin-inline-end: 8px; } :host([hide-routine-status]) .container-spacing {
diff --git a/ash/webui/diagnostics_ui/resources/system_page.html b/ash/webui/diagnostics_ui/resources/system_page.html index fc4bde3..c0a24e0 100644 --- a/ash/webui/diagnostics_ui/resources/system_page.html +++ b/ash/webui/diagnostics_ui/resources/system_page.html
@@ -45,7 +45,7 @@ font-size: 16px; font-weight: var(--diagnostics-medium-font-weight); margin-bottom: 10px; - margin-left: 22px; + margin-inline-start: 22px; } .overview-container {
diff --git a/ash/webui/guest_os_installer/resources/BUILD.gn b/ash/webui/guest_os_installer/resources/BUILD.gn index 0760071..fa0372cb0 100644 --- a/ash/webui/guest_os_installer/resources/BUILD.gn +++ b/ash/webui/guest_os_installer/resources/BUILD.gn
@@ -2,116 +2,97 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//third_party/closure_compiler/compile_js.gni") -import("//tools/grit/preprocess_if_expr.gni") -import("//tools/polymer/html_to_js.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//tools/polymer/html_to_wrapper.gni") import("//tools/typescript/ts_library.gni") import("//ui/webui/resources/tools/generate_grd.gni") assert(is_chromeos_ash) +# Files holding a Polymer element definition AND have an equivalent .html file. +web_component_files = [ "app.ts" ] + +# Files that are passed as input to html_to_wrapper(). +html_files = [] +foreach(f, web_component_files) { + html_files += [ string_replace(f, ".ts", ".html") ] +} + +# Files that are generated by html_to_wrapper(). +html_wrapper_files = [] +foreach(f, html_files) { + html_wrapper_files += [ f + ".ts" ] +} + +# Files that get passed through the Typescript compiler +ts_files = [ "browser_proxy.ts" ] + web_component_files + +# Static files that can be included in the resources pack as-is +static_resource_files = [ "index.html" ] + # This is a relatively complicated build file, so let me try to # explain things... -# Polymer components are made up of a HTML template and a typescript -# class. For ease of development we keep these in separate files, but -# at run-time the HTML template needs to be generated by the -# typescript code. This build rule substitiutes the contents of -# `app.html` for the string "{__html_template__}" in `app.ts`. -html_to_js("web_components") { - js_files = [ "app.ts" ] +# Polymer components are made up of an HTML template and a Custom +# Element description in Typescript. For ease of development these are +# kept these in separate files, but at run-time the HTML template +# needs to be generated by the Typescript code. This build rule wraps +# the .html files into Typescript files containing a single function +# the returns the HTML template, which is then imported from and +# called by the corresponding .ts file. +html_to_wrapper("html_wrapper_files") { + in_files = html_files } -# We have three different files that needs to be passed to the -# typescript compiler (the mojom file is included because the mojo -# bindings generator currently doesn't handle typescript, see -# crbug.com/1002798) in the same directory, but are currently in three -# different locations. These three build rules copy them all into -# $target_gen_dir/ts_inputs. - -copy("copy_mojom") { - sources = [ "$target_gen_dir/../mojom/guest_os_installer.mojom-lite.js" ] - outputs = [ "$target_gen_dir/ts_inputs/guest_os_installer.mojom-lite.js" ] - deps = [ "../mojom:mojom_js" ] +# Copy all files to be passed to the TS compiler to the some +# folder. Since files generated by html_to_wrapper() are already in +# target_gen_dir, copy remaining files here as well. The mojom file is +# included because the mojo bindings generator currently doesn't +# handle Typescript, see crbug.com/1002798. +copy("copy_ts") { + sources = [ "$root_gen_dir/mojom-webui/ash/webui/guest_os_installer/mojom/guest_os_installer.mojom-webui.js" ] + ts_files + outputs = [ "$target_gen_dir/{{source_file_part}}" ] + deps = [ "../mojom:mojom_webui_js" ] } -copy("copy_browser_proxy") { - sources = [ "browser_proxy.ts" ] - outputs = [ "$target_gen_dir/ts_inputs/browser_proxy.ts" ] -} - -copy("copy_app") { - sources = [ "$target_gen_dir/app.ts" ] - outputs = [ "$target_gen_dir/ts_inputs/app.ts" ] - deps = [ ":web_components" ] -} - -# Run the typescript compiler, putting the outputs in -# $target_gen_dir. This has to be a different directory to the inputs +# Run the Typescript compiler, putting the outputs in +# $target_gen_dir/tsc. This has to be a different directory to the inputs # because the mojom file has the same name in both input and output, # and they'd conflict otherwise. ts_library("build_ts") { - root_dir = "$target_gen_dir/ts_inputs" - in_files = [ - "app.ts", - "browser_proxy.ts", - "guest_os_installer.mojom-lite.js", - ] + root_dir = target_gen_dir + out_dir = "$target_gen_dir/tsc" + in_files = + ts_files + html_wrapper_files + [ "guest_os_installer.mojom-webui.js" ] # Allow javascript files in input tsconfig_base = "tsconfig_base.json" - # Dependencies that are typescript libraries + # Dependencies that are Typescript libraries i.e. ts_library() targets deps = [ "//ui/webui/resources:library" ] - # Dependencies that are arbitrary build targets + # Dependencies that are not ts_library() targets extra_deps = [ - ":copy_app", - ":copy_browser_proxy", - ":copy_mojom", + ":copy_ts", + ":html_wrapper_files", ] } -# Generate "manifest" files for assets that can be processed into .grd -# files. Relative paths are significant here, so we have one for the -# generated assets and one for the static assets. Assets end up -# available in the WebUI context at the same path as is listed in -# `in_files`, e.g. chrome://guest-os-installer/app.js - -preprocess_if_expr("preprocess_generated") { - deps = [ ":build_ts" ] - in_folder = target_gen_dir - in_files = [ - "app.js", - "browser_proxy.js", - "guest_os_installer.mojom-lite.js", - ] - out_folder = "$target_gen_dir/preprocessed" - out_manifest = "$target_gen_dir/manifest_generated.json" -} - -preprocess_if_expr("preprocess_static") { - in_folder = "." - in_files = [ "index.html" ] - out_folder = "$target_gen_dir/preprocessed" - out_manifest = "$target_gen_dir/manifest_static.json" -} - -# Generate the actual grd file from the manifests. This is pulled in +# Generate the grd file. This is done using a "manifest" file +# generated by :build_ts, and from the static assets listed in +# static_resource_files. This is pulled in # by //ash/webui/resources:guest_os_installer_resources, which is in # turn pulled in by //chrome/chrome_paks.gni (to add the resources to # the final resource pack), by //ash/webui/guest_os_installer to add # them to the WebUI context, and by anyone else who needs to use these # resources. generate_grd("build_grd") { - deps = [ - ":preprocess_generated", - ":preprocess_static", - ] - manifest_files = [ - "$target_gen_dir/manifest_generated.json", - "$target_gen_dir/manifest_static.json", - ] + input_files = static_resource_files + input_files_base_dir = rebase_path(".", "//") + + deps = [ ":build_ts" ] + manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] + grd_prefix = "ash_guest_os_installer" out_grd = "$target_gen_dir/${grd_prefix}_resources.grd" }
diff --git a/ash/webui/guest_os_installer/resources/app.ts b/ash/webui/guest_os_installer/resources/app.ts index d9a84f1..e1c769b 100644 --- a/ash/webui/guest_os_installer/resources/app.ts +++ b/ash/webui/guest_os_installer/resources/app.ts
@@ -2,32 +2,40 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './app.html.js'; import {BrowserProxy} from './browser_proxy.js'; -class GuestOsInstallerApp extends PolymerElement { +class GuestOsInstallerElement extends PolymerElement { static get is() { - return 'guest-os-installer-app'; + return 'guest-os-installer'; } static get template() { - return html`{__html_template__}`; + return getTemplate(); } private listenerIds_: number[] = []; override connectedCallback() { - this.listenerIds_ = []; super.connectedCallback(); + this.listenerIds_ = []; } override disconnectedCallback() { + super.disconnectedCallback(); const callbackRouter = BrowserProxy.getInstance().callbackRouter; this.listenerIds_.forEach( (id: number) => callbackRouter.removeListener(id)); - super.disconnectedCallback(); + this.listenerIds_.length = 0; } } -customElements.define('guest-os-installer-app', GuestOsInstallerApp); +declare global { + interface HTMLElementTagNameMap { + 'guest-os-installer': GuestOsInstallerElement; + } +} + +customElements.define(GuestOsInstallerElement.is, GuestOsInstallerElement);
diff --git a/ash/webui/guest_os_installer/resources/browser_proxy.ts b/ash/webui/guest_os_installer/resources/browser_proxy.ts index cc7e761..37e7f85 100644 --- a/ash/webui/guest_os_installer/resources/browser_proxy.ts +++ b/ash/webui/guest_os_installer/resources/browser_proxy.ts
@@ -2,28 +2,25 @@ // 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 './guest_os_installer.mojom-lite.js'; +import {PageCallbackRouter, PageHandlerFactory, PageHandlerRemote} from './guest_os_installer.mojom-webui.js'; export class BrowserProxy { - // The mojo generator doesn't generate typescript bindings yet, so - // we can't name the types these should have. - callbackRouter: any; - handler: any; + callbackRouter: PageCallbackRouter; + handler: PageHandlerRemote; constructor() { - this.callbackRouter = new ash.guestOsInstaller.mojom.PageCallbackRouter(); - this.handler = new ash.guestOsInstaller.mojom.PageHandlerRemote(); + this.callbackRouter = new PageCallbackRouter(); + this.handler = new PageHandlerRemote(); - const factory = ash.guestOsInstaller.mojom.PageHandlerFactory.getRemote(); + const factory = PageHandlerFactory.getRemote(); factory.createPageHandler( this.callbackRouter.$.bindNewPipeAndPassRemote(), this.handler.$.bindNewPipeAndPassReceiver()); } - static instance: BrowserProxy|null = null; static getInstance() { - return BrowserProxy.instance || - (BrowserProxy.instance = new BrowserProxy()); + return instance || (instance = new BrowserProxy()); } } + +let instance: BrowserProxy|null = null;
diff --git a/ash/webui/guest_os_installer/resources/index.html b/ash/webui/guest_os_installer/resources/index.html index 900a076..688376f 100644 --- a/ash/webui/guest_os_installer/resources/index.html +++ b/ash/webui/guest_os_installer/resources/index.html
@@ -13,6 +13,6 @@ <script type="module" src="/app.js"></script> </head> <body> - <guest-os-installer-app></guest-os-installer-app> + <guest-os-installer></guest-os-installer> </body> </html>
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc index aaf93d2..3b56ee9 100644 --- a/ash/webui/os_feedback_ui/os_feedback_ui.cc +++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -67,6 +67,8 @@ {"diagnosticsAppLabel", IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_LABEL}, {"userConsentLabel", IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL}, + {"includeSystemInfoAndMetricsCheckboxLabel", + IDS_FEEDBACK_TOOL_INCLUDE_SYSTEM_INFO_AND_METRICS_CHECKBOX_LABEL}, }; source->AddLocalizedStrings(kLocalizedStrings);
diff --git a/ash/webui/os_feedback_ui/resources/confirmation_page.html b/ash/webui/os_feedback_ui/resources/confirmation_page.html index b2930dfa..644a388f 100644 --- a/ash/webui/os_feedback_ui/resources/confirmation_page.html +++ b/ash/webui/os_feedback_ui/resources/confirmation_page.html
@@ -10,6 +10,14 @@ display: flex; flex-direction: column; } + + #message { + color: var(--cros-text-color-secondary); + font-family: 'Roboto'; + font-size: 13px; + font-weight: 400; + line-height: 18px; + } </style> <!--TODO(xiangdongkong): use localized strings --> <div id="container">
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.html b/ash/webui/os_feedback_ui/resources/share_data_page.html index 55a9210..8786239f 100644 --- a/ash/webui/os_feedback_ui/resources/share_data_page.html +++ b/ash/webui/os_feedback_ui/resources/share_data_page.html
@@ -123,9 +123,9 @@ </div> <!-- System Information --> <div id="sysInfoContainer" class="checkbox-field-container"> - <input id="sysInfoCheckbox" type="checkbox" aria-labelledby="sysInfoLabel" + <input id="sysInfoCheckbox" type="checkbox" aria-labelledby="sysInfoCheckboxLabel" checked> - <label id="sysInfoLabel">Send system and app info and metrics</label> + <label id="sysInfoCheckboxLabel" inner-h-t-m-l="[[sysInfoCheckboxLabel_]]"></label> </div> </div> <!-- Privacy note -->
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.js b/ash/webui/os_feedback_ui/resources/share_data_page.js index 533fe896..1d3cd5a 100644 --- a/ash/webui/os_feedback_ui/resources/share_data_page.js +++ b/ash/webui/os_feedback_ui/resources/share_data_page.js
@@ -60,12 +60,19 @@ * @type {string} * @protected */ + this.sysInfoCheckboxLabel_; + + /** + * @type {string} + * @protected + */ this.privacyNote_; } ready() { super.ready(); this.setPrivacyNote_(); + this.setSysInfoCheckboxLabelAndAttributes_(); // Set up event listener for email change to retarget |this| to be the // ShareDataPageElement's context. @@ -215,6 +222,17 @@ this.openLinkInNewWindow_( '#termsOfServiceUrl', FEEDBACK_TERMS_OF_SERVICE_URL); } + + /** @private */ + setSysInfoCheckboxLabelAndAttributes_() { + this.sysInfoCheckboxLabel_ = this.i18nAdvanced( + 'includeSystemInfoAndMetricsCheckboxLabel', {attrs: ['id']}); + + const sysInfoLink = this.shadowRoot.querySelector('#sysInfoLink'); + sysInfoLink.setAttribute('href', '#'); + const histogramsLink = this.shadowRoot.querySelector('#histogramsLink'); + histogramsLink.setAttribute('href', '#'); + } } customElements.define(ShareDataPageElement.is, ShareDataPageElement);
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html index a065b869..c27e2b83 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_router_element.html +++ b/ash/webui/personalization_app/resources/trusted/personalization_router_element.html
@@ -1,19 +1,21 @@ -<style> +<style include="common-style"> #container { display: flex; flex-flow: column nowrap; - height: 100%; position: relative; width: 100%; } #breadcrumbArea { + background-color: var(--cros-bg-color); display: grid; grid-template-areas: '. . breadcrumb . .'; grid-template-columns: 1fr 16px minmax(568px, 920px) 16px 1fr; grid-template-rows: 56px; - position: relative; + position: sticky; + top: 0; width: 100%; + z-index: 1; } personalization-breadcrumb { grid-area: breadcrumb; @@ -34,7 +36,6 @@ } wallpaper-subpage { flex-grow: 1; - overflow: hidden; } </style> <div id="container">
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html index 16831ce5..3064e49a 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.html
@@ -1,4 +1,4 @@ -<style> +<style include="common-style"> #wallpaperContainer { display: grid; grid-template-areas: @@ -7,7 +7,7 @@ '. leftspacer imagegrid rightspacer .' '. leftspacer . rightspacer .'; grid-template-columns: 1fr 16px minmax(568px, 920px) 16px 1fr; - grid-template-rows: 172px 12px minmax(0, 1fr) 12px; + grid-template-rows: 172px 12px minmax(0, 1fr) 32px; height: 100%; position: relative; width: 100%; @@ -22,7 +22,11 @@ } wallpaper-selected { + background-color: var(--cros-bg-color); grid-area: selected; + position: sticky; + top: 56px; + z-index: 1; } wallpaper-collections,
diff --git a/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn b/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn index 9351308..d707ba22 100644 --- a/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn +++ b/ash/webui/sample_system_web_app_ui/resources/trusted/BUILD.gn
@@ -11,6 +11,15 @@ "Sample System Web App is only built for unofficial builds") generate_grd("trusted_grd") { + # Note: Don't forget to: + # + # 1. Allocate resource id in //tools/gritsettings/resource_ids.spec for the + # .grd file + # 2. Generate the resource pack (a .pak file) from the .grd file generated + # here in //ash/webui/resources/BUILD.gn + # 3. Add the generated pack (from step 1) to //chrome/chrome_paks.gni + # + # Otherwise you'll see network errors when loading the resources. grd_prefix = "ash_sample_system_web_app" out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
diff --git a/ash/webui/sample_system_web_app_ui/resources/untrusted/BUILD.gn b/ash/webui/sample_system_web_app_ui/resources/untrusted/BUILD.gn index 3a0df76..75bc7ad 100644 --- a/ash/webui/sample_system_web_app_ui/resources/untrusted/BUILD.gn +++ b/ash/webui/sample_system_web_app_ui/resources/untrusted/BUILD.gn
@@ -11,6 +11,15 @@ "Sample System Web App is only built for unofficial builds") generate_grd("untrusted_grd") { + # Note: Don't forget to: + # + # 1. Allocate resource id in //tools/gritsettings/resource_ids.spec for the + # .grd file + # 2. Generate the resource pack (a .pak file) from the .grd file generated + # here in //ash/webui/resources/BUILD.gn + # 3. Add the generated pack (from step 1) to //chrome/chrome_paks.gni + # + # Otherwise you'll see network errors when loading the resources. grd_prefix = "ash_sample_system_web_app_untrusted" out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
diff --git a/ash/wm/desks/templates/saved_desk_dialog_controller.cc b/ash/wm/desks/templates/saved_desk_dialog_controller.cc index d2b1def..d15e63b1 100644 --- a/ash/wm/desks/templates/saved_desk_dialog_controller.cc +++ b/ash/wm/desks/templates/saved_desk_dialog_controller.cc
@@ -204,7 +204,7 @@ .PopulateIconContainerFromWindows(unsupported_apps)) .Build(); CreateDialogWidget(std::move(dialog), root_window); - RecordUnsupportedAppDialogShowHistogram(); + RecordUnsupportedAppDialogShowHistogram(unsupported_apps_template_->type()); } void SavedDeskDialogController::ShowReplaceDialog(
diff --git a/ash/wm/desks/templates/saved_desk_item_view.cc b/ash/wm/desks/templates/saved_desk_item_view.cc index 576c87a..30e8b25 100644 --- a/ash/wm/desks/templates/saved_desk_item_view.cc +++ b/ash/wm/desks/templates/saved_desk_item_view.cc
@@ -312,7 +312,7 @@ saved_desk_util::GetSavedDeskPresenter()->DeleteEntry( uuid, /*record_for_type=*/absl::nullopt); UpdateTemplateName(); - RecordReplaceTemplateHistogram(); + RecordReplaceSavedDeskHistogram(desk_template_->type()); } void SavedDeskItemView::RevertTemplateName() {
diff --git a/ash/wm/desks/templates/saved_desk_metrics_util.cc b/ash/wm/desks/templates/saved_desk_metrics_util.cc index 07ea25a5..ea546880 100644 --- a/ash/wm/desks/templates/saved_desk_metrics_util.cc +++ b/ash/wm/desks/templates/saved_desk_metrics_util.cc
@@ -36,6 +36,13 @@ true); } +void RecordReplaceSavedDeskHistogram(DeskTemplateType type) { + base::UmaHistogramBoolean(type == DeskTemplateType::kTemplate + ? kReplaceTemplateHistogramName + : kReplaceSaveAndRecallHistogramName, + true); +} + void RecordAddOrUpdateTemplateStatusHistogram( desks_storage::DeskModel::AddOrUpdateEntryStatus status) { base::UmaHistogramEnumeration(kAddOrUpdateTemplateStatusHistogramName, @@ -99,12 +106,28 @@ } } -void RecordUnsupportedAppDialogShowHistogram() { - base::UmaHistogramBoolean(kUnsupportedAppDialogShowHistogramName, true); +void RecordUnsupportedAppDialogShowHistogram(DeskTemplateType type) { + base::UmaHistogramBoolean( + type == DeskTemplateType::kTemplate + ? kTemplateUnsupportedAppDialogShowHistogramName + : kSaveAndRecallUnsupportedAppDialogShowHistogramName, + true); } -void RecordReplaceTemplateHistogram() { - base::UmaHistogramBoolean(kReplaceTemplateHistogramName, true); +void RecordTimeBetweenSaveAndRecall(base::TimeDelta duration) { + // Constants for the histogram. Do not change these values without also + // changing the histogram name. + constexpr size_t bucket_count = 50; + constexpr base::TimeDelta min_bucket = base::Seconds(1); + constexpr base::TimeDelta max_bucket = base::Hours(24 * 7); // One week. + + // Lazily construct the histogram. + static auto* histogram = base::Histogram::FactoryGet( + kTimeBetweenSaveAndRecallHistogramName, min_bucket.InSeconds(), + max_bucket.InSeconds(), bucket_count, + base::HistogramBase::kUmaTargetedHistogramFlag); + + histogram->Add(duration.InSeconds()); } } // namespace ash
diff --git a/ash/wm/desks/templates/saved_desk_metrics_util.h b/ash/wm/desks/templates/saved_desk_metrics_util.h index ac31984..dcfdec4 100644 --- a/ash/wm/desks/templates/saved_desk_metrics_util.h +++ b/ash/wm/desks/templates/saved_desk_metrics_util.h
@@ -6,6 +6,7 @@ #define ASH_WM_DESKS_TEMPLATES_SAVED_DESK_METRICS_UTIL_H_ #include "ash/public/cpp/desk_template.h" +#include "base/time/time.h" #include "components/desks_storage/core/desk_model.h" namespace ash { @@ -27,7 +28,7 @@ "Ash.DeskTemplate.WindowAndTabCount"; constexpr char kUserTemplateCountHistogramName[] = "Ash.DeskTemplate.UserTemplateCount"; -constexpr char kUnsupportedAppDialogShowHistogramName[] = +constexpr char kTemplateUnsupportedAppDialogShowHistogramName[] = "Ash.DeskTemplate.UnsupportedAppDialogShow"; constexpr char kReplaceTemplateHistogramName[] = "Ash.DeskTemplate.ReplaceTemplate"; @@ -47,20 +48,27 @@ "Ash.DeskTemplate.SaveAndRecallWindowAndTabCount"; constexpr char kUserSaveAndRecallCountHistogramName[] = "Ash.DeskTemplate.UserSaveAndRecallCount"; +constexpr char kReplaceSaveAndRecallHistogramName[] = + "Ash.DeskTemplate.ReplaceSaveAndRecall"; +constexpr char kTimeBetweenSaveAndRecallHistogramName[] = + "Ash.DeskTemplate.TimeBetweenSaveAndRecall"; +constexpr char kSaveAndRecallUnsupportedAppDialogShowHistogramName[] = + "Ash.DeskTemplate.SaveAndRecallUnsupportedAppDialogShow"; // Wrappers calls base::uma with correct histogram name. void RecordLoadSavedDeskLibraryHistogram(); void RecordDeleteSavedDeskHistogram(DeskTemplateType type); void RecordLaunchSavedDeskHistogram(DeskTemplateType type); void RecordNewSavedDeskHistogram(DeskTemplateType type); +void RecordReplaceSavedDeskHistogram(DeskTemplateType type); void RecordAddOrUpdateTemplateStatusHistogram( desks_storage::DeskModel::AddOrUpdateEntryStatus status); void RecordUserSavedDeskCountHistogram(DeskTemplateType type, size_t entry_count, size_t max_entry_count); void RecordWindowAndTabCountHistogram(const DeskTemplate& desk_template); -void RecordUnsupportedAppDialogShowHistogram(); -void RecordReplaceTemplateHistogram(); +void RecordUnsupportedAppDialogShowHistogram(DeskTemplateType type); +void RecordTimeBetweenSaveAndRecall(base::TimeDelta duration); } // namespace ash
diff --git a/ash/wm/desks/templates/saved_desk_presenter.cc b/ash/wm/desks/templates/saved_desk_presenter.cc index 4849992f..b288f3c 100644 --- a/ash/wm/desks/templates/saved_desk_presenter.cc +++ b/ash/wm/desks/templates/saved_desk_presenter.cc
@@ -333,9 +333,9 @@ // For Save & Recall, the underlying desk definition is deleted on launch. We // store the template ID here since we're about to move the desk template. - const bool delete_template_on_launch = - desk_template->type() == DeskTemplateType::kSaveAndRecall; - const std::string template_uuid = desk_template->uuid().AsLowercaseString(); + const auto saved_desk_type = desk_template->type(); + const auto saved_desk_creation_time = desk_template->created_time(); + const std::string uuid = desk_template->uuid().AsLowercaseString(); // Copy the index of the newly created desk to the template. This ensures that // apps appear on the right desk even if the user switches to another. @@ -349,10 +349,12 @@ overview_session_->GetGridWithRootWindow(root_window)->desks_bar_view()); desks_bar_view->NudgeDeskName(desk_index); - if (delete_template_on_launch) { + if (saved_desk_type == DeskTemplateType::kSaveAndRecall) { // Passing nullopt as type since this indicates that we don't want to record // the `delete` metric for this operation. - DeleteEntry(template_uuid, /*record_for_type=*/absl::nullopt); + DeleteEntry(uuid, /*record_for_type=*/absl::nullopt); + RecordTimeBetweenSaveAndRecall(base::Time::Now() - + saved_desk_creation_time); } }
diff --git a/ash/wm/desks/templates/saved_desk_unittest.cc b/ash/wm/desks/templates/saved_desk_unittest.cc index ce67a23..1513e35 100644 --- a/ash/wm/desks/templates/saved_desk_unittest.cc +++ b/ash/wm/desks/templates/saved_desk_unittest.cc
@@ -2878,8 +2878,8 @@ // Now we assert that we've recorded the metric. constexpr int kExpectedDialogShows = 1; - histogram_tester.ExpectTotalCount(kUnsupportedAppDialogShowHistogramName, - kExpectedDialogShows); + histogram_tester.ExpectTotalCount( + kTemplateUnsupportedAppDialogShowHistogramName, kExpectedDialogShows); } // Tests that the window and tab counts are properly recorded in their
diff --git a/ash/wm/multitask_menu_nudge_controller.cc b/ash/wm/multitask_menu_nudge_controller.cc index f4456f09..b114962 100644 --- a/ash/wm/multitask_menu_nudge_controller.cc +++ b/ash/wm/multitask_menu_nudge_controller.cc
@@ -7,6 +7,7 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" +#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/window_util.h" #include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h" #include "chromeos/ui/frame/frame_header.h" @@ -119,6 +120,11 @@ if (nudge_widget_) return; + // TODO(sammiequon): Tablet mode nudge will be different as there is no title + // bar with resize button. + if (Shell::Get()->tablet_mode_controller()->InTabletMode()) + return; + // Only regular users can see the nudge. auto* session_controller = Shell::Get()->session_controller(); const absl::optional<user_manager::UserType> user_type = @@ -142,16 +148,17 @@ return; } + auto* frame_header = chromeos::FrameHeader::Get( + views::Widget::GetWidgetForNativeWindow(window)); + // Frame might not be in tests. + if (!frame_header) + return; + window_ = window; window_observation_.Observe(window_); // The anchor is the button on the header that serves as the maximize or // restore button (depending on the window state). - auto* frame_header = chromeos::FrameHeader::Get( - views::Widget::GetWidgetForNativeWindow(window_)); - // Frame might not be in tests. - if (!frame_header) - return; anchor_view_ = frame_header->caption_button_container()->size_button(); DCHECK(anchor_view_);
diff --git a/base/BUILD.gn b/base/BUILD.gn index 73f2994..7ea3827 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2265,7 +2265,7 @@ } if (dep_libevent) { - deps += [ "//base/third_party/libevent" ] + deps += [ "//third_party/libevent" ] } if (use_libevent) { @@ -3750,7 +3750,7 @@ if (use_libevent) { sources += [ "message_loop/message_pump_libevent_unittest.cc" ] - deps += [ "//base/third_party/libevent" ] + deps += [ "//third_party/libevent" ] } if (is_fuchsia) {
diff --git a/base/DEPS b/base/DEPS index bec8afc..76772d4 100644 --- a/base/DEPS +++ b/base/DEPS
@@ -3,6 +3,7 @@ "+third_party/apple_apsl", "+third_party/boringssl/src/include", "+third_party/ced", + "+third_party/libevent", "+third_party/libunwindstack/src/libunwindstack/include", "+third_party/lss", "+third_party/modp_b64",
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc index 93c2aef..38500b3 100644 --- a/base/message_loop/message_pump_libevent.cc +++ b/base/message_loop/message_pump_libevent.cc
@@ -16,10 +16,10 @@ #include "base/logging.h" #include "base/notreached.h" #include "base/posix/eintr_wrapper.h" -#include "base/third_party/libevent/event.h" #include "base/time/time.h" #include "base/trace_event/base_tracing.h" #include "build/build_config.h" +#include "third_party/libevent/event.h" // Lifecycle of struct event // Libevent uses two main data structures:
diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc index 83826fb..ea6db66 100644 --- a/base/message_loop/message_pump_libevent_unittest.cc +++ b/base/message_loop/message_pump_libevent_unittest.cc
@@ -25,12 +25,12 @@ #include "base/task/single_thread_task_runner.h" #include "base/test/gtest_util.h" #include "base/test/task_environment.h" -#include "base/third_party/libevent/event.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libevent/event.h" namespace base {
diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm index 9c955aa..0f897d42 100644 --- a/base/message_loop/message_pump_mac.mm +++ b/base/message_loop/message_pump_mac.mm
@@ -428,7 +428,12 @@ // The timer fired, assume we have work and let RunWork() figure out what to // do and what to schedule after. base::mac::CallWithEHFrame(^{ +#if !BUILDFLAG(IS_IOS) + // TODO(crbug.com/1338267): Attempt to re-enable this DCHECK on iOS after + // migrating base::TimeTicks::Now() to + // clock_gettime_nsec_np(CLOCK_UPTIME_RAW). DCHECK_GE(base::TimeTicks::Now(), self->delayed_work_scheduled_at_); +#endif self->delayed_work_scheduled_at_ = base::TimeTicks::Max(); self->RunWork(); });
diff --git a/base/third_party/libevent/BUILD.gn b/base/third_party/libevent/BUILD.gn index 755a6a6e..c66c345 100644 --- a/base/third_party/libevent/BUILD.gn +++ b/base/third_party/libevent/BUILD.gn
@@ -2,68 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/nacl/config.gni") - -static_library("libevent") { - sources = [ - "buffer.c", - "evbuffer.c", - "evdns.c", - "evdns.h", - "event-config.h", - "event-internal.h", - "event.c", - "event.h", - "event_tagging.c", - "evhttp.h", - "evrpc-internal.h", - "evrpc.c", - "evrpc.h", - "evsignal.h", - "evutil.c", - "evutil.h", - "http-internal.h", - "http.c", - "log.c", - "log.h", - "min_heap.h", - "poll.c", - "select.c", - "signal.c", - "strlcpy-internal.h", - "strlcpy.c", - ] - - defines = [ "HAVE_CONFIG_H" ] - - if (is_apple) { - sources += [ - "kqueue.c", - "mac/config.h", - "mac/event-config.h", - ] - include_dirs = [ "mac" ] - } else if (is_linux || is_chromeos) { - sources += [ - "epoll.c", - "linux/config.h", - "linux/event-config.h", - ] - include_dirs = [ "linux" ] - } else if (is_android) { - sources += [ - "android/config.h", - "android/event-config.h", - "epoll.c", - ] - include_dirs = [ "android" ] - } - - if (!is_debug) { - configs -= [ "//build/config/compiler:default_optimization" ] - configs += [ "//build/config/compiler:optimize_max" ] - } - - configs -= [ "//build/config/compiler:chromium_code" ] - configs += [ "//build/config/compiler:no_chromium_code" ] +group("libevent") { + # TODO(https://crbug.com/1335194): Remove this when WebRTC migrates. + public_deps = [ "//third_party/libevent" ] }
diff --git a/base/third_party/libevent/event-config.h b/base/third_party/libevent/event-config.h deleted file mode 100644 index 5f301cf9..0000000 --- a/base/third_party/libevent/event-config.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file is Chromium-specific, and brings in the appropriate -// event-config.h depending on your platform. - -#if defined(__APPLE__) -#include "base/third_party/libevent/mac/event-config.h" -#elif defined(ANDROID) -#include "base/third_party/libevent/android/event-config.h" -#elif defined(__linux__) -#include "base/third_party/libevent/linux/event-config.h" -#elif defined(__FreeBSD__) -#include "base/third_party/libevent/freebsd/event-config.h" -#elif defined(__sun) -#include "base/third_party/libevent/solaris/event-config.h" -#elif defined(_AIX) -#include "base/third_party/libevent/aix/event-config.h" -#else -#error generate event-config.h for your platform -#endif
diff --git a/base/third_party/libevent/event.h b/base/third_party/libevent/event.h index f0887b96..8f2a899 100644 --- a/base/third_party/libevent/event.h +++ b/base/third_party/libevent/event.h
@@ -1,1212 +1,11 @@ -/* - * Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef _EVENT_H_ -#define _EVENT_H_ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -/** @mainpage +// TODO(https://crbug.com/1335194): Remove this when WebRTC migrates. +#ifndef BASE_THIRD_PARTY_LIBEVENT_EVENT_H_ +#define BASE_THIRD_PARTY_LIBEVENT_EVENT_H_ - @section intro Introduction +#include "third_party/libevent/event.h" - libevent is an event notification library for developing scalable network - servers. The libevent API provides a mechanism to execute a callback - function when a specific event occurs on a file descriptor or after a - timeout has been reached. Furthermore, libevent also support callbacks due - to signals or regular timeouts. - - libevent is meant to replace the event loop found in event driven network - servers. An application just needs to call event_dispatch() and then add or - remove events dynamically without having to change the event loop. - - Currently, libevent supports /dev/poll, kqueue(2), select(2), poll(2) and - epoll(4). It also has experimental support for real-time signals. The - internal event mechanism is completely independent of the exposed event API, - and a simple update of libevent can provide new functionality without having - to redesign the applications. As a result, Libevent allows for portable - application development and provides the most scalable event notification - mechanism available on an operating system. Libevent can also be used for - multi-threaded aplications; see Steven Grimm's explanation. Libevent should - compile on Linux, *BSD, Mac OS X, Solaris and Windows. - - @section usage Standard usage - - Every program that uses libevent must include the <event.h> header, and pass - the -levent flag to the linker. Before using any of the functions in the - library, you must call event_init() or event_base_new() to perform one-time - initialization of the libevent library. - - @section event Event notification - - For each file descriptor that you wish to monitor, you must declare an event - structure and call event_set() to initialize the members of the structure. - To enable notification, you add the structure to the list of monitored - events by calling event_add(). The event structure must remain allocated as - long as it is active, so it should be allocated on the heap. Finally, you - call event_dispatch() to loop and dispatch events. - - @section bufferevent I/O Buffers - - libevent provides an abstraction on top of the regular event callbacks. This - abstraction is called a buffered event. A buffered event provides input and - output buffers that get filled and drained automatically. The user of a - buffered event no longer deals directly with the I/O, but instead is reading - from input and writing to output buffers. - - Once initialized via bufferevent_new(), the bufferevent structure can be - used repeatedly with bufferevent_enable() and bufferevent_disable(). - Instead of reading and writing directly to a socket, you would call - bufferevent_read() and bufferevent_write(). - - When read enabled the bufferevent will try to read from the file descriptor - and call the read callback. The write callback is executed whenever the - output buffer is drained below the write low watermark, which is 0 by - default. - - @section timers Timers - - libevent can also be used to create timers that invoke a callback after a - certain amount of time has expired. The evtimer_set() function prepares an - event struct to be used as a timer. To activate the timer, call - evtimer_add(). Timers can be deactivated by calling evtimer_del(). - - @section timeouts Timeouts - - In addition to simple timers, libevent can assign timeout events to file - descriptors that are triggered whenever a certain amount of time has passed - with no activity on a file descriptor. The timeout_set() function - initializes an event struct for use as a timeout. Once initialized, the - event must be activated by using timeout_add(). To cancel the timeout, call - timeout_del(). - - @section evdns Asynchronous DNS resolution - - libevent provides an asynchronous DNS resolver that should be used instead - of the standard DNS resolver functions. These functions can be imported by - including the <evdns.h> header in your program. Before using any of the - resolver functions, you must call evdns_init() to initialize the library. To - convert a hostname to an IP address, you call the evdns_resolve_ipv4() - function. To perform a reverse lookup, you would call the - evdns_resolve_reverse() function. All of these functions use callbacks to - avoid blocking while the lookup is performed. - - @section evhttp Event-driven HTTP servers - - libevent provides a very simple event-driven HTTP server that can be - embedded in your program and used to service HTTP requests. - - To use this capability, you need to include the <evhttp.h> header in your - program. You create the server by calling evhttp_new(). Add addresses and - ports to listen on with evhttp_bind_socket(). You then register one or more - callbacks to handle incoming requests. Each URI can be assigned a callback - via the evhttp_set_cb() function. A generic callback function can also be - registered via evhttp_set_gencb(); this callback will be invoked if no other - callbacks have been registered for a given URI. - - @section evrpc A framework for RPC servers and clients - - libevents provides a framework for creating RPC servers and clients. It - takes care of marshaling and unmarshaling all data structures. - - @section api API Reference - - To browse the complete documentation of the libevent API, click on any of - the following links. - - event.h - The primary libevent header - - evdns.h - Asynchronous DNS resolution - - evhttp.h - An embedded libevent-based HTTP server - - evrpc.h - A framework for creating RPC servers and clients - - */ - -/** @file event.h - - A library for writing event-driven network servers - - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "event-config.h" -#ifdef _EVENT_HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef _EVENT_HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef _EVENT_HAVE_STDINT_H -#include <stdint.h> -#endif -#include <stdarg.h> - -/* For int types. */ -#include "evutil.h" - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN -typedef unsigned char u_char; -typedef unsigned short u_short; -#endif - -#define EVLIST_TIMEOUT 0x01 -#define EVLIST_INSERTED 0x02 -#define EVLIST_SIGNAL 0x04 -#define EVLIST_ACTIVE 0x08 -#define EVLIST_INTERNAL 0x10 -#define EVLIST_INIT 0x80 - -/* EVLIST_X_ Private space: 0x1000-0xf000 */ -#define EVLIST_ALL (0xf000 | 0x9f) - -#define EV_TIMEOUT 0x01 -#define EV_READ 0x02 -#define EV_WRITE 0x04 -#define EV_SIGNAL 0x08 -#define EV_PERSIST 0x10 /* Persistant event */ - -/* Fix so that ppl dont have to run with <sys/queue.h> */ -#ifndef TAILQ_ENTRY -#define _EVENT_DEFINED_TQENTRY -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} -#endif /* !TAILQ_ENTRY */ - -struct event_base; -#ifndef EVENT_NO_STRUCT -struct event { - TAILQ_ENTRY (event) ev_next; - TAILQ_ENTRY (event) ev_active_next; - TAILQ_ENTRY (event) ev_signal_next; - unsigned int min_heap_idx; /* for managing timeouts */ - - struct event_base *ev_base; - - int ev_fd; - short ev_events; - short ev_ncalls; - short *ev_pncalls; /* Allows deletes in callback */ - - struct timeval ev_timeout; - - int ev_pri; /* smaller numbers are higher priority */ - - void (*ev_callback)(int, short, void *arg); - void *ev_arg; - - int ev_res; /* result passed to event callback */ - int ev_flags; -}; -#else -struct event; -#endif - -#define EVENT_SIGNAL(ev) (int)(ev)->ev_fd -#define EVENT_FD(ev) (int)(ev)->ev_fd - -/* - * Key-Value pairs. Can be used for HTTP headers but also for - * query argument parsing. - */ -struct evkeyval { - TAILQ_ENTRY(evkeyval) next; - - char *key; - char *value; -}; - -#ifdef _EVENT_DEFINED_TQENTRY -#undef TAILQ_ENTRY -struct event_list; -struct evkeyvalq; -#undef _EVENT_DEFINED_TQENTRY -#else -TAILQ_HEAD (event_list, event); -TAILQ_HEAD (evkeyvalq, evkeyval); -#endif /* _EVENT_DEFINED_TQENTRY */ - -/** - Initialize the event API. - - Use event_base_new() to initialize a new event base, but does not set - the current_base global. If using only event_base_new(), each event - added must have an event base set with event_base_set() - - @see event_base_set(), event_base_free(), event_init() - */ -struct event_base *event_base_new(void); - -/** - Initialize the event API. - - The event API needs to be initialized with event_init() before it can be - used. Sets the current_base global representing the default base for - events that have no base associated with them. - - @see event_base_set(), event_base_new() - */ -struct event_base *event_init(void); - -/** - Reinitialized the event base after a fork - - Some event mechanisms do not survive across fork. The event base needs - to be reinitialized with the event_reinit() function. - - @param base the event base that needs to be re-initialized - @return 0 if successful, or -1 if some events could not be re-added. - @see event_base_new(), event_init() -*/ -int event_reinit(struct event_base *base); - -/** - Loop to process events. - - In order to process events, an application needs to call - event_dispatch(). This function only returns on error, and should - replace the event core of the application program. - - @see event_base_dispatch() - */ -int event_dispatch(void); - - -/** - Threadsafe event dispatching loop. - - @param eb the event_base structure returned by event_init() - @see event_init(), event_dispatch() - */ -int event_base_dispatch(struct event_base *); - - -/** - Get the kernel event notification mechanism used by libevent. - - @param eb the event_base structure returned by event_base_new() - @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) - */ -const char *event_base_get_method(struct event_base *); - - -/** - Deallocate all memory associated with an event_base, and free the base. - - Note that this function will not close any fds or free any memory passed - to event_set as the argument to callback. - - @param eb an event_base to be freed - */ -void event_base_free(struct event_base *); - - -#define _EVENT_LOG_DEBUG 0 -#define _EVENT_LOG_MSG 1 -#define _EVENT_LOG_WARN 2 -#define _EVENT_LOG_ERR 3 -typedef void (*event_log_cb)(int severity, const char *msg); -/** - Redirect libevent's log messages. - - @param cb a function taking two arguments: an integer severity between - _EVENT_LOG_DEBUG and _EVENT_LOG_ERR, and a string. If cb is NULL, - then the default log is used. - */ -void event_set_log_callback(event_log_cb cb); - -/** - Associate a different event base with an event. - - @param eb the event base - @param ev the event - */ -int event_base_set(struct event_base *, struct event *); - -/** - event_loop() flags - */ -/*@{*/ -#define EVLOOP_ONCE 0x01 /**< Block at most once. */ -#define EVLOOP_NONBLOCK 0x02 /**< Do not block. */ -/*@}*/ - -/** - Handle events. - - This is a more flexible version of event_dispatch(). - - @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK - @return 0 if successful, -1 if an error occurred, or 1 if no events were - registered. - @see event_loopexit(), event_base_loop() -*/ -int event_loop(int); - -/** - Handle events (threadsafe version). - - This is a more flexible version of event_base_dispatch(). - - @param eb the event_base structure returned by event_init() - @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK - @return 0 if successful, -1 if an error occurred, or 1 if no events were - registered. - @see event_loopexit(), event_base_loop() - */ -int event_base_loop(struct event_base *, int); - -/** - Exit the event loop after the specified time. - - The next event_loop() iteration after the given timer expires will - complete normally (handling all queued events) then exit without - blocking for events again. - - Subsequent invocations of event_loop() will proceed normally. - - @param tv the amount of time after which the loop should terminate. - @return 0 if successful, or -1 if an error occurred - @see event_loop(), event_base_loop(), event_base_loopexit() - */ -int event_loopexit(const struct timeval *); - - -/** - Exit the event loop after the specified time (threadsafe variant). - - The next event_base_loop() iteration after the given timer expires will - complete normally (handling all queued events) then exit without - blocking for events again. - - Subsequent invocations of event_base_loop() will proceed normally. - - @param eb the event_base structure returned by event_init() - @param tv the amount of time after which the loop should terminate. - @return 0 if successful, or -1 if an error occurred - @see event_loopexit() - */ -int event_base_loopexit(struct event_base *, const struct timeval *); - -/** - Abort the active event_loop() immediately. - - event_loop() will abort the loop after the next event is completed; - event_loopbreak() is typically invoked from this event's callback. - This behavior is analogous to the "break;" statement. - - Subsequent invocations of event_loop() will proceed normally. - - @return 0 if successful, or -1 if an error occurred - @see event_base_loopbreak(), event_loopexit() - */ -int event_loopbreak(void); - -/** - Abort the active event_base_loop() immediately. - - event_base_loop() will abort the loop after the next event is completed; - event_base_loopbreak() is typically invoked from this event's callback. - This behavior is analogous to the "break;" statement. - - Subsequent invocations of event_loop() will proceed normally. - - @param eb the event_base structure returned by event_init() - @return 0 if successful, or -1 if an error occurred - @see event_base_loopexit - */ -int event_base_loopbreak(struct event_base *); - - -/** - Add a timer event. - - @param ev the event struct - @param tv timeval struct - */ -#define evtimer_add(ev, tv) event_add(ev, tv) - - -/** - Define a timer event. - - @param ev event struct to be modified - @param cb callback function - @param arg argument that will be passed to the callback function - */ -#define evtimer_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg) - - -/** - * Delete a timer event. - * - * @param ev the event struct to be disabled - */ -#define evtimer_del(ev) event_del(ev) -#define evtimer_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) -#define evtimer_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) - -/** - * Add a timeout event. - * - * @param ev the event struct to be disabled - * @param tv the timeout value, in seconds - */ -#define timeout_add(ev, tv) event_add(ev, tv) - - -/** - * Define a timeout event. - * - * @param ev the event struct to be defined - * @param cb the callback to be invoked when the timeout expires - * @param arg the argument to be passed to the callback - */ -#define timeout_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg) - - -/** - * Disable a timeout event. - * - * @param ev the timeout event to be disabled - */ -#define timeout_del(ev) event_del(ev) - -#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) -#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) - -#define signal_add(ev, tv) event_add(ev, tv) -#define signal_set(ev, x, cb, arg) \ - event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) -#define signal_del(ev) event_del(ev) -#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv) -#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) - -/** - Prepare an event structure to be added. - - The function event_set() prepares the event structure ev to be used in - future calls to event_add() and event_del(). The event will be prepared to - call the function specified by the fn argument with an int argument - indicating the file descriptor, a short argument indicating the type of - event, and a void * argument given in the arg argument. The fd indicates - the file descriptor that should be monitored for events. The events can be - either EV_READ, EV_WRITE, or both. Indicating that an application can read - or write from the file descriptor respectively without blocking. - - The function fn will be called with the file descriptor that triggered the - event and the type of event which will be either EV_TIMEOUT, EV_SIGNAL, - EV_READ, or EV_WRITE. The additional flag EV_PERSIST makes an event_add() - persistent until event_del() has been called. - - @param ev an event struct to be modified - @param fd the file descriptor to be monitored - @param event desired events to monitor; can be EV_READ and/or EV_WRITE - @param fn callback function to be invoked when the event occurs - @param arg an argument to be passed to the callback function - - @see event_add(), event_del(), event_once() - - */ -void event_set(struct event *, int, short, void (*)(int, short, void *), void *); - -/** - Schedule a one-time event to occur. - - The function event_once() is similar to event_set(). However, it schedules - a callback to be called exactly once and does not require the caller to - prepare an event structure. - - @param fd a file descriptor to monitor - @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ | - EV_WRITE - @param callback callback function to be invoked when the event occurs - @param arg an argument to be passed to the callback function - @param timeout the maximum amount of time to wait for the event, or NULL - to wait forever - @return 0 if successful, or -1 if an error occurred - @see event_set() - - */ -int event_once(int, short, void (*)(int, short, void *), void *, - const struct timeval *); - - -/** - Schedule a one-time event (threadsafe variant) - - The function event_base_once() is similar to event_set(). However, it - schedules a callback to be called exactly once and does not require the - caller to prepare an event structure. - - @param base an event_base returned by event_init() - @param fd a file descriptor to monitor - @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ | - EV_WRITE - @param callback callback function to be invoked when the event occurs - @param arg an argument to be passed to the callback function - @param timeout the maximum amount of time to wait for the event, or NULL - to wait forever - @return 0 if successful, or -1 if an error occurred - @see event_once() - */ -int event_base_once(struct event_base *base, int fd, short events, - void (*callback)(int, short, void *), void *arg, - const struct timeval *timeout); - - -/** - Add an event to the set of monitored events. - - The function event_add() schedules the execution of the ev event when the - event specified in event_set() occurs or in at least the time specified in - the tv. If tv is NULL, no timeout occurs and the function will only be - called if a matching event occurs on the file descriptor. The event in the - ev argument must be already initialized by event_set() and may not be used - in calls to event_set() until it has timed out or been removed with - event_del(). If the event in the ev argument already has a scheduled - timeout, the old timeout will be replaced by the new one. - - @param ev an event struct initialized via event_set() - @param timeout the maximum amount of time to wait for the event, or NULL - to wait forever - @return 0 if successful, or -1 if an error occurred - @see event_del(), event_set() - */ -int event_add(struct event *ev, const struct timeval *timeout); - - -/** - Remove an event from the set of monitored events. - - The function event_del() will cancel the event in the argument ev. If the - event has already executed or has never been added the call will have no - effect. - - @param ev an event struct to be removed from the working set - @return 0 if successful, or -1 if an error occurred - @see event_add() - */ -int event_del(struct event *); - -void event_active(struct event *, int, short); - - -/** - Checks if a specific event is pending or scheduled. - - @param ev an event struct previously passed to event_add() - @param event the requested event type; any of EV_TIMEOUT|EV_READ| - EV_WRITE|EV_SIGNAL - @param tv an alternate timeout (FIXME - is this true?) - - @return 1 if the event is pending, or 0 if the event has not occurred - - */ -int event_pending(struct event *ev, short event, struct timeval *tv); - - -/** - Test if an event structure has been initialized. - - The event_initialized() macro can be used to check if an event has been - initialized. - - @param ev an event structure to be tested - @return 1 if the structure has been initialized, or 0 if it has not been - initialized - */ -#ifdef WIN32 -#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE) -#else -#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) -#endif - - -/** - Get the libevent version number. - - @return a string containing the version number of libevent - */ -const char *event_get_version(void); - - -/** - Get the kernel event notification mechanism used by libevent. - - @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) - */ -const char *event_get_method(void); - - -/** - Set the number of different event priorities. - - By default libevent schedules all active events with the same priority. - However, some time it is desirable to process some events with a higher - priority than others. For that reason, libevent supports strict priority - queues. Active events with a lower priority are always processed before - events with a higher priority. - - The number of different priorities can be set initially with the - event_priority_init() function. This function should be called before the - first call to event_dispatch(). The event_priority_set() function can be - used to assign a priority to an event. By default, libevent assigns the - middle priority to all events unless their priority is explicitly set. - - @param npriorities the maximum number of priorities - @return 0 if successful, or -1 if an error occurred - @see event_base_priority_init(), event_priority_set() - - */ -int event_priority_init(int); - - -/** - Set the number of different event priorities (threadsafe variant). - - See the description of event_priority_init() for more information. - - @param eb the event_base structure returned by event_init() - @param npriorities the maximum number of priorities - @return 0 if successful, or -1 if an error occurred - @see event_priority_init(), event_priority_set() - */ -int event_base_priority_init(struct event_base *, int); - - -/** - Assign a priority to an event. - - @param ev an event struct - @param priority the new priority to be assigned - @return 0 if successful, or -1 if an error occurred - @see event_priority_init() - */ -int event_priority_set(struct event *, int); - - -/* These functions deal with buffering input and output */ - -struct evbuffer { - u_char *buffer; - u_char *orig_buffer; - - size_t misalign; - size_t totallen; - size_t off; - - void (*cb)(struct evbuffer *, size_t, size_t, void *); - void *cbarg; -}; - -/* Just for error reporting - use other constants otherwise */ -#define EVBUFFER_READ 0x01 -#define EVBUFFER_WRITE 0x02 -#define EVBUFFER_EOF 0x10 -#define EVBUFFER_ERROR 0x20 -#define EVBUFFER_TIMEOUT 0x40 - -struct bufferevent; -typedef void (*evbuffercb)(struct bufferevent *, void *); -typedef void (*everrorcb)(struct bufferevent *, short what, void *); - -struct event_watermark { - size_t low; - size_t high; -}; - -#ifndef EVENT_NO_STRUCT -struct bufferevent { - struct event_base *ev_base; - - struct event ev_read; - struct event ev_write; - - struct evbuffer *input; - struct evbuffer *output; - - struct event_watermark wm_read; - struct event_watermark wm_write; - - evbuffercb readcb; - evbuffercb writecb; - everrorcb errorcb; - void *cbarg; - - int timeout_read; /* in seconds */ - int timeout_write; /* in seconds */ - - short enabled; /* events that are currently enabled */ -}; -#endif - -/** - Create a new bufferevent. - - libevent provides an abstraction on top of the regular event callbacks. - This abstraction is called a buffered event. A buffered event provides - input and output buffers that get filled and drained automatically. The - user of a buffered event no longer deals directly with the I/O, but - instead is reading from input and writing to output buffers. - - Once initialized, the bufferevent structure can be used repeatedly with - bufferevent_enable() and bufferevent_disable(). - - When read enabled the bufferevent will try to read from the file descriptor - and call the read callback. The write callback is executed whenever the - output buffer is drained below the write low watermark, which is 0 by - default. - - If multiple bases are in use, bufferevent_base_set() must be called before - enabling the bufferevent for the first time. - - @param fd the file descriptor from which data is read and written to. - This file descriptor is not allowed to be a pipe(2). - @param readcb callback to invoke when there is data to be read, or NULL if - no callback is desired - @param writecb callback to invoke when the file descriptor is ready for - writing, or NULL if no callback is desired - @param errorcb callback to invoke when there is an error on the file - descriptor - @param cbarg an argument that will be supplied to each of the callbacks - (readcb, writecb, and errorcb) - @return a pointer to a newly allocated bufferevent struct, or NULL if an - error occurred - @see bufferevent_base_set(), bufferevent_free() - */ -struct bufferevent *bufferevent_new(int fd, - evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); - - -/** - Assign a bufferevent to a specific event_base. - - @param base an event_base returned by event_init() - @param bufev a bufferevent struct returned by bufferevent_new() - @return 0 if successful, or -1 if an error occurred - @see bufferevent_new() - */ -int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev); - - -/** - Assign a priority to a bufferevent. - - @param bufev a bufferevent struct - @param pri the priority to be assigned - @return 0 if successful, or -1 if an error occurred - */ -int bufferevent_priority_set(struct bufferevent *bufev, int pri); - - -/** - Deallocate the storage associated with a bufferevent structure. - - @param bufev the bufferevent structure to be freed. - */ -void bufferevent_free(struct bufferevent *bufev); - - -/** - Changes the callbacks for a bufferevent. - - @param bufev the bufferevent object for which to change callbacks - @param readcb callback to invoke when there is data to be read, or NULL if - no callback is desired - @param writecb callback to invoke when the file descriptor is ready for - writing, or NULL if no callback is desired - @param errorcb callback to invoke when there is an error on the file - descriptor - @param cbarg an argument that will be supplied to each of the callbacks - (readcb, writecb, and errorcb) - @see bufferevent_new() - */ -void bufferevent_setcb(struct bufferevent *bufev, - evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); - -/** - Changes the file descriptor on which the bufferevent operates. - - @param bufev the bufferevent object for which to change the file descriptor - @param fd the file descriptor to operate on -*/ -void bufferevent_setfd(struct bufferevent *bufev, int fd); - -/** - Write data to a bufferevent buffer. - - The bufferevent_write() function can be used to write data to the file - descriptor. The data is appended to the output buffer and written to the - descriptor automatically as it becomes available for writing. - - @param bufev the bufferevent to be written to - @param data a pointer to the data to be written - @param size the length of the data, in bytes - @return 0 if successful, or -1 if an error occurred - @see bufferevent_write_buffer() - */ -int bufferevent_write(struct bufferevent *bufev, - const void *data, size_t size); - - -/** - Write data from an evbuffer to a bufferevent buffer. The evbuffer is - being drained as a result. - - @param bufev the bufferevent to be written to - @param buf the evbuffer to be written - @return 0 if successful, or -1 if an error occurred - @see bufferevent_write() - */ -int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf); - - -/** - Read data from a bufferevent buffer. - - The bufferevent_read() function is used to read data from the input buffer. - - @param bufev the bufferevent to be read from - @param data pointer to a buffer that will store the data - @param size the size of the data buffer, in bytes - @return the amount of data read, in bytes. - */ -size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); - -/** - Enable a bufferevent. - - @param bufev the bufferevent to be enabled - @param event any combination of EV_READ | EV_WRITE. - @return 0 if successful, or -1 if an error occurred - @see bufferevent_disable() - */ -int bufferevent_enable(struct bufferevent *bufev, short event); - - -/** - Disable a bufferevent. - - @param bufev the bufferevent to be disabled - @param event any combination of EV_READ | EV_WRITE. - @return 0 if successful, or -1 if an error occurred - @see bufferevent_enable() - */ -int bufferevent_disable(struct bufferevent *bufev, short event); - - -/** - Set the read and write timeout for a buffered event. - - @param bufev the bufferevent to be modified - @param timeout_read the read timeout - @param timeout_write the write timeout - */ -void bufferevent_settimeout(struct bufferevent *bufev, - int timeout_read, int timeout_write); - - -/** - Sets the watermarks for read and write events. - - On input, a bufferevent does not invoke the user read callback unless - there is at least low watermark data in the buffer. If the read buffer - is beyond the high watermark, the buffevent stops reading from the network. - - On output, the user write callback is invoked whenever the buffered data - falls below the low watermark. - - @param bufev the bufferevent to be modified - @param events EV_READ, EV_WRITE or both - @param lowmark the lower watermark to set - @param highmark the high watermark to set -*/ - -void bufferevent_setwatermark(struct bufferevent *bufev, short events, - size_t lowmark, size_t highmark); - -#define EVBUFFER_LENGTH(x) (x)->off -#define EVBUFFER_DATA(x) (x)->buffer -#define EVBUFFER_INPUT(x) (x)->input -#define EVBUFFER_OUTPUT(x) (x)->output - - -/** - Allocate storage for a new evbuffer. - - @return a pointer to a newly allocated evbuffer struct, or NULL if an error - occurred - */ -struct evbuffer *evbuffer_new(void); - - -/** - Deallocate storage for an evbuffer. - - @param pointer to the evbuffer to be freed - */ -void evbuffer_free(struct evbuffer *); - - -/** - Expands the available space in an event buffer. - - Expands the available space in the event buffer to at least datlen - - @param buf the event buffer to be expanded - @param datlen the new minimum length requirement - @return 0 if successful, or -1 if an error occurred -*/ -int evbuffer_expand(struct evbuffer *, size_t); - - -/** - Append data to the end of an evbuffer. - - @param buf the event buffer to be appended to - @param data pointer to the beginning of the data buffer - @param datlen the number of bytes to be copied from the data buffer - */ -int evbuffer_add(struct evbuffer *, const void *, size_t); - - - -/** - Read data from an event buffer and drain the bytes read. - - @param buf the event buffer to be read from - @param data the destination buffer to store the result - @param datlen the maximum size of the destination buffer - @return the number of bytes read - */ -int evbuffer_remove(struct evbuffer *, void *, size_t); - - -/** - * Read a single line from an event buffer. - * - * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. - * The returned buffer needs to be freed by the caller. - * - * @param buffer the evbuffer to read from - * @return pointer to a single line, or NULL if an error occurred - */ -char *evbuffer_readline(struct evbuffer *); - - -/** Used to tell evbuffer_readln what kind of line-ending to look for. - */ -enum evbuffer_eol_style { - /** Any sequence of CR and LF characters is acceptable as an EOL. */ - EVBUFFER_EOL_ANY, - /** An EOL is an LF, optionally preceded by a CR. This style is - * most useful for implementing text-based internet protocols. */ - EVBUFFER_EOL_CRLF, - /** An EOL is a CR followed by an LF. */ - EVBUFFER_EOL_CRLF_STRICT, - /** An EOL is a LF. */ - EVBUFFER_EOL_LF -}; - -/** - * Read a single line from an event buffer. - * - * Reads a line terminated by an EOL as determined by the evbuffer_eol_style - * argument. Returns a newly allocated nul-terminated string; the caller must - * free the returned value. The EOL is not included in the returned string. - * - * @param buffer the evbuffer to read from - * @param n_read_out if non-NULL, points to a size_t that is set to the - * number of characters in the returned string. This is useful for - * strings that can contain NUL characters. - * @param eol_style the style of line-ending to use. - * @return pointer to a single line, or NULL if an error occurred - */ -char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, - enum evbuffer_eol_style eol_style); - - -/** - Move data from one evbuffer into another evbuffer. - - This is a destructive add. The data from one buffer moves into - the other buffer. The destination buffer is expanded as needed. - - @param outbuf the output buffer - @param inbuf the input buffer - @return 0 if successful, or -1 if an error occurred - */ -int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *); - - -/** - Append a formatted string to the end of an evbuffer. - - @param buf the evbuffer that will be appended to - @param fmt a format string - @param ... arguments that will be passed to printf(3) - @return The number of bytes added if successful, or -1 if an error occurred. - */ -int evbuffer_add_printf(struct evbuffer *, const char *fmt, ...) -#ifdef __GNUC__ - __attribute__((format(printf, 2, 3))) -#endif -; - - -/** - Append a va_list formatted string to the end of an evbuffer. - - @param buf the evbuffer that will be appended to - @param fmt a format string - @param ap a varargs va_list argument array that will be passed to vprintf(3) - @return The number of bytes added if successful, or -1 if an error occurred. - */ -int evbuffer_add_vprintf(struct evbuffer *, const char *fmt, va_list ap); - - -/** - Remove a specified number of bytes data from the beginning of an evbuffer. - - @param buf the evbuffer to be drained - @param len the number of bytes to drain from the beginning of the buffer - */ -void evbuffer_drain(struct evbuffer *, size_t); - - -/** - Write the contents of an evbuffer to a file descriptor. - - The evbuffer will be drained after the bytes have been successfully written. - - @param buffer the evbuffer to be written and drained - @param fd the file descriptor to be written to - @return the number of bytes written, or -1 if an error occurred - @see evbuffer_read() - */ -int evbuffer_write(struct evbuffer *, int); - - -/** - Read from a file descriptor and store the result in an evbuffer. - - @param buf the evbuffer to store the result - @param fd the file descriptor to read from - @param howmuch the number of bytes to be read - @return the number of bytes read, or -1 if an error occurred - @see evbuffer_write() - */ -int evbuffer_read(struct evbuffer *, int, int); - - -/** - Find a string within an evbuffer. - - @param buffer the evbuffer to be searched - @param what the string to be searched for - @param len the length of the search string - @return a pointer to the beginning of the search string, or NULL if the search failed. - */ -u_char *evbuffer_find(struct evbuffer *, const u_char *, size_t); - -/** - Set a callback to invoke when the evbuffer is modified. - - @param buffer the evbuffer to be monitored - @param cb the callback function to invoke when the evbuffer is modified - @param cbarg an argument to be provided to the callback function - */ -void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *); - -/* - * Marshaling tagged data - We assume that all tags are inserted in their - * numeric order - so that unknown tags will always be higher than the - * known ones - and we can just ignore the end of an event buffer. - */ - -void evtag_init(void); - -void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data, - ev_uint32_t len); - -/** - Encode an integer and store it in an evbuffer. - - We encode integer's by nibbles; the first nibble contains the number - of significant nibbles - 1; this allows us to encode up to 64-bit - integers. This function is byte-order independent. - - @param evbuf evbuffer to store the encoded number - @param number a 32-bit integer - */ -void encode_int(struct evbuffer *evbuf, ev_uint32_t number); - -void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, - ev_uint32_t integer); - -void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, - const char *string); - -void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, - struct timeval *tv); - -int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, - struct evbuffer *dst); -int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag); -int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength); -int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength); -int evtag_consume(struct evbuffer *evbuf); - -int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, - ev_uint32_t *pinteger); - -int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, - void *data, size_t len); - -int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, - char **pstring); - -int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag, - struct timeval *ptv); - -#ifdef __cplusplus -} -#endif - -#endif /* _EVENT_H_ */ +#endif // BASE_THIRD_PARTY_LIBEVENT_EVENT_H_
diff --git a/base/threading/hang_watcher.cc b/base/threading/hang_watcher.cc index 97f2d81..8f38b8a8 100644 --- a/base/threading/hang_watcher.cc +++ b/base/threading/hang_watcher.cc
@@ -998,9 +998,9 @@ namespace internal { namespace { -constexpr uint64_t kOnlyDeadlineMask = 0x00FFFFFFFFFFFFFFu; +constexpr uint64_t kOnlyDeadlineMask = 0x00FF'FFFF'FFFF'FFFFu; constexpr uint64_t kOnlyFlagsMask = ~kOnlyDeadlineMask; -constexpr uint64_t kMaximumFlag = 0x8000000000000000u; +constexpr uint64_t kMaximumFlag = 0x8000'0000'0000'0000u; // Use as a mask to keep persistent flags and the deadline. constexpr uint64_t kPersistentFlagsAndDeadlineMask = @@ -1060,7 +1060,8 @@ const uint64_t old_bits = bits_.load(std::memory_order_relaxed); const uint64_t new_flags = ExtractFlags(old_bits & kPersistentFlagsAndDeadlineMask); - bits_.store(new_flags | ExtractDeadline(new_deadline.ToInternalValue()), + bits_.store(new_flags | ExtractDeadline(static_cast<uint64_t>( + new_deadline.ToInternalValue())), std::memory_order_relaxed); } @@ -1131,7 +1132,8 @@ // representable value. DCHECK(bits <= kOnlyDeadlineMask) << "Flags bits are set. Remove them before returning deadline."; - return TimeTicks::FromInternalValue(bits); + static_assert(kOnlyDeadlineMask <= std::numeric_limits<int64_t>::max()); + return TimeTicks::FromInternalValue(static_cast<int64_t>(bits)); } bool HangWatchDeadline::IsFlagSet(Flag flag) const {
diff --git a/base/threading/scoped_blocking_call_internal.cc b/base/threading/scoped_blocking_call_internal.cc index cc02ab5..37da6ca 100644 --- a/base/threading/scoped_blocking_call_internal.cc +++ b/base/threading/scoped_blocking_call_internal.cc
@@ -340,7 +340,8 @@ // Also record the data for extended crash reporting. const TimeTicks now = TimeTicks::Now(); auto& user_data = scoped_activity_.user_data(); - user_data.SetUint("timestamp_us", now.since_origin().InMicroseconds()); + user_data.SetUint("timestamp_us", static_cast<uint64_t>( + now.since_origin().InMicroseconds())); user_data.SetUint("blocking_type", static_cast<uint64_t>(blocking_type)); } }
diff --git a/base/threading/simple_thread.cc b/base/threading/simple_thread.cc index 70aa6b9..f387820 100644 --- a/base/threading/simple_thread.cc +++ b/base/threading/simple_thread.cc
@@ -101,7 +101,7 @@ DelegateSimpleThreadPool::DelegateSimpleThreadPool( const std::string& name_prefix, - int num_threads) + size_t num_threads) : name_prefix_(name_prefix), num_threads_(num_threads), dry_(WaitableEvent::ResetPolicy::MANUAL, @@ -115,7 +115,7 @@ void DelegateSimpleThreadPool::Start() { DCHECK(threads_.empty()) << "Start() called with outstanding threads."; - for (int i = 0; i < num_threads_; ++i) { + for (size_t i = 0; i < num_threads_; ++i) { std::string name(name_prefix_); name.push_back('/'); name.append(NumberToString(i)); @@ -132,7 +132,7 @@ AddWork(nullptr, num_threads_); // Join and destroy all the worker threads. - for (int i = 0; i < num_threads_; ++i) { + for (size_t i = 0; i < num_threads_; ++i) { threads_[i]->Join(); delete threads_[i]; } @@ -140,9 +140,10 @@ DCHECK(delegates_.empty()); } -void DelegateSimpleThreadPool::AddWork(Delegate* delegate, int repeat_count) { +void DelegateSimpleThreadPool::AddWork(Delegate* delegate, + size_t repeat_count) { AutoLock locked(lock_); - for (int i = 0; i < repeat_count; ++i) + for (size_t i = 0; i < repeat_count; ++i) delegates_.push(delegate); // If we were empty, signal that we have work now. if (!dry_.IsSignaled())
diff --git a/base/threading/simple_thread.h b/base/threading/simple_thread.h index ec25d79b..654cda5 100644 --- a/base/threading/simple_thread.h +++ b/base/threading/simple_thread.h
@@ -196,7 +196,7 @@ public: typedef DelegateSimpleThread::Delegate Delegate; - DelegateSimpleThreadPool(const std::string& name_prefix, int num_threads); + DelegateSimpleThreadPool(const std::string& name_prefix, size_t num_threads); DelegateSimpleThreadPool(const DelegateSimpleThreadPool&) = delete; DelegateSimpleThreadPool& operator=(const DelegateSimpleThreadPool&) = delete; @@ -213,17 +213,14 @@ // It is safe to AddWork() any time, before or after Start(). // Delegate* should always be a valid pointer, NULL is reserved internally. - void AddWork(Delegate* work, int repeat_count); - void AddWork(Delegate* work) { - AddWork(work, 1); - } + void AddWork(Delegate* work, size_t repeat_count = 1); // We implement the Delegate interface, for running our internal threads. void Run() override; private: const std::string name_prefix_; - int num_threads_; + size_t num_threads_; std::vector<DelegateSimpleThread*> threads_; base::queue<Delegate*> delegates_; base::Lock lock_; // Locks delegates_
diff --git a/base/threading/thread_local_storage.cc b/base/threading/thread_local_storage.cc index 6ff04f3f..56f8e6c 100644 --- a/base/threading/thread_local_storage.cc +++ b/base/threading/thread_local_storage.cc
@@ -142,7 +142,7 @@ "kUninitialized must be null"); // The maximum number of slots in our thread local storage stack. -constexpr int kThreadLocalStorageSize = 256; +constexpr size_t kThreadLocalStorageSize = 256; enum TlsStatus { FREE, @@ -175,7 +175,7 @@ // The maximum number of times to try to clear slots by calling destructors. // Use pthread naming convention for clarity. -constexpr int kMaxDestructorIterations = kThreadLocalStorageSize; +constexpr size_t kMaxDestructorIterations = kThreadLocalStorageSize; // Sets the value and state of the vector. void SetTlsVectorValue(PlatformThreadLocalStorage::TLSKey key, @@ -330,7 +330,7 @@ memcpy(tls_metadata, g_tls_metadata, sizeof(g_tls_metadata)); } - int remaining_attempts = kMaxDestructorIterations; + size_t remaining_attempts = kMaxDestructorIterations + 1; bool need_to_scan_destructors = true; while (need_to_scan_destructors) { need_to_scan_destructors = false; @@ -340,7 +340,7 @@ // allocator) and should also be destroyed last. If we get the order wrong, // then we'll iterate several more times, so it is really not that critical // (but it might help). - for (int slot = 0; slot < kThreadLocalStorageSize; ++slot) { + for (size_t slot = 0; slot < kThreadLocalStorageSize; ++slot) { void* tls_value = stack_allocated_tls_data[slot].data; if (!tls_value || tls_metadata[slot].status == TlsStatus::FREE || stack_allocated_tls_data[slot].version != tls_metadata[slot].version) @@ -357,7 +357,7 @@ // vector again. This is a pthread standard. need_to_scan_destructors = true; } - if (--remaining_attempts <= 0) { + if (--remaining_attempts == 0) { NOTREACHED(); // Destructors might not have been called. break; } @@ -433,7 +433,7 @@ // Grab a new slot. { base::AutoLock auto_lock(*GetTLSMetadataLock()); - for (int i = 0; i < kThreadLocalStorageSize; ++i) { + for (size_t i = 0; i < kThreadLocalStorageSize; ++i) { // Tracking the last assigned slot is an attempt to find the next // available slot within one iteration. Under normal usage, slots remain // in use for the lifetime of the process (otherwise before we reclaimed @@ -452,12 +452,10 @@ } } } - CHECK_NE(slot_, kInvalidSlotValue); CHECK_LT(slot_, kThreadLocalStorageSize); } void ThreadLocalStorage::Slot::Free() { - DCHECK_NE(slot_, kInvalidSlotValue); DCHECK_LT(slot_, kThreadLocalStorageSize); { base::AutoLock auto_lock(*GetTLSMetadataLock()); @@ -475,7 +473,6 @@ DCHECK_NE(state, TlsVectorState::kDestroyed); if (!tls_data) return nullptr; - DCHECK_NE(slot_, kInvalidSlotValue); DCHECK_LT(slot_, kThreadLocalStorageSize); // Version mismatches means this slot was previously freed. if (tls_data[slot_].version != version_) @@ -493,7 +490,6 @@ return; tls_data = ConstructTlsVector(); } - DCHECK_NE(slot_, kInvalidSlotValue); DCHECK_LT(slot_, kThreadLocalStorageSize); tls_data[slot_].data = value; tls_data[slot_].version = version_;
diff --git a/base/threading/thread_local_storage.h b/base/threading/thread_local_storage.h index 877a6bac..6f72a9f 100644 --- a/base/threading/thread_local_storage.h +++ b/base/threading/thread_local_storage.h
@@ -138,8 +138,8 @@ void Initialize(TLSDestructorFunc destructor); void Free(); - static constexpr int kInvalidSlotValue = -1; - int slot_ = kInvalidSlotValue; + static constexpr size_t kInvalidSlotValue = static_cast<size_t>(-1); + size_t slot_ = kInvalidSlotValue; uint32_t version_ = 0; };
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 676efed..6c9b73d 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -1552,15 +1552,6 @@ cflags += [ "-Wno-unqualified-std-cast-call" ] } - if (!is_nacl && !(is_chromeos || - default_toolchain == "//build/toolchain/cros:target")) { - # TODO(https://crbug.com/1322823): Remove flags once potential miscompile is investigated. - cflags += [ - "-Xclang", - "-no-opaque-pointers", - ] - } - if (is_fuchsia) { # TODO(https://bugs.chromium.org/p/fuchsia/issues/detail?id=77383) cflags += [ "-Wno-deprecated-copy" ]
diff --git a/build/config/fuchsia/BUILD.gn b/build/config/fuchsia/BUILD.gn index b53737b..15fd04b 100644 --- a/build/config/fuchsia/BUILD.gn +++ b/build/config/fuchsia/BUILD.gn
@@ -33,11 +33,17 @@ "//third_party/fuchsia-sdk/sdk/bin/fuchsia-common.sh", "//third_party/fuchsia-sdk/sdk/meta/manifest.json", "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/ffx", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/ffx-meta.json", "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/fvm", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/fvm-meta.json", "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/merkleroot", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/merkleroot-meta.json", "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/pm", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/pm-meta.json", "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/symbolizer", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/symbolizer-meta.json", "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/zbi", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/zbi-meta.json", ] if (test_isolate_uses_emulator) { data += [ @@ -50,7 +56,9 @@ if (test_host_cpu == "x64") { data += [ "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/aemu_internal", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/aemu_internal-meta.json", "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/qemu_internal", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/qemu_internal-meta.json", ] } else if (test_host_cpu == "arm64") { data += [ "//third_party/qemu-${host_os}-${test_host_cpu}/" ]
diff --git a/build/config/fuchsia/generate_runner_scripts.gni b/build/config/fuchsia/generate_runner_scripts.gni index 4a37b71c..45d73fed 100644 --- a/build/config/fuchsia/generate_runner_scripts.gni +++ b/build/config/fuchsia/generate_runner_scripts.gni
@@ -88,15 +88,11 @@ "executable_args", "data", "include_fuchsia_build_dir", - "metadata_deps", "target", ]) wrapper_script = _generated_script_path deps = [ invoker.package ] - if (defined(metadata_deps)) { - deps += metadata_deps - } if (!defined(data_deps)) { data_deps = [] @@ -211,7 +207,6 @@ executable = rebase_path("//build/fuchsia/deploy_to_pkg_repo.py") output_name_format = "deploy_%package%" include_fuchsia_build_dir = true - metadata_deps = [ ":${pkg_shortname}_script_meta" ] } } @@ -303,6 +298,10 @@ } data += [ _test_runner_py ] + if (use_cfv2_script) { + data += [ "$root_gen_dir/package_metadata/${invoker.package_name}.meta" ] + } + # TODO(crbug.com/1256870): Remove this once all out-of-tree references # to "package_name_override" are migrated to "package_name". if (defined(invoker.package_name_override)) {
diff --git a/build/fuchsia/device_target.py b/build/fuchsia/device_target.py index 7b2430f..af2766c 100644 --- a/build/fuchsia/device_target.py +++ b/build/fuchsia/device_target.py
@@ -48,6 +48,11 @@ return DeviceTarget +class ProvisionDeviceException(Exception): + def __init__(self, message: str): + super(ProvisionDeviceException, self).__init__(message) + + class DeviceTarget(target.Target): """Prepares a device to be used as a deployment target. Depending on the command line parameters, it automatically handling a number of preparatory @@ -402,7 +407,7 @@ return_code, stdout, stderr = SubprocessCallWithTimeout(pave_command, timeout_secs=300) if return_code != 0: - raise Exception('Could not pave device.') + raise ProvisionDeviceException('Could not pave device.') self._ParseNodename(stderr) def Restart(self):
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index d263a89..48e7aff 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -8.20220621.2.1 +8.20220621.3.1
diff --git a/build/fuchsia/runner_exceptions.py b/build/fuchsia/runner_exceptions.py index 03f872e..cf2769b3 100644 --- a/build/fuchsia/runner_exceptions.py +++ b/build/fuchsia/runner_exceptions.py
@@ -15,6 +15,7 @@ import sys import traceback +from device_target import ProvisionDeviceException from target import FuchsiaTargetException def _PrintException(value, trace): @@ -74,5 +75,8 @@ print('Error: qemu-img fuchsia image generation failed.') return 82 return 80 + elif type is ProvisionDeviceException: + print('Error: Failed to pave device') + return 90 else: return 1
diff --git a/build/fuchsia/test/common.py b/build/fuchsia/test/common.py index 82b5361..d70fac1 100644 --- a/build/fuchsia/test/common.py +++ b/build/fuchsia/test/common.py
@@ -111,8 +111,9 @@ Returns: A list of the absolute path to all FAR files the package depends on. """ - with open(os.path.join(DIR_SRC_ROOT, out_dir, 'gen', - f'{pkg_name}.meta')) as meta_file: + with open( + os.path.join(DIR_SRC_ROOT, out_dir, 'gen', 'package_metadata', + f'{pkg_name}.meta')) as meta_file: data = json.load(meta_file) packages = [] for package in data['packages']:
diff --git a/build/fuchsia/test/ffx_integration.py b/build/fuchsia/test/ffx_integration.py index a97980e..77072c4 100644 --- a/build/fuchsia/test/ffx_integration.py +++ b/build/fuchsia/test/ffx_integration.py
@@ -17,6 +17,19 @@ SDK_ROOT +def get_config(name: str) -> Optional[str]: + """Run a ffx config get command to retrieve the config value.""" + + try: + return run_ffx_command(['config', 'get', name], + capture_output=True).stdout.strip() + except subprocess.CalledProcessError as cpe: + # A return code of 2 indicates no previous value set. + if cpe.returncode == 2: + return None + raise + + class ScopedFfxConfig(AbstractContextManager): """Temporarily overrides `ffx` configuration. Restores the previous value upon exit.""" @@ -35,14 +48,7 @@ """Override the configuration.""" # Cache the old value. - try: - self._old_value = run_ffx_command( - ['config', 'get', self._name], - capture_output=True).stdout.strip() - except subprocess.CalledProcessError as cpe: - # A return code of 2 indicates no previous value set. - if cpe.returncode != 2: - raise + self._old_value = get_config(self._name) if self._new_value != self._old_value: run_ffx_command(['config', 'set', self._name, self._new_value]) return self
diff --git a/build/fuchsia/test/serve_repo.py b/build/fuchsia/test/serve_repo.py index e8abc642..43dd3f44 100755 --- a/build/fuchsia/test/serve_repo.py +++ b/build/fuchsia/test/serve_repo.py
@@ -12,34 +12,25 @@ import sys from common import REPO_ALIAS, register_device_args, run_ffx_command +from ffx_integration import get_config # Contains information about the active ephemeral repository. _REPO_CONFIG_FILE = os.path.join('/', 'tmp', 'fuchsia-repo-config') -def _configure_ffx_serving(): - """Configure ffx to allow serving a ffx-managed repository. +def _ensure_ffx_config(key: str, value: str) -> bool: + """Ensures ffx config for a given key is value. Returns True if the config + was changed, False otherwise.""" - Returns: - True if configuration was updated, otherwise False. - """ - config_updated = False - repo_cmd = run_ffx_command(['config', 'get', 'ffx_repository'], - capture_output=True) - if 'true' not in repo_cmd.stdout: - run_ffx_command(['config', 'set', 'ffx_repository', 'true']) - config_updated = True - - server_cmd = run_ffx_command(['config', 'get', 'repository.server.mode'], - capture_output=True) - if 'ffx' not in server_cmd.stdout: - run_ffx_command(['config', 'set', 'repository.server.mode', 'ffx']) - config_updated = True - return config_updated + if get_config(key) == value: + return False + run_ffx_command(['config', 'set', key, value]) + return True def _stop_serving() -> None: """Stop serving a repository configured in _REPO_CONFIG_FILE.""" + if not os.path.exists(_REPO_CONFIG_FILE): logging.warning('Could not find repository configuration.') return @@ -47,27 +38,33 @@ with open(_REPO_CONFIG_FILE, 'r') as file: data = json.load(file) + # Attempt to clean up. run_ffx_command( ['target', 'repository', 'deregister', '-r', data['repo_name']], - data['target']) - run_ffx_command(['repository', 'remove', data['repo_name']]) - run_ffx_command(['repository', 'server', 'stop']) + data['target'], + check=False) + run_ffx_command(['repository', 'remove', data['repo_name']], check=False) + run_ffx_command(['repository', 'server', 'stop'], check=False) os.remove(_REPO_CONFIG_FILE) def _start_serving(repo_dir: str, repo_name: str, target: str) -> None: """Start serving a repository. - Args: - repo_dir: directory the repository is served from. - repo_name: repository name. - target: Fuchsia device the repository is served to. - """ + + Args: + repo_dir: directory the repository is served from. + repo_name: repository name. + target: Fuchsia device the repository is served to. + """ if os.path.exists(_REPO_CONFIG_FILE): _stop_serving() - # Check ffx configs, restart daemon if necessary. - if _configure_ffx_serving(): + # Check ffx configs, restart daemon if the configuration was updated. + config_updated = False + config_updated |= _ensure_ffx_config('ffx_repository', 'true') + config_updated |= _ensure_ffx_config('repository.server.mode', '\"ffx\"') + if config_updated: run_ffx_command(['doctor', '--restart-daemon']) data = {} @@ -85,6 +82,7 @@ def register_serve_args(arg_parser: argparse.ArgumentParser) -> None: """Register common arguments for repository serving.""" + serve_args = arg_parser.add_argument_group('serve', 'repo serving arguments') serve_args.add_argument('--serve-repo', @@ -97,6 +95,7 @@ def run_serve_cmd(cmd: str, args: argparse.Namespace) -> None: """Helper for running serve commands.""" + if cmd == 'start': _start_serving(args.repo, args.repo_name, args.target_id) else: @@ -115,6 +114,7 @@ def main(): """Stand-alone function for serving a repository.""" + parser = argparse.ArgumentParser() parser.add_argument('cmd', choices=['start', 'stop'],
diff --git a/build/linux/unbundle/replace_gn_files.py b/build/linux/unbundle/replace_gn_files.py index 3a65f839..bc7e92a 100755 --- a/build/linux/unbundle/replace_gn_files.py +++ b/build/linux/unbundle/replace_gn_files.py
@@ -22,7 +22,7 @@ 'harfbuzz-ng': 'third_party/harfbuzz-ng/harfbuzz.gni', 'icu': 'third_party/icu/BUILD.gn', 'libdrm': 'third_party/libdrm/BUILD.gn', - 'libevent': 'base/third_party/libevent/BUILD.gn', + 'libevent': 'third_party/libevent/BUILD.gn', 'libjpeg': 'third_party/libjpeg.gni', 'libpng': 'third_party/libpng/BUILD.gn', 'libvpx': 'third_party/libvpx/BUILD.gn',
diff --git a/cc/paint/paint_filter.cc b/cc/paint/paint_filter.cc index 705aa95..9be014d 100644 --- a/cc/paint/paint_filter.cc +++ b/cc/paint/paint_filter.cc
@@ -1022,12 +1022,11 @@ // after PaintShader::CreateScaledPaintRecord. SkRect scaled_record_bounds = PaintRecord::GetFixedScaleBounds(ctm, record_bounds_, max_texture_size); - if (scaled_record_bounds.isEmpty()) - return nullptr; - gfx::SizeF raster_scale = { scaled_record_bounds.width() / record_bounds_.width(), scaled_record_bounds.height() / record_bounds_.height()}; + if (raster_scale.IsEmpty()) + return nullptr; return sk_make_sp<RecordPaintFilter>(record_, scaled_record_bounds, raster_scale,
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index f90a117..045a52d1 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -2462,13 +2462,13 @@ ] } -# Similar to chrome_public_base_module_java but for Java libraries that go into -# the public chrome test APK. -java_group("chrome_public_base_module_java_for_test") { +# Exists separately from chrome_public_base_module_java_for_test to allow +# downstream to depend on test support packages without needing to depend on +# delegate_public_impl_java. +java_group("chrome_public_base_module_java_test_support") { testonly = true deps = [ ":browser_java_test_support", - ":chrome_public_base_module_java", ":chrome_test_util_java", "//chrome/android/features/autofill_assistant:autofill_assistant_java_test_support", "//chrome/browser/android/metrics:ukm_java_test_support", @@ -2481,6 +2481,16 @@ ] } +# Similar to chrome_public_base_module_java but for Java libraries that go into +# the public chrome test APK. +java_group("chrome_public_base_module_java_for_test") { + testonly = true + deps = [ + ":chrome_public_base_module_java", + ":chrome_public_base_module_java_test_support", + ] +} + # Dependencies that are common to any chrome_public derivative targets. _chrome_public_shared_deps = [ ":chrome_public_apk_base_module_resources",
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java index f38575c..566c3ad 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -64,7 +64,6 @@ import org.chromium.chrome.test.util.browser.Features; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.ui.KeyboardVisibilityDelegate; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -186,7 +185,8 @@ ContextUtils.getApplicationContext())) { mTabSelectionEditorController = null; } - mActivity = Robolectric.buildActivity(TestActivity.class).get(); + mActivity = Robolectric.buildActivity(Activity.class).get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); mModel = new PropertyModel(TabGridPanelProperties.ALL_KEYS); mMediator = new TabGridDialogMediator(mActivity, mDialogController, mModel, mTabModelSelector, mTabCreatorManager, mTabSwitcherResetHandler,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java index 2eae8479..313c6f1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -82,11 +82,11 @@ */ int IS_TRANSLATION_DISABLED = 0; /** + * @deprecated * Whether detection of device-online should be disabled (default false). * (safety switch for disabling online-detection also used to disable detection when * running tests). */ - // TODO(donnd): Convert to test-only after launch and we have confidence it's robust. int IS_ONLINE_DETECTION_DISABLED = 1; /** @deprecated */ @@ -189,14 +189,12 @@ } @VisibleForTesting - static final String ONLINE_DETECTION_DISABLED = "disable_online_detection"; - @VisibleForTesting static final String TRANSLATION_DISABLED = "disable_translation"; // Indexed by ContextualSearchSwitch private static final String[] ContextualSearchSwitchNames = { TRANSLATION_DISABLED, // IS_TRANSLATION_DISABLED - ONLINE_DETECTION_DISABLED, // IS_ONLINE_DETECTION_DISABLED + "disable_online_detection", // IS_ONLINE_DETECTION_DISABLED "disable_search_term_resolution", // DISABLE_SEARCH_TERM_RESOLUTION "mandatory_promo_enabled", // IS_MANDATORY_PROMO_ENABLED "enable_english_target_translation", // IS_ENGLISH_TARGET_TRANSLATION_ENABLED
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java index 7172a26e..8be98e5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
@@ -16,8 +16,8 @@ import org.chromium.base.supplier.ObservableSupplier; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason; -import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch; import org.chromium.chrome.browser.firstrun.FirstRunStatus; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; @@ -330,8 +330,8 @@ /** @return Whether the device is online, or we have disabled online-detection. */ private boolean isDeviceOnline(ContextualSearchManager manager) { - return ContextualSearchFieldTrial.getSwitch( - ContextualSearchSwitch.IS_ONLINE_DETECTION_DISABLED) + return ChromeFeatureList.isEnabled( + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION) ? true : manager.isDeviceOnline(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java index ec1e041..ce9306d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java
@@ -287,7 +287,11 @@ public void onPictureInPictureModeChanged( boolean isInPictureInPictureMode, Configuration newConfig) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); - if (!isInPictureInPictureMode) this.finish(); + if (isInPictureInPictureMode) return; + if (sNativeOverlayWindowAndroid != 0) { + PictureInPictureActivityJni.get().onBackToTab(sNativeOverlayWindowAndroid); + } + this.finish(); } @Override @@ -462,5 +466,6 @@ void compositorViewCreated(long nativeOverlayWindowAndroid, CompositorView compositorView); void onViewSizeChanged(long nativeOverlayWindowAndroid, int width, int height); + void onBackToTab(long nativeOverlayWindowAndroid); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java index 6d879d0..d6bbd28 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchCriticalTest.java
@@ -21,8 +21,10 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIf; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.content_public.browser.WebContents; @@ -35,7 +37,7 @@ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED}) + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @Batch(Batch.PER_CLASS) public class ContextualSearchCriticalTest extends ContextualSearchInstrumentationBase { @@ -329,6 +331,7 @@ * Tests that chained searches load correctly. */ @Test + @DisabledTest(message = "crbug.com/549805") @SmallTest @Feature({"ContextualSearch"}) @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) @@ -355,7 +358,7 @@ waitToPreventDoubleTapRecognition(); // Now simulate a non-resolve search, leaving the Panel peeking. - simulateNonResolveSearchByLongPress("resolution"); + simulateNonResolveSearch("resolution"); // Expanding the Panel should load and display the new search. expandPanelAndAssert(); @@ -378,7 +381,11 @@ @Test @SmallTest @Feature({"ContextualSearch"}) - public void testChainedSearchContentVisibility() throws Exception { + // Previously flaky and disabled 4/2021. https://crbug.com/1192285 + @DisabledTest( + message = "TODO:donnd fix and reeenable once expanding resolve works for base tests.") + public void + testChainedSearchContentVisibility() throws Exception { // Chained searches are tap-triggered very close to existing tap-triggered searches. FeatureList.setTestFeatures(ENABLE_NONE); @@ -391,7 +398,7 @@ waitToPreventDoubleTapRecognition(); // Now simulate a non-resolve search, leaving the Panel peeking. - simulateNonResolveSearchByLongPress("resolution"); + simulateNonResolveSearch("resolution"); assertNeverCalledWebContentsOnShow(); Assert.assertEquals(1, mFakeServer.getLoadedUrlCount());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java index 64b27cb2..16f8340 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFakeServer.java
@@ -84,12 +84,6 @@ void triggerResolve(String nodeId) throws TimeoutException; /** - * Simulates a long press trigger on the given node and waits for the panel to peek. - * @param nodeId A string containing the node ID. - */ - void triggerLongPress(String nodeId) throws TimeoutException; - - /** * Waits for the selected text string to be the given string, and asserts. * @param text The string to wait for the selection to become. */ @@ -172,14 +166,6 @@ public abstract void simulate() throws InterruptedException, TimeoutException; /** - * Simulates a fake search by long press. - * - * @throws InterruptedException - * @throws TimeoutException - */ - public abstract void simulateLongPress() throws InterruptedException, TimeoutException; - - /** * @return The search term that will be used in the contextual search. */ public abstract String getSearchTerm(); @@ -220,15 +206,6 @@ } @Override - public void simulateLongPress() throws InterruptedException, TimeoutException { - boolean previousOptedInState = mPolicy.overrideDecidedStateForTesting(false); - - mTestHost.triggerLongPress(getNodeId()); - mTestHost.waitForSelectionToBe(mSearchTerm); - mPolicy.overrideDecidedStateForTesting(previousOptedInState); - } - - @Override public String getSearchTerm() { return mSearchTerm; } @@ -313,35 +290,6 @@ } @Override - public void simulateLongPress() throws InterruptedException, TimeoutException { - mActiveResolveSearch = this; - - // When a resolution is needed, the simulation does not start until the system - // requests one, and it does not finish until the simulated resolution happens. - mDidStartResolution = false; - mDidFinishResolution = false; - - boolean previousOptedInState = - mPolicy.overrideDecidedStateForTesting(mPolicy.shouldPreviousGestureResolve()); - mTestHost.triggerLongPress(getNodeId()); - mTestHost.waitForSelectionToBe(getSearchTerm()); - mPolicy.overrideDecidedStateForTesting(previousOptedInState); - - if (mPolicy.shouldPreviousGestureResolve()) { - // Now wait for the Search Term Resolution to start. - mTestHost.waitForSearchTermResolutionToStart(this); - - // Simulate a Search Term Resolution. - simulateSearchTermResolution(); - - // Now wait for the simulated Search Term Resolution to finish. - mTestHost.waitForSearchTermResolutionToFinish(this); - } else { - mDidFinishResolution = true; - } - } - - @Override public String getSearchTerm() { return mResolvedSearchTerm.searchTerm(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java index 6c022ecb..09269e3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationBase.java
@@ -525,11 +525,6 @@ } @Override - public void triggerLongPress(String nodeId) throws TimeoutException { - longPressNode(nodeId); - } - - @Override public void waitForSelectionToBe(final String text) { CriteriaHelper.pollInstrumentationThread(() -> { Criteria.checkThat(getSelectedText(), Matchers.is(text)); @@ -652,14 +647,6 @@ } /** - * Simulates a long press trigger on the given node and waits for the panel to peek. - * @param nodeId A string containing the node ID. - */ - protected void triggerLongPress(String nodeId) throws TimeoutException { - mTestHost.triggerLongPress(nodeId); - } - - /** * Waits for the selected text string to be the given string, and asserts. * @param text The string to wait for the selection to become. */ @@ -766,19 +753,6 @@ } /** - * Simulates a non-resolving search by long press. - * - * @param nodeId The id of the node to be triggered. - */ - protected void simulateNonResolveSearchByLongPress(String nodeId) - throws InterruptedException, TimeoutException { - ContextualSearchFakeServer.FakeNonResolveSearch search = - mFakeServer.getFakeNonResolveSearch(nodeId); - search.simulateLongPress(); - waitForPanelToPeek(); - } - - /** * Simulates a resolve-triggering search. * * @param nodeId The id of the node to be tapped.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java index d152237..6fc5c51 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchInstrumentationTest.java
@@ -32,7 +32,7 @@ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED, + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION, "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + "," + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index 516e9ed..e77f807 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -94,7 +94,7 @@ @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) // NOTE: Disable online detection so we we'll default to online on test bots with no network. @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED, + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION, "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + "," + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java index 81347f04..d85109da 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchObserverTest.java
@@ -34,7 +34,7 @@ @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) // NOTE: Disable online detection so we we'll default to online on test bots with no network. @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED, + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION, "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + "," + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java index 13ae139..3a8bde8c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java
@@ -38,7 +38,7 @@ @RunWith(BaseJUnit4ClassRunner.class) // NOTE: Disable online detection so we we'll default to online on test bots with no network. @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED}) + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @Batch(Batch.PER_CLASS) public class ContextualSearchRelatedSearchesTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java index a61f7cf..e668ed1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSystemTest.java
@@ -45,7 +45,7 @@ @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) // NOTE: Disable online detection so we we'll default to online on test bots with no network. @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED, + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION, "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + "," + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java index a7ac57d..fd80196 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTriggerTest.java
@@ -41,7 +41,7 @@ @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) // NOTE: Disable online detection so we we'll default to online on test bots with no network. @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED}) + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @Batch(Batch.PER_CLASS) public class ContextualSearchTriggerTest extends ContextualSearchInstrumentationBase {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java index a455e8f1..b69e600 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUnbatchedTest.java
@@ -18,6 +18,7 @@ import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.RelatedSearchesControl; @@ -34,10 +35,12 @@ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ContextualSearchFieldTrial.ONLINE_DETECTION_DISABLED, + ChromeFeatureList.CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION, "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION + "," + ChromeFeatureList.CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) +// TODO(crbug.com/1338223):update the tests to be batched. +@DoNotBatch(reason = "Tests cannot runn batched due to RecordHistogram#forgetHistogram method.") public class ContextualSearchUnbatchedTest extends ContextualSearchInstrumentationBase { @Override @Before
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java index 7c58d36..8c6bb9e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java
@@ -186,6 +186,7 @@ @Test @MediumTest @EnableFeatures({ChromeFeatureList.READER_MODE_IN_CCT, ChromeFeatureList.CCT_INCOGNITO}) + @DisabledTest(message = "https://crbug.com/1338273") public void testCloseAllIncognitoNotification_ClosesCCT() throws PendingIntent.CanceledException, TimeoutException { CustomTabActivity customTabActivity = openReaderModeInIncognitoCCT();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java index e4f173d..a3b6b18 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java
@@ -11,6 +11,7 @@ import android.app.Activity; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; @@ -140,6 +141,19 @@ Assert.assertTrue(mBounds == null); } + @Test + @MediumTest + @MinAndroidSdkLevel(Build.VERSION_CODES.O) + public void testExitOnBackToTab() throws Throwable { + PictureInPictureActivity activity = startPictureInPictureActivity(); + Configuration newConfig = activity.getResources().getConfiguration(); + testExitOn(activity, + () + -> activity.onPictureInPictureModeChanged( + /*isInPictureInPictureMode=*/false, newConfig)); + verify(mNativeMock, times(1)).onBackToTab(NATIVE_OVERLAY); + } + private WebContents getWebContents() { return mActivityTestRule.getActivity().getCurrentWebContents(); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ChromeActivityUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ChromeActivityUnitTest.java index fa35835..e80635e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ChromeActivityUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ChromeActivityUnitTest.java
@@ -16,11 +16,11 @@ import org.robolectric.Robolectric; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.ui.BottomContainer; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; -import org.chromium.ui.base.TestActivity; /** * Unit tests for ChromeActivity. @@ -31,7 +31,8 @@ @Before public void setup() { - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java index 646be1d..9040bc62 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinatorTest.java
@@ -52,7 +52,6 @@ import org.chromium.components.embedder_support.contextmenu.ContextMenuParams; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.ContentFeatures; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.base.ViewAndroidDelegate; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.dragdrop.DragStateTracker; @@ -143,7 +142,8 @@ @Before public void setUpTest() { - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); mCoordinator = new ContextMenuCoordinator(TOP_CONTENT_OFFSET_PX, mNativeDelegate); MockitoAnnotations.initMocks(this); mocker.mock(PerformanceHintsObserverJni.TEST_HOOKS, mNativeMock);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderMediatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderMediatorTest.java index 17f75f57..7cc0741 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderMediatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderMediatorTest.java
@@ -33,6 +33,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.blink_public.common.ContextMenuDataMediaType; +import org.chromium.chrome.R; import org.chromium.chrome.browser.performance_hints.PerformanceHintsObserver; import org.chromium.chrome.browser.performance_hints.PerformanceHintsObserver.PerformanceClass; import org.chromium.chrome.browser.performance_hints.PerformanceHintsObserverJni; @@ -41,7 +42,6 @@ import org.chromium.components.embedder_support.contextmenu.ContextMenuParams; import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.favicon.LargeIconBridgeJni; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -73,7 +73,8 @@ @Before public void setUpTest() { - mActivity = Robolectric.setupActivity(TestActivity.class); + mActivity = Robolectric.setupActivity(Activity.class); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); MockitoAnnotations.initMocks(this); mocker.mock(PerformanceHintsObserverJni.TEST_HOOKS, mMockPerformanceHintsObserverJni); mocker.mock(LargeIconBridgeJni.TEST_HOOKS, mMockLargeIconBridgeJni);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/TileRendererTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/TileRendererTest.java index dbc9820..5d08e190 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/TileRendererTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/TileRendererTest.java
@@ -28,6 +28,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; +import org.robolectric.android.controller.ActivityController; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowDrawable; @@ -46,7 +47,6 @@ import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.testing.local.LocalRobolectricTestRunner; -import org.chromium.ui.base.TestActivity; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -102,6 +102,7 @@ private ColorStateList mFakeColorStateList; private ShadowPostTaskImpl mPostTaskRunner; + private ActivityController<Activity> mActivityController; private Activity mActivity; private LinearLayout mSharedParent; private final ArgumentCaptor<Drawable> mIconCaptor = ArgumentCaptor.forClass(Drawable.class); @@ -113,7 +114,10 @@ @Before public void setUp() { MockitoAnnotations.initMocks(this); - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivityController = Robolectric.buildActivity(Activity.class); + mActivityController.setup(); + mActivity = mActivityController.get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); mPostTaskRunner = new ShadowPostTaskImpl(); ShadowPostTask.setTestImpl(mPostTaskRunner);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java index 8b15c51..eee86b6b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/usage_stats/PageViewObserverTest.java
@@ -36,6 +36,7 @@ import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.Supplier; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; import org.chromium.chrome.browser.tab.Tab; @@ -45,7 +46,6 @@ import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tab.TabViewManager; import org.chromium.chrome.browser.tab.TabViewProvider; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.base.WindowAndroid; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -119,7 +119,8 @@ mDestroyedUserDataHost = new UserDataHost(); mDestroyedUserDataHost.destroy(); - Activity activity = Robolectric.buildActivity(TestActivity.class).get(); + Activity activity = Robolectric.buildActivity(Activity.class).get(); + activity.setTheme(R.style.Theme_BrowserUI_DayNight); doReturn(false).when(mTab).isIncognito(); doReturn(null).when(mTab).getUrl();
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 2ee3e0c1..a64782b 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -329,6 +329,8 @@ "component_updater/chrome_component_updater_configurator.h", "component_updater/chrome_origin_trials_component_installer.cc", "component_updater/chrome_origin_trials_component_installer.h", + "component_updater/commerce_heuristics_component_installer.cc", + "component_updater/commerce_heuristics_component_installer.h", "component_updater/component_updater_prefs.cc", "component_updater/component_updater_prefs.h", "component_updater/component_updater_utils.cc", @@ -1270,6 +1272,8 @@ "prefetch/prefetch_headers.h", "prefetch/prefetch_prefs.cc", "prefetch/prefetch_prefs.h", + "prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc", + "prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h", "prefetch/prefetch_proxy/chrome_speculation_host_delegate.cc", "prefetch/prefetch_proxy/chrome_speculation_host_delegate.h", "prefetch/prefetch_proxy/prefetch_container.cc", @@ -2010,8 +2014,6 @@ "//chrome/browser/ui/webui/realbox:mojo_bindings", "//chrome/browser/ui/webui/reset_password:mojo_bindings", "//chrome/browser/ui/webui/segmentation_internals:mojo_bindings", - "//chrome/browser/ui/webui/side_panel/bookmarks:mojo_bindings", - "//chrome/browser/ui/webui/side_panel/reading_list:mojo_bindings", "//chrome/browser/ui/webui/tab_search:mojo_bindings", "//chrome/browser/ui/webui/usb_internals:mojo_bindings", "//chrome/browser/updates/announcement_notification", @@ -3576,8 +3578,6 @@ "commerce/coupons/coupon_service_factory.cc", "commerce/coupons/coupon_service_factory.h", "commerce/coupons/coupon_service_observer.h", - "component_updater/commerce_heuristics_component_installer.cc", - "component_updater/commerce_heuristics_component_installer.h", "component_updater/desktop_screenshot_editor_component_installer.cc", "component_updater/desktop_screenshot_editor_component_installer.h", "component_updater/desktop_sharing_hub_component_installer.cc", @@ -4389,6 +4389,8 @@ "//chrome/browser/ui/webui/image_editor:mojo_bindings", "//chrome/browser/ui/webui/new_tab_page:mojo_bindings", "//chrome/browser/ui/webui/new_tab_page_third_party:mojo_bindings", + "//chrome/browser/ui/webui/side_panel/bookmarks:mojo_bindings", + "//chrome/browser/ui/webui/side_panel/reading_list:mojo_bindings", "//chrome/browser/ui/webui/tab_strip:mojo_bindings", "//chrome/browser/web_applications", "//chrome/browser/web_applications/adjustments",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 17112a6..523f792 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -7223,11 +7223,6 @@ flag_descriptions::kForceShowContinueSectionName, flag_descriptions::kForceShowContinueSectionDescription, kOsCrOS, FEATURE_VALUE_TYPE(app_list_features::kForceShowContinueSection)}, - {"launcher-feedback-on-continue-section-remove", - flag_descriptions::kLauncherFeedbackOnContinueSectionRemoveName, - flag_descriptions::kLauncherFeedbackOnContinueSectionRemoveDescription, - kOsCrOS, - FEATURE_VALUE_TYPE(app_list_features::kFeedbackOnContinueSectionRemove)}, {"launcher-game-search", flag_descriptions::kLauncherGameSearchName, flag_descriptions::kLauncherGameSearchDescription, kOsCrOS, FEATURE_VALUE_TYPE(search_features::kLauncherGameSearch)},
diff --git a/chrome/browser/ash/file_manager/file_manager_jstest_base.cc b/chrome/browser/ash/file_manager/file_manager_jstest_base.cc index 5c430466..9bc3ea97 100644 --- a/chrome/browser/ash/file_manager/file_manager_jstest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_jstest_base.cc
@@ -58,14 +58,14 @@ // generated HTML to run see js_test_gen_html.py. source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, - "script-src chrome://resources chrome://webui-test chrome://test " + "script-src chrome://resources chrome://webui-test " "'self' chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj " "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp " "'unsafe-inline'; "); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrcElem, - "script-src chrome://resources chrome://webui-test chrome://test " + "script-src chrome://resources chrome://webui-test " "'self' chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj " "chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp " "'unsafe-inline'; ");
diff --git a/chrome/browser/ash/login/demo_mode/demo_resources.cc b/chrome/browser/ash/login/demo_mode/demo_resources.cc index 76e53bb..1d4c047 100644 --- a/chrome/browser/ash/login/demo_mode/demo_resources.cc +++ b/chrome/browser/ash/login/demo_mode/demo_resources.cc
@@ -4,10 +4,12 @@ #include "chrome/browser/ash/login/demo_mode/demo_resources.h" +#include "ash/constants/ash_features.h" #include "ash/constants/ash_paths.h" #include "base/bind.h" #include "base/callback.h" #include "base/check_op.h" +#include "base/files/file_path.h" #include "base/path_service.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" @@ -92,6 +94,13 @@ // CrOSComponentManager. DCHECK(cros_component_manager); + if (ash::features::IsDemoModeSWAEnabled()) { + // Skip the load of Chrome Apps when SWA enabled and mark them as loaded. + InstalledComponentLoaded( + component_updater::CrOSComponentManager::Error::NONE, base::FilePath()); + return; + } + cros_component_manager->Load( kDemoModeResourcesComponentName, component_updater::CrOSComponentManager::MountPolicy::kMount,
diff --git a/chrome/browser/ash/login/demo_mode/demo_session.cc b/chrome/browser/ash/login/demo_mode/demo_session.cc index 1a09ade..300d9947 100644 --- a/chrome/browser/ash/login/demo_mode/demo_session.cc +++ b/chrome/browser/ash/login/demo_mode/demo_session.cc
@@ -430,7 +430,14 @@ void DemoSession::SetExtensionsExternalLoader( scoped_refptr<DemoExtensionsExternalLoader> extensions_external_loader) { extensions_external_loader_ = extensions_external_loader; - InstallAppFromUpdateUrl(GetScreensaverAppId()); + if (!ash::features::IsDemoModeSWAEnabled() || + extension_misc::IsDemoModeChromeApp(GetScreensaverAppId())) { + // Do app installation when one of the following condition holds: + // 1. Demo Mode SWA is NOT enabled, OR + // 2. Demo Mode SWA is enabled but the app ID to be installed is NOT + // one of the Demo Mode app IDs. + InstallAppFromUpdateUrl(GetScreensaverAppId()); + } } void DemoSession::OverrideIgnorePinPolicyAppsForTesting( @@ -549,7 +556,14 @@ } RestoreDefaultLocaleForNextSession(); - InstallAppFromUpdateUrl(GetHighlightsAppId()); + if (!ash::features::IsDemoModeSWAEnabled() || + extension_misc::IsDemoModeChromeApp(GetHighlightsAppId())) { + // Do app installation when one of the following condition holds: + // 1. Demo Mode SWA is NOT enabled, OR + // 2. Demo Mode SWA is enabled but the app ID to be installed is NOT + // one of the Demo Mode app IDs. + InstallAppFromUpdateUrl(GetHighlightsAppId()); + } // Download/update the Demo app component during session startup if (features::IsDemoModeSWAEnabled()) {
diff --git a/chrome/browser/ash/printing/server_printers_fetcher.cc b/chrome/browser/ash/printing/server_printers_fetcher.cc index 6162f14..74094e6 100644 --- a/chrome/browser/ash/printing/server_printers_fetcher.cc +++ b/chrome/browser/ash/printing/server_printers_fetcher.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/profiles/profile.h" #include "components/device_event_log/device_event_log.h" #include "net/base/load_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" @@ -30,6 +31,32 @@ namespace { +constexpr net::NetworkTrafficAnnotationTag kServerPrintersFetcherNetworkTag = + net::DefineNetworkTrafficAnnotation("printing_server_printers_query", R"( + semantics { + sender: "ChromeOS Printers Manager" + description: + "Fetches the list of available printers from the Print Server." + trigger: "1. User asked for the list of available printers from " + "a chosen Print Server." + "2. ChromeOS automatically queries printers from Print " + "Servers whose addresses are set by the organization's " + "administrator at the Google admin console." + data: "None." + destination: OTHER + destination_other: "Print Server" + } + policy { + cookies_allowed: NO + setting: + "This feature is enabled as long as printing is enabled." + chrome_policy { + PrintingEnabled { + PrintingEnabled: false + } + } + })"); + std::string ServerPrinterId(const std::string& url) { base::MD5Context ctx; base::MD5Init(&ctx); @@ -168,7 +195,7 @@ resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; // TODO(pawliczek): create a traffic annotation for printing network traffic simple_url_loader_ = network::SimpleURLLoader::Create( - std::move(resource_request), MISSING_TRAFFIC_ANNOTATION); + std::move(resource_request), kServerPrintersFetcherNetworkTag); std::string request_body(request_frame.begin(), request_frame.end()); simple_url_loader_->AttachStringForUpload(request_body, "application/ipp"); simple_url_loader_->DownloadAsStream(
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index 0250e87..9b7af74 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -126,6 +126,7 @@ #include "content/public/browser/browsing_data_filter_builder.h" #include "content/public/browser/host_zoom_map.h" #include "content/public/browser/plugin_data_remover.h" +#include "content/public/browser/prefetch_service_delegate.h" #include "content/public/browser/ssl_host_state_delegate.h" #include "content/public/browser/storage_partition.h" #include "google_apis/gaia/gaia_urls.h" @@ -540,6 +541,8 @@ prefetch_proxy_service->origin_decider()->OnBrowsingDataCleared(); } + content::PrefetchServiceDelegate::ClearData(profile_); + #if BUILDFLAG(IS_ANDROID) OomInterventionDecider* oom_intervention_decider = OomInterventionDecider::GetForBrowserContext(profile_);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index a17c09e..9ead8957 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -87,6 +87,7 @@ #include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h" #include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_navigation_throttle.h" #include "chrome/browser/prefetch/prefetch_prefs.h" +#include "chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h" #include "chrome/browser/prefetch/prefetch_proxy/chrome_speculation_host_delegate.h" #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_features.h" #include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_service.h" @@ -6496,6 +6497,12 @@ return std::make_unique<ChromeSpeculationHostDelegate>(render_frame_host); } +std::unique_ptr<content::PrefetchServiceDelegate> +ChromeContentBrowserClient::CreatePrefetchServiceDelegate( + content::BrowserContext* browser_context) { + return std::make_unique<ChromePrefetchServiceDelegate>(browser_context); +} + void ChromeContentBrowserClient::OnWebContentsCreated( content::WebContents* web_contents) { // NOTE: Please don't add additional code to this method - attaching universal
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index d84961a..34baff2 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -780,9 +780,15 @@ bool SuppressDifferentOriginSubframeJSDialogs( content::BrowserContext* browser_context) override; + std::unique_ptr<content::SpeculationHostDelegate> CreateSpeculationHostDelegate( content::RenderFrameHost& render_frame_host) override; + + std::unique_ptr<content::PrefetchServiceDelegate> + CreatePrefetchServiceDelegate( + content::BrowserContext* browser_context) override; + void OnWebContentsCreated(content::WebContents* web_contents) override; bool IsFindInPageDisabledForOrigin(const url::Origin& origin) override;
diff --git a/chrome/browser/component_updater/commerce_heuristics_component_installer.cc b/chrome/browser/component_updater/commerce_heuristics_component_installer.cc index 155829a..f59e9a0 100644 --- a/chrome/browser/component_updater/commerce_heuristics_component_installer.cc +++ b/chrome/browser/component_updater/commerce_heuristics_component_installer.cc
@@ -18,7 +18,11 @@ #include "base/task/thread_pool.h" #include "components/commerce/core/commerce_heuristics_data.h" #include "components/component_updater/component_updater_paths.h" +#if !BUILDFLAG(IS_ANDROID) #include "components/search/ntp_features.h" +#else +#include "components/commerce/core/commerce_feature_list.h" +#endif namespace { @@ -182,7 +186,11 @@ void RegisterCommerceHeuristicsComponent( component_updater::ComponentUpdateService* cus) { +#if !BUILDFLAG(IS_ANDROID) if (base::FeatureList::IsEnabled(ntp_features::kNtpChromeCartModule)) { +#else + if (base::FeatureList::IsEnabled(commerce::kCommerceHintAndroid)) { +#endif VLOG(1) << "Registering Commerce Heuristics component."; auto installer = base::MakeRefCounted<ComponentInstaller>( std::make_unique<CommerceHeuristicsInstallerPolicy>());
diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc index bd90f50..fb84248 100644 --- a/chrome/browser/component_updater/registration.cc +++ b/chrome/browser/component_updater/registration.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/component_updater/autofill_regex_remover.h" #include "chrome/browser/component_updater/chrome_client_side_phishing_component_installer.h" #include "chrome/browser/component_updater/chrome_origin_trials_component_installer.h" +#include "chrome/browser/component_updater/commerce_heuristics_component_installer.h" #include "chrome/browser/component_updater/crl_set_component_installer.h" #include "chrome/browser/component_updater/crowd_deny_component_installer.h" #include "chrome/browser/component_updater/file_type_policies_component_installer.h" @@ -64,7 +65,6 @@ #endif // BUILDFLAG(IS_ANDROID) #if !BUILDFLAG(IS_ANDROID) -#include "chrome/browser/component_updater/commerce_heuristics_component_installer.h" #include "chrome/browser/component_updater/desktop_sharing_hub_component_installer.h" #include "chrome/browser/component_updater/zxcvbn_data_component_installer.h" #include "chrome/browser/resource_coordinator/tab_manager.h" @@ -207,7 +207,6 @@ #if !BUILDFLAG(IS_ANDROID) RegisterDesktopSharingHubComponent(cus); RegisterZxcvbnDataComponent(cus); - RegisterCommerceHeuristicsComponent(cus); #endif // !BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID) @@ -223,6 +222,7 @@ #endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) RegisterUrlParamClassificationComponent(cus); + RegisterCommerceHeuristicsComponent(cus); } } // namespace component_updater
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc index ff05b74..7c0b5df 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
@@ -248,8 +248,15 @@ // has been initialized by ShowWebModalDialogViews(). // We can't move it any earlier or it will crash when we try to get the // color from the widget. (see b/232104687) - if (!is_pending()) - UpdateDialog(); + // if (!is_pending()) + // UpdateDialog(); + + // TODO(crbug.com/1337078): Remove if this doesn't fix the CQ + if (is_warning() && bypass_requires_justification()) { + bypass_justification_text_length_->SetEnabledColor( + bypass_justification_text_length_->GetColorProvider()->GetColor( + ui::kColorAlertHighSeverity)); + } if (observer_for_testing) observer_for_testing->ViewsFirstShown(this, first_shown_timestamp_); @@ -373,6 +380,10 @@ message_->SetMultiLine(true); message_->SetVerticalAlignment(gfx::ALIGN_MIDDLE); message_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + + // TODO(crbug.com/1337078): Remove if this doesn't fix the CQ + if (!is_pending()) + UpdateDialog(); } return contents_view_; @@ -495,7 +506,7 @@ // lines after changing. auto height_after = contents_view_->GetPreferredSize().height(); int height_to_add = std::max(height_after - height_before, 0); - if (height_to_add > 0) + if (height_to_add > 0 && GetWidget()) Resize(height_to_add); // Update the dialog. @@ -866,10 +877,13 @@ base::NumberToString16(0), base::NumberToString16(kMaxBypassJustificationLength))); - // Set the color to red initially because a 0 length message is invalid - bypass_justification_text_length_->SetEnabledColor( - bypass_justification_text_length_->GetColorProvider()->GetColor( - ui::kColorAlertHighSeverity)); + // Set the color to red initially because a 0 length message is invalid. Skip + // this if the color provider is unavailable. + if (bypass_justification_text_length_->GetColorProvider()) { + bypass_justification_text_length_->SetEnabledColor( + bypass_justification_text_length_->GetColorProvider()->GetColor( + ui::kColorAlertHighSeverity)); + } } bool ContentAnalysisDialog::ShouldUseDarkTopImage() const {
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc index 182c152..490a57c3 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc
@@ -1085,13 +1085,7 @@ } }; -// Flaky on Windows, http://crbug.com/1337078 -#if BUILDFLAG(IS_WIN) -#define MAYBE_InvokeUi_default DISABLED_InvokeUi_default -#else -#define MAYBE_InvokeUi_default InvokeUi_default -#endif -IN_PROC_BROWSER_TEST_P(ContentAnalysysDialogUiTest, MAYBE_InvokeUi_default) { +IN_PROC_BROWSER_TEST_P(ContentAnalysysDialogUiTest, InvokeUi_default) { ShowAndVerifyUi(); }
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc index 418069eb..1580bc1 100644 --- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc +++ b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -686,6 +686,9 @@ ExtensionFunction::ResponseAction TerminalPrivateGetOSInfoFunction::Run() { base::DictionaryValue info; + info.SetBoolKey("alternative_renderer", + base::FeatureList::IsEnabled( + chromeos::features::kTerminalAlternativeRenderer)); info.SetBoolKey( "multi_profile", base::FeatureList::IsEnabled(chromeos::features::kTerminalMultiProfile));
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 60279d7..895daf2 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -100,6 +100,7 @@ #include "extensions/browser/updater/extension_cache.h" #include "extensions/browser/updater/extension_downloader.h" #include "extensions/browser/updater/manifest_fetch_data.h" +#include "extensions/common/constants.h" #include "extensions/common/extension_messages.h" #include "extensions/common/extension_urls.h" #include "extensions/common/features/feature_developer_mode_only.h" @@ -113,6 +114,7 @@ #include "extensions/common/switches.h" #if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_features.h" #include "base/system/sys_info.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/chromeos/extensions/install_limiter.h" @@ -1913,6 +1915,15 @@ return false; } +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (ash::features::IsDemoModeSWAEnabled()) { + if (extension_misc::IsDemoModeChromeApp(info.extension_id)) { + pending_extension_manager()->Remove(info.extension_id); + return true; + } + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + // no client (silent install) scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this)); installer->set_installer_callback(
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java index 74b694f..9728b24 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedFollowIntroControllerTest.java
@@ -39,6 +39,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.feed.test.R; import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; @@ -54,7 +55,6 @@ import org.chromium.components.prefs.PrefService; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.components.user_prefs.UserPrefsJni; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -119,8 +119,9 @@ Profile.setLastUsedProfileForTesting(mProfile); Mockito.when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); + mActivity = Robolectric.setupActivity(Activity.class); // Required for resolving an attribute used in AppMenuItemText. - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); mClock = new FakeClock(); when(mTracker.shouldTriggerHelpUI(FeatureConstants.IPH_WEB_FEED_FOLLOW_FEATURE)) .thenReturn(true);
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java index e518291..9308f8e 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedMainMenuItemTest.java
@@ -49,7 +49,6 @@ import org.chromium.components.embedder_support.util.ShadowUrlUtilities; import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.components.url_formatter.UrlFormatterJni; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.widget.LoadingView; import org.chromium.url.GURL; @@ -109,8 +108,9 @@ doReturn(GURL.emptyGURL()).when(mTab).getOriginalUrl(); doReturn(false).when(mTab).isShowingErrorPage(); + mActivity = Robolectric.setupActivity(Activity.class); // Required for resolving an attribute used in AppMenuItemText. - mActivity = Robolectric.setupActivity(TestActivity.class); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); // Add requests for web feed information to mWaitingMetadataCallbacks. doAnswer(invocation -> {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index c3a21b9..bc44710 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2779,7 +2779,7 @@ { "name": "enable-tab-groups-for-tablets", "owners": [ "skavuluru", "clank-app-team@google.com" ], - "expiry_milestone": 104 + "expiry_milestone": 114 }, { "name": "enable-tab-groups-ui-improvements", @@ -2794,7 +2794,7 @@ { "name": "enable-tab-strip-improvements", "owners": [ "skavuluru", "clank-app-team@google.com" ], - "expiry_milestone": 105 + "expiry_milestone": 114 }, { "name": "enable-tab-switcher-on-return", @@ -3515,7 +3515,7 @@ { "name": "grid-tab-switcher-for-tablets", "owners": [ "nemco", "clank-app-team@google.com" ], - "expiry_milestone": 104 + "expiry_milestone": 114 }, { "name": "guest-os-files", @@ -3962,11 +3962,6 @@ "expiry_milestone": 105 }, { - "name": "launcher-feedback-on-continue-section-remove", - "owners": ["anasalazar", "//ash/app_list/OWNERS"], - "expiry_milestone": 107 - }, - { "name": "launcher-game-search", "owners": ["wrong", "napper", "tby"], "expiry_milestone": 110
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 89deadf..882748d 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -5647,12 +5647,6 @@ const char kLauncherGameSearchDescription[] = "Enables cloud game search results in the launcher."; -const char kLauncherFeedbackOnContinueSectionRemoveName[] = - "Enable requesting for feedback on continue section suggestions"; -const char kLauncherFeedbackOnContinueSectionRemoveDescription[] = - "When enabled, if a user removes a continue section suggestion, a dialog " - "will appear on the launcher requesting feedback on the suggestions shown."; - const char kLauncherHideContinueSectionName[] = "Launcher hide continue section"; const char kLauncherHideContinueSectionDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index d00c8167..d94828b 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -3237,9 +3237,6 @@ extern const char kLauncherGameSearchName[]; extern const char kLauncherGameSearchDescription[]; -extern const char kLauncherFeedbackOnContinueSectionRemoveName[]; -extern const char kLauncherFeedbackOnContinueSectionRemoveDescription[]; - extern const char kLauncherHideContinueSectionName[]; extern const char kLauncherHideContinueSectionDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index d8bb63a..293ce4a1 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -210,6 +210,7 @@ &kContextMenuPopupStyle, &kContextualSearchDebug, &kContextualSearchDelayedIntelligence, + &kContextualSearchDisableOnlineDetection, &kContextualSearchForceCaption, &kContextualSearchMlTapSuppression, &kContextualSearchTapDisableOverride, @@ -588,6 +589,10 @@ const base::Feature kContextualSearchDelayedIntelligence{ "ContextualSearchDelayedIntelligence", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kContextualSearchDisableOnlineDetection{ + "ContextualSearchDisableOnlineDetection", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kContextualSearchForceCaption{ "ContextualSearchForceCaption", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 33221554..b9326af 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -70,6 +70,7 @@ extern const base::Feature kContextMenuTranslateWithGoogleLens; extern const base::Feature kContextualSearchDebug; extern const base::Feature kContextualSearchDelayedIntelligence; +extern const base::Feature kContextualSearchDisableOnlineDetection; extern const base::Feature kContextualSearchForceCaption; extern const base::Feature kContextualSearchMlTapSuppression; extern const base::Feature kContextualSearchTapDisableOverride;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index e603b96..6cf410e3 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -296,6 +296,8 @@ public static final String CONTEXTUAL_SEARCH_DEBUG = "ContextualSearchDebug"; public static final String CONTEXTUAL_SEARCH_DELAYED_INTELLIGENCE = "ContextualSearchDelayedIntelligence"; + public static final String CONTEXTUAL_SEARCH_DISABLE_ONLINE_DETECTION = + "ContextualSearchDisableOnlineDetection"; public static final String CONTEXTUAL_SEARCH_FORCE_CAPTION = "ContextualSearchForceCaption"; public static final String CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION = "ContextualSearchMlTapSuppression";
diff --git a/chrome/browser/metrics_settings/OWNERS b/chrome/browser/metrics_settings/OWNERS index b09a27b..81065f27 100644 --- a/chrome/browser/metrics_settings/OWNERS +++ b/chrome/browser/metrics_settings/OWNERS
@@ -1,2 +1 @@ -andzaytsev@google.com msramek@chromium.org
diff --git a/chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc b/chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc new file mode 100644 index 0000000..4506441 --- /dev/null +++ b/chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.cc
@@ -0,0 +1,84 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h" + +#include "chrome/browser/prefetch/prefetch_prefs.h" +#include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_origin_decider.h" +#include "chrome/browser/profiles/profile.h" +#include "components/google/core/common/google_util.h" +#include "components/language/core/browser/pref_names.h" +#include "components/prefs/pref_service.h" +#include "components/unified_consent/url_keyed_data_collection_consent_helper.h" +#include "components/version_info/version_info.h" +#include "content/public/browser/browser_context.h" +#include "google_apis/google_api_keys.h" +#include "net/http/http_util.h" +#include "url/gurl.h" + +ChromePrefetchServiceDelegate::ChromePrefetchServiceDelegate( + content::BrowserContext* browser_context) + : profile_(Profile::FromBrowserContext(browser_context)), + origin_decider_( + std::make_unique<PrefetchProxyOriginDecider>(profile_->GetPrefs())) {} + +ChromePrefetchServiceDelegate::~ChromePrefetchServiceDelegate() = default; + +std::string ChromePrefetchServiceDelegate::GetMajorVersionNumber() { + return version_info::GetMajorVersionNumber(); +} + +std::string ChromePrefetchServiceDelegate::GetAcceptLanguageHeader() { + return net::HttpUtil::GenerateAcceptLanguageHeader( + profile_->GetPrefs()->GetString(language::prefs::kAcceptLanguages)); +} + +GURL ChromePrefetchServiceDelegate::GetDefaultPrefetchProxyHost() { + return GURL("https://tunnel.googlezip.net/"); +} + +std::string ChromePrefetchServiceDelegate::GetAPIKey() { + return google_apis::GetAPIKey(); +} + +void ChromePrefetchServiceDelegate::ReportOriginRetryAfter( + const GURL& url, + base::TimeDelta retry_after) { + return origin_decider_->ReportOriginRetryAfter(url, retry_after); +} + +bool ChromePrefetchServiceDelegate::IsOriginOutsideRetryAfterWindow( + const GURL& url) { + return origin_decider_->IsOriginOutsideRetryAfterWindow(url); +} + +void ChromePrefetchServiceDelegate::ClearData() { + origin_decider_->OnBrowsingDataCleared(); +} + +bool ChromePrefetchServiceDelegate::DisableDecoysBasedOnUserSettings() { + // If the user has opted-in to Make Search and Browsing Better, then there is + // no need to send decoy requests. + std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper> helper = + unified_consent::UrlKeyedDataCollectionConsentHelper:: + NewAnonymizedDataCollectionConsentHelper(profile_->GetPrefs()); + return helper->IsEnabled(); +} + +bool ChromePrefetchServiceDelegate::IsSomePreloadingEnabled() { + return prefetch::IsSomePreloadingEnabled(*profile_->GetPrefs()); +} + +bool ChromePrefetchServiceDelegate::IsExtendedPreloadingEnabled() { + return prefetch::GetPreloadPagesState(*profile_->GetPrefs()) == + prefetch::PreloadPagesState::kExtendedPreloading; +} + +bool ChromePrefetchServiceDelegate::IsDomainInPrefetchAllowList( + const GURL& referring_url) { + return IsGoogleDomainUrl(referring_url, google_util::ALLOW_SUBDOMAIN, + google_util::ALLOW_NON_STANDARD_PORTS) || + IsYoutubeDomainUrl(referring_url, google_util::ALLOW_SUBDOMAIN, + google_util::ALLOW_NON_STANDARD_PORTS); +}
diff --git a/chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h b/chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h new file mode 100644 index 0000000..e005ddf --- /dev/null +++ b/chrome/browser/prefetch/prefetch_proxy/chrome_prefetch_service_delegate.h
@@ -0,0 +1,54 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_PREFETCH_PREFETCH_PROXY_CHROME_PREFETCH_SERVICE_DELEGATE_H_ +#define CHROME_BROWSER_PREFETCH_PREFETCH_PROXY_CHROME_PREFETCH_SERVICE_DELEGATE_H_ + +#include <string> + +#include "base/time/time.h" +#include "content/public/browser/prefetch_service_delegate.h" +#include "url/gurl.h" + +namespace content { +class BrowserContext; +} + +class Profile; +class PrefetchProxyOriginDecider; + +class ChromePrefetchServiceDelegate : public content::PrefetchServiceDelegate { + public: + explicit ChromePrefetchServiceDelegate( + content::BrowserContext* browser_context); + ~ChromePrefetchServiceDelegate() override; + + ChromePrefetchServiceDelegate(const ChromePrefetchServiceDelegate&) = delete; + ChromePrefetchServiceDelegate& operator=( + const ChromePrefetchServiceDelegate&) = delete; + + // content::PrefetchServiceDelegate + std::string GetMajorVersionNumber() override; + std::string GetAcceptLanguageHeader() override; + GURL GetDefaultPrefetchProxyHost() override; + std::string GetAPIKey() override; + void ReportOriginRetryAfter(const GURL& url, + base::TimeDelta retry_after) override; + bool IsOriginOutsideRetryAfterWindow(const GURL& url) override; + void ClearData() override; + bool DisableDecoysBasedOnUserSettings() override; + bool IsSomePreloadingEnabled() override; + bool IsExtendedPreloadingEnabled() override; + bool IsDomainInPrefetchAllowList(const GURL& referring_url) override; + + private: + // The profile that |this| is associated with. + raw_ptr<Profile> profile_; + + // Tracks "Retry-After" responses, and determines whether new prefetches are + // eligible based on those responses. + std::unique_ptr<PrefetchProxyOriginDecider> origin_decider_; +}; + +#endif // CHROME_BROWSER_PREFETCH_PREFETCH_PROXY_CHROME_PREFETCH_SERVICE_DELEGATE_H_
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn index 57b0d9c..9e4bd82 100644 --- a/chrome/browser/resources/chromeos/BUILD.gn +++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -24,6 +24,7 @@ "login:unconditional_resources", "multidevice_internals:resources", "network_ui:resources", + "notification_tester:resources", ] }
diff --git a/chrome/browser/resources/chromeos/notification_tester/BUILD.gn b/chrome/browser/resources/chromeos/notification_tester/BUILD.gn new file mode 100644 index 0000000..1c26ded --- /dev/null +++ b/chrome/browser/resources/chromeos/notification_tester/BUILD.gn
@@ -0,0 +1,61 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/grit/grit_rule.gni") +import("//tools/polymer/html_to_js.gni") +import("//ui/webui/resources/tools/generate_grd.gni") + +resources_grd_file = "$target_gen_dir/resources.grd" +generated_grdp_file = "$target_gen_dir/gen_resources.grdp" + +generate_grd("build_grd") { + grd_prefix = "notification_tester" + out_grd = resources_grd_file + input_files = [ "index.html" ] + input_files_base_dir = rebase_path(".", "//") + + grdp_files = [ generated_grdp_file ] + + deps = [ ":build_grdp" ] +} + +generate_grd("build_grdp") { + grd_prefix = "notification_tester" + out_grd = generated_grdp_file + input_files_base_dir = rebase_path(target_gen_dir, root_build_dir) + input_files = [ "notification_tester.js" ] +} + +grit("resources") { + enable_input_discovery_for_gn_analyze = false + source = resources_grd_file + deps = [ + ":build_grd", + ":web_components", + ] + outputs = [ + "grit/notification_tester_resources.h", + "grit/notification_tester_resources_map.cc", + "grit/notification_tester_resources_map.h", + "notification_tester_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" +} + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ ":notification_tester" ] +} + +js_library("notification_tester") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:cr.m", + ] +} + +html_to_js("web_components") { + js_files = [ "notification_tester.js" ] +}
diff --git a/chrome/browser/resources/chromeos/notification_tester/index.html b/chrome/browser/resources/chromeos/notification_tester/index.html index a300eae..30bb56a 100644 --- a/chrome/browser/resources/chromeos/notification_tester/index.html +++ b/chrome/browser/resources/chromeos/notification_tester/index.html
@@ -3,22 +3,18 @@ found in the LICENSE file. --> <!DOCTYPE HTML> -<html i18n-values="dir:textdirection"> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> <meta charset="utf-8"> <title>Notification Tester</title> - <script type="module" src="index.js"></script> + <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <script src="chrome://resources/js/cr.js"></script> - <script src="chrome://resources/js/load_time_data.js"></script> - <script src="chrome://resources/js/util.js"></script> - <script src="strings.js"></script> </head> <body> - <h1>Hello World</h1> - <p id="p1">test words</p> - <button type="button">Click Me!</button> + <notification-tester></notification-tester> + <script type="module" src="notification_tester.js"></script> </body> </html> \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/notification_tester/notification_tester.html b/chrome/browser/resources/chromeos/notification_tester/notification_tester.html new file mode 100644 index 0000000..bf0950eb --- /dev/null +++ b/chrome/browser/resources/chromeos/notification_tester/notification_tester.html
@@ -0,0 +1,101 @@ +<style> + :host { + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + } + + app-header { + background-color: rgb(0, 134, 179); + color: white; + font-size: 200%; + padding: 8px; + text-align: center; + } + + .input-field { + margin: 2.5% 5%; + } + + .input-field ol { + margin: 0 0 8px 0; + padding: 0 16px; + } + + .input-field ol>li { + align-items: center; + border-bottom: none; + display: flex; + padding: 0 0 8px 0; + } + + .label { + margin: 2px; + } +</style> +<app-header> + <app-toolbar>Notification Tester</app-toolbar> +</app-header> +<div class="input-field"> + <ol> + <h2> Visual Configuration </h2> + <li> + <label> Title + <select id="title"> + <option data-id="0" value="Sample Notification Title">Short sentence + (LTR)</option> + <option data-id="1" value="כותרת הודעה">Short sentence (RTL)</option> + <option data-id="2" + value="This is a very long notification title which is unncessarily long in order to increase it"> + Long sentence (LTR) </option> + <option data-id="3" + value="המבורגרים: אבן הפינה של כל ארוחת בוקר מזינה. צ'יזבורגר"> + Long sentence (RTL) + </option> + <option data-id="4" + value="sshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"> + Repetitive characters (LTR) + </option> + <option data-id="5" + value="שששששששששששששששששששששששששששששששששששששששששששששששששששש"> + Repetitive characters (RTL) + </option> + <option data-id="6" value="😁🚒❤😹🙋⌛❇🚅☎☺">Unicode smileys</option> + <option data-id="7" value="">Empty</option> + <option data-custom value="custom">Custom</option> + </select> + </label> + </li> + <li> + <label> Body + <select id="body"> + <option data-id="0" value="Notification content">One sentence (LTR) + </option> + <option data-id="1" value="תוכן הודעה">One sentence (RTL)</option> + <option data-id="2" + value="This is the notification's message. It may be able to stretch over multiple lines, or become visible when the notification is expanded by the user, depending on the notification center that's being used."> + Multiple sentences (LTR)</option> + <option data-id="3" + value="זהו המסר של ההודעה. זה עשוי להיות מסוגל למתוח על קווים מרובים, או להיות גלוי, כאשר ההודעה מורחבת על ידי המשתמש, בהתאם להודעה שהמרכז נמצא בשימוש"> + Multiple sentences (RTL)</option> + <option data-id="4" + value="sshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"> + Repetitive characters (LTR)</option> + <option data-id="5" + value="ששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששששש"> + Repetitive characters (RTL)</option> + <option data-id="6" value="🌇😃🍈😆🍜🍻😋⛅⛳😚">Unicode smileys + </option> + <option data-id="7" value="">Empty</option> + <option data-custom value="custom">Custom</option> + </select> + </label> + </li> + <li> + <button type="button" id="generateBtn" on-click="onClickGenerate_"> + Generate </button> + <button type="button" id="resetBtn"> Reset </button> + </li> + </ol> +</div> \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/notification_tester/notification_tester.js b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js new file mode 100644 index 0000000..3590c1b --- /dev/null +++ b/chrome/browser/resources/chromeos/notification_tester/notification_tester.js
@@ -0,0 +1,32 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +export class NotificationTester extends PolymerElement { + static get is() { + return 'notification-tester'; + } + + static get template() { + return html`{__html_template__}`; + } + + static get properties() { + return {}; + } + + onClickGenerate_() { + // Extract arguments from user selections. + const notifTitleElem = this.$.title; + const notifBodyElem = this.$.body; + const notifTitleValue = + notifTitleElem.options[notifTitleElem.selectedIndex].value; + const notifBodyValue = + notifBodyElem.options[notifBodyElem.selectedIndex].value; + chrome.send('generateNotificationForm', [notifTitleValue, notifBodyValue]); + } +} + +customElements.define(NotificationTester.is, NotificationTester); \ No newline at end of file
diff --git a/chrome/browser/resources/new_tab_page/realbox/icons/journeys.svg b/chrome/browser/resources/new_tab_page/realbox/icons/journeys.svg index 240dd90..81e790e 100644 --- a/chrome/browser/resources/new_tab_page/realbox/icons/journeys.svg +++ b/chrome/browser/resources/new_tab_page/realbox/icons/journeys.svg
@@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#5f6368"><path d="M19 21Q18.025 21 17.25 20.438Q16.475 19.875 16.175 19H11Q9.35 19 8.175 17.825Q7 16.65 7 15Q7 13.35 8.175 12.175Q9.35 11 11 11H13Q13.825 11 14.413 10.412Q15 9.825 15 9Q15 8.175 14.413 7.587Q13.825 7 13 7H7.825Q7.5 7.875 6.738 8.438Q5.975 9 5 9Q3.75 9 2.875 8.125Q2 7.25 2 6Q2 4.75 2.875 3.875Q3.75 3 5 3Q5.975 3 6.738 3.562Q7.5 4.125 7.825 5H13Q14.65 5 15.825 6.175Q17 7.35 17 9Q17 10.65 15.825 11.825Q14.65 13 13 13H11Q10.175 13 9.588 13.587Q9 14.175 9 15Q9 15.825 9.588 16.413Q10.175 17 11 17H16.175Q16.5 16.125 17.263 15.562Q18.025 15 19 15Q20.25 15 21.125 15.875Q22 16.75 22 18Q22 19.25 21.125 20.125Q20.25 21 19 21ZM5 7Q5.425 7 5.713 6.713Q6 6.425 6 6Q6 5.575 5.713 5.287Q5.425 5 5 5Q4.575 5 4.287 5.287Q4 5.575 4 6Q4 6.425 4.287 6.713Q4.575 7 5 7Z"/></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#5f6368"><path d="M19 21q-.975 0-1.75-.562-.775-.563-1.075-1.438H11q-1.65 0-2.825-1.175Q7 16.65 7 15q0-1.65 1.175-2.825Q9.35 11 11 11h2q.825 0 1.413-.588Q15 9.825 15 9t-.587-1.413Q13.825 7 13 7H7.825q-.325.875-1.087 1.438Q5.975 9 5 9q-1.25 0-2.125-.875T2 6q0-1.25.875-2.125T5 3q.975 0 1.738.562Q7.5 4.125 7.825 5H13q1.65 0 2.825 1.175Q17 7.35 17 9q0 1.65-1.175 2.825Q14.65 13 13 13h-2q-.825 0-1.412.587Q9 14.175 9 15q0 .825.588 1.413Q10.175 17 11 17h5.175q.325-.875 1.088-1.438Q18.025 15 19 15q1.25 0 2.125.875T22 18q0 1.25-.875 2.125T19 21ZM5 7q.425 0 .713-.287Q6 6.425 6 6t-.287-.713Q5.425 5 5 5t-.713.287Q4 5.575 4 6t.287.713Q4.575 7 5 7Z"/></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html index 7b3696b..5a633a61 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -15,6 +15,7 @@ <settings-live-caption prefs="{{prefs}}"></settings-live-caption> </template> <cr-link-row id="captions" + class="hr" label="$i18n{captionsPreferencesTitle}" sub-label="$i18n{captionsPreferencesSubtitle}" on-click="onCaptionsClick_" @@ -23,6 +24,7 @@ </template> <template is="dom-if" if="[[!captionSettingsOpensExternally_]]"> <cr-link-row id="captions" + class="hr" label="$i18n{captionsTitle}" on-click="onCaptionsClick_" role-description="$i18n{subpageArrowRoleDescription}">
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.html b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.html index 611337c1..5a210b0 100644 --- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.html +++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.html
@@ -51,7 +51,7 @@ aria-hidden="true"> </div> </div> - <template is="dom-repeat" items="[[allContainers_]]"> + <template is="dom-repeat" items="[[allContainers_]]" mutable-data> <div class="list-item"> <div class="start" aria-hidden="true"> [[item.id.container_name]]
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js index 2b0e22c..a97d814 100644 --- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js +++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_extra_containers.js
@@ -51,7 +51,10 @@ allContainers_: { type: Array, - value: [], + notify: true, + value() { + return []; + }, }, lastMenuContainerInfo_: { @@ -123,7 +126,7 @@ * @param {!Array<!ContainerInfo>} containerInfos */ onContainerInfo_(containerInfos) { - this.allContainers_ = containerInfos; + this.set('allContainers_', containerInfos); } /**
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java index 60bc2bc..621e8115 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.share.share_sheet; import android.app.Activity; -import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.text.TextUtils; @@ -13,16 +12,13 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import androidx.appcompat.content.res.AppCompatResources; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; -import org.chromium.base.ContextUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.supplier.Supplier; import org.chromium.base.task.PostTask; -import org.chromium.chrome.R; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -30,8 +26,6 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ChromeShareExtras; import org.chromium.chrome.browser.share.ChromeShareExtras.DetailedContentType; -import org.chromium.chrome.browser.share.ShareHelper; -import org.chromium.chrome.browser.share.ShareRankingBridge; import org.chromium.chrome.browser.share.link_to_text.LinkToTextCoordinator; import org.chromium.chrome.browser.share.link_to_text.LinkToTextCoordinator.LinkGeneration; import org.chromium.chrome.browser.share.link_to_text.LinkToTextMetricsHelper; @@ -55,11 +49,8 @@ import org.chromium.ui.modelutil.PropertyModel; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -69,15 +60,6 @@ public class ShareSheetCoordinator implements ActivityStateObserver, ChromeOptionShareCallback, ConfigurationChangedObserver, View.OnLayoutChangeListener { - // Knobs to allow for overriding the layout behavior of the share sheet row, - // as used for deciding how to rank share targets. These are here to allow - // tests not to depend on either the real physical dimensions of the test - // device or the real layout values, which are in the resource bundle and - // may vary depending on screen DPI. - public static int FORCED_SCREEN_WIDTH_FOR_TEST; - public static int FORCED_TILE_WIDTH_FOR_TEST; - public static int FORCED_TILE_MARGIN_FOR_TEST; - private final BottomSheetController mBottomSheetController; private final Supplier<Tab> mTabProvider; private final ShareSheetPropertyModelBuilder mPropertyModelBuilder; @@ -103,19 +85,11 @@ private ChromeShareExtras mChromeShareExtras; private LinkToTextCoordinator mLinkToTextCoordinator; private ShareSheetLinkToggleCoordinator mShareSheetLinkToggleCoordinator; + private ShareSheetUsageRankingHelper mShareSheetUsageRankingHelper; private @LinkGeneration int mLinkGenerationStatusForMetrics = LinkGeneration.MAX; private LinkToggleMetricsDetails mLinkToggleMetricsDetails = new LinkToggleMetricsDetails(LinkToggleState.COUNT, DetailedContentType.NOT_SPECIFIED); - // This same constant is used on the C++ side, in ShareRanking, to indicate - // the position of the special "More..." target. Don't change its value - // without also changing the C++ side. - private static final String MORE_TARGET_NAME = "$more"; - - // Don't log click indexes for usage-ranked items: the ordering is local to this client, so - // histogramming them would have no value. - private static final int NO_LOG_INDEX = -1; - /** * Constructs a new ShareSheetCoordinator. * @@ -334,27 +308,6 @@ && mTabProvider != null && mTabProvider.hasValue(); } - private PropertyModel createMorePropertyModel( - Activity activity, ShareParams params, boolean saveLastUsed) { - return ShareSheetPropertyModelBuilder.createPropertyModel( - AppCompatResources.getDrawable(activity, R.drawable.sharing_more), - activity.getResources().getString(R.string.sharing_more_icon_label), - /*accessibilityDescription=*/null, - (shareParams) - -> { - Profile profile = mProfileSupplier.get(); - recordShareMetrics("SharingHubAndroid.MoreSelected", - mLinkGenerationStatusForMetrics, mLinkToggleMetricsDetails, profile); - mBottomSheetController.hideContent(mBottomSheet, true); - ShareHelper.showDefaultShareUi(params, profile, saveLastUsed); - // Reset callback to prevent cancel() being called when the custom sheet is - // closed. The callback will be called by ShareHelper on actions from the - // default share UI. - params.setCallback(null); - }, - /*displayNew*/ false); - } - @VisibleForTesting void setDisableUsageRankingForTesting(boolean shouldDisableUsageRanking) { mDisableUsageRankingForTesting = shouldDisableUsageRanking; @@ -381,8 +334,12 @@ return; } + mShareSheetUsageRankingHelper = new ShareSheetUsageRankingHelper(mBottomSheetController, + mBottomSheet, mShareStartTime, mLinkGenerationStatusForMetrics, + mLinkToggleMetricsDetails, mPropertyModelBuilder, mProfileSupplier); + if (!mDisableUsageRankingForTesting) { - createThirdPartyPropertyModelsFromUsageRanking( + mShareSheetUsageRankingHelper.createThirdPartyPropertyModelsFromUsageRanking( activity, params, contentTypes, saveLastUsed, callback); return; } @@ -390,7 +347,8 @@ List<PropertyModel> models = mPropertyModelBuilder.selectThirdPartyApps(mBottomSheet, contentTypes, params, saveLastUsed, mShareStartTime, mLinkGenerationStatusForMetrics, mLinkToggleMetricsDetails); - models.add(createMorePropertyModel(activity, params, saveLastUsed)); + models.add(mShareSheetUsageRankingHelper.createMorePropertyModel( + activity, params, saveLastUsed)); PostTask.postTask(UiThreadTaskTraits.DEFAULT, callback.bind(models)); } @@ -402,122 +360,6 @@ } }; - private void createThirdPartyPropertyModelsFromUsageRanking(Activity activity, - ShareParams params, Set<Integer> contentTypes, boolean saveLastUsed, - Callback<List<PropertyModel>> callback) { - Profile profile = mProfileSupplier.get(); - assert profile != null; - - String type = contentTypesToTypeForRanking(contentTypes); - - PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); - - List<ResolveInfo> availableResolveInfos = - pm.queryIntentActivities(ShareHelper.getShareLinkAppCompatibilityIntent(), 0); - availableResolveInfos.addAll(pm.queryIntentActivities( - ShareHelper.createShareFileAppCompatibilityIntent(params.getFileContentType()), 0)); - - List<String> availableActivities = new ArrayList<String>(); - Map<String, ResolveInfo> resolveInfos = new HashMap<String, ResolveInfo>(); - - // The system can return ResolveInfos which refer to activities exported - // by Chrome - especially the Print activity. We don't want to offer - // these as "third party" targets, so filter them out. - availableResolveInfos = filterOutOwnResolveInfos(availableResolveInfos); - - // Sort the resolve infos by package name: on the backend, we store them by activity name, - // but there's no particular reason activity names would be unique, and when we get them - // from the system they're in arbitrary order. Here we sort them by package name (which *is* - // unique) so that the user always gets a consistent option in a given slot. - Collections.sort(availableResolveInfos, new ResolveInfoPackageNameComparator()); - - // Accumulate the ResolveInfos for every package available on the system, but do not - // construct their PropertyModels yet - there may be many packages but we will only show a - // handful of them, and constructing a PropertyModel involves multiple synchronous calls to - // the PackageManager which can be quite slow. - for (ResolveInfo r : availableResolveInfos) { - String name = r.activityInfo.packageName + "/" + r.activityInfo.name; - availableActivities.add(name); - resolveInfos.put(name, r); - } - - int fold = numberOf3PTilesThatFitOnScreen(activity); - int length = fold; - - // TODO(ellyjones): Does !saveLastUsed always imply that we shouldn't incorporate the share - // into our ranking? - boolean persist = !profile.isOffTheRecord() && saveLastUsed; - - ShareRankingBridge.rank( - profile, type, availableActivities, fold, length, persist, ranking -> { - onThirdPartyShareTargetsReceived( - callback, resolveInfos, activity, params, saveLastUsed, ranking); - }); - } - - // Returns a new list of ResovleInfos containing only the elements of the - // supplied list which are not references to activities from the current - // package. - private List<ResolveInfo> filterOutOwnResolveInfos(List<ResolveInfo> infos) { - String currentPackageName = ContextUtils.getApplicationContext().getPackageName(); - List<ResolveInfo> remaining = new ArrayList<ResolveInfo>(); - for (ResolveInfo info : infos) { - if (!info.activityInfo.packageName.equals(currentPackageName)) { - remaining.add(info); - } - } - return remaining; - } - private int numberOf3PTilesThatFitOnScreen(Activity activity) { - int screenWidth = FORCED_SCREEN_WIDTH_FOR_TEST != 0 ? FORCED_SCREEN_WIDTH_FOR_TEST - : ContextUtils.getApplicationContext() - .getResources() - .getDisplayMetrics() - .widthPixels; - int tileWidth = FORCED_TILE_WIDTH_FOR_TEST != 0 - ? FORCED_TILE_WIDTH_FOR_TEST - : activity.getResources().getDimensionPixelSize(R.dimen.sharing_hub_tile_width); - int tileMargin = FORCED_TILE_MARGIN_FOR_TEST != 0 - ? FORCED_TILE_MARGIN_FOR_TEST - : activity.getResources().getDimensionPixelSize(R.dimen.sharing_hub_tile_margin); - // In 'fix more' mode, ask for as many tiles as can fit; this will probably end up looking a - // bit strange since there will likely be an uneven amount of padding on the right edge. - // When not in that mode, the default is 10 tiles. - // - // Each tile has margin on both sides, so: - int tileVisualWidth = (2 * tileMargin) + tileWidth; - return (screenWidth - (2 * tileMargin)) / tileVisualWidth; - } - - private String contentTypesToTypeForRanking(Set<Integer> contentTypes) { - // TODO(ellyjones): Once we have field data, check whether the split into image vs not image - // is sufficient (i.e. is share ranking is performing well with a split this coarse). - if (contentTypes.contains(ShareSheetPropertyModelBuilder.ContentType.IMAGE)) { - return "image"; - } else { - return "other"; - } - } - - private void onThirdPartyShareTargetsReceived(Callback<List<PropertyModel>> callback, - Map<String, ResolveInfo> resolveInfos, Activity activity, ShareParams params, - boolean saveLastUsed, List<String> targets) { - // Build PropertyModels for all the ResolveInfos that correspond to - // actual targets, in the order that we're going to show them. - List<PropertyModel> models = new ArrayList<PropertyModel>(); - for (String target : targets) { - if (target.equals(MORE_TARGET_NAME)) { - models.add(createMorePropertyModel(activity, params, saveLastUsed)); - } else if (!target.equals("")) { - assert resolveInfos.get(target) != null; - models.add(mPropertyModelBuilder.buildThirdPartyAppModel(mBottomSheet, params, - resolveInfos.get(target), saveLastUsed, mShareStartTime, NO_LOG_INDEX, - mLinkGenerationStatusForMetrics, mLinkToggleMetricsDetails)); - } - } - PostTask.postTask(UiThreadTaskTraits.DEFAULT, callback.bind(models)); - } - static void recordShareMetrics(String featureName, @LinkGeneration int linkGenerationStatus, LinkToggleMetricsDetails linkToggleMetricsDetails, long shareStartTime, Profile profile) { @@ -624,5 +466,4 @@ mBottomSheet.getThirdPartyView().invalidate(); mBottomSheet.getThirdPartyView().requestLayout(); } - }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelper.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelper.java new file mode 100644 index 0000000..8058b69 --- /dev/null +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelper.java
@@ -0,0 +1,257 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.share.share_sheet; + +import android.app.Activity; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; + +import androidx.annotation.VisibleForTesting; +import androidx.appcompat.content.res.AppCompatResources; + +import org.chromium.base.Callback; +import org.chromium.base.ContextUtils; +import org.chromium.base.supplier.Supplier; +import org.chromium.base.task.PostTask; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.share.ShareHelper; +import org.chromium.chrome.browser.share.ShareRankingBridge; +import org.chromium.chrome.browser.share.link_to_text.LinkToTextCoordinator.LinkGeneration; +import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleMetricsHelper.LinkToggleMetricsDetails; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.share.ShareParams; +import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.ui.modelutil.PropertyModel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Helper class for ShareSheetCoordinator that hold Usage Ranking functions. + */ +public class ShareSheetUsageRankingHelper { + // Knobs to allow for overriding the layout behavior of the share sheet row, + // as used for deciding how to rank share targets. These are here to allow + // tests not to depend on either the real physical dimensions of the test + // device or the real layout values, which are in the resource bundle and + // may vary depending on screen DPI. + public static int FORCED_SCREEN_WIDTH_FOR_TEST; + public static int FORCED_TILE_WIDTH_FOR_TEST; + public static int FORCED_TILE_MARGIN_FOR_TEST; + + // This same constant is used on the C++ side, in ShareRanking, to indicate + // the position of the special "More..." target. Don't change its value + // without also changing the C++ side. + private static final String MORE_TARGET_NAME = "$more"; + + // Don't log click indexes for usage-ranked items: the ordering is local to this client, so + // histogramming them would have no value. + private static final int NO_LOG_INDEX = -1; + + private final BottomSheetController mBottomSheetController; + private final ShareSheetPropertyModelBuilder mPropertyModelBuilder; + private final Supplier<Profile> mProfileSupplier; + + private ShareSheetBottomSheetContent mBottomSheet; + private long mShareStartTime; + private @LinkGeneration int mLinkGenerationStatusForMetrics; + private LinkToggleMetricsDetails mLinkToggleMetricsDetails; + + // Variables used for testing + private boolean mDisableBridgeForTesting; + private List<String> mTargetsForTesting; + + /** + * Constructs a new ShareSheetUsageRankingHelper. + * + * @param bottomSheetController The {@link BottomSheetController} for the current activity. + * @param bottomSheet The bottomSheet for the current activity. + * @param shareStartTime The start time of the current share. + * @param linkGenerationStatusForMetrics User action of sharing text from failed link-to-text + * generation, sharing text from successful link-to-text generation, or sharing + * link-to-text. + * @param linkToggleMetricsDetails {@link LinkToggleMetricsDetails} to record link toggle + * metrics, and contains the {@link LinkToggleState} to update to. + * @param propertyModelBuilder The {@link ShareSheetPropertyModelBuilder} for the share sheet. + * @param profileSupplier A profile supplier to pull the current profile of the User. + */ + ShareSheetUsageRankingHelper(BottomSheetController bottomSheetController, + ShareSheetBottomSheetContent bottomSheet, long shareStartTime, + int linkGenerationStatusForMetrics, LinkToggleMetricsDetails linkToggleMetricsDetails, + ShareSheetPropertyModelBuilder propertyModelBuilder, + Supplier<Profile> profileSupplier) { + mBottomSheetController = bottomSheetController; + mPropertyModelBuilder = propertyModelBuilder; + mProfileSupplier = profileSupplier; + mBottomSheet = bottomSheet; + mShareStartTime = shareStartTime; + mLinkGenerationStatusForMetrics = linkGenerationStatusForMetrics; + mLinkToggleMetricsDetails = linkToggleMetricsDetails; + } + + @VisibleForTesting + void setTargetsForTesting(List<String> targets) { + mDisableBridgeForTesting = true; + mTargetsForTesting = targets; + } + + void createThirdPartyPropertyModelsFromUsageRanking(Activity activity, ShareParams params, + Set<Integer> contentTypes, boolean saveLastUsed, + Callback<List<PropertyModel>> callback) { + Profile profile = mProfileSupplier.get(); + assert profile != null; + + String type = contentTypesToTypeForRanking(contentTypes); + + PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); + + List<ResolveInfo> availableResolveInfos = + pm.queryIntentActivities(ShareHelper.getShareLinkAppCompatibilityIntent(), 0); + availableResolveInfos.addAll(pm.queryIntentActivities( + ShareHelper.createShareFileAppCompatibilityIntent(params.getFileContentType()), 0)); + + List<String> availableActivities = new ArrayList<String>(); + Map<String, ResolveInfo> resolveInfos = new HashMap<String, ResolveInfo>(); + + // The system can return ResolveInfos which refer to activities exported + // by Chrome - especially the Print activity. We don't want to offer + // these as "third party" targets, so filter them out. + availableResolveInfos = filterOutOwnResolveInfos(availableResolveInfos); + + // Sort the resolve infos by package name: on the backend, we store them by activity name, + // but there's no particular reason activity names would be unique, and when we get them + // from the system they're in arbitrary order. Here we sort them by package name (which *is* + // unique) so that the user always gets a consistent option in a given slot. + Collections.sort(availableResolveInfos, new ResolveInfoPackageNameComparator()); + + // Accumulate the ResolveInfos for every package available on the system, but do not + // construct their PropertyModels yet - there may be many packages but we will only show a + // handful of them, and constructing a PropertyModel involves multiple synchronous calls to + // the PackageManager which can be quite slow. + for (ResolveInfo r : availableResolveInfos) { + String name = r.activityInfo.packageName + "/" + r.activityInfo.name; + availableActivities.add(name); + resolveInfos.put(name, r); + } + + int fold = numberOf3PTilesThatFitOnScreen(activity); + int length = fold; + + if (mDisableBridgeForTesting) { + onThirdPartyShareTargetsReceived( + callback, resolveInfos, activity, params, saveLastUsed, mTargetsForTesting); + return; + } + + // TODO(ellyjones): Does !saveLastUsed always imply that we shouldn't incorporate the share + // into our ranking? + boolean persist = !profile.isOffTheRecord() && saveLastUsed; + + ShareRankingBridge.rank( + profile, type, availableActivities, fold, length, persist, ranking -> { + onThirdPartyShareTargetsReceived( + callback, resolveInfos, activity, params, saveLastUsed, ranking); + }); + } + + private String contentTypesToTypeForRanking(Set<Integer> contentTypes) { + // TODO(ellyjones): Once we have field data, check whether the split into image vs not image + // is sufficient (i.e. is share ranking is performing well with a split this coarse). + if (contentTypes.contains(ShareSheetPropertyModelBuilder.ContentType.IMAGE)) { + return "image"; + } else { + return "other"; + } + } + + // Returns a new list of ResovleInfos containing only the elements of the + // supplied list which are not references to activities from the current + // package. + private List<ResolveInfo> filterOutOwnResolveInfos(List<ResolveInfo> infos) { + String currentPackageName = ContextUtils.getApplicationContext().getPackageName(); + List<ResolveInfo> remaining = new ArrayList<ResolveInfo>(); + for (ResolveInfo info : infos) { + if (!info.activityInfo.packageName.equals(currentPackageName)) { + remaining.add(info); + } + } + return remaining; + } + + private int numberOf3PTilesThatFitOnScreen(Activity activity) { + int screenWidth = FORCED_SCREEN_WIDTH_FOR_TEST != 0 ? FORCED_SCREEN_WIDTH_FOR_TEST + : ContextUtils.getApplicationContext() + .getResources() + .getDisplayMetrics() + .widthPixels; + int tileWidth = FORCED_TILE_WIDTH_FOR_TEST != 0 + ? FORCED_TILE_WIDTH_FOR_TEST + : activity.getResources().getDimensionPixelSize(R.dimen.sharing_hub_tile_width); + int tileMargin = FORCED_TILE_MARGIN_FOR_TEST != 0 + ? FORCED_TILE_MARGIN_FOR_TEST + : activity.getResources().getDimensionPixelSize(R.dimen.sharing_hub_tile_margin); + // In 'fix more' mode, ask for as many tiles as can fit; this will probably end up looking a + // bit strange since there will likely be an uneven amount of padding on the right edge. + // When not in that mode, the default is 10 tiles. + // + // Each tile has margin on both sides, so: + int tileVisualWidth = (2 * tileMargin) + tileWidth; + return (screenWidth - (2 * tileMargin)) / tileVisualWidth; + } + + private void onThirdPartyShareTargetsReceived(Callback<List<PropertyModel>> callback, + Map<String, ResolveInfo> resolveInfos, Activity activity, ShareParams params, + boolean saveLastUsed, List<String> targets) { + // Build PropertyModels for all the ResolveInfos that correspond to + // actual targets, in the order that we're going to show them. + List<PropertyModel> models = new ArrayList<PropertyModel>(); + for (String target : targets) { + if (target.equals(MORE_TARGET_NAME)) { + models.add(createMorePropertyModel(activity, params, saveLastUsed)); + } else if (!target.equals("")) { + assert resolveInfos.get(target) != null; + models.add(mPropertyModelBuilder.buildThirdPartyAppModel(mBottomSheet, params, + resolveInfos.get(target), saveLastUsed, mShareStartTime, NO_LOG_INDEX, + mLinkGenerationStatusForMetrics, mLinkToggleMetricsDetails)); + } + } + PostTask.postTask(UiThreadTaskTraits.DEFAULT, callback.bind(models)); + } + + PropertyModel createMorePropertyModel( + Activity activity, ShareParams params, boolean saveLastUsed) { + return ShareSheetPropertyModelBuilder.createPropertyModel( + AppCompatResources.getDrawable(activity, R.drawable.sharing_more), + activity.getResources().getString(R.string.sharing_more_icon_label), + /*accessibilityDescription=*/null, + (shareParams) + -> { + Profile profile = mProfileSupplier.get(); + ShareSheetCoordinator.recordShareMetrics("SharingHubAndroid.MoreSelected", + mLinkGenerationStatusForMetrics, mLinkToggleMetricsDetails, + mShareStartTime, profile); + mBottomSheetController.hideContent(mBottomSheet, true); + ShareHelper.showDefaultShareUi(params, profile, saveLastUsed); + // Reset callback to prevent cancel() being called when the custom sheet is + // closed. The callback will be called by ShareHelper on actions from the + // default share UI. + params.setCallback(null); + }, + /*displayNew*/ false); + } + + static class ResolveInfoPackageNameComparator implements Comparator<ResolveInfo> { + @Override + public int compare(ResolveInfo a, ResolveInfo b) { + return a.activityInfo.packageName.compareTo(b.activityInfo.packageName); + } + }; +}
diff --git a/chrome/browser/share/android/java_sources.gni b/chrome/browser/share/android/java_sources.gni index 3827d812..31af648 100644 --- a/chrome/browser/share/android/java_sources.gni +++ b/chrome/browser/share/android/java_sources.gni
@@ -79,6 +79,7 @@ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetLinkToggleCoordinator.java", "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetLinkToggleMetricsHelper.java", "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java", + "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelper.java", ] share_java_deps = [
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java index 117ca84..b1fc975 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java
@@ -135,9 +135,9 @@ final int kTileVisualWidth = kTileWidth + 2 * kTileMargin; final int kScreenWidth = 4 * kTileVisualWidth + 2 * kTileMargin; - ShareSheetCoordinator.FORCED_TILE_WIDTH_FOR_TEST = kTileWidth; - ShareSheetCoordinator.FORCED_TILE_MARGIN_FOR_TEST = kTileMargin; - ShareSheetCoordinator.FORCED_SCREEN_WIDTH_FOR_TEST = kScreenWidth; + ShareSheetUsageRankingHelper.FORCED_TILE_WIDTH_FOR_TEST = kTileWidth; + ShareSheetUsageRankingHelper.FORCED_TILE_MARGIN_FOR_TEST = kTileMargin; + ShareSheetUsageRankingHelper.FORCED_SCREEN_WIDTH_FOR_TEST = kScreenWidth; } @Before
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelperTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelperTest.java new file mode 100644 index 0000000..6494900 --- /dev/null +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelperTest.java
@@ -0,0 +1,143 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.share.share_sheet; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +import android.app.Activity; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.annotation.LooperMode; + +import org.chromium.base.supplier.ObservableSupplierImpl; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.share.ChromeShareExtras.DetailedContentType; +import org.chromium.chrome.browser.share.link_to_text.LinkToTextCoordinator.LinkGeneration; +import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleCoordinator.LinkToggleState; +import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleMetricsHelper.LinkToggleMetricsDetails; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.share.ShareParams; +import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; +import org.chromium.components.dom_distiller.core.DomDistillerUrlUtilsJni; +import org.chromium.ui.base.WindowAndroid; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.url.JUnitTestGURLs; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Tests {@link ShareSheetUsageRankingHelper}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Features.EnableFeatures({ChromeFeatureList.PREEMPTIVE_LINK_TO_TEXT_GENERATION}) +@LooperMode(LooperMode.Mode.LEGACY) + +public class ShareSheetUsageRankingHelperTest { + private static final String MOCK_URL = JUnitTestGURLs.EXAMPLE_URL; + + @Rule + public TestRule mFeatureProcessor = new Features.JUnitProcessor(); + @Rule + public JniMocker mJniMocker = new JniMocker(); + + @Mock + private DomDistillerUrlUtils.Natives mDistillerUrlUtilsJniMock; + @Mock + private BottomSheetController mBottomSheetController; + @Mock + private ShareSheetBottomSheetContent mBottomSheet; + @Mock + private ShareSheetPropertyModelBuilder mPropertyModelBuilder; + @Mock + private Set<Integer> mContentTypes; + @Mock + private Profile mProfile; + @Mock + private ShareParams.TargetChosenCallback mTargetChosenCallback; + @Mock + private WindowAndroid mWindow; + + private Activity mActivity; + private ShareParams mParams; + private ShareSheetUsageRankingHelper mShareSheetUsageRankingHelper; + private ObservableSupplierImpl<Profile> mProfileSupplier; + private long mShareStartTime; + private @LinkGeneration int mLinkGenerationStatusForMetrics = LinkGeneration.MAX; + private LinkToggleMetricsDetails mLinkToggleMetricsDetails = + new LinkToggleMetricsDetails(LinkToggleState.COUNT, DetailedContentType.NOT_SPECIFIED); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mJniMocker.mock(DomDistillerUrlUtilsJni.TEST_HOOKS, mDistillerUrlUtilsJniMock); + + mActivity = Robolectric.setupActivity(Activity.class); + when(mWindow.getActivity()).thenReturn(new WeakReference<>(mActivity)); + when(mDistillerUrlUtilsJniMock.getOriginalUrlFromDistillerUrl(anyString())) + .thenReturn(JUnitTestGURLs.getGURL(MOCK_URL)); + when(mContentTypes.contains(ShareSheetPropertyModelBuilder.ContentType.IMAGE)) + .thenReturn(true); + + mProfileSupplier = new ObservableSupplierImpl<>(); + mProfileSupplier.set(mProfile); + + mParams = new ShareParams.Builder(mWindow, "title", MOCK_URL) + .setCallback(mTargetChosenCallback) + .build(); + + mShareSheetUsageRankingHelper = new ShareSheetUsageRankingHelper(mBottomSheetController, + mBottomSheet, mShareStartTime, mLinkGenerationStatusForMetrics, + mLinkToggleMetricsDetails, mPropertyModelBuilder, mProfileSupplier); + } + + @Test + @SmallTest + public void testCreateThirdPartyPropertyModelsFromUsageRanking() throws TimeoutException { + List<String> targets = new ArrayList<String>(); + targets.add("$more"); + targets.add("$more"); + final AtomicReference<List<PropertyModel>> resultPropertyModels = new AtomicReference<>(); + CallbackHelper helper = new CallbackHelper(); + + mShareSheetUsageRankingHelper.setTargetsForTesting(targets); + mShareSheetUsageRankingHelper.createThirdPartyPropertyModelsFromUsageRanking( + mActivity, mParams, mContentTypes, /*saveLastUsed=*/false, models -> { + resultPropertyModels.set(models); + helper.notifyCalled(); + }); + helper.waitForFirst(); + List<PropertyModel> propertyModels = resultPropertyModels.get(); + + assertEquals("Incorrect number of property models.", 2, propertyModels.size()); + assertEquals("First property model isn't More.", + mActivity.getResources().getString(R.string.sharing_more_icon_label), + propertyModels.get(0).get(ShareSheetItemViewProperties.LABEL)); + assertEquals("Second property model isn't More.", + mActivity.getResources().getString(R.string.sharing_more_icon_label), + propertyModels.get(1).get(ShareSheetItemViewProperties.LABEL)); + } +}
diff --git a/chrome/browser/share/android/test_java_sources.gni b/chrome/browser/share/android/test_java_sources.gni index 1ca6e50..bf5b6f1 100644 --- a/chrome/browser/share/android/test_java_sources.gni +++ b/chrome/browser/share/android/test_java_sources.gni
@@ -39,6 +39,7 @@ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetLinkToggleCoordinatorTest.java", + "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelperTest.java", ] share_unit_device_javatest_java_deps = [
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc index c2f740e6..19cd1cd0 100644 --- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -1300,13 +1300,18 @@ ukm::builders::Blink_AutomaticLazyLoadFrame::kEntryName, ukm_loop.QuitClosure()); + const std::string kMainFrameOrigin = "a_main_frame.com"; const GURL kMainFrameUrl(embedded_test_server()->GetURL( - "a_main_frame.com", "/ads_observer/blank_with_adiframe_writer.html")); + kMainFrameOrigin, "/ads_observer/blank_with_adiframe_writer.html")); const GURL kAdUrl(embedded_test_server()->GetURL("ad.com", "/title1.html")); const GURL kEmbedUrl( embedded_test_server()->GetURL("embed.com", "/title1.html")); const GURL kNonAdNonEmbed( embedded_test_server()->GetURL("non_ad_non_embed.com", "/title1.html")); + const GURL kSameOriginAdUrl( + embedded_test_server()->GetURL(kMainFrameOrigin, "/title1.html")); + const GURL kSameOriginEmbedUrl( + embedded_test_server()->GetURL(kMainFrameOrigin, "/title1.html")); content::RenderFrameHost* render_frame_host = ui_test_utils::NavigateToURL(browser(), kMainFrameUrl); @@ -1329,6 +1334,11 @@ // Add iframe that is not detected as an ad-frame nor an embed. AddIframe(render_frame_host, kNonAdNonEmbed); + // Add same-origin iframe that is specified to lazy-load or ad-frame should + // not be counted as LazyAdsFrameCount and LazyEmbedFrameCount. + AddAdIframe(render_frame_host, kSameOriginAdUrl); + AddIframe(render_frame_host, kSameOriginEmbedUrl); + EXPECT_TRUE(content::WaitForLoadStop(web_contents())); // LazyEmbeds and LazyAds must be disabled when the page is reloaded.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 588cea7..8611881e 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2783,6 +2783,8 @@ "webui/chromeos/network_logs_message_handler.h", "webui/chromeos/network_ui.cc", "webui/chromeos/network_ui.h", + "webui/chromeos/notification_tester/notification_tester_handler.cc", + "webui/chromeos/notification_tester/notification_tester_handler.h", "webui/chromeos/notification_tester/notification_tester_ui.cc", "webui/chromeos/notification_tester/notification_tester_ui.h", "webui/chromeos/onc_import_message_handler.cc",
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn index a0f524e..281d7bf 100644 --- a/chrome/browser/ui/android/omnibox/BUILD.gn +++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -477,7 +477,6 @@ "//third_party/junit", "//third_party/metrics_proto:metrics_proto_java", "//third_party/mockito:mockito_java", - "//ui/android:ui_java_test_support", "//ui/android:ui_no_recycler_view_java", "//ui/android:ui_recycler_view_java", "//url:gurl_java",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java index 6ae4d09..0001363 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java
@@ -27,7 +27,6 @@ import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.styles.SemanticColorUtils; -import org.chromium.ui.base.TestActivity; /** Tests for {@link OmniboxResourceProvider}. */ @RunWith(BaseRobolectricTestRunner.class) @@ -41,7 +40,9 @@ @Before public void setUp() { - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); + mDefaultColor = ChromeColors.getDefaultThemeColor(mActivity, false); }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java index 03925cb..e7a86091 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java
@@ -35,12 +35,12 @@ import org.robolectric.shadows.ShadowLooper; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconFetchCompleteListener; import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconType; import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback; -import org.chromium.ui.base.TestActivity; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -75,7 +75,8 @@ // Enable logs to be printed along with possible test failures. ShadowLog.stream = System.out; - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); mFetcher = new FaviconFetcher(mActivity, () -> mLargeIconBridge); mFetcher.setRoundedIconGeneratorForTesting(mIconGenerator);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java index 01a9191..b892982 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java
@@ -33,7 +33,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -66,8 +65,9 @@ public void setUp() { MockitoAnnotations.initMocks(this); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); // First set the app theme, then apply the feed theme overlay. - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); mResources = mActivity.getResources(); when(mContentView.getContext()).thenReturn(mActivity);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java index 3fb7aab..69c75c7 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java
@@ -30,7 +30,6 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -51,7 +50,7 @@ @Before public void setUp() { MockitoAnnotations.initMocks(this); - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); mHeaderView = mock(HeaderView.class,
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java index bb4c6b2..1cb8ef5 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java
@@ -46,7 +46,6 @@ import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatch.SuggestTile; import org.chromium.components.omnibox.AutocompleteMatchBuilder; -import org.chromium.ui.base.TestActivity; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; @@ -84,7 +83,8 @@ public void setUp() { // Enable logs to be printed along with possible test failures. ShadowLog.stream = System.out; - mActivity = Robolectric.buildActivity(TestActivity.class).setup().get(); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); doNothing() .when(mFaviconFetcher)
diff --git a/chrome/browser/ui/android/overlay/overlay_window_android.cc b/chrome/browser/ui/android/overlay/overlay_window_android.cc index f65ab0b..3c221a28 100644 --- a/chrome/browser/ui/android/overlay/overlay_window_android.cc +++ b/chrome/browser/ui/android/overlay/overlay_window_android.cc
@@ -152,6 +152,10 @@ controller_->UpdateLayerBounds(); } +void OverlayWindowAndroid::OnBackToTab(JNIEnv* env) { + Hide(); +} + void OverlayWindowAndroid::Close() { CloseInternal(); controller_->OnWindowDestroyed(/*should_pause_video=*/true);
diff --git a/chrome/browser/ui/android/overlay/overlay_window_android.h b/chrome/browser/ui/android/overlay/overlay_window_android.h index fe77e627..2dc31bfd 100644 --- a/chrome/browser/ui/android/overlay/overlay_window_android.h +++ b/chrome/browser/ui/android/overlay/overlay_window_android.h
@@ -40,6 +40,7 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& compositor_view); void OnViewSizeChanged(JNIEnv* env, jint width, jint height); + void OnBackToTab(JNIEnv* env); // ui::WindowAndroidObserver implementation. void OnCompositingDidCommit() override {}
diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn index 19bc263..58ac4bd 100644 --- a/chrome/browser/ui/android/toolbar/BUILD.gn +++ b/chrome/browser/ui/android/toolbar/BUILD.gn
@@ -270,6 +270,7 @@ robolectric_library("junit") { sources = [ + "java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java", "java/src/org/chromium/chrome/browser/toolbar/VoiceToolbarButtonControllerUnitTest.java", "java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinatorTest.java", "java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonControllerTest.java", @@ -312,6 +313,7 @@ "//chrome/browser/user_education:java", "//chrome/test/android:chrome_java_unit_test_support", "//components/browser_ui/settings/android:java", + "//components/browser_ui/styles/android:java", "//components/browser_ui/widget/android:java", "//components/feature_engagement:feature_engagement_java", "//components/search_engines/android:java", @@ -327,6 +329,7 @@ "//third_party/junit", "//third_party/mockito:mockito_java", "//ui/android:ui_java", + "//ui/android:ui_java_test_support", "//url:gurl_java", "//url:gurl_junit_test_support", ] @@ -335,7 +338,6 @@ android_library("javatests") { testonly = true sources = [ - "java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java", "java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarPreferenceFragmentTest.java", ]
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java index 98f9a84f..7d67b70b 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java
@@ -7,6 +7,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import android.animation.Animator; import android.content.res.Resources; @@ -15,75 +17,78 @@ import android.widget.FrameLayout; import androidx.annotation.ColorInt; +import androidx.test.core.app.ActivityScenario; import androidx.test.filters.SmallTest; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.shadows.ShadowLooper; import org.chromium.base.MathUtils; import org.chromium.base.supplier.ObservableSupplierImpl; -import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.Restriction; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar.ProgressBarObserver; -import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.BlankUiTestActivityTestCase; -import org.chromium.ui.test.util.UiRestriction; +import org.chromium.ui.base.TestActivity; import java.util.concurrent.TimeoutException; /** * Tests related to the ToolbarProgressBar. */ -@RunWith(ChromeJUnit4ClassRunner.class) -@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) -public class ToolbarProgressBarTest extends BlankUiTestActivityTestCase { - private final CallbackHelper mProgressUpdateHelper = new CallbackHelper(); - private final CallbackHelper mProgressVisibilityHelper = new CallbackHelper(); +@RunWith(BaseRobolectricTestRunner.class) +public class ToolbarProgressBarTest { + @Mock + ProgressBarObserver mMockProgressBarObserver; private ToolbarProgressBar mProgressBar; + private ShadowLooper mShadowLooper; + private ActivityScenario<TestActivity> mActivityScenario; - @Override - public void setUpTest() throws Exception { - super.setUpTest(); - TestThreadUtils.runOnUiThreadBlocking(this::setUpTestOnUi); + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mShadowLooper = ShadowLooper.shadowMainLooper(); + + mActivityScenario = ActivityScenario.launch(TestActivity.class).onActivity(activity -> { + activity.setTheme(org.chromium.chrome.R.style.Theme_BrowserUI_DayNight); + + ViewGroup view = new FrameLayout(activity); + view.setVisibility(View.VISIBLE); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + activity.setContentView(view, params); + + Resources res = activity.getResources(); + int heightPx = res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_height); + + View anchor = new View(activity); + view.addView(anchor, + new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, heightPx * 2)); + + ObservableSupplierImpl<Boolean> isVisibleSupplier = new ObservableSupplierImpl<>(); + isVisibleSupplier.set(true); + mProgressBar = + new ToolbarProgressBar(activity, heightPx, anchor, false, isVisibleSupplier); + final @ColorInt int toolbarColor = + SemanticColorUtils.getToolbarBackgroundPrimary(activity); + mProgressBar.setThemeColor(toolbarColor, false); + mProgressBar.setProgressBarObserver(mMockProgressBarObserver); + + view.addView(mProgressBar, + new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, heightPx)); + }); } - private void setUpTestOnUi() { - ViewGroup view = new FrameLayout(getActivity()); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - getActivity().setContentView(view, params); - - Resources res = getActivity().getResources(); - int heightPx = res.getDimensionPixelSize(R.dimen.toolbar_progress_bar_height); - - View anchor = new View(getActivity()); - view.addView(anchor, - new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, heightPx * 2)); - - ObservableSupplierImpl<Boolean> isVisibleSupplier = new ObservableSupplierImpl<>(); - isVisibleSupplier.set(true); - mProgressBar = - new ToolbarProgressBar(getActivity(), heightPx, anchor, false, isVisibleSupplier); - final @ColorInt int toolbarColor = - SemanticColorUtils.getToolbarBackgroundPrimary(getActivity()); - mProgressBar.setThemeColor(toolbarColor, false); - mProgressBar.setProgressBarObserver(new ProgressBarObserver() { - @Override - public void onVisibleProgressUpdated() { - mProgressUpdateHelper.notifyCalled(); - } - - @Override - public void onVisibilityChanged() { - mProgressVisibilityHelper.notifyCalled(); - } - }); - - view.addView(mProgressBar, - new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, heightPx)); + @After + public void tearDown() throws Exception { + mActivityScenario.close(); } /** @@ -91,7 +96,7 @@ * @return The current progress displayed by the progress bar. */ private float getProgress() { - return TestThreadUtils.runOnUiThreadBlockingNoException(() -> mProgressBar.getProgress()); + return mProgressBar.getProgress(); } /** @@ -99,8 +104,7 @@ * @return The current progress displayed by the progress bar. */ private boolean isProgressBarVisible() { - return TestThreadUtils.runOnUiThreadBlockingNoException( - () -> mProgressBar.getVisibility() == View.VISIBLE); + return mProgressBar.getVisibility() == View.VISIBLE; } /** @@ -112,36 +116,28 @@ public void testProgressBarCompletion_indeterminateAnimation() throws TimeoutException { Animator progressAnimator = mProgressBar.getIndeterminateAnimatorForTesting(); - int currentVisibilityCallCount = mProgressVisibilityHelper.getCallCount(); - - TestThreadUtils.runOnUiThreadBlocking(() -> mProgressBar.start()); + mProgressBar.start(); assertFalse("Indeterminate animation should not be running.", progressAnimator.isRunning()); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mProgressBar.startIndeterminateAnimationForTesting(); - mProgressBar.setProgress(0.5f); - }); - // Wait for a visibility change. - mProgressVisibilityHelper.waitForCallback(currentVisibilityCallCount, 1); - currentVisibilityCallCount++; + mShadowLooper.idle(); + verify(mMockProgressBarObserver, times(1)).onVisibilityChanged(); + + mProgressBar.startIndeterminateAnimationForTesting(); + mProgressBar.setProgress(0.5f); assertTrue("Indeterminate animation should be running.", progressAnimator.isRunning()); // Wait for progress updates to reach 50%. - int currentProgressCallCount = mProgressUpdateHelper.getCallCount(); while (!MathUtils.areFloatsEqual(getProgress(), 0.5f)) { - mProgressUpdateHelper.waitForCallback(currentProgressCallCount, 1); - currentProgressCallCount++; + mShadowLooper.runOneTask(); } - TestThreadUtils.runOnUiThreadBlocking(() -> mProgressBar.finish(true)); + mProgressBar.finish(true); // Wait for progress updates to reach 100%. - currentProgressCallCount = mProgressUpdateHelper.getCallCount(); while (!MathUtils.areFloatsEqual(getProgress(), 1.0f)) { - mProgressUpdateHelper.waitForCallback(currentProgressCallCount, 1); - currentProgressCallCount++; + mShadowLooper.runOneTask(); } // Make sure the progress bar remains visible through completion. @@ -150,8 +146,9 @@ assertEquals("Progress should have reached 100%.", 1.0f, getProgress(), MathUtils.EPSILON); // Wait for a visibility change now that progress has completed. - mProgressVisibilityHelper.waitForCallback(currentVisibilityCallCount, 1); + mShadowLooper.runToEndOfTasks(); + verify(mMockProgressBarObserver, times(2)).onVisibilityChanged(); assertFalse("Indeterminate animation should not be running.", progressAnimator.isRunning()); assertFalse("Progress bar should not be visible.", isProgressBarVisible()); } @@ -163,38 +160,34 @@ @Feature({"Android-Progress-Bar"}) @SmallTest public void testProgressBarCompletion_noAnimation() throws TimeoutException { - int currentVisibilityCallCount = mProgressVisibilityHelper.getCallCount(); - int currentProgressCallCount = mProgressUpdateHelper.getCallCount(); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mProgressBar.start(); - mProgressBar.setProgress(0.5f); - }); + mProgressBar.start(); + mProgressBar.setProgress(0.5f); // Wait for a visibility change. - mProgressVisibilityHelper.waitForCallback(currentVisibilityCallCount, 1); - currentVisibilityCallCount++; + mShadowLooper.idle(); + verify(mMockProgressBarObserver).onVisibilityChanged(); + assertTrue("Progress bar should be visible.", isProgressBarVisible()); - // Wait for progress updates to reach 50%. - mProgressUpdateHelper.waitForCallback(currentProgressCallCount, 1); - currentProgressCallCount++; + // Ensure progress updates reached 50%. + verify(mMockProgressBarObserver, times(1)).onVisibleProgressUpdated(); assertEquals("Progress should have reached 50%.", 0.5f, getProgress(), MathUtils.EPSILON); - currentProgressCallCount = mProgressUpdateHelper.getCallCount(); - TestThreadUtils.runOnUiThreadBlocking(() -> mProgressBar.finish(true)); + // Finish progress bar. + mProgressBar.finish(true); - // Wait for progress updates to reach 100%. - mProgressUpdateHelper.waitForCallback(currentProgressCallCount, 1); - currentProgressCallCount++; + // Ensure progress reached 100%. + verify(mMockProgressBarObserver, times(2)).onVisibleProgressUpdated(); assertEquals("Progress should have reached 100%.", 1.0f, getProgress(), MathUtils.EPSILON); // Make sure the progress bar remains visible through completion. assertTrue("Progress bar should still be visible.", isProgressBarVisible()); - // Wait for a visibility change now that progress has completed. - mProgressVisibilityHelper.waitForCallback(currentVisibilityCallCount, 1); + // Wait for hiding tasks. + mShadowLooper.runToEndOfTasks(); + // Ensure that visibility changed now that progress has completed. assertFalse("Progress bar should not be visible.", isProgressBarVisible()); + verify(mMockProgressBarObserver, times(2)).onVisibilityChanged(); } /** @@ -206,31 +199,26 @@ public void testProgressBarCompletion_indeterminateAnimation_noDelay() throws TimeoutException { Animator progressAnimator = mProgressBar.getIndeterminateAnimatorForTesting(); - int currentVisibilityCallCount = mProgressVisibilityHelper.getCallCount(); - - TestThreadUtils.runOnUiThreadBlocking(() -> mProgressBar.start()); + mProgressBar.start(); assertFalse("Indeterminate animation should not be running.", progressAnimator.isRunning()); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mProgressBar.startIndeterminateAnimationForTesting(); - mProgressBar.setProgress(0.5f); - }); - // Wait for a visibility change. - mProgressVisibilityHelper.waitForCallback(currentVisibilityCallCount, 1); - currentVisibilityCallCount++; + mShadowLooper.idle(); + verify(mMockProgressBarObserver).onVisibilityChanged(); + assertTrue("Progress bar should be visible.", isProgressBarVisible()); + + mProgressBar.startIndeterminateAnimationForTesting(); + mProgressBar.setProgress(0.5f); assertTrue("Indeterminate animation should be running.", progressAnimator.isRunning()); // Wait for progress updates to reach 50%. - int currentProgressCallCount = mProgressUpdateHelper.getCallCount(); while (!MathUtils.areFloatsEqual(getProgress(), 0.5f)) { - mProgressUpdateHelper.waitForCallback(currentProgressCallCount, 1); - currentProgressCallCount++; + mShadowLooper.runOneTask(); } // Finish progress with no delay. - TestThreadUtils.runOnUiThreadBlocking(() -> mProgressBar.finish(false)); + mProgressBar.finish(false); // The progress bar should immediately be invisible. assertFalse("Progress bar should be invisible.", isProgressBarVisible()); @@ -248,36 +236,27 @@ public void testProgressBarReset_indeterminateAnimation() throws TimeoutException { Animator progressAnimator = mProgressBar.getIndeterminateAnimatorForTesting(); - int currentVisibilityCallCount = mProgressVisibilityHelper.getCallCount(); - - TestThreadUtils.runOnUiThreadBlocking(() -> mProgressBar.start()); + mProgressBar.start(); assertFalse("Indeterminate animation should not be running.", progressAnimator.isRunning()); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - mProgressBar.startIndeterminateAnimationForTesting(); - mProgressBar.setProgress(0.5f); - }); - // Wait for a visibility change. - mProgressVisibilityHelper.waitForCallback(currentVisibilityCallCount, 1); - currentVisibilityCallCount++; + mShadowLooper.idle(); + verify(mMockProgressBarObserver).onVisibilityChanged(); + + mProgressBar.startIndeterminateAnimationForTesting(); + mProgressBar.setProgress(0.5f); assertTrue("Indeterminate animation should be running.", progressAnimator.isRunning()); // Wait for progress updates to reach 50%. - int currentProgressCallCount = mProgressUpdateHelper.getCallCount(); while (!MathUtils.areFloatsEqual(getProgress(), 0.5f)) { - mProgressUpdateHelper.waitForCallback(currentProgressCallCount, 1); - currentProgressCallCount++; + mShadowLooper.runOneTask(); } // Restart the progress bar. - currentProgressCallCount = mProgressUpdateHelper.getCallCount(); - TestThreadUtils.runOnUiThreadBlocking(() -> mProgressBar.start()); + mProgressBar.start(); - // Wait for progress update. - mProgressUpdateHelper.waitForCallback(currentProgressCallCount, 1); - currentProgressCallCount++; + // Cancel the indeterminate animator, it doesn't stop on its own. + progressAnimator.cancel(); // Make sure the progress bar remains visible through completion. assertTrue("Progress bar should still be visible.", isProgressBarVisible());
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index 629113f6..580ab05 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -190,6 +190,9 @@ session_controller_client_ = std::make_unique<SessionControllerClientImpl>(); session_controller_client_->Init(); + // By this point ash shell should have initialized its D-Bus signal + // listeners, so inform the session manager that Ash is initialized. + session_controller_client_->EmitAshInitialized(); system_tray_client_ = std::make_unique<SystemTrayClientImpl>(); network_connect_delegate_->SetSystemTrayClient(system_tray_client_.get());
diff --git a/chrome/browser/ui/ash/shelf/arc_app_window_info.cc b/chrome/browser/ui/ash/shelf/arc_app_window_info.cc index c335c7f..230b286 100644 --- a/chrome/browser/ui/ash/shelf/arc_app_window_info.cc +++ b/chrome/browser/ui/ash/shelf/arc_app_window_info.cc
@@ -40,6 +40,12 @@ ArcAppWindowInfo::~ArcAppWindowInfo() = default; +void ArcAppWindowInfo::OnWindowDestroying(aura::Window* window) { + DCHECK(observed_window_.IsObservingSource(window)); + observed_window_.Reset(); + window_ = nullptr; +} + void ArcAppWindowInfo::SetDescription(const std::string& title, const gfx::ImageSkia& icon) { DCHECK(base::IsStringUTF8(title)); @@ -69,8 +75,17 @@ } void ArcAppWindowInfo::set_window(aura::Window* window) { + if (window_ == window) + return; + + if (window_ && observed_window_.IsObservingSource(window_)) + observed_window_.Reset(); + window_ = window; UpdateWindowProperties(); + + if (window && !observed_window_.IsObservingSource(window)) + observed_window_.Observe(window); } aura::Window* ArcAppWindowInfo::ArcAppWindowInfo::window() {
diff --git a/chrome/browser/ui/ash/shelf/arc_app_window_info.h b/chrome/browser/ui/ash/shelf/arc_app_window_info.h index 69fa17d..c5b4fe5a 100644 --- a/chrome/browser/ui/ash/shelf/arc_app_window_info.h +++ b/chrome/browser/ui/ash/shelf/arc_app_window_info.h
@@ -9,22 +9,27 @@ #include <vector> #include "ash/public/cpp/shelf_types.h" +#include "base/scoped_observation.h" #include "chrome/browser/ui/ash/shelf/arc_app_shelf_id.h" #include "ui/aura/window.h" +#include "ui/aura/window_observer.h" #include "ui/gfx/image/image_skia.h" // The information about the ARC application window which has to be kept // even when its AppWindow is not present. -class ArcAppWindowInfo { +class ArcAppWindowInfo : public aura::WindowObserver { public: ArcAppWindowInfo(const arc::ArcAppShelfId& app_shelf_id, const std::string& launch_intent, const std::string& package_name); - ~ArcAppWindowInfo(); + ~ArcAppWindowInfo() override; ArcAppWindowInfo(const ArcAppWindowInfo&) = delete; ArcAppWindowInfo& operator=(const ArcAppWindowInfo&) = delete; + // aura::WindowObserver: + void OnWindowDestroying(aura::Window* window) override; + void SetDescription(const std::string& title, const gfx::ImageSkia& icon); void set_window(aura::Window* window); @@ -68,6 +73,15 @@ gfx::ImageSkia icon_; aura::Window* window_ = nullptr; + + // Scoped list of observed windows (for removal on destruction) + // TODO(crbug.com/1323913, crbug.com/1316374): When the window is destroyed, + // it looks like that set_window is not set in AppServiceAppWindowArcTracker + // for an unknown reason. So observe windows in ArcAppWindowInfo, to clear + // window_, when the window is destroyed. When the root cause is figured out, + // observed_windows_ can be removed. + base::ScopedObservation<aura::Window, aura::WindowObserver> observed_window_{ + this}; }; #endif // CHROME_BROWSER_UI_ASH_SHELF_ARC_APP_WINDOW_INFO_H_
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index f51371d..f3e1413 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -193,11 +193,7 @@ #else int help_string_id = IDS_HELP_PAGE; #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT)); -#else - AddItem(IDC_ABOUT, l10n_util::GetStringUTF16(IDS_ABOUT)); -#endif #if BUILDFLAG(GOOGLE_CHROME_BRANDING) if (base::FeatureList::IsEnabled(features::kChromeTipsInMainMenu)) { AddItem(IDC_CHROME_TIPS, l10n_util::GetStringUTF16(IDS_CHROME_TIPS));
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index 2983c9b..cfb9a2f 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -161,10 +161,9 @@ SkColor BrowserNonClientFrameView::GetFrameColor( BrowserFrameActiveState active_state) const { - return GetThemeProvider()->GetColor( - ShouldPaintAsActive(active_state) - ? ThemeProperties::COLOR_FRAME_ACTIVE - : ThemeProperties::COLOR_FRAME_INACTIVE); + return GetColorProvider()->GetColor(ShouldPaintAsActive(active_state) + ? ui::kColorFrameActive + : ui::kColorFrameInactive); } void BrowserNonClientFrameView::UpdateFrameColor() {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc index 80bfd374..a641263 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
@@ -32,6 +32,8 @@ #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" #include "third_party/blink/public/mojom/manifest/manifest.mojom.h" #include "ui/base/theme_provider.h" +#include "ui/color/color_id.h" +#include "ui/color/color_provider.h" class BrowserNonClientFrameViewBrowserTest : public extensions::ExtensionBrowserTest { @@ -107,11 +109,11 @@ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser()); const BrowserNonClientFrameView* frame_view = browser_view->frame()->GetFrameView(); - const ui::ThemeProvider* theme_provider = frame_view->GetThemeProvider(); + const ui::ColorProvider* color_provider = frame_view->GetColorProvider(); const SkColor expected_active_color = - theme_provider->GetColor(ThemeProperties::COLOR_FRAME_ACTIVE); + color_provider->GetColor(ui::kColorFrameActive); const SkColor expected_inactive_color = - theme_provider->GetColor(ThemeProperties::COLOR_FRAME_INACTIVE); + color_provider->GetColor(ui::kColorFrameInactive); EXPECT_EQ(expected_active_color, frame_view->GetFrameColor(BrowserFrameActiveState::kActive));
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc index 433ac86..15ad1402 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc
@@ -10,7 +10,6 @@ #include "base/memory/raw_ptr.h" #include "base/test/bind.h" #include "build/build_config.h" -#include "build/chromeos_buildflags.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" @@ -37,6 +36,10 @@ #include "ui/views/test/test_views.h" #include "ui/views/view_utils.h" +#if BUILDFLAG(IS_LINUX) +#include "ui/views/linux_ui/linux_ui.h" +#endif + // Tests web-app windows that use the OpaqueBrowserFrameView implementation // for their non client frames. class WebAppOpaqueBrowserFrameViewTest : public InProcessBrowserTest { @@ -52,7 +55,13 @@ static GURL GetAppURL() { return GURL("https://test.org"); } - void SetUpOnMainThread() override { SetThemeMode(ThemeMode::kDefault); } + void SetUpOnMainThread() override { + SetThemeMode(ThemeMode::kDefault); +#if BUILDFLAG(IS_LINUX) + views::LinuxUI::instance()->SetUseSystemThemeCallback( + base::BindRepeating([](aura::Window* window) { return false; })); +#endif + } bool InstallAndLaunchWebApp( absl::optional<SkColor> theme_color = absl::nullopt) { @@ -74,8 +83,7 @@ // browser windows, see |CreateBrowserNonClientFrameView()|. bool is_opaque_browser_frame_view = views::IsViewClass<OpaqueBrowserFrameView>(frame_view); -#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \ - !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) DCHECK(is_opaque_browser_frame_view); #else if (!is_opaque_browser_frame_view) @@ -129,8 +137,7 @@ kColorFrameCaptionActive)); } -#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \ - !BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_LINUX) // The app theme color should be ignored in system theme mode. IN_PROC_BROWSER_TEST_F(WebAppOpaqueBrowserFrameViewTest, SystemThemeColor) { SetThemeMode(ThemeMode::kSystem); @@ -161,7 +168,7 @@ EXPECT_EQ(web_app_frame_toolbar_->active_color_for_testing(), expected_caption_color); } -#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) +#endif // BUILDFLAG(IS_LINUX) IN_PROC_BROWSER_TEST_F(WebAppOpaqueBrowserFrameViewTest, LightThemeColor) { if (!InstallAndLaunchWebApp(SK_ColorYELLOW)) @@ -217,6 +224,7 @@ // Tests for the appearance of the origin text in the titlebar. The origin text // shows and then hides both when the window is first opened and any time the // titlebar's appearance changes. +// TODO(crbug.com/1337118): Revise this test. IN_PROC_BROWSER_TEST_F(WebAppOpaqueBrowserFrameViewTest, OriginTextVisibility) { ui_test_utils::UrlLoadObserver url_observer( GetAppURL(), content::NotificationService::AllSources());
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc index fc2d2d2..8dbd3a57 100644 --- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/security_interstitials/content/security_interstitial_controller_client.h" #include "components/security_interstitials/content/security_interstitial_page.h" @@ -35,10 +36,6 @@ #include "ui/base/clipboard/clipboard.h" #include "ui/views/controls/button/image_button.h" -#if BUILDFLAG(IS_LINUX) -#include "ui/ozone/public/ozone_switches.h" -#endif - namespace { // Waits until the title of any tab in the browser for |contents| has the title @@ -88,6 +85,9 @@ // Opens a new popup window from |web_contents| on |target_url| and returns // the Browser it opened in. Browser* OpenPopup(content::WebContents* web_contents, const GURL& target_url) { + ui_test_utils::BrowserChangeObserver browser_change_observer( + /*browser=*/nullptr, + ui_test_utils::BrowserChangeObserver::ChangeType::kAdded); content::TestNavigationObserver nav_observer(target_url); nav_observer.StartWatchingNewWebContents(); @@ -96,7 +96,9 @@ EXPECT_TRUE(content::ExecuteScript(web_contents, script)); nav_observer.Wait(); - return chrome::FindLastActive(); + Browser* browser = browser_change_observer.Wait(); + ui_test_utils::BrowserActivationWaiter(browser).WaitForActivation(); + return browser; } // Navigates to |target_url| and waits for navigation to complete. @@ -258,27 +260,7 @@ EXPECT_FALSE(custom_tab_bar_); } -// Check the custom tab bar is not instantiated for a popup window. -// Flaky on linux and chromeos : crbug.com/1186608, crbug.com/1179071, -// crbug.com/1338068 -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -#define MAYBE_IsNotCreatedInPopup DISABLED_IsNotCreatedInPopup -#else -#define MAYBE_IsNotCreatedInPopup IsNotCreatedInPopup -#endif -IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, MAYBE_IsNotCreatedInPopup) { -#if BUILDFLAG(IS_LINUX) - { - auto* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kOzonePlatform) && - command_line->GetSwitchValueASCII(switches::kOzonePlatform) == - "wayland") { - // TODO(crbug.com/1179071): Test is flaky on Linux Wayland configuration. - GTEST_SKIP() << "Flaky on Linux Wayland"; - } - } -#endif - +IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, IsNotCreatedInPopup) { Browser* popup = OpenPopup(browser_view_->GetActiveWebContents(), GURL("http://example.com")); EXPECT_TRUE(popup); @@ -295,16 +277,8 @@ EXPECT_FALSE(popup_view->toolbar()->custom_tab_bar()); } -// Flaky on linux: crbug.com/1202694 -#if BUILDFLAG(IS_LINUX) -#define MAYBE_BackToAppButtonIsNotVisibleInOutOfScopePopups \ - DISABLED_BackToAppButtonIsNotVisibleInOutOfScopePopups -#else -#define MAYBE_BackToAppButtonIsNotVisibleInOutOfScopePopups \ - BackToAppButtonIsNotVisibleInOutOfScopePopups -#endif IN_PROC_BROWSER_TEST_F(CustomTabBarViewBrowserTest, - MAYBE_BackToAppButtonIsNotVisibleInOutOfScopePopups) { + BackToAppButtonIsNotVisibleInOutOfScopePopups) { const GURL app_url = https_server()->GetURL("app.com", "/ssl/google.html"); const GURL out_of_scope_url = GURL("https://example.com");
diff --git a/chrome/browser/ui/webui/chromeos/notification_tester/DEPS b/chrome/browser/ui/webui/chromeos/notification_tester/DEPS new file mode 100644 index 0000000..3121dba --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/notification_tester/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ui/message_center" +] \ No newline at end of file
diff --git a/chrome/browser/ui/webui/chromeos/notification_tester/OWNERS b/chrome/browser/ui/webui/chromeos/notification_tester/OWNERS new file mode 100644 index 0000000..0fa385f --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/notification_tester/OWNERS
@@ -0,0 +1 @@ +leandre@chromium.org \ No newline at end of file
diff --git a/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.cc b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.cc new file mode 100644 index 0000000..3cf2769 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.cc
@@ -0,0 +1,74 @@ +// Copyright (c) 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.h" + +#include <string> + +#include "ash/constants/notifier_catalogs.h" +#include "ash/public/cpp/notification_utils.h" +#include "base/bind.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/app/vector_icons/vector_icons.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/public/cpp/notification.h" + +namespace chromeos { + +NotificationTesterHandler::NotificationTesterHandler() = default; + +NotificationTesterHandler::~NotificationTesterHandler() = default; + +void NotificationTesterHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "generateNotificationForm", + base::BindRepeating( + &NotificationTesterHandler::HandleGenerateNotificationForm, + base::Unretained(this))); +} + +void NotificationTesterHandler::HandleGenerateNotificationForm( + const base::Value::List& args) { + AllowJavascript(); + + // Parse JS args. + std::u16string title = base::UTF8ToUTF16(args[0].GetString()); + std::u16string message = base::UTF8ToUTF16(args[1].GetString()); + + GenerateNotification(title, message); +} + +void NotificationTesterHandler::GenerateNotification( + const std::u16string& title, + const std::u16string& message) { + std::u16string display_source = u"Sample Display Source"; + GURL origin_url("https://test-url.xyz"); + message_center::NotifierId notifier_id( + message_center::NotifierType::SYSTEM_COMPONENT, "test notifier id", + ash::NotificationCatalogName::kTestCatalogName); + message_center::RichNotificationData optional_fields; + + // Delegate does nothing. + scoped_refptr<message_center::NotificationDelegate> delegate = + base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( + base::BindRepeating([](absl::optional<int> button_index) {})); + + // Generate a unique notification id based on the system time in ms. + auto current_time_in_ms = + base::Time::Now().ToDeltaSinceWindowsEpoch().InMilliseconds(); + std::string notification_id = base::NumberToString(current_time_in_ms); + + std::unique_ptr<message_center::Notification> notification = + ash::CreateSystemNotification( + message_center::NOTIFICATION_TYPE_SIMPLE, notification_id, title, + message, display_source, origin_url, notifier_id, optional_fields, + delegate, kTerminalSshIcon, + message_center::SystemNotificationWarningLevel::WARNING); + + message_center::MessageCenter::Get()->AddNotification( + std::move(notification)); +} + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.h b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.h new file mode 100644 index 0000000..60956f3 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.h
@@ -0,0 +1,38 @@ +// Copyright (c) 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_NOTIFICATION_TESTER_NOTIFICATION_TESTER_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_NOTIFICATION_TESTER_NOTIFICATION_TESTER_HANDLER_H_ + +#include "content/public/browser/web_ui_message_handler.h" + +namespace chromeos { + +// WebUI message handler for chrome://notification-tester from the front-end to +// the message center. +class NotificationTesterHandler : public content::WebUIMessageHandler { + public: + NotificationTesterHandler(); + NotificationTesterHandler(const NotificationTesterHandler&) = delete; + NotificationTesterHandler& operator=(const NotificationTesterHandler&) = + delete; + ~NotificationTesterHandler() override; + + // content::WebUIMessageHandler: + void RegisterMessages() override; + + private: + // MessageHandler callback that fires when the MessageHandler receives a + // message to generate a notification from the front-end. + void HandleGenerateNotificationForm(const base::Value::List& args); + + // Generates a notification via the message center with the given title and + // body. + void GenerateNotification(const std::u16string& title, + const std::u16string& message); +}; + +} // namespace chromeos + +#endif
diff --git a/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_ui.cc b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_ui.cc index fd439ab6..15f3125 100644 --- a/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_ui.cc +++ b/chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_ui.cc
@@ -3,11 +3,20 @@ // found in the LICENSE file. #include "chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_ui.h" + +#include "base/containers/span.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/chromeos/notification_tester/notification_tester_handler.h" +#include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" +#include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" +#include "chrome/grit/notification_tester_resources.h" +#include "chrome/grit/notification_tester_resources_map.h" +#include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "ui/base/webui/web_ui_util.h" namespace chromeos { @@ -18,9 +27,16 @@ content::WebUIDataSource::Create(chrome::kChromeUINotificationTesterHost); // Add required resources. - html_source->SetDefaultResource(IDR_NOTIFICATION_TESTER_HTML); + webui::SetupWebUIDataSource(html_source, + base::make_span(kNotificationTesterResources, + kNotificationTesterResourcesSize), + IDR_NOTIFICATION_TESTER_INDEX_HTML); + Profile* profile = Profile::FromWebUI(web_ui); content::WebUIDataSource::Add(profile, html_source); + + // Add message handler. + web_ui->AddMessageHandler(std::make_unique<NotificationTesterHandler>()); } NotificationTesterUI::~NotificationTesterUI() = default;
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/BUILD.gn b/chrome/browser/ui/webui/side_panel/bookmarks/BUILD.gn index 5bc70f42..f3066da 100644 --- a/chrome/browser/ui/webui/side_panel/bookmarks/BUILD.gn +++ b/chrome/browser/ui/webui/side_panel/bookmarks/BUILD.gn
@@ -4,6 +4,8 @@ import("//mojo/public/tools/bindings/mojom.gni") +assert(!is_android) + mojom("mojo_bindings") { sources = [ "bookmarks.mojom" ] webui_module_path = "/"
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/BUILD.gn b/chrome/browser/ui/webui/side_panel/read_anything/BUILD.gn index 3b218d5..b629fb3e 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/BUILD.gn +++ b/chrome/browser/ui/webui/side_panel/read_anything/BUILD.gn
@@ -4,6 +4,8 @@ import("//mojo/public/tools/bindings/mojom.gni") +assert(!is_android) + mojom("mojo_bindings") { sources = [ "read_anything.mojom" ] webui_module_path = "/"
diff --git a/chrome/browser/ui/webui/side_panel/reading_list/BUILD.gn b/chrome/browser/ui/webui/side_panel/reading_list/BUILD.gn index 465afff..81afc59 100644 --- a/chrome/browser/ui/webui/side_panel/reading_list/BUILD.gn +++ b/chrome/browser/ui/webui/side_panel/reading_list/BUILD.gn
@@ -4,6 +4,8 @@ import("//mojo/public/tools/bindings/mojom.gni") +assert(!is_android) + mojom("mojo_bindings") { sources = [ "reading_list.mojom" ] webui_module_path = "/"
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 44ce315..765190a 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1655812488-8b09e9486b9180454e1cb0c2bdf7ba0d8a6b046a.profdata +chrome-mac-main-1655834389-8a8167b3e3797bddaeb706c6915cfcc104babd9d.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index eeca1cc..1aaa7ef 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1655823537-daa62db3b88be48c2a30be0206afd093cbae5b3a.profdata +chrome-win32-main-1655844917-c51458a42e2b5fa0adfd893af29e66a60bc8a280.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index f0f4eb6..0d000c6 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1655823537-91204d4cfe59f5faebc20c310ab776ecebdc3740.profdata +chrome-win64-main-1655844917-bba1c641be9afcf0b1904f78b08e448fa0413558.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 6b47275..981f263e 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -255,6 +255,7 @@ "$root_gen_dir/chrome/nearby_internals_resources.pak", "$root_gen_dir/chrome/nearby_share_dialog_resources.pak", "$root_gen_dir/chrome/network_ui_resources.pak", + "$root_gen_dir/chrome/notification_tester_resources.pak", "$root_gen_dir/chrome/oobe_conditional_resources.pak", "$root_gen_dir/chrome/oobe_unconditional_resources.pak", "$root_gen_dir/chrome/os_settings_resources.pak", @@ -312,6 +313,7 @@ "//chrome/browser/resources/chromeos/login:unconditional_resources", "//chrome/browser/resources/chromeos/multidevice_internals:resources", "//chrome/browser/resources/chromeos/network_ui:resources", + "//chrome/browser/resources/chromeos/notification_tester:resources", "//chrome/browser/resources/nearby_internals:resources", "//chrome/browser/resources/nearby_share:resources", "//chrome/browser/resources/settings/chromeos:resources",
diff --git a/chrome/common/extensions/api/terminal_private.json b/chrome/common/extensions/api/terminal_private.json index 316a04c..b38f0d6 100644 --- a/chrome/common/extensions/api/terminal_private.json +++ b/chrome/common/extensions/api/terminal_private.json
@@ -238,6 +238,10 @@ "name": "info", "type": "object", "properties": { + "alternative_renderer": { + "description": "True if alternative renderer flag is enabled.", + "type": "boolean" + }, "multi_profile": { "description": "True if multi profile settings is enabled.", "type": "boolean"
diff --git a/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js b/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js index 2e91a40..f9e101d 100644 --- a/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js +++ b/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js
@@ -20,7 +20,7 @@ /** @override */ browsePreload: - 'chrome://bluetooth-internals/bluetooth_internals.html?module=bluetooth_internals/bluetooth_internals_test.js', + 'chrome://bluetooth-internals/bluetooth_internals.html?module=bluetooth_internals/bluetooth_internals_test.js&host=test', /** @override */ isAsync: true,
diff --git a/chrome/test/data/webui/chromeos/crostini_installer_app_test.js b/chrome/test/data/webui/chromeos/crostini_installer_app_test.js index df48c24..677d359 100644 --- a/chrome/test/data/webui/chromeos/crostini_installer_app_test.js +++ b/chrome/test/data/webui/chromeos/crostini_installer_app_test.js
@@ -296,9 +296,19 @@ // Test invalid usernames const invalidUsernames = [ - 'root', // Unavailable. - '0abcd', // Invalid first character. - 'aBcd', // Invalid (uppercase) character. + '0abcd', // Invalid (number) starting character. + 'aBcd', // Invalid (uppercase) character. + 'spa ce', // Invalid (space) character. + '-dash', // Invalid (dash) starting character. + 'name\\backslash', // Invalid (backslash) character. + 'name@mpersand', // Invalid (ampersand) character. + // Reserved users + 'root', 'daemon', 'bin', 'sys', 'sync', 'games', 'man', 'lp', 'mail', + 'news', 'uucp', 'proxy', 'www-data', 'backup', 'list', 'irc', 'gnats', + 'nobody', '_apt', 'systemd-timesync', 'systemd-network', + 'systemd-resolve', 'systemd-bus-proxy', 'messagebus', 'sshd', 'rtkit', + 'pulse', 'android-root', 'chronos-access', 'android-everybody', + // End reserved users ]; for (const username of invalidUsernames) {
diff --git a/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_browsertest.js b/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_browsertest.js index 0d55126..9bcbdf9 100644 --- a/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_browsertest.js +++ b/chrome/test/data/webui/chromeos/edu_coexistence/edu_coexistence_browsertest.js
@@ -29,7 +29,7 @@ /** @override */ get browsePreload() { return 'chrome://chrome-signin/test_loader.html?module=' + - 'chromeos/edu_coexistence/edu_coexistence_app_test.js'; + 'chromeos/edu_coexistence/edu_coexistence_app_test.js&host=test'; } /** @override */ @@ -103,7 +103,7 @@ /** @override */ get browsePreload() { return 'chrome://chrome-signin/test_loader.html?module=' + - 'chromeos/edu_coexistence/edu_coexistence_controller_test.js'; + 'chromeos/edu_coexistence/edu_coexistence_controller_test.js&host=test'; } /** @override */ @@ -121,7 +121,7 @@ /** @override */ get browsePreload() { return 'chrome://chrome-signin/test_loader.html?module=' + - 'chromeos/edu_coexistence/edu_coexistence_ui_test.js'; + 'chromeos/edu_coexistence/edu_coexistence_ui_test.js&host=test'; } /** @override */
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js index ede60187..372b4f62 100644 --- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js +++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js
@@ -31,7 +31,7 @@ /** @override */ get browsePreload() { return 'chrome://emoji-picker/test_loader.html?module=' + - 'chromeos/emoji_picker/emoji_picker_test.js'; + 'chromeos/emoji_picker/emoji_picker_test.js&host=test'; } }; @@ -45,7 +45,7 @@ /** @override */ get browsePreload() { return 'chrome://emoji-picker/test_loader.html?module=' + - 'chromeos/emoji_picker/emoji_picker_store_test.js'; + 'chromeos/emoji_picker/emoji_picker_store_test.js&host=test'; } }; @@ -63,7 +63,7 @@ /** @override */ get browsePreload() { return 'chrome://emoji-picker/test_loader.html?module=' + - 'chromeos/emoji_picker/emoji_picker_extension_test.js'; + 'chromeos/emoji_picker/emoji_picker_extension_test.js&host=test'; } }; @@ -80,7 +80,7 @@ /** @override */ get browsePreload() { return 'chrome://emoji-picker/test_loader.html?module=' + - 'chromeos/emoji_picker/emoji_picker_search_test.js'; + 'chromeos/emoji_picker/emoji_picker_search_test.js&host=test'; } }; @@ -98,7 +98,7 @@ /** @override */ get browsePreload() { return 'chrome://emoji-picker/test_loader.html?module=' + - 'chromeos/emoji_picker/emoji_picker_trie_test.js'; + 'chromeos/emoji_picker/emoji_picker_trie_test.js&host=test'; } }; @@ -111,10 +111,10 @@ /** @override */ get browsePreload() { return 'chrome://emoji-picker/test_loader.html?module=' + - 'chromeos/emoji_picker/emoji_picker_prefix_search_test.js'; + 'chromeos/emoji_picker/emoji_picker_prefix_search_test.js&host=test'; } }; TEST_F('EmojiPickerPrefixSearchTest', 'All', function() { mocha.run(); -}); \ No newline at end of file +});
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js index 649a563..fa2f997 100644 --- a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js +++ b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
@@ -129,7 +129,7 @@ assertTrue(!!getElement('#pageUrlText')); // System info label is a localized string in HTML format. - assertTrue(getElementContent('#sysInfoLabel').length > 0); + assertTrue(getElementContent('#sysInfoCheckboxLabel').length > 0); // Privacy note is a long localized string in HTML format. assertTrue(page.i18nExists('privacyNote'));
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js index 42130780..cf279051 100644 --- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js +++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
@@ -100,7 +100,8 @@ // TODO(jhawkins): Set up test_loader.html for internet-config-dialog // and use it here instead of os-settings. return `chrome://${ - webuiHost}/test_loader.html?module=cr_components/chromeos/${module}`; + webuiHost}/test_loader.html?module=cr_components/chromeos/${ + module}&host=test`; } /** @override */
diff --git a/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js b/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js index 40e8c66..064729c8 100644 --- a/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js +++ b/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js
@@ -15,7 +15,7 @@ var CrFocusRowBehaviorTest = class extends PolymerInteractiveUITest { /** @override */ get browsePreload() { - return 'chrome://test/test_loader.html?module=cr_focus_row_behavior_test.js'; + return 'chrome://test/test_loader.html?module=cr_focus_row_behavior_test.js&host=test'; } /** @override */
diff --git a/chrome/test/data/webui/inline_login/inline_login_browsertest.js b/chrome/test/data/webui/inline_login/inline_login_browsertest.js index a975047..61e5866 100644 --- a/chrome/test/data/webui/inline_login/inline_login_browsertest.js +++ b/chrome/test/data/webui/inline_login/inline_login_browsertest.js
@@ -22,7 +22,7 @@ /** @override */ get browsePreload() { // See Reason enum in components/signin/public/base/signin_metrics.h. - return 'chrome://chrome-signin/test_loader.html?module=inline_login/inline_login_test.js&reason=5'; + return 'chrome://chrome-signin/test_loader.html?module=inline_login/inline_login_test.js&reason=5&host=test'; } get suiteName() { @@ -97,7 +97,7 @@ /** @override */ get browsePreload() { // See Reason enum in components/signin/public/base/signin_metrics.h. - return 'chrome://chrome-signin/test_loader.html?module=inline_login/inline_login_welcome_page_test.js&reason=5'; + return 'chrome://chrome-signin/test_loader.html?module=inline_login/inline_login_welcome_page_test.js&reason=5&host=test'; } get suiteName() { @@ -190,7 +190,7 @@ /** @override */ get browsePreload() { // See Reason enum in components/signin/public/base/signin_metrics.h. - return 'chrome://chrome-signin/test_loader.html?module=inline_login/arc_account_picker_page_test.js&reason=5'; + return 'chrome://chrome-signin/test_loader.html?module=inline_login/arc_account_picker_page_test.js&reason=5&host=test'; } get suiteName() { @@ -242,7 +242,7 @@ get browsePreload() { // Reason 1: Add secondary account. // See Reason enum in components/signin/public/base/signin_metrics.h. - return 'chrome://chrome-signin/test_loader.html?module=inline_login/inline_login_signin_blocked_by_policy_page_test.js&reason=1'; + return 'chrome://chrome-signin/test_loader.html?module=inline_login/inline_login_signin_blocked_by_policy_page_test.js&reason=1&host=test'; } get suiteName() {
diff --git a/chrome/test/data/webui/invalidations/about_invalidations_browsertest.js b/chrome/test/data/webui/invalidations/about_invalidations_browsertest.js index 19b4ec5a..fb6f8ca 100644 --- a/chrome/test/data/webui/invalidations/about_invalidations_browsertest.js +++ b/chrome/test/data/webui/invalidations/about_invalidations_browsertest.js
@@ -18,7 +18,7 @@ * Browse to the Invalidations page. */ browsePreload: - 'chrome://invalidations/invalidations.html?module=invalidations/invalidations_test.js', + 'chrome://invalidations/invalidations.html?module=invalidations/invalidations_test.js&host=test', extraLibraries: [ '//third_party/mocha/mocha.js',
diff --git a/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js b/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js index cf12424c..7c89348 100644 --- a/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js +++ b/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js
@@ -172,7 +172,7 @@ var StaticTypesTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test/test_loader.html?module=js/static_types_test.js'; + return 'chrome://test/test_loader.html?module=js/static_types_test.js&host=test'; } };
diff --git a/chrome/test/data/webui/nearby_share/nearby_browsertest.js b/chrome/test/data/webui/nearby_share/nearby_browsertest.js index 05295d07..9eb3aad 100644 --- a/chrome/test/data/webui/nearby_share/nearby_browsertest.js +++ b/chrome/test/data/webui/nearby_share/nearby_browsertest.js
@@ -38,7 +38,8 @@ this[className] = class extends NearbyBrowserTest { /** @override */ get browsePreload() { - return `chrome://nearby/test_loader.html?module=nearby_share/${module}`; + return `chrome://nearby/test_loader.html?module=nearby_share/${ + module}&host=test`; } };
diff --git a/chrome/test/data/webui/nearby_share/shared/nearby_shared_v3_browsertest.js b/chrome/test/data/webui/nearby_share/shared/nearby_shared_v3_browsertest.js index e089364c8..67fae617 100644 --- a/chrome/test/data/webui/nearby_share/shared/nearby_shared_v3_browsertest.js +++ b/chrome/test/data/webui/nearby_share/shared/nearby_shared_v3_browsertest.js
@@ -44,7 +44,7 @@ /** @override */ get browsePreload() { return `chrome://nearby/test_loader.html?module=nearby_share/shared/${ - module}`; + module}&host=test`; } };
diff --git a/chrome/test/data/webui/net_internals/net_internals_browsertest.js b/chrome/test/data/webui/net_internals/net_internals_browsertest.js index b02ac60a..dc711eb 100644 --- a/chrome/test/data/webui/net_internals/net_internals_browsertest.js +++ b/chrome/test/data/webui/net_internals/net_internals_browsertest.js
@@ -58,7 +58,7 @@ __proto__: NetInternalsBrowserTest.prototype, browsePreload: - 'chrome://net-internals/index.html?module=net_internals/dns_view_test.js', + 'chrome://net-internals/index.html?module=net_internals/dns_view_test.js&host=test', }; TEST_F('NetInternalsDnsViewTest', 'ClearCache', function() { @@ -75,7 +75,7 @@ __proto__: NetInternalsBrowserTest.prototype, browsePreload: - 'chrome://net-internals/index.html?module=net_internals/main_test.js', + 'chrome://net-internals/index.html?module=net_internals/main_test.js&host=test', }; TEST_F('NetInternalsMainTest', 'TabVisibility', function() { @@ -87,7 +87,7 @@ __proto__: NetInternalsBrowserTest.prototype, browsePreload: - 'chrome://net-internals/index.html?module=net_internals/domain_security_policy_view_test.js', + 'chrome://net-internals/index.html?module=net_internals/domain_security_policy_view_test.js&host=test', get suiteName() { return domain_security_policy_view_test.suiteName;
diff --git a/chrome/test/data/webui/resources/webui_resources_browsertest.js b/chrome/test/data/webui/resources/webui_resources_browsertest.js index a8611b48..6b60113 100644 --- a/chrome/test/data/webui/resources/webui_resources_browsertest.js +++ b/chrome/test/data/webui/resources/webui_resources_browsertest.js
@@ -27,7 +27,7 @@ class extends WebUIResourcesBrowserTest { /** @override */ get browsePreload() { - return 'chrome://test/test_loader.html?module=resources/list_property_update_behavior_tests.js'; + return 'chrome://test/test_loader.html?module=resources/list_property_update_behavior_tests.js&host=test'; } };
diff --git a/chrome/test/data/webui/settings/chromeos/a11y/os_settings_accessibility_v3_test.js b/chrome/test/data/webui/settings/chromeos/a11y/os_settings_accessibility_v3_test.js index 5f7ae714..7eefb76d 100644 --- a/chrome/test/data/webui/settings/chromeos/a11y/os_settings_accessibility_v3_test.js +++ b/chrome/test/data/webui/settings/chromeos/a11y/os_settings_accessibility_v3_test.js
@@ -65,7 +65,7 @@ /** @override */ browsePreload: - 'chrome://os-settings/test_loader.html?module=settings/a11y/basic_a11y_v3_test.js', + 'chrome://os-settings/test_loader.html?module=settings/a11y/basic_a11y_v3_test.js&host=test', // Include files that define the mocha tests. extraLibraries: [
diff --git a/chrome/test/data/webui/settings/chromeos/a11y/v3_os_a11y_browsertest.js b/chrome/test/data/webui/settings/chromeos/a11y/v3_os_a11y_browsertest.js index 34016dbf..edd8855 100644 --- a/chrome/test/data/webui/settings/chromeos/a11y/v3_os_a11y_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/a11y/v3_os_a11y_browsertest.js
@@ -131,7 +131,7 @@ /** @override */ get browsePreload() { return `chrome://os-settings/test_loader.html?module=settings/chromeos/a11y/${ - module}`; + module}&host=test`; } /** @override */ @@ -174,4 +174,4 @@ /** @override */ violationFilter: filter, }); -} \ No newline at end of file +}
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js index 6809ce7..33e3a44d0 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -37,7 +37,7 @@ var OSSettingsDevicePageV3Test = class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/device_page_tests.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/device_page_tests.js&host=test'; } /** @override */ @@ -61,7 +61,7 @@ class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/people_page_account_manager_test.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/people_page_account_manager_test.js&host=test'; } /** @override */ @@ -81,7 +81,7 @@ class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/people_page_account_manager_test.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/people_page_account_manager_test.js&host=test'; } /** @override */ @@ -102,7 +102,7 @@ var OSSettingsNearbyShareSubPageV3Test = class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/nearby_share_subpage_tests.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/nearby_share_subpage_tests.js&host=test'; } /** @override */ @@ -119,7 +119,7 @@ var OSSettingsPeoplePageOsSyncV3Test = class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/os_sync_controls_test.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/os_sync_controls_test.js&host=test'; } /** @override */ @@ -141,7 +141,7 @@ class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/os_bluetooth_devices_subpage_tests.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/os_bluetooth_devices_subpage_tests.js&host=test'; } /** @override */ @@ -162,7 +162,7 @@ var OSSettingsSearchEngineV3Test = class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/search_engine_test.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/search_engine_test.js&host=test'; } /** @override */ @@ -179,7 +179,7 @@ class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/app_management/app_details_item_test.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/app_management/app_details_item_test.js&host=test'; } /** @override */ @@ -203,7 +203,7 @@ var OSSettingsCrostiniPageV3Test = class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/crostini_page_test.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/crostini_page_test.js&host=test'; } /** @override */ @@ -220,7 +220,7 @@ class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://os-settings/test_loader.html?module=settings/chromeos/crostini_extra_containers_subpage_test.js'; + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/crostini_extra_containers_subpage_test.js&host=test'; } /** @override */ @@ -417,7 +417,7 @@ /** @override */ get browsePreload() { return `chrome://os-settings/test_loader.html?module=settings/chromeos/${ - module}`; + module}&host=test`; } };
diff --git a/chromecast/browser/webview/cast_app_controller.cc b/chromecast/browser/webview/cast_app_controller.cc index 52581b4..ea711c2b 100644 --- a/chromecast/browser/webview/cast_app_controller.cc +++ b/chromecast/browser/webview/cast_app_controller.cc
@@ -15,10 +15,10 @@ content::WebContentsObserver::Observe(contents_); // There may be existing RenderWidgets that we need to observe. - contents->ForEachFrame(base::BindRepeating( + contents->GetPrimaryMainFrame()->ForEachRenderFrameHost(base::BindRepeating( &WebContentController:: RegisterRenderWidgetInputObserverFromRenderFrameHost, - this)); + base::Unretained(this))); std::unique_ptr<webview::WebviewResponse> response = std::make_unique<webview::WebviewResponse>();
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc index 53f8459f..7ae3619 100644 --- a/chromecast/browser/webview/web_content_controller.cc +++ b/chromecast/browser/webview/web_content_controller.cc
@@ -97,6 +97,9 @@ // Therefore, it is not safe to call RemoveInputEventObserver on every // RenderWidgetHost that we started observing; we need to remove only // from currently live RenderWidgetHosts. + // + // Or, consider listening to + // |RenderWidgetHostObserver::RenderWidgetHostDestroyed| instead. std::unique_ptr<content::RenderWidgetHostIterator> widgets( content::RenderWidgetHost::GetRenderWidgetHosts()); while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 84050eb..886bad6 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -3413,6 +3413,9 @@ <message name="IDS_FEEDBACK_TOOL_ADD_FILE_LABEL" desc="Label for the field of adding a file"> Add file </message> + <message name="IDS_FEEDBACK_TOOL_INCLUDE_SYSTEM_INFO_AND_METRICS_CHECKBOX_LABEL" desc="Checkbox for including system information and metrics on the bug report dialog box"> + Send <ph name="BEGIN_LINK1"><a id="sysInfoLink"></ph>system and app info<ph name="END_LINK1"></a></ph> and <ph name="BEGIN_LINK2"><a id="histogramsLink"></ph>metrics<ph name="END_LINK2"></a></ph> + </message> <message name="IDS_FEEDBACK_TOOL_PRIVACY_NOTE" desc="Text for the privacy note included in the feedback app"> Go to the <ph name="BEGIN_LINK1"><a id="legalHelpPageUrl"></ph>Legal Help page<ph name="END_LINK1"></a></ph> to request content changes for legal reasons. Some account and system information may be sent to Google. We will use the information you give us to help address technical issues and to improve our services, subject to our <ph name="BEGIN_LINK2"><a id="privacyPolicyUrl"></ph>Privacy Policy<ph name="END_LINK2"></a></ph> and <ph name="BEGIN_LINK3"><a id="termsOfServiceUrl"></ph>Terms of Service<ph name="END_LINK3"></a></ph>. </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_INCLUDE_SYSTEM_INFO_AND_METRICS_CHECKBOX_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_INCLUDE_SYSTEM_INFO_AND_METRICS_CHECKBOX_LABEL.png.sha1 new file mode 100644 index 0000000..551eb6d7 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_INCLUDE_SYSTEM_INFO_AND_METRICS_CHECKBOX_LABEL.png.sha1
@@ -0,0 +1 @@ +8a17eb16b0023947c9a63d87989c3b3a2f990d90 \ No newline at end of file
diff --git a/chromeos/services/libassistant/DIR_METADATA b/chromeos/services/libassistant/DIR_METADATA index 5cf9e51..5ba0efa 100644 --- a/chromeos/services/libassistant/DIR_METADATA +++ b/chromeos/services/libassistant/DIR_METADATA
@@ -1,3 +1 @@ -monorail { - component: "UI>Shell>Assistant" -} +mixins: "//chromeos/ash/components/assistant/COMMON_METADATA"
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index da4ed01..4c3c0ca 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -310,6 +310,7 @@ # http://b/236312054 "crostini.AppGeditFilesharing", + "crostini.AppGeditFilesharing.stable", # http://crbug.com/1338038 "arc.IMEBlockingVK",
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc index 021a02d..158a195 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.cc
@@ -234,6 +234,49 @@ personal_data().Refresh(); } +std::string AutofillMetricsBaseTest::CreateLocalMasterCard( + bool clear_existing_cards) { + if (clear_existing_cards) { + personal_data().ClearCreditCards(); + } + std::string guid("10000000-0000-0000-0000-000000000003"); + CreditCard local_credit_card; + test::SetCreditCardInfo(&local_credit_card, "Test User", + "5454545454545454" /* Mastercard */, "08", "2022", + "1"); + local_credit_card.set_guid(guid); + personal_data().AddCreditCard(local_credit_card); + return guid; +} + +std::vector<std::string> +AutofillMetricsBaseTest::CreateLocalAndDuplicateServerCreditCard() { + personal_data().ClearCreditCards(); + + // Local credit card creation. + CreditCard local_credit_card; + test::SetCreditCardInfo(&local_credit_card, "Test User", + "4111111111111111" /* Visa */, "11", "2022", "1"); + std::string local_card_guid("10000000-0000-0000-0000-000000000001"); + local_credit_card.set_guid(local_card_guid); + personal_data().AddCreditCard(local_credit_card); + + // Duplicate masked server card with same card information as local card. + CreditCard masked_server_credit_card(CreditCard::MASKED_SERVER_CARD, + "server_id_2"); + std::string server_card_guid("10000000-0000-0000-0000-000000000002"); + masked_server_credit_card.set_guid(server_card_guid); + test::SetCreditCardInfo(&masked_server_credit_card, "Test User", + "4111111111111111" /* Visa */, "11", "2022", "1"); + masked_server_credit_card.set_instrument_id(1); + masked_server_credit_card.SetNetworkForMaskedCard(kVisaCard); + masked_server_credit_card.SetNumber(u"1111"); + personal_data().AddServerCreditCard(masked_server_credit_card); + + personal_data().Refresh(); + return {local_card_guid, server_card_guid}; +} + void AutofillMetricsBaseTest::AddMaskedServerCreditCardWithOffer( std::string guid, std::string offer_reward_amount,
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h index 9054d3a..c869713d0 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_test_base.h +++ b/components/autofill/core/browser/metrics/autofill_metrics_test_base.h
@@ -52,6 +52,16 @@ bool include_full_server_credit_card, bool masked_card_is_enrolled_for_virtual_card); + // Creates a local card to existing card deck or clear them all and then add a + // new local card. + // The GUID for the card created is returned as a string. + std::string CreateLocalMasterCard(bool clear_existing_cards = false); + + // Creates a local card and then a duplicate server card with the same + // credentials/info. + // The GUIDs for the cards crated are returned as a vector of strings. + std::vector<std::string> CreateLocalAndDuplicateServerCreditCard(); + void AddMaskedServerCreditCardWithOffer(std::string guid, std::string offer_reward_amount, GURL url,
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc index efaa5de..f90b801a 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -5421,6 +5421,98 @@ } } +// Test to log when an unique local card is autofilled, when other duplicated +// server cards exist. +TEST_P( + AutofillMetricsIFrameTest, + CreditCardFilledFormEventsUsingUniqueLocalCardWhenOtherDuplicateServerCardsPresent) { + CreateLocalAndDuplicateServerCreditCard(); + // Creating a local mastercard credit card. + std::string local_guid = CreateLocalMasterCard(); + + // Set up our form data. + FormData form = test::GetFormData( + {.description_for_logging = "PaymentProfileImportRequirements", + .fields = { + {.role = ServerFieldType::CREDIT_CARD_EXP_MONTH, .value = u""}, + {.role = ServerFieldType::CREDIT_CARD_EXP_2_DIGIT_YEAR, + .value = u""}, + {.role = ServerFieldType::CREDIT_CARD_NUMBER, .value = u""}}}); + std::vector<ServerFieldType> field_types = { + CREDIT_CARD_EXP_MONTH, CREDIT_CARD_EXP_2_DIGIT_YEAR, CREDIT_CARD_NUMBER}; + + autofill_manager().AddSeenForm(form, field_types, field_types); + // Simulate filling a unique local card suggestion. + base::HistogramTester histogram_tester; + autofill_manager().FillOrPreviewForm( + mojom::RendererFormDataAction::kFill, 0, form, form.fields.front(), + autofill_manager().suggestion_generator()->MakeFrontendId(local_guid, + std::string())); + + EXPECT_THAT( + histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), + BucketsInclude( + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1), + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1), + Bucket( + FORM_EVENT_LOCAL_SUGGESTION_FILLED_FOR_AN_EXISTING_SERVER_CARD_ONCE, + 0))); + EXPECT_THAT( + histogram_tester.GetAllSamples(credit_card_form_events_frame_histogram_), + BucketsInclude( + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1), + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1), + Bucket( + FORM_EVENT_LOCAL_SUGGESTION_FILLED_FOR_AN_EXISTING_SERVER_CARD_ONCE, + 0))); +} + +// Test to log when a local card is autofilled and its duplicated +// server card exists. +TEST_P(AutofillMetricsIFrameTest, + CreditCardFilledFormEventsUsingDuplicateServerCard) { + // Creating a local and a duplicate server card. + std::vector<std::string> local_and_duplicate_server_card_guids = + CreateLocalAndDuplicateServerCreditCard(); + // Set up our form data. + FormData form = test::GetFormData( + {.description_for_logging = "PaymentProfileImportRequirements", + .fields = { + {.role = ServerFieldType::CREDIT_CARD_EXP_MONTH, .value = u""}, + {.role = ServerFieldType::CREDIT_CARD_EXP_2_DIGIT_YEAR, + .value = u""}, + {.role = ServerFieldType::CREDIT_CARD_NUMBER, .value = u""}}}); + std::vector<ServerFieldType> field_types = { + CREDIT_CARD_EXP_MONTH, CREDIT_CARD_EXP_2_DIGIT_YEAR, CREDIT_CARD_NUMBER}; + + autofill_manager().AddSeenForm(form, field_types, field_types); + // Simulate filling a local card suggestion with a duplicate server card. + base::HistogramTester histogram_tester; + // Local card with a duplicate server card present at index 0. + std::string local_guid(local_and_duplicate_server_card_guids.at(0)); + autofill_manager().FillOrPreviewForm( + mojom::RendererFormDataAction::kFill, 0, form, form.fields.front(), + autofill_manager().suggestion_generator()->MakeFrontendId(local_guid, + std::string())); + + EXPECT_THAT( + histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), + BucketsInclude( + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1), + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1), + Bucket( + FORM_EVENT_LOCAL_SUGGESTION_FILLED_FOR_AN_EXISTING_SERVER_CARD_ONCE, + 1))); + EXPECT_THAT( + histogram_tester.GetAllSamples(credit_card_form_events_frame_histogram_), + BucketsInclude( + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1), + Bucket(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, 1), + Bucket( + FORM_EVENT_LOCAL_SUGGESTION_FILLED_FOR_AN_EXISTING_SERVER_CARD_ONCE, + 1))); +} + // Test that we log preflight calls for credit card unmasking. TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) { scoped_feature_list_.InitAndEnableFeature(
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc index 172dbf8e..b1858523 100644 --- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc +++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
@@ -150,6 +150,12 @@ record_type == CreditCard::VIRTUAL_CARD; switch (record_type) { case CreditCard::LOCAL_CARD: + // Check if the local card is a duplicate of an existing server card + // and log an additional metric if so. + if (IsLocalDuplicateOfServerCard(credit_card)) { + Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED_FOR_AN_EXISTING_SERVER_CARD_ONCE, + form); + } Log(FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE, form); break; case CreditCard::MASKED_SERVER_CARD: @@ -284,6 +290,17 @@ } } +bool CreditCardFormEventLogger::IsLocalDuplicateOfServerCard( + const CreditCard& credit_card) { + // Get the list of all the server credit cards for the user and see if any + // card in the list matches/isDuplicateOf the local card. + return base::ranges::any_of( + personal_data_manager_->GetServerCreditCards(), + [&credit_card](CreditCard* card_from_list) { + return credit_card.IsLocalDuplicateOfServerCard(*card_from_list); + }); +} + FormEvent CreditCardFormEventLogger::GetCardNumberStatusFormEvent( const CreditCard& credit_card) { const std::u16string number = credit_card.number();
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h index 928a537fa..17ccdbe3 100644 --- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h +++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
@@ -116,6 +116,7 @@ using FormEventLoggerBase::Log; private: + bool IsLocalDuplicateOfServerCard(const CreditCard& credit_card); FormEvent GetCardNumberStatusFormEvent(const CreditCard& credit_card); void RecordCardUnmaskFlowEvent(UnmaskAuthFlowType flow, UnmaskAuthFlowEvent event);
diff --git a/components/autofill/core/browser/metrics/form_events/form_events.h b/components/autofill/core/browser/metrics/form_events/form_events.h index 05a68e1c..da269f8 100644 --- a/components/autofill/core/browser/metrics/form_events/form_events.h +++ b/components/autofill/core/browser/metrics/form_events/form_events.h
@@ -135,6 +135,10 @@ FORM_EVENT_CREDIT_CARD_SEAMLESS_FILLABLE_FULL_FILL_BUT_EXPDATE_MISSING = 54, FORM_EVENT_CREDIT_CARD_SEAMLESS_FILLABLE_PARTIAL_FILL = 55, + // Metric logged when a local card with a matching deduplicated server + // suggestion was filled. + FORM_EVENT_LOCAL_SUGGESTION_FILLED_FOR_AN_EXISTING_SERVER_CARD_ONCE = 56, + NUM_FORM_EVENTS, };
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 804b7f8..e7bf750e 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -30,6 +30,8 @@ "buffer.h", "capabilities.cc", "capabilities.h", + "common_utils.cc", + "common_utils.h", "data_device.cc", "data_device.h", "data_device_delegate.h",
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc index eb97bee..3a52741b 100644 --- a/components/exo/buffer.cc +++ b/components/exo/buffer.cc
@@ -457,8 +457,6 @@ resource->format = viz::RGBA_8888; resource->filter = GL_LINEAR; resource->size = gpu_memory_buffer_->GetSize(); - resource->synchronization_type = - viz::TransferableResource::SynchronizationType::kReleaseFence; // Create a new image texture for |gpu_memory_buffer_| with |texture_target_| // if one doesn't already exist. The contents of this buffer are copied to
diff --git a/components/exo/common_utils.cc b/components/exo/common_utils.cc new file mode 100644 index 0000000..48dcfc7 --- /dev/null +++ b/components/exo/common_utils.cc
@@ -0,0 +1,27 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/common_utils.h" + +#include "base/logging.h" + +#if defined(USE_OZONE) +#include "ui/ozone/public/ozone_platform.h" +#endif + +namespace exo { + +bool IsDrmAtomicAvailable() { +#if defined(USE_OZONE) + auto& host_properties = + ui::OzonePlatform::GetInstance()->GetPlatformRuntimeProperties(); + return host_properties.supports_overlays; +#else + LOG(WARNING) << "Ozone disabled, cannot determine whether DrmAtomic is " + "present. Assuming it is not"; + return false; +#endif +} + +} // namespace exo
diff --git a/components/exo/common_utils.h b/components/exo/common_utils.h new file mode 100644 index 0000000..175b69b --- /dev/null +++ b/components/exo/common_utils.h
@@ -0,0 +1,14 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_EXO_COMMON_UTILS_H_ +#define COMPONENTS_EXO_COMMON_UTILS_H_ + +namespace exo { + +bool IsDrmAtomicAvailable(); + +} // namespace exo + +#endif // COMPONENTS_EXO_COMMON_UTILS_H_
diff --git a/components/exo/layer_tree_frame_sink_holder.cc b/components/exo/layer_tree_frame_sink_holder.cc index 11f20135..4d0e604 100644 --- a/components/exo/layer_tree_frame_sink_holder.cc +++ b/components/exo/layer_tree_frame_sink_holder.cc
@@ -4,6 +4,7 @@ #include "components/exo/layer_tree_frame_sink_holder.h" +#include "base/bind.h" #include "base/containers/contains.h" #include "base/threading/thread_task_runner_handle.h" #include "cc/trees/layer_tree_frame_sink.h" @@ -11,6 +12,9 @@ #include "components/viz/common/frame_timing_details.h" #include "components/viz/common/hit_test/hit_test_region_list.h" #include "components/viz/common/resources/returned_resource.h" +#include "gpu/command_buffer/client/context_support.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "ui/gfx/gpu_fence.h" namespace exo { @@ -19,9 +23,13 @@ LayerTreeFrameSinkHolder::LayerTreeFrameSinkHolder( SurfaceTreeHost* surface_tree_host, - std::unique_ptr<cc::LayerTreeFrameSink> frame_sink) + std::unique_ptr<cc::LayerTreeFrameSink> frame_sink, + scoped_refptr<viz::ContextProvider> context_provider) : surface_tree_host_(surface_tree_host), - frame_sink_(std::move(frame_sink)) { + frame_sink_(std::move(frame_sink)), + context_provider_(context_provider), + use_gpu_fence_( + context_provider_->ContextCapabilities().chromium_gpu_fence) { frame_sink_->BindToClient(this); } @@ -110,17 +118,19 @@ void LayerTreeFrameSinkHolder::ReclaimResources( std::vector<viz::ReturnedResource> resources) { - for (auto& resource : resources) { - // Skip resources that are also in last frame. This can happen if - // the frame sink id changed. - if (base::Contains(last_frame_resources_, resource.id)) { - continue; - } - resource_manager_.ReclaimResource(std::move(resource)); + if (!use_gpu_fence_) { + ReclaimResourcesInternal(std::move(resources), nullptr); + return; } - if (lifetime_manager_ && resource_manager_.HasNoCallbacks()) - ScheduleDelete(); + // See the comment at ReclaimResourcesInternal's declaration. + gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); + auto gpu_fence_id = gles2->CreateGpuFenceCHROMIUM(); + context_provider_->ContextSupport()->GetGpuFence( + gpu_fence_id, + base::BindOnce(&LayerTreeFrameSinkHolder::ReclaimResourcesInternal, + weak_ptr_factory_.GetWeakPtr(), std::move(resources))); + gles2->DestroyGpuFenceCHROMIUM(gpu_fence_id); } void LayerTreeFrameSinkHolder::DidReceiveCompositorFrameAck() { @@ -166,4 +176,24 @@ ScheduleDelete(); } +void LayerTreeFrameSinkHolder::ReclaimResourcesInternal( + std::vector<viz::ReturnedResource> resources, + std::unique_ptr<gfx::GpuFence> release_fence) { + for (auto& resource : resources) { + // Skip resources that are also in last frame. This can happen if + // the frame sink id changed. + if (base::Contains(last_frame_resources_, resource.id)) { + continue; + } + + if (resource.release_fence.is_null() && release_fence) + resource.release_fence = release_fence->GetGpuFenceHandle().Clone(); + + resource_manager_.ReclaimResource(std::move(resource)); + } + + if (lifetime_manager_ && resource_manager_.HasNoCallbacks()) + ScheduleDelete(); +} + } // namespace exo
diff --git a/components/exo/layer_tree_frame_sink_holder.h b/components/exo/layer_tree_frame_sink_holder.h index 7f260f56..0c16a62f 100644 --- a/components/exo/layer_tree_frame_sink_holder.h +++ b/components/exo/layer_tree_frame_sink_holder.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/memory/weak_ptr.h" #include "cc/trees/layer_tree_frame_sink_client.h" #include "components/exo/frame_sink_resource_manager.h" #include "components/exo/wm_helper.h" @@ -14,9 +15,14 @@ #include "components/viz/common/resources/release_callback.h" namespace viz { +class ContextProvider; struct FrameTimingDetails; } +namespace gfx { +class GpuFence; +} + namespace cc { class LayerTreeFrameSink; } @@ -30,8 +36,10 @@ class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient, public WMHelper::LifetimeManager::Observer { public: - LayerTreeFrameSinkHolder(SurfaceTreeHost* surface_tree_host, - std::unique_ptr<cc::LayerTreeFrameSink> frame_sink); + LayerTreeFrameSinkHolder( + SurfaceTreeHost* surface_tree_host, + std::unique_ptr<cc::LayerTreeFrameSink> frame_sink, + scoped_refptr<viz::ContextProvider> context_provider); LayerTreeFrameSinkHolder(const LayerTreeFrameSinkHolder&) = delete; LayerTreeFrameSinkHolder& operator=(const LayerTreeFrameSinkHolder&) = delete; @@ -78,8 +86,17 @@ // WMHelper::LifetimeManager::Observer: void OnDestroyed() override; + // |release_fence| is a fence that is created when ReclaimResources call comes + // and that is used for those resources that do not have fences. That + // happens when resources are not overlaid, but rather composited. + // TODO(crbug.com/1310136): this should be managed by SkiaRenderer instead. + void ReclaimResourcesInternal(std::vector<viz::ReturnedResource> resources, + std::unique_ptr<gfx::GpuFence> release_fence); + SurfaceTreeHost* surface_tree_host_; std::unique_ptr<cc::LayerTreeFrameSink> frame_sink_; + scoped_refptr<viz::ContextProvider> context_provider_; + const bool use_gpu_fence_; FrameSinkResourceManager resource_manager_; @@ -92,6 +109,8 @@ bool delete_pending_ = false; WMHelper::LifetimeManager* lifetime_manager_ = nullptr; + + base::WeakPtrFactory<LayerTreeFrameSinkHolder> weak_ptr_factory_{this}; }; } // namespace exo
diff --git a/components/exo/surface_tree_host.cc b/components/exo/surface_tree_host.cc index 8348b7f..1693ba9 100644 --- a/components/exo/surface_tree_host.cc +++ b/components/exo/surface_tree_host.cc
@@ -108,13 +108,14 @@ host_window_->SetEventTargetingPolicy( aura::EventTargetingPolicy::kDescendantsOnly); host_window_->SetEventTargeter(std::make_unique<CustomWindowTargeter>(this)); - layer_tree_frame_sink_holder_ = std::make_unique<LayerTreeFrameSinkHolder>( - this, host_window_->CreateLayerTreeFrameSink()); + context_provider_ = aura::Env::GetInstance() ->context_factory() ->SharedMainThreadContextProvider(); DCHECK(context_provider_); context_provider_->AddObserver(this); + layer_tree_frame_sink_holder_ = std::make_unique<LayerTreeFrameSinkHolder>( + this, host_window_->CreateLayerTreeFrameSink(), context_provider_); } SurfaceTreeHost::~SurfaceTreeHost() { @@ -378,7 +379,7 @@ // We can immediately delete the old LayerTreeFrameSinkHolder because all of // it's resources are lost anyways. layer_tree_frame_sink_holder_ = std::make_unique<LayerTreeFrameSinkHolder>( - this, host_window_->CreateLayerTreeFrameSink()); + this, host_window_->CreateLayerTreeFrameSink(), context_provider_); } viz::CompositorFrame frame;
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 9e1b4223..2e6270a 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -53,6 +53,7 @@ #include "build/chromeos_buildflags.h" #include "components/exo/buildflags.h" #include "components/exo/capabilities.h" +#include "components/exo/common_utils.h" #include "components/exo/display.h" #include "components/exo/wayland/overlay_prioritizer.h" #include "components/exo/wayland/serial_tracker.h" @@ -142,18 +143,6 @@ constexpr base::FilePath::CharType kCustomServerDir[] = FILE_PATH_LITERAL("wayland"); -bool IsDrmAtomicAvailable() { -#if defined(USE_OZONE) - auto& host_properties = - ui::OzonePlatform::GetInstance()->GetPlatformRuntimeProperties(); - return host_properties.supports_overlays; -#else - LOG(WARNING) << "Ozone disabled, cannot determine whether DrmAtomic is " - "present. Assuming it is not"; - return false; -#endif -} - void wayland_log(const char* fmt, va_list argp) { LOG(WARNING) << "libwayland: " << base::StringPrintV(fmt, argp); }
diff --git a/components/lookalikes/core/features.cc b/components/lookalikes/core/features.cc index a5bb9d4..ca60bbe 100644 --- a/components/lookalikes/core/features.cc +++ b/components/lookalikes/core/features.cc
@@ -12,5 +12,8 @@ const char kLookalikeDigitalAssetLinksTimeoutParameter[] = "timeout"; +const base::Feature kDetectComboSquattingLookalikes{ + "ComboSquattingLookalikes", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace lookalikes
diff --git a/components/lookalikes/core/features.h b/components/lookalikes/core/features.h index 366e28e..1b4cc1f 100644 --- a/components/lookalikes/core/features.h +++ b/components/lookalikes/core/features.h
@@ -21,6 +21,10 @@ COMPONENT_EXPORT(LOOKALIKES_FEATURES) extern const char kLookalikeDigitalAssetLinksTimeoutParameter[]; +// This feature enables warnings for ComboSquatting heuristic. +COMPONENT_EXPORT(LOOKALIKES_FEATURES) +extern const base::Feature kDetectComboSquattingLookalikes; + } // namespace features } // namespace lookalikes
diff --git a/components/policy/resources/webui/policy.html b/components/policy/resources/webui/policy.html index 8675505..5126fac 100644 --- a/components/policy/resources/webui/policy.html +++ b/components/policy/resources/webui/policy.html
@@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, user-scalable=no"> <title>$i18n{title}</title> -<link rel="stylesheet" href="chrome://policy/policy.css"> +<link rel="stylesheet" href="./policy.css"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> </head> @@ -40,175 +40,6 @@ <!-- This is where policy tables get dynamically added. --> </section> </main> - <div hidden> - <fieldset id="status-box-template"> - <legend class="legend"></legend> - <div class="status-entry" hidden> - <div class="label">$i18n{labelVersion}</div> - <div class="version"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelMachineEnrollmentMachineName}</div> - <div class="machine-enrollment-name"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelMachineEnrollmentDomain}</div> - <div class="machine-enrollment-domain"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelMachineEnrollmentToken}</div> - <div class="machine-enrollment-token"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelMachineEntrollmentDeviceId}</div> - <div class="machine-enrollment-device-id"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelUsername}</div> - <div class="username"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelManagedBy}</div> - <div class="managed-by"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelGaiaId}</div> - <div class="gaia-id"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelClientId}</div> - <div class="client-id"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelAssetId}</div> - <div class="asset-id"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelLocation}</div> - <div class="location"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelDirectoryApiId}</div> - <div class="directory-api-id"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelTimeSinceLastFetchAttempt}</div> - <div class="time-since-last-fetch-attempt"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelTimeSinceLastRefresh}</div> - <div class="time-since-last-refresh"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelRefreshInterval}</div> - <div class="refresh-interval"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelPoliciesPush}</div> - <div class="policy-push"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelStatus}</div> - <div class="status"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelIsAffiliated}</div> - <div class="is-affiliated"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelIsOffHoursActive}</div> - <div class="is-offhours-active"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelVersion}</div> - <div class="version"></div> - </div> - <div class="status-entry" hidden> - <div class="label">$i18n{labelLastCloudReportSentTimestamp}</div> - <div class="last-cloud-report-sent-timestamp"></div> - </div> - </fieldset> - - <div class="policy-table" id="policy-table-template" role="table" - aria-labelledby="policy-header"> - <h3 class="header" id="policy-header"></h3> - <p class="id"></p> - <div class="main"> - <div class="header row" role="row"> - <div class="name" role="columnheader">$i18n{headerName}</div> - <div class="value" role="columnheader">$i18n{headerValue}</div> - <div class="source" role="columnheader">$i18n{headerSource}</div> - <div class="scope" role="columnheader">$i18n{headerScope}</div> - <div class="level" role="columnheader">$i18n{headerLevel}</div> - <div class="messages" role="columnheader">$i18n{headerStatus}</div> - <div class="toggle" role="columnheader"></div> - </div> - <div class="no-policy">$i18n{noPoliciesSet}</div> - </div> - </div> - - <div class="policy-conflict-data" id="policy-conflict-template" - role="rowgroup" hidden> - <div class="policy conflict row" role="row"> - <div class="name" role="rowheader">$i18n{conflictValue}</div> - <div class="value" role="cell"></div> - <div class="source" role="cell"></div> - <div class="scope" role="cell"></div> - <div class="level" role="cell"></div> - <div class="messages" role="cell"></div> - <div class="toggle" role="cell"></div> - </div> - </div> - - <div class="policy-data" id="policy-template" role="rowgroup"> - <div class="policy row" role="row"> - <div class="name" role="rowheader" aria-labelledby="name"> - <a class="link" target="_blank"> - <span id="name"></span> - <img src="chrome://resources/images/open_in_new.svg"> - </a> - </div> - <div class="value" role="cell"></div> - <div class="source" role="cell"></div> - <div class="scope" role="cell"></div> - <div class="level" role="cell"></div> - <div class="messages" role="cell"></div> - <div class="toggle" role="cell"> - <a is="action-link" class="show-more">$i18n{showMore}</a> - <a is="action-link" class="show-less" hidden>$i18n{showLess}</a> - </div> - </div> - <div class="value row" role="row" hidden> - <div class="name" role="rowheader">$i18n{value}</div> - <div class="value" role="cell"></div> - <div class="copy" role="cell"> - <a is="action-link" class="copy-value link" role="cell"> - <img src="chrome://resources/images/icon_copy_content.svg"> - </a> - </div> - </div> - <div class="errors row" role="row" hidden> - <div class="name" role="rowheader">$i18n{error}</div> - <div class="value" role="cell"></div> - </div> - <div class="warnings row" role="row" hidden> - <div class="name" role="rowheader">$i18n{warning}</div> - <div class="value" role="cell"></div> - </div> - <div class="infos row" role="row" hidden> - <div class="name" role="rowheader">$i18n{info}</div> - <div class="value" role="cell"></div> - </div> - </div> - - <div class="policy-precedence-data" id="policy-precedence-template" - role="rowgroup"> - <div class="precedence row" role="row"> - <div class="name" role="rowheader">$i18n{labelPrecedence}</div> - <div class="value" role="cell"></div> - </div> - </div> - </div> </body> <script type="module" src="policy.js"></script>
diff --git a/components/policy/resources/webui/policy.js b/components/policy/resources/webui/policy.js index e745cc8..a9d997b 100644 --- a/components/policy/resources/webui/policy.js +++ b/components/policy/resources/webui/policy.js
@@ -13,31 +13,39 @@ // Functions for tests that directly inject JS to access certain UI elements. function getPolicyFieldsets() { - const statusSection = document.querySelector('#status-section'); - return statusSection.querySelectorAll('fieldset'); + const statusBoxes = document.querySelectorAll('status-box'); + return Array.from(statusBoxes) + .map(box => box.shadowRoot.querySelector('fieldset')); } function getAllPolicyTables() { - return document.querySelector('#policy-ui').querySelectorAll('.policy-table'); + return document.querySelectorAll('#policy-ui policy-table'); } function getAllPolicyRows(policyTable) { - return policyTable.querySelectorAll('.policy.row'); + return policyTable.shadowRoot.querySelectorAll('policy-row'); } function getAllPolicyRowDivs(policyRow) { - return policyRow.querySelectorAll('div'); + const row = policyRow.shadowRoot.querySelector('.policy.row'); + return row.querySelectorAll('div'); } function getPrecedenceRowValue() { - const precedenceRow = - document.querySelector('#policy-ui') - .querySelector('.policy-table .precedence.row > .value'); + const tables = document.querySelectorAll('policy-table'); + let precedenceRow = null; + tables.forEach(table => { + const row = table.shadowRoot.querySelector('policy-precedence-row'); + if (row) { + precedenceRow = row.shadowRoot.querySelector('.value'); + } + }); return precedenceRow; } function getRefreshIntervalEl() { - return document.querySelector('#status-box-container .refresh-interval'); + return document.querySelector('status-box') + .shadowRoot.querySelector('.refresh-interval'); } Object.assign(window, {
diff --git a/components/policy/resources/webui/policy_base.js b/components/policy/resources/webui/policy_base.js index 54a34474..ba187c7 100644 --- a/components/policy/resources/webui/policy_base.js +++ b/components/policy/resources/webui/policy_base.js
@@ -4,13 +4,14 @@ import './strings.m.js'; import 'chrome://resources/js/action_link.js'; - // <if expr="is_ios"> import 'chrome://resources/js/ios/web_ui.js'; // </if> +import './status_box.js'; +import './policy_table.js'; + import {addSingletonGetter, addWebUIListener} from 'chrome://resources/js/cr.m.js'; -import {define as crUiDefine} from 'chrome://resources/js/cr/ui.m.js'; import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {$} from 'chrome://resources/js/util.m.js'; @@ -35,551 +36,6 @@ let PolicyValuesResponse; /** - * @typedef {{ - * level: string, - * scope: string, - * source: string, - * value: any, - * }} - */ -let Conflict; - -/** - * @typedef {{ - * ignored?: boolean, - * name: string, - * level: string, - * link: ?string, - * scope: string, - * source: string, - * error: string, - * warning: string, - * info: string, - * value: any, - * deprecated: ?boolean, - * future: ?boolean, - * allSourcesMerged: ?boolean, - * conflicts: ?Array<!Conflict>, - * superseded: ?Array<!Conflict>, - * }} - */ -let Policy; - -/** - * @typedef {{ - * id: ?string, - * isExtension?: boolean, - * name: string, - * policies: !Array<!Policy>, - * precedenceOrder: ?Array<string>, - * }} - */ -let PolicyTableModel; - -/** - * A box that shows the status of cloud policy for a device, machine or user. - * @constructor - * @extends {HTMLFieldSetElement} - */ -const StatusBox = crUiDefine(function() { - const node = $('status-box-template').cloneNode(true); - node.removeAttribute('id'); - return node; -}); - -StatusBox.prototype = { - // Set up the prototype chain. - __proto__: HTMLFieldSetElement.prototype, - - /** - * Initialization function for the cr.ui framework. - */ - decorate() {}, - - /** - * Sets the text of a particular named label element in the status box - * and updates the visibility if needed. - * @param {string} labelName The name of the label element that is being - * updated. - * @param {string} labelValue The new text content for the label. - * @param {boolean=} needsToBeShown True if we want to show the label - * False otherwise. - */ - setLabelAndShow_(labelName, labelValue, needsToBeShown = true) { - const labelElement = this.querySelector(labelName); - labelElement.textContent = labelValue ? ' ' + labelValue : ''; - if (needsToBeShown) { - labelElement.parentElement.hidden = false; - } - }, - /** - * Populate the box with the given cloud policy status. - * @param {string} scope The policy scope, either "device", "machine", - * "user", or "updater". - * @param {Object} status Dictionary with information about the status. - */ - initialize(scope, status) { - const notSpecifiedString = loadTimeData.getString('notSpecified'); - - // Set appropriate box legend based on status key - this.querySelector('.legend').textContent = - loadTimeData.getString(status.boxLegendKey); - - if (scope === 'device') { - // Populate the device naming information. - // Populate the asset identifier. - this.setLabelAndShow_('.asset-id', status.assetId || notSpecifiedString); - - // Populate the device location. - this.setLabelAndShow_('.location', status.location || notSpecifiedString); - - // Populate the directory API ID. - this.setLabelAndShow_( - '.directory-api-id', status.directoryApiId || notSpecifiedString); - this.setLabelAndShow_('.client-id', status.clientId); - // For off-hours policy, indicate if it's active or not. - if (status.isOffHoursActive != null) { - this.setLabelAndShow_( - '.is-offhours-active', - loadTimeData.getString( - status.isOffHoursActive ? 'offHoursActive' : - 'offHoursNotActive')); - } - } else if (scope === 'machine') { - this.setLabelAndShow_('.machine-enrollment-device-id', status.deviceId); - this.setLabelAndShow_( - '.machine-enrollment-token', status.enrollmentToken); - if (status.machine) { - this.setLabelAndShow_('.machine-enrollment-name', status.machine); - } - this.setLabelAndShow_('.machine-enrollment-domain', status.domain); - } else if (scope === 'updater') { - if (status.version) { - this.setLabelAndShow_('.version', status.version); - } - if (status.domain) { - this.setLabelAndShow_('.machine-enrollment-domain', status.domain); - } - } else { - // Populate the topmost item with the username. - this.setLabelAndShow_('.username', status.username); - // Populate the user gaia id. - this.setLabelAndShow_('.gaia-id', status.gaiaId || notSpecifiedString); - this.setLabelAndShow_('.client-id', status.clientId); - if (status.isAffiliated != null) { - this.setLabelAndShow_( - '.is-affiliated', - loadTimeData.getString( - status.isAffiliated ? 'isAffiliatedYes' : 'isAffiliatedNo')); - } - } - - if (status.enterpriseDomainManager) { - this.setLabelAndShow_('.managed-by', status.enterpriseDomainManager); - } - - if (status.timeSinceLastFetchAttempt) { - this.setLabelAndShow_( - '.time-since-last-fetch-attempt', status.timeSinceLastFetchAttempt); - } - - if (status.timeSinceLastRefresh) { - this.setLabelAndShow_( - '.time-since-last-refresh', status.timeSinceLastRefresh); - } - - if (scope !== 'updater') { - if (status.refreshInterval) { - this.setLabelAndShow_('.refresh-interval', status.refreshInterval); - } - this.setLabelAndShow_('.status', status.status); - this.setLabelAndShow_( - '.policy-push', - loadTimeData.getString( - status.policiesPushAvailable ? 'policiesPushOn' : - 'policiesPushOff')); - } - - if (status.lastCloudReportSentTimestamp) { - this.setLabelAndShow_( - '.last-cloud-report-sent-timestamp', - status.lastCloudReportSentTimestamp + ' (' + - status.timeSinceLastCloudReportSent + ')'); - } - }, -}; - -/** - * A single policy conflict's entry in the policy table. - * @constructor - * @extends {HTMLDivElement} - */ -const PolicyConflict = crUiDefine(function() { - const node = $('policy-conflict-template').cloneNode(true); - node.removeAttribute('id'); - return node; -}); - -PolicyConflict.prototype = { - // Set up the prototype chain. - __proto__: HTMLDivElement.prototype, - - decorate() {}, - - /** - * @param {Conflict} conflict - * @param {string} row_label - */ - initialize(conflict, row_label) { - this.querySelector('.scope').textContent = loadTimeData.getString( - conflict.scope === 'user' ? 'scopeUser' : 'scopeDevice'); - this.querySelector('.level').textContent = loadTimeData.getString( - conflict.level === 'recommended' ? 'levelRecommended' : - 'levelMandatory'); - this.querySelector('.source').textContent = - loadTimeData.getString(conflict.source); - this.querySelector('.value').textContent = conflict.value; - this.querySelector('.name').textContent = loadTimeData.getString(row_label); - } -}; - -/** - * A single policy's row entry in the policy table. - * @constructor - * @extends {HTMLDivElement} - */ -const PolicyRow = crUiDefine(function() { - const node = $('policy-template').cloneNode(true); - node.removeAttribute('id'); - return node; -}); - -PolicyRow.prototype = { - // Set up the prototype chain. - __proto__: HTMLDivElement.prototype, - - /** - * Initialization function for the cr.ui framework. - */ - decorate() { - const toggle = this.querySelector('.policy.row .toggle'); - toggle.addEventListener('click', () => this.toggleExpanded_()); - - const copy = this.querySelector('.copy-value'); - copy.addEventListener('click', () => this.copyValue_()); - }, - - /** @param {Policy} policy */ - initialize(policy) { - /** @type {Policy} */ - this.policy = policy; - - /** @private {boolean} */ - this.unset_ = policy.value === undefined; - - /** @private {boolean} */ - this.hasErrors_ = !!policy.error; - - /** @private {boolean} */ - this.hasWarnings_ = !!policy.warning; - - /** @private {boolean} */ - this.hasInfos_ = !!policy.info; - - /** @private {boolean} */ - this.hasConflicts_ = !!policy.conflicts; - - /** @private {boolean} */ - this.hasSuperseded_ = !!policy.superseded; - - /** @private {boolean} */ - this.isMergedValue_ = !!policy.allSourcesMerged; - - /** @private {boolean} */ - this.deprecated_ = !!policy.deprecated; - - /** @private {boolean} */ - this.future_ = !!policy.future; - - // Populate the name column. - const nameDisplay = this.querySelector('.name .link span'); - nameDisplay.textContent = policy.name; - if (policy.link) { - const link = this.querySelector('.name .link'); - link.href = policy.link; - link.title = loadTimeData.getStringF('policyLearnMore', policy.name); - } else { - this.classList.add('no-help-link'); - } - - // Populate the remaining columns with policy scope, level and value if a - // value has been set. Otherwise, leave them blank. - if (!this.unset_) { - const scopeDisplay = this.querySelector('.scope'); - scopeDisplay.textContent = loadTimeData.getString( - policy.scope === 'user' ? 'scopeUser' : 'scopeDevice'); - - const levelDisplay = this.querySelector('.level'); - levelDisplay.textContent = loadTimeData.getString( - policy.level === 'recommended' ? 'levelRecommended' : - 'levelMandatory'); - - const sourceDisplay = this.querySelector('.source'); - sourceDisplay.textContent = loadTimeData.getString(policy.source); - // Reduces load on the DOM for long values; - const truncatedValue = - (policy.value && policy.value.toString().length > 256) ? - `${policy.value.toString().substr(0, 256)}\u2026` : - policy.value; - - const valueDisplay = this.querySelector('.value'); - valueDisplay.textContent = truncatedValue; - - const copyLink = this.querySelector('.copy .link'); - copyLink.title = loadTimeData.getStringF('policyCopyValue', policy.name); - - const valueRowContentDisplay = this.querySelector('.value.row .value'); - valueRowContentDisplay.textContent = policy.value; - - const errorRowContentDisplay = this.querySelector('.errors.row .value'); - errorRowContentDisplay.textContent = policy.error; - const warningRowContentDisplay = - this.querySelector('.warnings.row .value'); - warningRowContentDisplay.textContent = policy.warning; - const infoRowContentDisplay = this.querySelector('.infos.row .value'); - infoRowContentDisplay.textContent = policy.info; - - const messagesDisplay = this.querySelector('.messages'); - const errorsNotice = - this.hasErrors_ ? loadTimeData.getString('error') : ''; - const deprecationNotice = - this.deprecated_ ? loadTimeData.getString('deprecated') : ''; - const futureNotice = this.future_ ? loadTimeData.getString('future') : ''; - const warningsNotice = - this.hasWarnings_ ? loadTimeData.getString('warning') : ''; - const conflictsNotice = this.hasConflicts_ && !this.isMergedValue_ ? - loadTimeData.getString('conflict') : - ''; - const ignoredNotice = - this.policy.ignored ? loadTimeData.getString('ignored') : ''; - let notice = - [ - errorsNotice, deprecationNotice, futureNotice, warningsNotice, - ignoredNotice, conflictsNotice - ].filter(x => !!x) - .join(', ') || - loadTimeData.getString('ok'); - const supersededNotice = this.hasSuperseded_ && !this.isMergedValue_ ? - loadTimeData.getString('superseding') : - ''; - if (supersededNotice) { - // Include superseded notice regardless of other notices - notice += `, ${supersededNotice}`; - } - messagesDisplay.textContent = notice; - - if (policy.conflicts) { - policy.conflicts.forEach(conflict => { - const row = new PolicyConflict(); - row.initialize(conflict, 'conflictValue'); - this.appendChild(row); - }); - } - if (policy.superseded) { - policy.superseded.forEach(superseded => { - const row = new PolicyConflict(); - row.initialize(superseded, 'supersededValue'); - this.appendChild(row); - }); - } - } else { - const messagesDisplay = this.querySelector('.messages'); - messagesDisplay.textContent = loadTimeData.getString('unset'); - } - }, - - /** - * Copies the policy's value to the clipboard. - * @private - */ - copyValue_() { - const policyValueDisplay = this.querySelector('.value.row .value'); - - // Select the text that will be copied. - const selection = window.getSelection(); - const range = window.document.createRange(); - range.selectNodeContents(policyValueDisplay); - selection.removeAllRanges(); - selection.addRange(range); - - // Copy the policy value to the clipboard. - navigator.clipboard.writeText(policyValueDisplay.innerText).catch(error => { - console.error('Unable to copy policy value to clipboard:', error); - }); - }, - - /** - * Toggle the visibility of an additional row containing the complete text. - * @private - */ - toggleExpanded_() { - const warningRowDisplay = this.querySelector('.warnings.row'); - const errorRowDisplay = this.querySelector('.errors.row'); - const infoRowDisplay = this.querySelector('.infos.row'); - const valueRowDisplay = this.querySelector('.value.row'); - valueRowDisplay.hidden = !valueRowDisplay.hidden; - if (valueRowDisplay.hidden) { - this.classList.remove('expanded'); - } else { - this.classList.add('expanded'); - } - - this.querySelector('.show-more').hidden = !valueRowDisplay.hidden; - this.querySelector('.show-less').hidden = valueRowDisplay.hidden; - if (this.hasWarnings_) { - warningRowDisplay.hidden = !warningRowDisplay.hidden; - } - if (this.hasErrors_) { - errorRowDisplay.hidden = !errorRowDisplay.hidden; - } - if (this.hasInfos_) { - infoRowDisplay.hidden = !infoRowDisplay.hidden; - } - this.querySelectorAll('.policy-conflict-data') - .forEach(row => row.hidden = !row.hidden); - this.querySelectorAll('.policy-superseded-data') - .forEach(row => row.hidden = !row.hidden); - }, -}; - -/** - * A row describing the current policy precedence. - * @constructor - * @extends {HTMLDivElement} - */ -const PolicyPrecedenceRow = crUiDefine(function() { - const node = $('policy-precedence-template').cloneNode(true); - node.removeAttribute('id'); - return node; -}); - -PolicyPrecedenceRow.prototype = { - // Set up the prototype chain. - __proto__: HTMLDivElement.prototype, - - decorate() {}, - - /** - * @param {Array<String>} precedenceOrder Array containing ordered strings - * which represent the order of policy precedence. - */ - initialize(precedenceOrder) { - this.querySelector('.precedence.row > .value').textContent = - precedenceOrder.join(' > '); - } -}; - -/** - * A table of policies and their values. - * @constructor - * @extends {HTMLDivElement} - */ -const PolicyTable = crUiDefine(function() { - const node = $('policy-table-template').cloneNode(true); - node.removeAttribute('id'); - return node; -}); - - -PolicyTable.prototype = { - // Set up the prototype chain. - __proto__: HTMLDivElement.prototype, - - /** - * Initialization function for the cr.ui framework. - */ - decorate() { - this.policies_ = {}; - this.filterPattern_ = ''; - }, - - /** @param {PolicyTableModel} dataModel */ - update(dataModel) { - // Clear policies - const mainContent = this.querySelector('.main'); - const policies = this.querySelectorAll('.policy-data'); - this.querySelector('.header').textContent = dataModel.name; - this.querySelector('.id').textContent = dataModel.id; - this.querySelector('.id').hidden = !dataModel.id; - policies.forEach(row => mainContent.removeChild(row)); - - dataModel.policies - .sort((a, b) => { - if ((a.value !== undefined && b.value !== undefined) || - a.value === b.value) { - if (a.link !== undefined && b.link !== undefined) { - // Sorting the policies in ascending alpha order. - return a.name > b.name ? 1 : -1; - } - - // Sorting so unknown policies are last. - return a.link !== undefined ? -1 : 1; - } - - // Sorting so unset values are last. - return a.value !== undefined ? -1 : 1; - }) - .forEach(policy => { - const policyRow = new PolicyRow(); - policyRow.initialize(policy); - mainContent.appendChild(policyRow); - }); - this.filter(); - - // Show the current policy precedence order in the Policy Precedence table. - if (dataModel.name === 'Policy Precedence') { - // Clear previous precedence row. - const precedenceRowOld = this.querySelectorAll('.policy-precedence-data'); - precedenceRowOld.forEach(row => mainContent.removeChild(row)); - - const precedenceRow = new PolicyPrecedenceRow(); - precedenceRow.initialize(dataModel.precedenceOrder); - mainContent.appendChild(precedenceRow); - } - }, - - /** - * Set the filter pattern. Only policies whose name contains |pattern| are - * shown in the policy table. The filter is case insensitive. It can be - * disabled by setting |pattern| to an empty string. - * @param {string} pattern The filter pattern. - */ - setFilterPattern(pattern) { - this.filterPattern_ = pattern.toLowerCase(); - this.filter(); - }, - - /** - * Filter policies. Only policies whose name contains the filter pattern are - * shown in the table. Furthermore, policies whose value is not currently - * set are only shown if the corresponding checkbox is checked. - */ - filter() { - const showUnset = $('show-unset').checked; - const policies = this.querySelectorAll('.policy-data'); - for (let i = 0; i < policies.length; i++) { - const policyDisplay = policies[i]; - policyDisplay.hidden = - policyDisplay.policy.value === undefined && !showUnset || - policyDisplay.policy.name.toLowerCase().indexOf( - this.filterPattern_) === -1; - } - this.querySelector('.no-policy').hidden = - !!this.querySelector('.policy-data:not([hidden])'); - }, -}; - -/** * A singleton object that handles communication between browser and WebUI. */ export class Page { @@ -710,7 +166,7 @@ createOrUpdatePolicyTable(dataModel) { const id = `${dataModel.name}-${dataModel.id}`; if (!this.policyTables[id]) { - this.policyTables[id] = new PolicyTable(); + this.policyTables[id] = document.createElement('policy-table'); this.mainSection.appendChild(this.policyTables[id]); } this.policyTables[id].update(dataModel); @@ -733,7 +189,7 @@ // Add a status box for each scope that has a cloud policy status. for (const scope in status) { - const box = new StatusBox(); + const box = document.createElement('status-box'); box.initialize(scope, status[scope]); container.appendChild(box); // Show the status section.
diff --git a/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.html b/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.html index 685ee88..24a3d63 100644 --- a/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.html +++ b/components/safe_browsing/content/browser/web_ui/resources/safe_browsing.html
@@ -14,7 +14,7 @@ <div slot="tab" id="preferences">Preferences</div> <div slot="tab" id="db-manager">Database Manager</div> <div slot="tab" id="hash-cache">Hash Cache</div> - <div slot="tab" id="csbrr">ClientSafeBrowsingReportRequests</div> + <div slot="tab" id="csbrr">Client Safe Browsing Report Requests</div> <div slot="tab" id="download-protection">Download Protection</div> <div slot="tab" id="cpr">Client Phishing Requests</div> <div slot="tab" id="password-protection">Password Protection</div>
diff --git a/components/segmentation_platform/README.md b/components/segmentation_platform/README.md index 687eeaf..7fbe54b 100644 --- a/components/segmentation_platform/README.md +++ b/components/segmentation_platform/README.md
@@ -41,7 +41,7 @@ To update the list of tests, you can run the following command: ``` -for test in $(git grep -E '^TEST(_F)?\(' -- components/segmentation_platform | \ +for test in $(git grep -E '^TEST(_F)?\(' -- components/segmentation_platform/**.cc | \ cut -d"(" -f 2 | cut -d"," -f 1 | sort | uniq); do echo ${test}.* ; done > \ components/segmentation_platform/components_unittests.filter ```
diff --git a/components/segmentation_platform/internal/database/ukm_database_backend.cc b/components/segmentation_platform/internal/database/ukm_database_backend.cc index 2cde5ba..8a7bd1138 100644 --- a/components/segmentation_platform/internal/database/ukm_database_backend.cc +++ b/components/segmentation_platform/internal/database/ukm_database_backend.cc
@@ -47,6 +47,9 @@ case processing::ProcessedValue::Type::INT64: statement.BindInt64(i, value.int64_val); break; + case processing::ProcessedValue::Type::URL: + statement.BindString(i, UkmUrlTable::GetDatabaseUrlString(*value.url)); + break; case processing::ProcessedValue::Type::UNKNOWN: NOTREACHED(); }
diff --git a/components/segmentation_platform/internal/database/ukm_types.cc b/components/segmentation_platform/internal/database/ukm_types.cc index 8786b77..652de399 100644 --- a/components/segmentation_platform/internal/database/ukm_types.cc +++ b/components/segmentation_platform/internal/database/ukm_types.cc
@@ -6,43 +6,4 @@ namespace segmentation_platform::processing { -ProcessedValue::ProcessedValue(bool val) : type(Type::BOOL), bool_val(val) {} -ProcessedValue::ProcessedValue(int val) : type(Type::INT), int_val(val) {} -ProcessedValue::ProcessedValue(float val) : type(Type::FLOAT), float_val(val) {} -ProcessedValue::ProcessedValue(double val) - : type(Type::DOUBLE), double_val(val) {} -ProcessedValue::ProcessedValue(const std::string& val) - : type(Type::STRING), str_val(val) {} -ProcessedValue::ProcessedValue(base::Time val) - : type(Type::TIME), time_val(val) {} -ProcessedValue::ProcessedValue(int64_t val) - : type(Type::INT64), int64_val(val) {} - -ProcessedValue::ProcessedValue(const ProcessedValue& other) = default; -ProcessedValue& ProcessedValue::operator=(const ProcessedValue& other) = - default; - -bool ProcessedValue::operator==(const ProcessedValue& rhs) const { - if (type != rhs.type) - return false; - switch (type) { - case Type::UNKNOWN: - return false; - case Type::BOOL: - return bool_val == rhs.bool_val; - case Type::INT: - return int_val == rhs.int_val; - case Type::FLOAT: - return float_val == rhs.float_val; - case Type::DOUBLE: - return double_val == rhs.double_val; - case Type::STRING: - return str_val == rhs.str_val; - case Type::TIME: - return time_val == rhs.time_val; - case Type::INT64: - return int64_val == rhs.int64_val; - } -} - } // namespace segmentation_platform::processing
diff --git a/components/segmentation_platform/internal/database/ukm_types.h b/components/segmentation_platform/internal/database/ukm_types.h index 5b94a59..5ec5c813 100644 --- a/components/segmentation_platform/internal/database/ukm_types.h +++ b/components/segmentation_platform/internal/database/ukm_types.h
@@ -12,6 +12,7 @@ #include "base/containers/flat_set.h" #include "base/time/time.h" #include "base/types/id_type.h" +#include "components/segmentation_platform/public/types/processed_value.h" namespace segmentation_platform { @@ -27,46 +28,6 @@ namespace processing { -// A struct that can accommodate multiple output types needed for Segmentation -// metadata's feature processing. It can only hold one value at a time with the -// corresponding type. -struct ProcessedValue { - explicit ProcessedValue(bool val); - explicit ProcessedValue(int val); - explicit ProcessedValue(float val); - explicit ProcessedValue(double val); - explicit ProcessedValue(const std::string& val); - explicit ProcessedValue(base::Time val); - explicit ProcessedValue(int64_t val); - - ProcessedValue(const ProcessedValue& other); - ProcessedValue& operator=(const ProcessedValue& other); - - bool operator==(const ProcessedValue& rhs) const; - - enum Type { - UNKNOWN = 0, - BOOL = 1, - INT = 2, - FLOAT = 3, - DOUBLE = 4, - STRING = 5, - TIME = 6, - INT64 = 7, - }; - Type type{UNKNOWN}; - bool bool_val{false}; - int int_val{0}; - float float_val{0}; - double double_val{0}; - std::string str_val; - base::Time time_val; - int64_t int64_val{0}; -}; - -// Represents a set of values that can represent inputs or outputs for a model. -using Tensor = std::vector<ProcessedValue>; - // Intermediate representation of processed features from the metadata queries. using FeatureIndex = int; using IndexedTensors = base::flat_map<FeatureIndex, Tensor>;
diff --git a/components/segmentation_platform/internal/database/ukm_url_table.cc b/components/segmentation_platform/internal/database/ukm_url_table.cc index a91ef06..0124adf 100644 --- a/components/segmentation_platform/internal/database/ukm_url_table.cc +++ b/components/segmentation_platform/internal/database/ukm_url_table.cc
@@ -23,10 +23,15 @@ UkmUrlTable::~UkmUrlTable() = default; // static +std::string UkmUrlTable::GetDatabaseUrlString(const GURL& url) { + return database_utils::GurlToDatabaseUrl(url); +} + +// static UrlId UkmUrlTable::GenerateUrlId(const GURL& url) { // Converts the 8-byte prefix of an MD5 hash into a int64_t value. This // hashing scheme is architecture dependent. - std::string db_url = database_utils::GurlToDatabaseUrl(url); + std::string db_url = GetDatabaseUrlString(url); base::MD5Digest digest; base::MD5Sum(db_url.data(), db_url.size(), &digest); int64_t hash;
diff --git a/components/segmentation_platform/internal/database/ukm_url_table.h b/components/segmentation_platform/internal/database/ukm_url_table.h index 7e08977..033409c1 100644 --- a/components/segmentation_platform/internal/database/ukm_url_table.h +++ b/components/segmentation_platform/internal/database/ukm_url_table.h
@@ -27,6 +27,9 @@ UkmUrlTable(UkmUrlTable&) = delete; UkmUrlTable& operator=(UkmUrlTable&) = delete; + // Converts the given GURL to string. + static std::string GetDatabaseUrlString(const GURL& url); + // Returns an ID for the URL. The ID will be a persistent hash of the `url`. static UrlId GenerateUrlId(const GURL& url);
diff --git a/components/segmentation_platform/public/BUILD.gn b/components/segmentation_platform/public/BUILD.gn index 859a5d68..93d1bbb 100644 --- a/components/segmentation_platform/public/BUILD.gn +++ b/components/segmentation_platform/public/BUILD.gn
@@ -26,6 +26,8 @@ "trigger.h", "trigger_context.cc", "trigger_context.h", + "types/processed_value.cc", + "types/processed_value.h", ] public_deps = [ "//components/segmentation_platform/public/proto" ] @@ -33,6 +35,7 @@ deps = [ "//base", "//components/keyed_service/core", + "//url", ] if (is_android) {
diff --git a/components/segmentation_platform/public/types/processed_value.cc b/components/segmentation_platform/public/types/processed_value.cc new file mode 100644 index 0000000..9a051a2 --- /dev/null +++ b/components/segmentation_platform/public/types/processed_value.cc
@@ -0,0 +1,87 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/segmentation_platform/public/types/processed_value.h" + +namespace segmentation_platform::processing { + +ProcessedValue::ProcessedValue(bool val) : type(Type::BOOL), bool_val(val) {} +ProcessedValue::ProcessedValue(int val) : type(Type::INT), int_val(val) {} +ProcessedValue::ProcessedValue(float val) : type(Type::FLOAT), float_val(val) {} +ProcessedValue::ProcessedValue(double val) + : type(Type::DOUBLE), double_val(val) {} +ProcessedValue::ProcessedValue(const std::string& val) + : type(Type::STRING), str_val(val) {} +ProcessedValue::ProcessedValue(base::Time val) + : type(Type::TIME), time_val(val) {} +ProcessedValue::ProcessedValue(int64_t val) + : type(Type::INT64), int64_val(val) {} +ProcessedValue::ProcessedValue(const GURL& val) + : url(std::make_unique<GURL>(val)) {} + +ProcessedValue::ProcessedValue(const ProcessedValue& other) { + *this = other; +} +ProcessedValue::ProcessedValue(ProcessedValue&& other) = default; + +ProcessedValue& ProcessedValue::operator=(const ProcessedValue& other) { + type = other.type; + switch (type) { + case Type::UNKNOWN: + return *this; + case Type::BOOL: + bool_val = other.bool_val; + return *this; + case Type::INT: + int_val = other.int_val; + return *this; + case Type::FLOAT: + float_val = other.float_val; + return *this; + case Type::DOUBLE: + double_val = other.double_val; + return *this; + case Type::STRING: + str_val = other.str_val; + return *this; + case Type::TIME: + time_val = other.time_val; + return *this; + case Type::INT64: + int64_val = other.int64_val; + return *this; + case Type::URL: + url = std::make_unique<GURL>(*url); + return *this; + } +} + +ProcessedValue::~ProcessedValue() = default; + +bool ProcessedValue::operator==(const ProcessedValue& rhs) const { + if (type != rhs.type) + return false; + switch (type) { + case Type::UNKNOWN: + return false; + case Type::BOOL: + return bool_val == rhs.bool_val; + case Type::INT: + return int_val == rhs.int_val; + case Type::FLOAT: + return float_val == rhs.float_val; + case Type::DOUBLE: + return double_val == rhs.double_val; + case Type::STRING: + return str_val == rhs.str_val; + case Type::TIME: + return time_val == rhs.time_val; + case Type::INT64: + return int64_val == rhs.int64_val; + case Type::URL: + return *url == *rhs.url; + } +} + +} // namespace segmentation_platform::processing
diff --git a/components/segmentation_platform/public/types/processed_value.h b/components/segmentation_platform/public/types/processed_value.h new file mode 100644 index 0000000..35c0b0b --- /dev/null +++ b/components/segmentation_platform/public/types/processed_value.h
@@ -0,0 +1,62 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_TYPES_PROCESSED_VALUE_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_TYPES_PROCESSED_VALUE_H_ + +#include <string> + +#include "base/time/time.h" +#include "url/gurl.h" + +namespace segmentation_platform::processing { + +// A struct that can accommodate multiple output types needed for Segmentation +// metadata's feature processing. It can only hold one value at a time with the +// corresponding type. +struct ProcessedValue { + explicit ProcessedValue(bool val); + explicit ProcessedValue(int val); + explicit ProcessedValue(float val); + explicit ProcessedValue(double val); + explicit ProcessedValue(const std::string& val); + explicit ProcessedValue(base::Time val); + explicit ProcessedValue(int64_t val); + explicit ProcessedValue(const GURL& url); + + ProcessedValue(const ProcessedValue& other); + ProcessedValue(ProcessedValue&& other); + ProcessedValue& operator=(const ProcessedValue& other); + ~ProcessedValue(); + + bool operator==(const ProcessedValue& rhs) const; + + enum Type { + UNKNOWN = 0, + BOOL = 1, + INT = 2, + FLOAT = 3, + DOUBLE = 4, + STRING = 5, + TIME = 6, + INT64 = 7, + URL = 8, + }; + Type type{UNKNOWN}; + bool bool_val{false}; + int int_val{0}; + float float_val{0}; + double double_val{0}; + std::string str_val; + base::Time time_val; + int64_t int64_val{0}; + std::unique_ptr<GURL> url; +}; + +// Represents a set of values that can represent inputs or outputs for a model. +using Tensor = std::vector<ProcessedValue>; + +} // namespace segmentation_platform::processing + +#endif // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_TYPES_PROCESSED_VALUE_H_
diff --git a/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc b/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc index dd071fa4..18ae0ad 100644 --- a/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc +++ b/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc
@@ -844,7 +844,7 @@ EXPECT_EQ(2, LengthSync(kOrigin1)); EXPECT_EQ(OperationResult::kSuccess, DeleteSync(kOrigin1, u"key1")); - EXPECT_FALSE(GetSync(kOrigin1, u"key1").data); + EXPECT_EQ(OperationResult::kKeyNotFound, GetSync(kOrigin1, u"key1").result); EXPECT_EQ(1, LengthSync(kOrigin1)); EXPECT_EQ(OperationResult::kSet, AppendSync(kOrigin1, u"key1", u"value1")); @@ -1466,8 +1466,8 @@ EXPECT_FALSE(open1); EXPECT_EQ(InitStatus::kUnattempted, status1); - EXPECT_FALSE(value1.data); - EXPECT_EQ(OperationResult::kSuccess, value1.result); + EXPECT_TRUE(value1.data.empty()); + EXPECT_EQ(OperationResult::kKeyNotFound, value1.result); EXPECT_EQ(!GetParam().in_memory_only, open2); EXPECT_EQ(InitStatus::kUnattempted, status2);
diff --git a/components/services/storage/shared_storage/shared_storage_database.cc b/components/services/storage/shared_storage/shared_storage_database.cc index 049c2e7..704a3a8 100644 --- a/components/services/storage/shared_storage/shared_storage_database.cc +++ b/components/services/storage/shared_storage/shared_storage_database.cc
@@ -166,10 +166,10 @@ GetResult result; if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) { - // We do not return an error if the database doesn't exist, but only if it - // pre-exists on disk and yet fails to initialize. + // We do not return `OperationResult::kInitFailure` if the database doesn't + // exist, but only if it pre-exists on disk and yet fails to initialize. if (db_status_ == InitStatus::kUnattempted) - result.result = OperationResult::kSuccess; + result.result = OperationResult::kKeyNotFound; else result.result = OperationResult::kInitFailure; @@ -189,13 +189,18 @@ statement.BindString(0, origin_str); statement.BindString16(1, key); - if (statement.Step()) + bool key_found = false; + if (statement.Step()) { result.data = statement.ColumnString16(0); - if (!statement.Succeeded()) + key_found = true; + } else if (!statement.Succeeded()) { return result; + } - if (UpdateLastUsedTime(origin_str)) - result.result = OperationResult::kSuccess; + if (UpdateLastUsedTime(origin_str)) { + result.result = + key_found ? OperationResult::kSuccess : OperationResult::kKeyNotFound; + } return result; } @@ -265,14 +270,16 @@ return OperationResult::kSqlError; GetResult get_result = Get(context_origin, key); - if (get_result.result != OperationResult::kSuccess) + if (get_result.result != OperationResult::kSuccess && + get_result.result != OperationResult::kKeyNotFound) { return OperationResult::kSqlError; + } std::u16string new_value; std::string origin_str(SerializeOrigin(context_origin)); - if (get_result.data) { - new_value = std::move(*get_result.data); + if (get_result.result == OperationResult::kSuccess) { + new_value = std::move(get_result.data); new_value.append(tail_value); if (new_value.size() > max_string_length_)
diff --git a/components/services/storage/shared_storage/shared_storage_database.h b/components/services/storage/shared_storage/shared_storage_database.h index 24377c9..6155a18 100644 --- a/components/services/storage/shared_storage/shared_storage_database.h +++ b/components/services/storage/shared_storage/shared_storage_database.h
@@ -100,12 +100,14 @@ // requesting origin. kInvalidAppend = 6, // Result if the length of the value after appending // would exceed the maximum allowed length. + kKeyNotFound = 7, // Result if a key could not be retrieved via `Get()` + // because it doesn't exist in the database. }; // Bundles a retrieved string from the database along with a field indicating // whether the transaction was free of SQL errors. struct GetResult { - absl::optional<std::u16string> data; + std::u16string data; OperationResult result = OperationResult::kSqlError; GetResult(); GetResult(const GetResult&) = delete;
diff --git a/components/services/storage/shared_storage/shared_storage_database_unittest.cc b/components/services/storage/shared_storage/shared_storage_database_unittest.cc index 132366a..61e3a2a 100644 --- a/components/services/storage/shared_storage/shared_storage_database_unittest.cc +++ b/components/services/storage/shared_storage/shared_storage_database_unittest.cc
@@ -407,13 +407,14 @@ EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"value2"); EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin1, u"key1")); - EXPECT_FALSE(db_->Get(kOrigin1, u"key1").data); + EXPECT_EQ(OperationResult::kKeyNotFound, db_->Get(kOrigin1, u"key1").result); - // Check that trying to retrieve the empty key doesn't give an error, even - // though the input is invalid and no value is found. + // Check that trying to retrieve the empty key returns + // `OperationResult::kKeyNotFound` rather than `OperationResult::kSqlError`, + // even though the input is considered invalid. GetResult result = db_->Get(kOrigin1, u""); - EXPECT_EQ(OperationResult::kSuccess, result.result); - EXPECT_FALSE(result.data); + EXPECT_EQ(OperationResult::kKeyNotFound, result.result); + EXPECT_TRUE(result.data.empty()); // Check that trying to delete the empty key doesn't give an error, even // though the input is invalid and no value is found to delete.
diff --git a/components/services/storage/shared_storage/shared_storage_manager_unittest.cc b/components/services/storage/shared_storage/shared_storage_manager_unittest.cc index 1fd66a7..7c798ee 100644 --- a/components/services/storage/shared_storage/shared_storage_manager_unittest.cc +++ b/components/services/storage/shared_storage/shared_storage_manager_unittest.cc
@@ -969,7 +969,7 @@ EXPECT_EQ(GetSync(kOrigin1, u"key1").data, u"value2"); EXPECT_EQ(OperationResult::kSuccess, DeleteSync(kOrigin1, u"key1")); - EXPECT_FALSE(GetSync(kOrigin1, u"key1").data); + EXPECT_EQ(OperationResult::kKeyNotFound, GetSync(kOrigin1, u"key1").result); } TEST_P(SharedStorageManagerParamTest, IgnoreIfPresent) {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index d7c4983..67912374 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -408,6 +408,8 @@ "attribution_reporting/attribution_default_random_generator.h", "attribution_reporting/attribution_filter_data.cc", "attribution_reporting/attribution_filter_data.h", + "attribution_reporting/attribution_header_utils.cc", + "attribution_reporting/attribution_header_utils.h", "attribution_reporting/attribution_host.cc", "attribution_reporting/attribution_host.h", "attribution_reporting/attribution_info.cc",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc index 27a1f1e..2a9ed273 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -120,6 +120,74 @@ *runtime_id_out = runtime_id.Release(); } +void GetUIARoot(ui::AXPlatformNodeDelegate* start, + IUIAutomation* uia, + IUIAutomationElement** root) { + content::BrowserAccessibility* start_internal = + content::BrowserAccessibility::FromAXPlatformNodeDelegate(start); + // Start by getting the root element for the HWND hosting the web content. + HWND hwnd = start_internal->manager() + ->GetRoot() + ->GetTargetForNativeAccessibilityEvent(); + uia->ElementFromHandle(hwnd, root); +} + +void GetUIAElementFromDelegate(ui::AXPlatformNodeDelegate* start, + IUIAutomation* uia, + IUIAutomationElement** element) { + // We use the UI Automation client API to produce the tree dump, but + // BrowserAccessibility has a pointer to a provider API implementation, and + // we can't directly relate the two -- the OS manages the relationship. + // To locate the client element we want, we'll construct a RuntimeId + // corresponding to our provider element, then search for that. + Microsoft::WRL::ComPtr<IUIAutomationElement> root; + GetUIARoot(start, uia, &root); + CHECK(root.Get()); + + // The root element is provided by AXFragmentRootWin, whose RuntimeId is not + // in the same form as elements provided by BrowserAccessibility. + // Find the root element's first child, which should be provided by + // BrowserAccessibility. We'll use that element's RuntimeId as a template for + // the RuntimeId of the element we're looking for. + Microsoft::WRL::ComPtr<IUIAutomationTreeWalker> tree_walker; + uia->get_RawViewWalker(&tree_walker); + Microsoft::WRL::ComPtr<IUIAutomationElement> first_child; + tree_walker->GetFirstChildElement(root.Get(), &first_child); + CHECK(first_child.Get()); + + // Get first_child's RuntimeId and swap out the last element in its SAFEARRAY + // for the UniqueId of the element we want to start from. + Microsoft::WRL::ComPtr<IUnknown> start_unknown = + content::BrowserAccessibility::FromAXPlatformNodeDelegate(start) + ->GetNativeViewAccessible(); + Microsoft::WRL::ComPtr<IRawElementProviderFragment> start_fragment; + start_unknown.As(&start_fragment); + CHECK(start_fragment.Get()); + base::win::ScopedSafearray uia_runtime_id; + GetUIARuntimeId(first_child.Get(), start_fragment.Get(), + uia_runtime_id.Receive()); + + // Find the element with the desired RuntimeId. + base::win::ScopedVariant runtime_id_variant(uia_runtime_id.Release()); + Microsoft::WRL::ComPtr<IUIAutomationCondition> condition; + uia->CreatePropertyCondition(UIA_RuntimeIdPropertyId, runtime_id_variant, + &condition); + CHECK(condition); + + root->FindFirst(TreeScope_Subtree, condition.Get(), element); +} + +RECT GetUIARootBounds(ui::AXPlatformNodeDelegate* delegate, + IUIAutomation* uia) { + Microsoft::WRL::ComPtr<IUIAutomationElement> root; + GetUIARoot(delegate, uia, &root); + CHECK(root.Get()); + RECT root_bounds = {0}; + root->get_CurrentBoundingRectangle(&root_bounds); + + return root_bounds; +} + } // namespace namespace content { @@ -402,58 +470,10 @@ base::Value AccessibilityTreeFormatterUia::BuildTree( ui::AXPlatformNodeDelegate* start) const { - // We use the UI Automation client API to produce the tree dump, but - // BrowserAccessibility has a pointer to a provider API implementation, and - // we can't directly relate the two -- the OS manages the relationship. - // To locate the client element we want, we'll construct a RuntimeId - // corresponding to our provider element, then search for that. - - BrowserAccessibility* start_internal = - BrowserAccessibility::FromAXPlatformNodeDelegate(start); - // Start by getting the root element for the HWND hosting the web content. - HWND hwnd = start_internal->manager() - ->GetRoot() - ->GetTargetForNativeAccessibilityEvent(); - Microsoft::WRL::ComPtr<IUIAutomationElement> root; - uia_->ElementFromHandle(hwnd, &root); - CHECK(root.Get()); - - // Get the bounds of the root element, to pass into tree building later. - RECT root_bounds = {0}; - root->get_CurrentBoundingRectangle(&root_bounds); - - // The root element is provided by AXFragmentRootWin, whose RuntimeId is not - // in the same form as elements provided by BrowserAccessibility. - // Find the root element's first child, which should be provided by - // BrowserAccessibility. We'll use that element's RuntimeId as a template for - // the RuntimeId of the element we're looking for. - Microsoft::WRL::ComPtr<IUIAutomationTreeWalker> tree_walker; - uia_->get_RawViewWalker(&tree_walker); - Microsoft::WRL::ComPtr<IUIAutomationElement> first_child; - tree_walker->GetFirstChildElement(root.Get(), &first_child); - CHECK(first_child.Get()); - - // Get first_child's RuntimeId and swap out the last element in its SAFEARRAY - // for the UniqueId of the element we want to start from. - Microsoft::WRL::ComPtr<IUnknown> start_unknown = - start_internal->GetNativeViewAccessible(); - Microsoft::WRL::ComPtr<IRawElementProviderFragment> start_fragment; - start_unknown.As(&start_fragment); - CHECK(start_fragment.Get()); - base::win::ScopedSafearray uia_runtime_id; - GetUIARuntimeId(first_child.Get(), start_fragment.Get(), - uia_runtime_id.Receive()); - - // Find the element with the desired RuntimeId. - base::win::ScopedVariant runtime_id_variant(uia_runtime_id.Release()); - Microsoft::WRL::ComPtr<IUIAutomationCondition> condition; - uia_->CreatePropertyCondition(UIA_RuntimeIdPropertyId, runtime_id_variant, - &condition); - CHECK(condition); Microsoft::WRL::ComPtr<IUIAutomationElement> start_element; + GetUIAElementFromDelegate(start, uia_.Get(), &start_element); - root->FindFirst(TreeScope_Subtree, condition.Get(), &start_element); - + RECT root_bounds = GetUIARootBounds(start, uia_.Get()); base::DictionaryValue tree; if (start_element.Get()) { // Build an accessibility tree starting from that element. @@ -472,6 +492,9 @@ &is_pane_condition); Microsoft::WRL::ComPtr<IUIAutomationCondition> not_is_pane_condition; uia_->CreateNotCondition(is_pane_condition.Get(), ¬_is_pane_condition); + Microsoft::WRL::ComPtr<IUIAutomationElement> root; + GetUIARoot(start, uia_.Get(), &root); + CHECK(root.Get()); root->FindFirst(TreeScope_Subtree, not_is_pane_condition.Get(), &non_pane_descendant); @@ -502,6 +525,23 @@ return base::Value(base::Value::Type::DICTIONARY); } +base::Value AccessibilityTreeFormatterUia::BuildNode( + ui::AXPlatformNodeDelegate* node) const { + Microsoft::WRL::ComPtr<IUIAutomationElement> uia_element; + GetUIAElementFromDelegate(node, uia_.Get(), &uia_element); + // Note that we have to go through external UIA APIs to get a reference to + // the given node's UIA Element. This requires that the node is marked as + // a content/control element (see IsUIAControl for more details). If you see + // the following CHECK hit, most likely the node is not a UIA control and thus + // not exposed via the Find* APIs. + CHECK(uia_element.Get()); + + RECT root_bounds = GetUIARootBounds(node, uia_.Get()); + base::DictionaryValue tree; + AddProperties(uia_element.Get(), root_bounds.left, root_bounds.top, &tree); + return tree; +} + void AccessibilityTreeFormatterUia::RecursiveBuildTree( IUIAutomationElement* uncached_node, int root_x,
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.h b/content/browser/accessibility/accessibility_tree_formatter_uia_win.h index bab0776..980f7e3 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.h +++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
@@ -28,6 +28,7 @@ base::Value BuildTree(ui::AXPlatformNodeDelegate* start) const override; base::Value BuildTreeForSelector( const AXTreeSelector& selector) const override; + base::Value BuildNode(ui::AXPlatformNodeDelegate* node) const override; protected: void AddDefaultFilters(
diff --git a/content/browser/accessibility/dump_accessibility_node_browsertest.cc b/content/browser/accessibility/dump_accessibility_node_browsertest.cc index 9a53f5e..8bfc8e9 100644 --- a/content/browser/accessibility/dump_accessibility_node_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_node_browsertest.cc
@@ -30,6 +30,7 @@ // Enable MathMLCore for some MathML tests. base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( switches::kEnableBlinkFeatures, "MathMLCore"); + DumpAccessibilityTestBase::SetUpCommandLine(command_line); } std::vector<ui::AXPropertyFilter> DefaultFilters() const override {
diff --git a/content/browser/attribution_reporting/attribution_aggregation_keys.cc b/content/browser/attribution_reporting/attribution_aggregation_keys.cc index 6ac791e..0f1672e 100644 --- a/content/browser/attribution_reporting/attribution_aggregation_keys.cc +++ b/content/browser/attribution_reporting/attribution_aggregation_keys.cc
@@ -9,6 +9,8 @@ #include "base/check.h" #include "base/ranges/algorithm.h" +#include "base/strings/abseil_string_number_conversions.h" +#include "base/values.h" #include "content/browser/attribution_reporting/attribution_reporting.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/attribution_reporting/constants.h" @@ -30,6 +32,43 @@ } // static +absl::optional<AttributionAggregationKeys> AttributionAggregationKeys::FromJSON( + const base::Value* value) { + // TODO(johnidel): Consider logging registration JSON metrics here. + if (!value) + return AttributionAggregationKeys(); + + const base::Value::Dict* dict = value->GetIfDict(); + if (!dict) + return absl::nullopt; + + const size_t num_keys = dict->size(); + + if (num_keys > blink::kMaxAttributionAggregationKeysPerSourceOrTrigger) + return absl::nullopt; + + Keys::container_type keys; + keys.reserve(num_keys); + + for (auto [key_id, value] : *dict) { + if (key_id.size() > blink::kMaxBytesPerAttributionAggregationKeyId) + return absl::nullopt; + + const std::string* s = value.GetIfString(); + if (!s) + return absl::nullopt; + + absl::uint128 key; + if (!base::HexStringToUInt128(*s, &key)) + return absl::nullopt; + + keys.emplace_back(key_id, key); + } + + return AttributionAggregationKeys(Keys(base::sorted_unique, std::move(keys))); +} + +// static absl::optional<AttributionAggregationKeys> AttributionAggregationKeys::Deserialize(const std::string& str) { proto::AttributionAggregatableSource msg;
diff --git a/content/browser/attribution_reporting/attribution_aggregation_keys.h b/content/browser/attribution_reporting/attribution_aggregation_keys.h index f455266..70148342 100644 --- a/content/browser/attribution_reporting/attribution_aggregation_keys.h +++ b/content/browser/attribution_reporting/attribution_aggregation_keys.h
@@ -12,6 +12,10 @@ #include "third_party/abseil-cpp/absl/numeric/int128.h" #include "third_party/abseil-cpp/absl/types/optional.h" +namespace base { +class Value; +} // namespace base + namespace content { class CONTENT_EXPORT AttributionAggregationKeys { @@ -21,6 +25,9 @@ // Returns `absl::nullopt` if `keys` is invalid. static absl::optional<AttributionAggregationKeys> FromKeys(Keys keys); + static absl::optional<AttributionAggregationKeys> FromJSON( + const base::Value*); + // Deserializes `str`, if valid. Returns `absl::nullopt` if not. static absl::optional<AttributionAggregationKeys> Deserialize( const std::string& str);
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager.h b/content/browser/attribution_reporting/attribution_data_host_manager.h index 2d10a31..0a570c9 100644 --- a/content/browser/attribution_reporting/attribution_data_host_manager.h +++ b/content/browser/attribution_reporting/attribution_data_host_manager.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_DATA_HOST_MANAGER_H_ #define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_DATA_HOST_MANAGER_H_ +#include <string> + #include "mojo/public/cpp/bindings/pending_receiver.h" #include "third_party/blink/public/common/tokens/tokens.h" @@ -40,6 +42,15 @@ mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host, const blink::AttributionSrcToken& attribution_src_token) = 0; + // Notifies the manager that an attribution enabled navigation has registered + // a source header. May be called multiple times for the same navigation. + // Important: `header_value` is untrusted. + virtual void NotifyNavigationRedirectRegistation( + const blink::AttributionSrcToken& attribution_src_token, + const std::string& header_value, + url::Origin reporting_origin, + const url::Origin& source_origin) = 0; + // Notifies the manager that we have received a navigation for a given data // host. This may arrive before or after the attribution configuration is // available for a given data host.
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc index 4084c683..f2b01e88 100644 --- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc +++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
@@ -18,6 +18,7 @@ #include "content/browser/attribution_reporting/attribution_aggregatable_values.h" #include "content/browser/attribution_reporting/attribution_aggregation_keys.h" #include "content/browser/attribution_reporting/attribution_filter_data.h" +#include "content/browser/attribution_reporting/attribution_header_utils.h" #include "content/browser/attribution_reporting/attribution_manager.h" #include "content/browser/attribution_reporting/attribution_source_type.h" #include "content/browser/attribution_reporting/attribution_trigger.h" @@ -183,6 +184,27 @@ base::TimeTicks register_time; }; +struct AttributionDataHostManagerImpl::NavigationRedirectSourceRegistrations { + // Source origin to use for all registrations on a redirect chain. Will not + // change over the course of the redirect chain. + url::Origin source_origin; + + // Number of source data we are waiting to be decoded/received. + size_t pending_source_data = 0; + + // Source data that has been received as part of this redirect chain. Sources + // cannot be processed until `destination` is set. + std::vector<StorableSource> sources; + + // The final, committed destination of the navigation associated with this. + // This can be set before or after all `pending_source_data` is received. + url::Origin destination; + + // The time the first registration header was received for the redirect chain. + // Will not change over the course of the redirect chain. + base::TimeTicks register_time; +}; + AttributionDataHostManagerImpl::AttributionDataHostManagerImpl( AttributionManager* attribution_manager) : attribution_manager_(attribution_manager) { @@ -224,6 +246,45 @@ return true; } +void AttributionDataHostManagerImpl::NotifyNavigationRedirectRegistation( + const blink::AttributionSrcToken& attribution_src_token, + const std::string& header_value, + url::Origin reporting_origin, + const url::Origin& source_origin) { + if (!network::IsOriginPotentiallyTrustworthy(source_origin) || + !network::IsOriginPotentiallyTrustworthy(reporting_origin)) { + return; + } + + // Avoid costly isolated JSON parsing below if the header is obviously + // invalid. + if (header_value.empty()) + return; + + auto [it, inserted] = redirect_registrations_.try_emplace( + attribution_src_token, NavigationRedirectSourceRegistrations{ + .source_origin = source_origin, + .register_time = base::TimeTicks::Now()}); + + // Redirect data may not be registered if the navigation is already finished. + DCHECK(it->second.destination.opaque()); + + // Treat ongoing redirect registrations within a chain as a data host for the + // purpose of trigger queuing. + if (inserted) + data_hosts_in_source_mode_++; + + it->second.pending_source_data++; + + // Send the data to the decoder, but track that we are now waiting on a new + // registration. + data_decoder::DataDecoder::ParseJsonIsolated( + header_value, + base::BindOnce(&AttributionDataHostManagerImpl::OnRedirectSourceParsed, + weak_factory_.GetWeakPtr(), attribution_src_token, + std::move(reporting_origin))); +} + void AttributionDataHostManagerImpl::NotifyNavigationForDataHost( const blink::AttributionSrcToken& attribution_src_token, const url::Origin& source_origin, @@ -236,33 +297,66 @@ auto it = navigation_data_host_map_.find(attribution_src_token); - if (it == navigation_data_host_map_.end()) { + if (it != navigation_data_host_map_.end()) { + receivers_.Add( + this, std::move(it->second.data_host), + FrozenContext{.context_origin = source_origin, + .source_type = AttributionSourceType::kNavigation, + .destination = destination_origin, + .register_time = it->second.register_time}); + + navigation_data_host_map_.erase(it); + RecordNavigationDataHostStatus(NavigationDataHostStatus::kProcessed); + } else { RecordNavigationDataHostStatus(NavigationDataHostStatus::kNotFound); - return; } - receivers_.Add( - this, std::move(it->second.data_host), - FrozenContext{.context_origin = source_origin, - .source_type = AttributionSourceType::kNavigation, - .destination = destination_origin, - .register_time = it->second.register_time}); + // Process any registrations on redirects for this navigation now that we know + // the destination. + auto redirect_it = redirect_registrations_.find(attribution_src_token); + if (redirect_it == redirect_registrations_.end()) { + return; + } + NavigationRedirectSourceRegistrations& registrations = redirect_it->second; + registrations.destination = destination_origin; + const net::SchemefulSite destination_site(destination_origin); - navigation_data_host_map_.erase(it); + for (StorableSource& source : registrations.sources) { + // The reporting origin has mis-configured the destination, ignore the + // source. + if (source.common_info().ConversionDestination() != destination_site) + continue; - RecordNavigationDataHostStatus(NavigationDataHostStatus::kProcessed); + // Process the registration if the destination matched. + attribution_manager_->HandleSource(std::move(source)); + } + registrations.sources.clear(); + + if (registrations.pending_source_data == 0u) { + // We have finished processing all sources on this redirect chain, cleanup + // the map. + OnSourceEligibleDataHostFinished(registrations.register_time); + redirect_registrations_.erase(redirect_it); + } } void AttributionDataHostManagerImpl::NotifyNavigationFailure( const blink::AttributionSrcToken& attribution_src_token) { auto it = navigation_data_host_map_.find(attribution_src_token); - DCHECK(it != navigation_data_host_map_.end()); + if (it != navigation_data_host_map_.end()) { + base::TimeTicks register_time = it->second.register_time; + navigation_data_host_map_.erase(it); + OnSourceEligibleDataHostFinished(register_time); + RecordNavigationDataHostStatus(NavigationDataHostStatus::kNavigationFailed); + } - base::TimeTicks register_time = it->second.register_time; - navigation_data_host_map_.erase(it); - OnSourceEligibleDataHostFinished(register_time); - - RecordNavigationDataHostStatus(NavigationDataHostStatus::kNavigationFailed); + // We are not guaranteed to be processing redirect registrations for a given + // navigation. + auto redirect_it = redirect_registrations_.find(attribution_src_token); + if (redirect_it != redirect_registrations_.end()) { + OnSourceEligibleDataHostFinished(redirect_it->second.register_time); + redirect_registrations_.erase(redirect_it); + } } void AttributionDataHostManagerImpl::SourceDataAvailable( @@ -573,4 +667,50 @@ delayed_triggers_.clear(); } +void AttributionDataHostManagerImpl::OnRedirectSourceParsed( + const blink::AttributionSrcToken& attribution_src_token, + url::Origin reporting_origin, + data_decoder::DataDecoder::ValueOrError result) { + // TODO(johnidel): Add metrics regarding parsing failures / misconfigured + // headers. + auto it = redirect_registrations_.find(attribution_src_token); + + // The registration may no longer be tracked in the event the navigation + // failed. + if (it == redirect_registrations_.end()) + return; + + DCHECK_GE(it->second.pending_source_data, 0u); + NavigationRedirectSourceRegistrations& registrations = it->second; + registrations.pending_source_data--; + + absl::optional<StorableSource> source; + if (result.value && result.value->is_dict()) { + source = ParseSourceRegistration( + std::move(result.value->GetDict()), /*source_time=*/base::Time::Now(), + std::move(reporting_origin), registrations.source_origin, + AttributionSourceType::kNavigation); + } + // Do not access `reporting_origin` below this line, it is no longer valid. + + // An opaque destination means that navigation has not finished, delay + // handling. + if (registrations.destination.opaque()) { + if (source) + registrations.sources.push_back(std::move(*source)); + return; + } + + // Process the registration if it was valid. + if (source) + attribution_manager_->HandleSource(std::move(*source)); + + if (registrations.pending_source_data == 0u) { + // We have finished processing all sources on this redirect chain, cleanup + // the map. + OnSourceEligibleDataHostFinished(registrations.register_time); + redirect_registrations_.erase(it); + } +} + } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.h b/content/browser/attribution_reporting/attribution_data_host_manager_impl.h index bfcbffe2..0ac7eb2 100644 --- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.h +++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.h
@@ -10,10 +10,12 @@ #include "base/containers/circular_deque.h" #include "base/containers/flat_map.h" #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "content/browser/attribution_reporting/attribution_data_host_manager.h" #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/receiver_set.h" +#include "services/data_decoder/public/cpp/data_decoder.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/conversions/attribution_data_host.mojom.h" @@ -54,6 +56,11 @@ bool RegisterNavigationDataHost( mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host, const blink::AttributionSrcToken& attribution_src_token) override; + void NotifyNavigationRedirectRegistation( + const blink::AttributionSrcToken& attribution_src_token, + const std::string& header_value, + url::Origin reporting_origin, + const url::Origin& source_origin) override; void NotifyNavigationForDataHost( const blink::AttributionSrcToken& attribution_src_token, const url::Origin& source_origin, @@ -65,11 +72,13 @@ // Represents frozen data from the browser process associated with each // receiver. struct FrozenContext; - struct DelayedTrigger; - struct NavigationDataHost; + // Represents a set of attribution sources which registered in a top-level + // navigation redirect chain, and associated info to process them. + struct NavigationRedirectSourceRegistrations; + // blink::mojom::AttributionDataHost: void SourceDataAvailable( blink::mojom::AttributionSourceDataPtr data) override; @@ -79,6 +88,11 @@ void OnReceiverDisconnected(); void OnSourceEligibleDataHostFinished(base::TimeTicks register_time); + void OnRedirectSourceParsed( + const blink::AttributionSrcToken& attribution_src_token, + url::Origin reporting_origin, + data_decoder::DataDecoder::ValueOrError result); + void SetTriggerTimer(base::TimeDelta delay); void ProcessDelayedTrigger(); @@ -95,12 +109,20 @@ base::flat_map<blink::AttributionSrcToken, NavigationDataHost> navigation_data_host_map_; + // Stores registrations received for redirects within a navigation with a + // given token. + base::flat_map<blink::AttributionSrcToken, + NavigationRedirectSourceRegistrations> + redirect_registrations_; + // The number of connected receivers that may register a source. Used to // determine whether to buffer triggers. Event receivers are counted here // until they register a trigger. size_t data_hosts_in_source_mode_ = 0; base::OneShotTimer trigger_timer_; base::circular_deque<DelayedTrigger> delayed_triggers_; + + base::WeakPtrFactory<AttributionDataHostManagerImpl> weak_factory_{this}; }; } // namespace content
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc index 1e75cba..bdd6b61 100644 --- a/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc
@@ -29,6 +29,7 @@ #include "content/public/test/test_utils.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/test_support/test_utils.h" +#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/numeric/int128.h" @@ -56,6 +57,9 @@ constexpr char kTriggerDataHandleStatusMetric[] = "Conversions.TriggerDataHandleStatus"; +constexpr char kRegisterSourceJson[] = + R"json({"source_event_id":"5","destination":"https://destination.example"})json"; + struct ExpectedTriggerQueueEventCounts { base::HistogramBase::Count skipped_queue = 0; base::HistogramBase::Count dropped = 0; @@ -108,6 +112,7 @@ BrowserTaskEnvironment task_environment_; MockAttributionManager mock_manager_; AttributionDataHostManagerImpl data_host_manager_; + data_decoder::test::InProcessDataDecoder in_process_data_decoder_; }; TEST_F(AttributionDataHostManagerImplTest, SourceDataHost_SourceRegistered) { @@ -1218,6 +1223,280 @@ } TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_SourceSiteTrustworthyChecksPerformed) { + EXPECT_CALL(mock_manager_, HandleSource).Times(0); + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("http://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); + + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination.example"))); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_ReportingTrustworthyChecksPerformed) { + EXPECT_CALL(mock_manager_, HandleSource).Times(0); + + auto reporter = url::Origin::Create(GURL("http://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); + + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination.example"))); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_RegistrationWithDestinationMismatchIgnored) { + EXPECT_CALL(mock_manager_, HandleSource).Times(0); + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); + + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination2.example"))); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_NavigationFailed) { + EXPECT_CALL(mock_manager_, HandleSource).Times(0); + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); + + data_host_manager_.NotifyNavigationFailure(attribution_src_token); + + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination.example"))); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_NavigationFailedBeforeParsing) { + EXPECT_CALL(mock_manager_, HandleSource).Times(0); + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + data_host_manager_.NotifyNavigationFailure(attribution_src_token); + + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_ParsingFinishesBeforeAndAfterNav) { + EXPECT_CALL(mock_manager_, HandleSource).Times(2); + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); + + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination.example"))); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_ParsingFailsBeforeAndSucceedsAfterNav) { + EXPECT_CALL(mock_manager_, HandleSource).Times(1); + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, "!!!invalid json", reporter, source_site); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); + + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination.example"))); + // Wait for parsing to finish. + task_environment_.FastForwardBy(base::TimeDelta()); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_TriggerDelayed) { + base::HistogramTester histograms; + + Checkpoint checkpoint; + { + InSequence seq; + + EXPECT_CALL(mock_manager_, HandleTrigger).Times(0); + EXPECT_CALL(checkpoint, Call(1)); + EXPECT_CALL(mock_manager_, HandleTrigger); + } + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + + mojo::Remote<blink::mojom::AttributionDataHost> trigger_data_host_remote; + data_host_manager_.RegisterDataHost( + trigger_data_host_remote.BindNewPipeAndPassReceiver(), + url::Origin::Create(GURL("https://page2.example"))); + + // Because there is a connected data host in source mode, this trigger should + // be delayed. + auto trigger_data = blink::mojom::AttributionTriggerData::New(); + trigger_data->reporting_origin = reporter; + trigger_data->filters = blink::mojom::AttributionFilterData::New(); + trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data)); + trigger_data_host_remote.FlushForTesting(); + + task_environment_.FastForwardBy(base::Seconds(5) - base::Microseconds(1)); + checkpoint.Call(1); + task_environment_.FastForwardBy(base::Microseconds(1)); + + CheckTriggerQueueHistograms(histograms, { + .enqueued = 1, + .processed_with_delay = 1, + .delays = + { + {base::Seconds(5), 1}, + }, + }); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_NavigationFinishedQueueSkipped) { + base::HistogramTester histograms; + + Checkpoint checkpoint; + { + InSequence seq; + + EXPECT_CALL(mock_manager_, HandleSource).Times(2); + EXPECT_CALL(mock_manager_, HandleTrigger).Times(0); + EXPECT_CALL(checkpoint, Call(1)); + EXPECT_CALL(mock_manager_, HandleTrigger); + } + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + + // Wait for parsing. + task_environment_.FastForwardBy(base::TimeDelta()); + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination.example"))); + + checkpoint.Call(1); + + mojo::Remote<blink::mojom::AttributionDataHost> trigger_data_host_remote; + data_host_manager_.RegisterDataHost( + trigger_data_host_remote.BindNewPipeAndPassReceiver(), + url::Origin::Create(GURL("https://page2.example"))); + + auto trigger_data = blink::mojom::AttributionTriggerData::New(); + trigger_data->reporting_origin = + url::Origin::Create(GURL("https://report.test")); + trigger_data->filters = blink::mojom::AttributionFilterData::New(); + trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data)); + trigger_data_host_remote.FlushForTesting(); + + CheckTriggerQueueHistograms(histograms, {.skipped_queue = 1}); +} + +TEST_F(AttributionDataHostManagerImplTest, + NavigationRedirectSource_ParsingAfterNavigationFinishedQueueSkipped) { + base::HistogramTester histograms; + + Checkpoint checkpoint; + { + InSequence seq; + + EXPECT_CALL(mock_manager_, HandleSource).Times(2); + EXPECT_CALL(mock_manager_, HandleTrigger).Times(0); + EXPECT_CALL(checkpoint, Call(1)); + EXPECT_CALL(mock_manager_, HandleTrigger); + } + + auto reporter = url::Origin::Create(GURL("https://report.test")); + auto source_site = url::Origin::Create(GURL("https://source.test")); + + const blink::AttributionSrcToken attribution_src_token; + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + data_host_manager_.NotifyNavigationRedirectRegistation( + attribution_src_token, kRegisterSourceJson, reporter, source_site); + + // Wait for parsing. + data_host_manager_.NotifyNavigationForDataHost( + attribution_src_token, source_site, + url::Origin::Create(GURL("https://destination.example"))); + task_environment_.FastForwardBy(base::TimeDelta()); + checkpoint.Call(1); + + mojo::Remote<blink::mojom::AttributionDataHost> trigger_data_host_remote; + data_host_manager_.RegisterDataHost( + trigger_data_host_remote.BindNewPipeAndPassReceiver(), + url::Origin::Create(GURL("https://page2.example"))); + + auto trigger_data = blink::mojom::AttributionTriggerData::New(); + trigger_data->reporting_origin = + url::Origin::Create(GURL("https://report.test")); + trigger_data->filters = blink::mojom::AttributionFilterData::New(); + trigger_data_host_remote->TriggerDataAvailable(std::move(trigger_data)); + trigger_data_host_remote.FlushForTesting(); + + CheckTriggerQueueHistograms(histograms, {.skipped_queue = 1}); +} + +TEST_F(AttributionDataHostManagerImplTest, SourceModeReceiverConnectsDisconnects_TriggerNotDelayed) { base::HistogramTester histograms;
diff --git a/content/browser/attribution_reporting/attribution_filter_data.cc b/content/browser/attribution_reporting/attribution_filter_data.cc index 4f66a4b..3bc896c 100644 --- a/content/browser/attribution_reporting/attribution_filter_data.cc +++ b/content/browser/attribution_reporting/attribution_filter_data.cc
@@ -11,6 +11,7 @@ #include "base/check.h" #include "base/check_op.h" +#include "base/values.h" #include "content/browser/attribution_reporting/attribution_reporting.pb.h" #include "third_party/blink/public/common/attribution_reporting/constants.h" @@ -79,6 +80,60 @@ } // static +absl::optional<AttributionFilterData> AttributionFilterData::FromSourceJSON( + base::Value* value) { + // TODO(johnidel): Consider logging registration JSON metrics here. + if (!value) + return AttributionFilterData(); + + base::Value::Dict* dict = value->GetIfDict(); + if (!dict) + return absl::nullopt; + + const size_t num_filters = dict->size(); + if (num_filters > blink::kMaxAttributionFiltersPerSource) + return absl::nullopt; + + if (dict->contains(kFilterSourceType)) + return absl::nullopt; + + FilterValues::container_type filter_values; + filter_values.reserve(dict->size()); + + for (auto [filter, value] : *dict) { + if (filter.size() > blink::kMaxBytesPerAttributionFilterString) + return absl::nullopt; + + base::Value::List* list = value.GetIfList(); + if (!list) + return absl::nullopt; + + const size_t num_values = list->size(); + if (num_values > blink::kMaxValuesPerAttributionFilter) + return absl::nullopt; + + std::vector<std::string> values; + values.reserve(num_values); + + for (base::Value& value : *list) { + std::string* string = value.GetIfString(); + if (!string) + return absl::nullopt; + + if (string->size() > blink::kMaxBytesPerAttributionFilterString) + return absl::nullopt; + + values.push_back(std::move(*string)); + } + + filter_values.emplace_back(filter, std::move(values)); + } + + return AttributionFilterData( + FilterValues(base::sorted_unique, std::move(filter_values))); +} + +// static AttributionFilterData AttributionFilterData::ForSourceType( AttributionSourceType source_type) { std::vector<std::string> values;
diff --git a/content/browser/attribution_reporting/attribution_filter_data.h b/content/browser/attribution_reporting/attribution_filter_data.h index 9eba0c4d..94fc341 100644 --- a/content/browser/attribution_reporting/attribution_filter_data.h +++ b/content/browser/attribution_reporting/attribution_filter_data.h
@@ -15,6 +15,10 @@ #include "content/common/content_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" +namespace base { +class Value; +} // namespace base + namespace content { // Supports persistence to disk via serializaton to/from proto. @@ -39,6 +43,8 @@ static absl::optional<AttributionFilterData> FromTriggerFilterValues( FilterValues&&); + static absl::optional<AttributionFilterData> FromSourceJSON(base::Value*); + // Returns filter data that matches only the given source type. static AttributionFilterData ForSourceType(AttributionSourceType);
diff --git a/content/browser/attribution_reporting/attribution_header_utils.cc b/content/browser/attribution_reporting/attribution_header_utils.cc new file mode 100644 index 0000000..12097b9 --- /dev/null +++ b/content/browser/attribution_reporting/attribution_header_utils.cc
@@ -0,0 +1,107 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/attribution_reporting/attribution_header_utils.h" + +#include <stdint.h> + +#include <string> +#include <utility> + +#include "base/strings/string_number_conversions.h" +#include "base/time/time.h" +#include "base/values.h" +#include "content/browser/attribution_reporting/attribution_filter_data.h" +#include "content/browser/attribution_reporting/attribution_source_type.h" +#include "content/browser/attribution_reporting/common_source_info.h" +#include "content/browser/attribution_reporting/storable_source.h" +#include "services/network/public/cpp/is_potentially_trustworthy.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/attribution_reporting/constants.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace content { + +namespace { + +absl::optional<uint64_t> ParseDebugKey(const base::Value::Dict& dict) { + const std::string* s = dict.FindString("debug_key"); + if (!s) + return absl::nullopt; + + uint64_t value; + return base::StringToUint64(*s, &value) ? absl::make_optional(value) + : absl::nullopt; +} + +int64_t ParsePriority(const base::Value::Dict& dict) { + const std::string* s = dict.FindString("priority"); + if (!s) + return 0; + + int64_t value; + return base::StringToInt64(*s, &value) ? value : 0; +} + +} // namespace + +absl::optional<StorableSource> ParseSourceRegistration( + base::Value::Dict registration, + base::Time source_time, + url::Origin reporting_origin, + url::Origin source_origin, + AttributionSourceType source_type) { + uint64_t source_event_id; + { + const std::string* s = registration.FindString("source_event_id"); + if (!s) + return absl::nullopt; + + if (!base::StringToUint64(*s, &source_event_id)) + source_event_id = 0; + } + + url::Origin destination; + { + const std::string* s = registration.FindString("destination"); + if (!s) + return absl::nullopt; + + destination = url::Origin::Create(GURL(*s)); + if (!network::IsOriginPotentiallyTrustworthy(destination)) + return absl::nullopt; + } + + int64_t priority = ParsePriority(registration); + + absl::optional<base::TimeDelta> expiry; + if (const std::string* s = registration.FindString("expiry")) { + int64_t seconds; + if (base::StringToInt64(*s, &seconds)) + expiry = base::Seconds(seconds); + } + + absl::optional<uint64_t> debug_key = ParseDebugKey(registration); + + absl::optional<AttributionFilterData> filter_data = + AttributionFilterData::FromSourceJSON(registration.Find("filter_data")); + if (!filter_data) + return absl::nullopt; + + absl::optional<AttributionAggregationKeys> aggregation_keys = + AttributionAggregationKeys::FromJSON( + registration.Find("aggregation_keys")); + if (!aggregation_keys) + return absl::nullopt; + + return StorableSource(CommonSourceInfo( + source_event_id, std::move(source_origin), std::move(destination), + std::move(reporting_origin), source_time, + CommonSourceInfo::GetExpiryTime(expiry, source_time, source_type), + source_type, priority, std::move(*filter_data), debug_key, + std::move(*aggregation_keys))); +} + +} // namespace content
diff --git a/content/browser/attribution_reporting/attribution_header_utils.h b/content/browser/attribution_reporting/attribution_header_utils.h new file mode 100644 index 0000000..9cf31bf --- /dev/null +++ b/content/browser/attribution_reporting/attribution_header_utils.h
@@ -0,0 +1,34 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_HEADER_UTILS_H_ +#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_HEADER_UTILS_H_ + +#include "base/values.h" +#include "content/browser/attribution_reporting/attribution_source_type.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace base { +class Time; +} // namespace base + +namespace url { +class Origin; +} // namespace url + +namespace content { + +class StorableSource; + +// TODO(apaseltiner): Add a fuzzer. +absl::optional<StorableSource> ParseSourceRegistration( + base::Value::Dict registration, + base::Time source_time, + url::Origin reporting_origin, + url::Origin source_origin, + AttributionSourceType source_type); + +} // namespace content + +#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_HEADER_UTILS_H_
diff --git a/content/browser/attribution_reporting/attribution_header_utils_unittest.cc b/content/browser/attribution_reporting/attribution_header_utils_unittest.cc new file mode 100644 index 0000000..fa48f8e3 --- /dev/null +++ b/content/browser/attribution_reporting/attribution_header_utils_unittest.cc
@@ -0,0 +1,249 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/attribution_reporting/attribution_header_utils.h" + +#include <limits> +#include <memory> +#include <string> +#include <utility> + +#include "base/stl_util.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/values_test_util.h" +#include "base/values.h" +#include "content/browser/attribution_reporting/attribution_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/numeric/int128.h" +#include "third_party/blink/public/common/attribution_reporting/constants.h" + +namespace content { +namespace { + +TEST(AttributionRegistrationParsingTest, ParseAggregationKeys) { + const struct { + const char* description; + absl::optional<base::Value> json; + absl::optional<AttributionAggregationKeys> expected; + } kTestCases[] = { + {"Null", absl::nullopt, AttributionAggregationKeys()}, + {"Not a dictionary", base::Value(base::Value::List()), absl::nullopt}, + {"key not a string", base::test::ParseJson(R"({"key":123})"), + absl::nullopt}, + {"Invalid key", base::test::ParseJson(R"({"key":"0xG59"})"), + absl::nullopt}, + {"One valid key", base::test::ParseJson(R"({"key":"0x159"})"), + *AttributionAggregationKeys::FromKeys( + {{"key", absl::MakeUint128(/*high=*/0, /*low=*/345)}})}, + {"Two valid keys", + base::test::ParseJson( + R"({"key1":"0x159","key2":"0x50000000000000159"})"), + *AttributionAggregationKeys::FromKeys({ + {"key1", absl::MakeUint128(/*high=*/0, /*low=*/345)}, + {"key2", absl::MakeUint128(/*high=*/5, /*low=*/345)}, + })}, + {"Second key invalid", + base::test::ParseJson(R"({"key1":"0x159","key2":""})"), absl::nullopt}, + }; + + for (const auto& test_case : kTestCases) { + EXPECT_EQ(AttributionAggregationKeys::FromJSON( + base::OptionalOrNullptr(test_case.json)), + test_case.expected) + << test_case.description; + } +} + +TEST(AttributionRegistrationParsingTest, ParseAggregationKeys_CheckSize) { + struct AttributionAggregatableSourceSizeTestCase { + const char* description; + bool valid; + size_t key_count; + size_t key_size; + + base::Value::Dict GetHeader() const { + base::Value::Dict dict; + for (size_t i = 0u; i < key_count; ++i) { + dict.Set(GetKey(i), "0x1"); + } + return dict; + } + + absl::optional<AttributionAggregationKeys> Expected() const { + if (!valid) + return absl::nullopt; + + AttributionAggregationKeys::Keys keys; + for (size_t i = 0u; i < key_count; ++i) { + keys.emplace(GetKey(i), absl::MakeUint128(/*high=*/0, /*low=*/1)); + } + + return *AttributionAggregationKeys::FromKeys(std::move(keys)); + } + + private: + std::string GetKey(size_t index) const { + // Note that this might not be robust as + // `blink::kMaxAttributionAggregationKeysPerSourceOrTrigger` varies which + // might generate invalid JSON. + return std::string(key_size, 'A' + index % 26 + 32 * (index / 26)); + } + }; + + const AttributionAggregatableSourceSizeTestCase kTestCases[] = { + {"empty", true, 0, 0}, + {"max_keys", true, + blink::kMaxAttributionAggregationKeysPerSourceOrTrigger, 1}, + {"too_many_keys", false, + blink::kMaxAttributionAggregationKeysPerSourceOrTrigger + 1, 1}, + {"max_key_size", true, 1, blink::kMaxBytesPerAttributionAggregationKeyId}, + {"excessive_key_size", false, 1, + blink::kMaxBytesPerAttributionAggregationKeyId + 1}, + }; + + for (const auto& test_case : kTestCases) { + base::Value value(test_case.GetHeader()); + EXPECT_EQ(AttributionAggregationKeys::FromJSON(&value), + test_case.Expected()) + << test_case.description; + } +} + +TEST(AttributionRegistrationParsingTest, ParseFilterData) { + const auto make_filter_data_with_keys = [](size_t n) { + base::Value::Dict dict; + for (size_t i = 0; i < n; ++i) { + dict.Set(base::NumberToString(i), base::Value::List()); + } + return base::Value(std::move(dict)); + }; + + const auto make_filter_data_with_key_length = [](size_t n) { + base::Value::Dict dict; + dict.Set(std::string(n, 'a'), base::Value::List()); + return base::Value(std::move(dict)); + }; + + const auto make_filter_data_with_values = [](size_t n) { + base::Value::List list; + for (size_t i = 0; i < n; ++i) { + list.Append("x"); + } + + base::Value::Dict dict; + dict.Set("a", std::move(list)); + return base::Value(std::move(dict)); + }; + + const auto make_filter_data_with_value_length = [](size_t n) { + base::Value::List list; + list.Append(std::string(n, 'a')); + + base::Value::Dict dict; + dict.Set("a", std::move(list)); + return base::Value(std::move(dict)); + }; + + struct { + const char* description; + absl::optional<base::Value> json; + absl::optional<AttributionFilterData> expected; + } kTestCases[] = { + { + "Null", + absl::nullopt, + AttributionFilterData(), + }, + { + "empty", + base::Value(base::Value::Dict()), + AttributionFilterData(), + }, + { + "multiple", + base::test::ParseJson(R"json({ + "a": ["b"], + "c": ["e", "d"], + "f": [] + })json"), + AttributionFilterData::CreateForTesting({ + {"a", {"b"}}, + {"c", {"e", "d"}}, + {"f", {}}, + }), + }, + { + "forbidden_key", + base::test::ParseJson(R"json({ + "source_type": ["a"] + })json"), + absl::nullopt, + }, + { + "not_dictionary", + base::Value(base::Value::List()), + absl::nullopt, + }, + { + "value_not_array", + base::test::ParseJson(R"json({"a": true})json"), + absl::nullopt, + }, + { + "array_element_not_string", + base::test::ParseJson(R"json({"a": [true]})json"), + absl::nullopt, + }, + { + "too_many_keys", + make_filter_data_with_keys(51), + absl::nullopt, + }, + { + "key_too_long", + make_filter_data_with_key_length(26), + absl::nullopt, + }, + { + "too_many_values", + make_filter_data_with_values(51), + absl::nullopt, + }, + { + "value_too_long", + make_filter_data_with_value_length(26), + absl::nullopt, + }, + }; + + for (auto& test_case : kTestCases) { + EXPECT_EQ(AttributionFilterData::FromSourceJSON( + base::OptionalOrNullptr(test_case.json)), + test_case.expected) + << test_case.description; + } + + { + base::Value json = make_filter_data_with_keys(50); + EXPECT_TRUE(AttributionFilterData::FromSourceJSON(&json)); + } + + { + base::Value json = make_filter_data_with_key_length(25); + EXPECT_TRUE(AttributionFilterData::FromSourceJSON(&json)); + } + + { + base::Value json = make_filter_data_with_values(50); + EXPECT_TRUE(AttributionFilterData::FromSourceJSON(&json)); + } + + { + base::Value json = make_filter_data_with_value_length(25); + EXPECT_TRUE(AttributionFilterData::FromSourceJSON(&json)); + } +} + +} // namespace +} // namespace content
diff --git a/content/browser/attribution_reporting/attribution_host.cc b/content/browser/attribution_reporting/attribution_host.cc index f98f17d..d11887f 100644 --- a/content/browser/attribution_reporting/attribution_host.cc +++ b/content/browser/attribution_reporting/attribution_host.cc
@@ -109,6 +109,37 @@ initiator_root_frame_origin); } +void AttributionHost::DidRedirectNavigation( + NavigationHandle* navigation_handle) { + auto it = + navigation_impression_origins_.find(navigation_handle->GetNavigationId()); + if (it == navigation_impression_origins_.end()) + return; + + DCHECK(navigation_handle->GetImpression()); + + std::string source_header; + if (!navigation_handle->GetResponseHeaders()->GetNormalizedHeader( + "Attribution-Reporting-Register-Source", &source_header)) { + return; + } + + AttributionManager* attribution_manager = + AttributionManager::FromWebContents(web_contents()); + if (!attribution_manager) + return; + + auto* data_host_manager = attribution_manager->GetDataHostManager(); + if (!data_host_manager) + return; + + const url::Origin& impression_origin = it->second; + + data_host_manager->NotifyNavigationRedirectRegistation( + navigation_handle->GetImpression()->attribution_src_token, source_header, + url::Origin::Create(navigation_handle->GetURL()), impression_origin); +} + void AttributionHost::DidFinishNavigation(NavigationHandle* navigation_handle) { // Observe only navigation toward a new document in the primary main frame. // Impressions should never be attached to same-document navigations but can @@ -157,16 +188,15 @@ DCHECK(navigation_handle->GetImpression()); const blink::Impression& impression = *(navigation_handle->GetImpression()); - auto* data_host_manager = attribution_manager->GetDataHostManager(); - if (!data_host_manager) - return; + auto* data_host_manager = attribution_manager->GetDataHostManager(); + if (!data_host_manager) + return; - const url::Origin& destination_origin = - navigation_handle->GetRenderFrameHost()->GetLastCommittedOrigin(); + const url::Origin& destination_origin = + navigation_handle->GetRenderFrameHost()->GetLastCommittedOrigin(); - data_host_manager->NotifyNavigationForDataHost( - impression.attribution_src_token, impression_origin, - destination_origin); + data_host_manager->NotifyNavigationForDataHost( + impression.attribution_src_token, impression_origin, destination_origin); } void AttributionHost::MaybeNotifyFailedSourceNavigation(
diff --git a/content/browser/attribution_reporting/attribution_host.h b/content/browser/attribution_reporting/attribution_host.h index b54d318d..c2b0ed0 100644 --- a/content/browser/attribution_reporting/attribution_host.h +++ b/content/browser/attribution_reporting/attribution_host.h
@@ -50,6 +50,7 @@ // WebContentsObserver: void DidStartNavigation(NavigationHandle* navigation_handle) override; + void DidRedirectNavigation(NavigationHandle* navigation_handle) override; void DidFinishNavigation(NavigationHandle* navigation_handle) override; // Notifies the `AttributionDataHostManager` that a navigation with an
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc index e9dfe31..94fcc50 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -17,6 +17,7 @@ #include "base/notreached.h" #include "base/observer_list.h" #include "base/task/lazy_thread_pool_task_runner.h" +#include "base/threading/thread_restrictions.h" #include "base/time/time.h" #include "content/browser/aggregation_service/aggregation_service.h" #include "content/browser/aggregation_service/aggregation_service_impl.h" @@ -220,6 +221,23 @@ AttributionStorageSql::RunInMemoryForTesting(); } +// static +std::unique_ptr<AttributionManagerImpl> +AttributionManagerImpl::CreateWithNewDbForTesting( + StoragePartitionImpl* storage_partition, + const base::FilePath& user_data_directory, + scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) { + { + base::ScopedAllowBlockingForTesting allow_blocking; + if (!AttributionStorageSql::DeleteStorageForTesting(user_data_directory)) + return nullptr; + } + + return std::make_unique<AttributionManagerImpl>( + storage_partition, user_data_directory, + std::move(special_storage_policy)); +} + bool AttributionManagerImpl::IsReportAllowed( const AttributionReport& report) const { const CommonSourceInfo& common_info =
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.h b/content/browser/attribution_reporting/attribution_manager_impl.h index 0f59521..d1faaf6 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.h +++ b/content/browser/attribution_reporting/attribution_manager_impl.h
@@ -71,6 +71,11 @@ std::unique_ptr<AttributionReportSender> report_sender, StoragePartitionImpl* storage_partition); + static std::unique_ptr<AttributionManagerImpl> CreateWithNewDbForTesting( + StoragePartitionImpl* storage_partition, + const base::FilePath& user_data_directory, + scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy); + AttributionManagerImpl( StoragePartitionImpl* storage_partition, const base::FilePath& user_data_directory,
diff --git a/content/browser/attribution_reporting/attribution_src_browsertest.cc b/content/browser/attribution_reporting/attribution_src_browsertest.cc index 1e15589..7035e0a 100644 --- a/content/browser/attribution_reporting/attribution_src_browsertest.cc +++ b/content/browser/attribution_reporting/attribution_src_browsertest.cc
@@ -306,6 +306,40 @@ // AttributionsBrowserTest. } +IN_PROC_BROWSER_TEST_F(AttributionSrcBrowserTest, + AnchorClickEmptyAttributionSrc_ImpressionReceived) { + GURL page_url = + https_server()->GetURL("b.test", "/page_with_impression_creator.html"); + EXPECT_TRUE(NavigateToURL(web_contents(), page_url)); + + EXPECT_CALL(mock_attribution_host(), RegisterNavigationDataHost).Times(0); + + SourceObserver source_observer(web_contents()); + EXPECT_TRUE(ExecJs(web_contents(), R"( + createAndClickAttributionSrcAnchor({url: 'page_with_conversion_redirect.html', + attributionsrc: ''});)")); + + // Wait for the impression to be seen by the observer. + blink::Impression last_impression = source_observer.Wait(); +} + +IN_PROC_BROWSER_TEST_F(AttributionSrcBrowserTest, + WindowOpenAttributionSrc_ImpressionReceived) { + GURL page_url = + https_server()->GetURL("b.test", "/page_with_impression_creator.html"); + EXPECT_TRUE(NavigateToURL(web_contents(), page_url)); + + EXPECT_CALL(mock_attribution_host(), RegisterNavigationDataHost).Times(0); + + SourceObserver source_observer(web_contents()); + EXPECT_TRUE(ExecJs(web_contents(), R"( + window.open("page_with_conversion_redirect.html", "_top", + "attributionsrc=");)")); + + // Wait for the impression to be seen by the observer. + blink::Impression last_impression = source_observer.Wait(); +} + // See crbug.com/1322450 IN_PROC_BROWSER_TEST_F(AttributionSrcBrowserTest, AttributionSrcWindowOpen_URLEncoded_SourceRegistered) {
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc index 89f7dc0f..646d5ca 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -368,6 +368,10 @@ return ReadSourceFromStatement(statement); } +base::FilePath DatabasePath(const base::FilePath& user_data_directory) { + return user_data_directory.Append(kDatabasePath); +} + } // namespace // static @@ -378,12 +382,17 @@ // static bool AttributionStorageSql::g_run_in_memory_ = false; +// static +bool AttributionStorageSql::DeleteStorageForTesting( + const base::FilePath& user_data_directory) { + return sql::Database::Delete(DatabasePath(user_data_directory)); +} + AttributionStorageSql::AttributionStorageSql( const base::FilePath& path_to_database, std::unique_ptr<AttributionStorageDelegate> delegate) - : path_to_database_(g_run_in_memory_ - ? base::FilePath(kInMemoryPath) - : path_to_database.Append(kDatabasePath)), + : path_to_database_(g_run_in_memory_ ? base::FilePath(kInMemoryPath) + : DatabasePath(path_to_database)), rate_limit_table_(delegate.get()), delegate_(std::move(delegate)) { DCHECK(delegate_);
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.h b/content/browser/attribution_reporting/attribution_storage_sql.h index 692eda0..88e3f73 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.h +++ b/content/browser/attribution_reporting/attribution_storage_sql.h
@@ -53,6 +53,9 @@ static void RunInMemoryForTesting(); + [[nodiscard]] static bool DeleteStorageForTesting( + const base::FilePath& user_data_directory); + AttributionStorageSql(const base::FilePath& path_to_database, std::unique_ptr<AttributionStorageDelegate> delegate); AttributionStorageSql(const AttributionStorageSql& other) = delete;
diff --git a/content/browser/attribution_reporting/attribution_test_utils.h b/content/browser/attribution_reporting/attribution_test_utils.h index 7a53de9c..7b3d829 100644 --- a/content/browser/attribution_reporting/attribution_test_utils.h +++ b/content/browser/attribution_reporting/attribution_test_utils.h
@@ -168,6 +168,14 @@ (override)); MOCK_METHOD(void, + NotifyNavigationRedirectRegistation, + (const blink::AttributionSrcToken& attribution_src_token, + const std::string& header_value, + url::Origin reporting_origin, + const url::Origin& source_origin), + (override)); + + MOCK_METHOD(void, NotifyNavigationForDataHost, (const blink::AttributionSrcToken& attribution_src_token, const url::Origin& source_origin,
diff --git a/content/browser/attribution_reporting/attributions_browsertest.cc b/content/browser/attribution_reporting/attributions_browsertest.cc index 020e7b4..63d6ad01 100644 --- a/content/browser/attribution_reporting/attributions_browsertest.cc +++ b/content/browser/attribution_reporting/attributions_browsertest.cc
@@ -220,7 +220,7 @@ void CreateAndClickSource(WebContents* web_contents, const GURL& href, - const GURL& attribution_src) { + const std::string& attribution_src) { CreateAndClickSourceInFrame(web_contents, web_contents->GetPrimaryMainFrame(), href, attribution_src, @@ -229,7 +229,7 @@ WebContents* CreateAndClickPopupSource(WebContents* web_contents, const GURL& href, - const GURL& attribution_src, + const std::string& attribution_src, const std::string& target) { return CreateAndClickSourceInFrame(nullptr, web_contents->GetPrimaryMainFrame(), @@ -239,7 +239,7 @@ WebContents* CreateAndClickSourceInFrame(WebContents* web_contents, RenderFrameHost* rfh, const GURL& href, - const GURL& attribution_src, + const std::string& attribution_src, const std::string& target) { EXPECT_TRUE(ExecJs(rfh, JsReplace(R"( createAttributionSrcAnchor({id: 'link', @@ -319,7 +319,8 @@ GURL register_source_url = https_server()->GetURL( "a.test", "/attribution_reporting/register_source_headers.html"); - CreateAndClickSource(web_contents(), conversion_url, register_source_url); + CreateAndClickSource(web_contents(), conversion_url, + register_source_url.spec()); GURL register_trigger_url = https_server()->GetURL( "a.test", "/attribution_reporting/register_trigger_headers.html"); @@ -331,6 +332,75 @@ } IN_PROC_BROWSER_TEST_F(AttributionsBrowserTest, + ImpressionNavigationRedirect_ReportSent) { + // Expected reports must be registered before the server starts. + ExpectedReportWaiter expected_report( + GURL("https://d.test/.well-known/attribution-reporting/" + "report-event-attribution"), + /*attribution_destination=*/"https://d.test", + /*source_event_id=*/"1", /*source_type=*/"navigation", + /*trigger_data=*/"7", https_server()); + ASSERT_TRUE(https_server()->Start()); + + GURL impression_url = https_server()->GetURL( + "a.test", "/attribution_reporting/page_with_impression_creator.html"); + EXPECT_TRUE(NavigateToURL(web_contents(), impression_url)); + + // Create an anchor tag with impression attributes and click the link. By + // default the target is set to "_top". + GURL register_source_url = https_server()->GetURL( + "d.test", + "/attribution_reporting/register_source_navigation_redirect.html"); + + CreateAndClickSource(web_contents(), register_source_url, + /*attribution_src*/ ""); + + GURL register_trigger_url = https_server()->GetURL( + "d.test", "/attribution_reporting/register_trigger_headers.html"); + + EXPECT_TRUE(ExecJs(web_contents(), JsReplace("createAttributionSrcImg($1);", + register_trigger_url))); + + expected_report.WaitForReport(); +} + +IN_PROC_BROWSER_TEST_F(AttributionsBrowserTest, + ImpressionNavigationRedirectWindowOpen_ReportSent) { + // Expected reports must be registered before the server starts. + ExpectedReportWaiter expected_report( + GURL("https://d.test/.well-known/attribution-reporting/" + "report-event-attribution"), + /*attribution_destination=*/"https://d.test", + /*source_event_id=*/"1", /*source_type=*/"navigation", + /*trigger_data=*/"7", https_server()); + ASSERT_TRUE(https_server()->Start()); + + GURL impression_url = https_server()->GetURL( + "a.test", "/attribution_reporting/page_with_impression_creator.html"); + EXPECT_TRUE(NavigateToURL(web_contents(), impression_url)); + + // Create an anchor tag with impression attributes and click the link. By + // default the target is set to "_top". + GURL register_source_url = https_server()->GetURL( + "d.test", + "/attribution_reporting/register_source_navigation_redirect.html"); + + TestNavigationObserver observer(web_contents()); + EXPECT_TRUE(ExecJs(web_contents(), JsReplace(R"(window.open($1, '_top', + "attributionsrc="+$2);)", + register_source_url, ""))); + observer.Wait(); + + GURL register_trigger_url = https_server()->GetURL( + "d.test", "/attribution_reporting/register_trigger_headers.html"); + + EXPECT_TRUE(ExecJs(web_contents(), JsReplace("createAttributionSrcImg($1);", + register_trigger_url))); + + expected_report.WaitForReport(); +} + +IN_PROC_BROWSER_TEST_F(AttributionsBrowserTest, WindowOpenDeprecatedAPI_NoException) { // Expected reports must be registered before the server starts. ExpectedReportWaiter expected_report( @@ -432,7 +502,8 @@ // Create an impression tag in the subframe and target a popup window. auto* popup_contents = CreateAndClickSourceInFrame( - /*web-contents=*/nullptr, subframe, conversion_url, register_source_url, + /*web-contents=*/nullptr, subframe, conversion_url, + register_source_url.spec(), /*target=*/"new_frame"); GURL register_trigger_url = https_server()->GetURL( @@ -463,7 +534,8 @@ "a.test", "/attribution_reporting/register_source_headers.html"); // target="_blank" navs are rel="noopener" by default. - CreateAndClickPopupSource(web_contents(), conversion_url, register_source_url, + CreateAndClickPopupSource(web_contents(), conversion_url, + register_source_url.spec(), /*target=*/"_blank"); GURL register_trigger_url = https_server()->GetURL( @@ -495,7 +567,8 @@ GURL register_source_url = https_server()->GetURL( "d.test", "/attribution_reporting/register_source_headers.html"); - CreateAndClickSource(web_contents(), conversion_url, register_source_url); + CreateAndClickSource(web_contents(), conversion_url, + register_source_url.spec()); GURL register_trigger_url = https_server()->GetURL( "d.test", "/attribution_reporting/register_trigger_headers.html"); @@ -527,7 +600,8 @@ GURL register_source_url = https_server()->GetURL( "a.test", "/attribution_reporting/register_source_headers.html"); - CreateAndClickSource(web_contents(), conversion_url, register_source_url); + CreateAndClickSource(web_contents(), conversion_url, + register_source_url.spec()); // Navigate to a same domain origin that is different than the landing page // for the click and convert there. A report should still be sent. @@ -572,12 +646,12 @@ "b.test", "/attribution_reporting/register_source_headers.html"); CreateAndClickSource(shell()->web_contents(), conversion_url, - register_source_url); + register_source_url.spec()); GURL register_source_url_2 = https_server()->GetURL( "b.test", "/attribution_reporting/register_source_headers_2.html"); CreateAndClickSource(shell2->web_contents(), conversion_url, - register_source_url_2); + register_source_url_2.spec()); GURL register_trigger_url = https_server()->GetURL( "b.test", "/attribution_reporting/register_trigger_headers.html"); @@ -618,12 +692,12 @@ "/attribution_reporting/register_source_headers_high_priority.html"); CreateAndClickSource(shell()->web_contents(), conversion_url, - register_source_url); + register_source_url.spec()); GURL register_source_url_2 = https_server()->GetURL( "b.test", "/attribution_reporting/register_source_headers.html"); CreateAndClickSource(shell2->web_contents(), conversion_url, - register_source_url_2); + register_source_url_2.spec()); GURL register_trigger_url = https_server()->GetURL( "b.test", "/attribution_reporting/register_trigger_headers.html"); @@ -816,7 +890,8 @@ GURL register_source_url = https_server()->GetURL( "a.test", "/attribution_reporting/register_source_headers.html"); - CreateAndClickSource(web_contents(), conversion_url, register_source_url); + CreateAndClickSource(web_contents(), conversion_url, + register_source_url.spec()); GURL register_trigger_with_dedup_url = https_server()->GetURL( "a.test", "/attribution_reporting/register_trigger_headers_dedup.html");
diff --git a/content/browser/attribution_reporting/source_declaration_browsertest.cc b/content/browser/attribution_reporting/source_declaration_browsertest.cc index 48fb038..1b87655 100644 --- a/content/browser/attribution_reporting/source_declaration_browsertest.cc +++ b/content/browser/attribution_reporting/source_declaration_browsertest.cc
@@ -311,7 +311,7 @@ } IN_PROC_BROWSER_TEST_F(AttributionSourceDeclarationBrowserTest, - ImpressionWithInsecureReportingOrigin_NotRegistered) { + ImpressionWithInsecureReportingOrigin_ReceivesToken) { // Navigate to a page with the non-https server. EXPECT_TRUE(NavigateToURL( web_contents(), @@ -328,8 +328,9 @@ SourceObserver source_observer(web_contents()); EXPECT_TRUE(ExecJs(shell(), "simulateClick('link');")); - // We should see a null impression on the navigation - EXPECT_TRUE(source_observer.WaitForNavigationWithNoImpression()); + // We should see an impression, as there may be registrations that happen on + // the navigation redirect. + source_observer.Wait(); } IN_PROC_BROWSER_TEST_F(AttributionSourceDeclarationBrowserTest,
diff --git a/content/browser/devtools/frame_auto_attacher.cc b/content/browser/devtools/frame_auto_attacher.cc index 8b643a8..6852790 100644 --- a/content/browser/devtools/frame_auto_attacher.cc +++ b/content/browser/devtools/frame_auto_attacher.cc
@@ -134,7 +134,7 @@ void FrameAutoAttacher::DidFinishNavigation( NavigationRequest* navigation_request) { - if (!render_frame_host_) + if (!auto_attach() || !render_frame_host_) return; if (navigation_request->frame_tree_node() == @@ -158,7 +158,11 @@ // navigation started, so no throttle was installed. We auto-attach them // here instead (note that we cannot honor |wait_for_debugger_on_start_| in // this case). - AutoAttachToFrame(navigation_request, false); + constexpr bool wait_for_debugger_on_start = false; + scoped_refptr<RenderFrameDevToolsAgentHost> agent_host = + HandleNavigation(navigation_request, wait_for_debugger_on_start); + if (agent_host) + DispatchAutoAttach(agent_host.get(), wait_for_debugger_on_start); } void FrameAutoAttacher::UpdatePages() {
diff --git a/content/browser/devtools/protocol/target_auto_attacher.cc b/content/browser/devtools/protocol/target_auto_attacher.cc index f64edd7..56ea2e8 100644 --- a/content/browser/devtools/protocol/target_auto_attacher.cc +++ b/content/browser/devtools/protocol/target_auto_attacher.cc
@@ -30,12 +30,10 @@ return !clients_requesting_wait_for_debugger_.empty(); } -DevToolsAgentHost* TargetAutoAttacher::AutoAttachToFrame( - NavigationRequest* navigation_request, - bool wait_for_debugger_on_start) { - if (!auto_attach()) - return nullptr; - +scoped_refptr<RenderFrameDevToolsAgentHost> +TargetAutoAttacher::HandleNavigation(NavigationRequest* navigation_request, + bool wait_for_debugger_on_start) { + DCHECK(auto_attach()); FrameTreeNode* frame_tree_node = navigation_request->frame_tree_node(); RenderFrameHostImpl* new_host = navigation_request->GetRenderFrameHost(); @@ -45,7 +43,7 @@ if (!new_host) return nullptr; - scoped_refptr<DevToolsAgentHost> agent_host = + scoped_refptr<RenderFrameDevToolsAgentHost> agent_host = RenderFrameDevToolsAgentHost::FindForDangling(frame_tree_node); bool is_portal_main_frame = @@ -60,17 +58,14 @@ agent_host = RenderFrameDevToolsAgentHost:: CreateForLocalRootOrEmbeddedPageNavigation(navigation_request); } - return DispatchAutoAttach(agent_host.get(), wait_for_debugger_on_start) - ? agent_host.get() - : nullptr; + return agent_host; } - if (!agent_host) - return nullptr; - // At this point we don't need a host, so we must auto detach if we auto // attached earlier. - DispatchAutoDetach(agent_host.get()); + if (agent_host) + DispatchAutoDetach(agent_host.get()); + return nullptr; } @@ -118,18 +113,14 @@ } } -bool TargetAutoAttacher::DispatchAutoAttach(DevToolsAgentHost* host, +void TargetAutoAttacher::DispatchAutoAttach(DevToolsAgentHost* host, bool waiting_for_debugger) { - bool attached = false; for (auto& client : clients_) { - attached = - client.AutoAttach( - this, host, - waiting_for_debugger && - clients_requesting_wait_for_debugger_.contains(&client)) || - attached; + client.AutoAttach( + this, host, + waiting_for_debugger && + clients_requesting_wait_for_debugger_.contains(&client)); } - return attached; } void TargetAutoAttacher::DispatchAutoDetach(DevToolsAgentHost* host) {
diff --git a/content/browser/devtools/protocol/target_auto_attacher.h b/content/browser/devtools/protocol/target_auto_attacher.h index 0c17160..524c174a 100644 --- a/content/browser/devtools/protocol/target_auto_attacher.h +++ b/content/browser/devtools/protocol/target_auto_attacher.h
@@ -18,6 +18,7 @@ class NavigationHandle; class NavigationRequest; class NavigationThrottle; +class RenderFrameDevToolsAgentHost; namespace protocol { @@ -61,8 +62,9 @@ NavigationHandle* navigation_handle, std::vector<std::unique_ptr<NavigationThrottle>>* throttles); - DevToolsAgentHost* AutoAttachToFrame(NavigationRequest* navigation_request, - bool wait_for_debugger_on_start); + scoped_refptr<RenderFrameDevToolsAgentHost> HandleNavigation( + NavigationRequest* navigation_request, + bool wait_for_debugger_on_start); protected: using Hosts = base::flat_set<scoped_refptr<DevToolsAgentHost>>; @@ -74,7 +76,7 @@ virtual void UpdateAutoAttach(base::OnceClosure callback); - bool DispatchAutoAttach(DevToolsAgentHost* host, bool waiting_for_debugger); + void DispatchAutoAttach(DevToolsAgentHost* host, bool waiting_for_debugger); void DispatchAutoDetach(DevToolsAgentHost* host); void DispatchSetAttachedTargetsOfType( const base::flat_set<scoped_refptr<DevToolsAgentHost>>& hosts,
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc index d35afe7..6234ba22 100644 --- a/content/browser/devtools/protocol/target_handler.cc +++ b/content/browser/devtools/protocol/target_handler.cc
@@ -343,11 +343,19 @@ ThrottleCheckResult MaybeThrottle() { if (target_handler_ && auto_attacher()) { NavigationRequest* request = NavigationRequest::From(navigation_handle()); - bool wait_for_debugger_on_start = + const bool wait_for_debugger_on_start = target_handler_->ShouldWaitForDebuggerOnStart(request); - DevToolsAgentHost* new_host = auto_attacher()->AutoAttachToFrame( - request, wait_for_debugger_on_start); - SetThrottledAgentHost(wait_for_debugger_on_start ? new_host : nullptr); + scoped_refptr<RenderFrameDevToolsAgentHost> new_host = + auto_attacher()->HandleNavigation(request, + wait_for_debugger_on_start); + if (new_host && + target_handler_->AutoAttach(auto_attacher(), new_host.get(), + wait_for_debugger_on_start) && + wait_for_debugger_on_start) { + SetThrottledAgentHost(new_host.get()); + } else { + SetThrottledAgentHost(nullptr); + } } is_deferring_ = !!agent_host_; return is_deferring_ ? DEFER : PROCEED;
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 85401127..546a6fb 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -155,7 +155,7 @@ } // static -scoped_refptr<DevToolsAgentHost> +scoped_refptr<RenderFrameDevToolsAgentHost> RenderFrameDevToolsAgentHost::CreateForLocalRootOrEmbeddedPageNavigation( NavigationRequest* request) { // Note that this method does not use FrameTreeNode::current_frame_host(), @@ -170,8 +170,8 @@ } // static -scoped_refptr<DevToolsAgentHost> RenderFrameDevToolsAgentHost::FindForDangling( - FrameTreeNode* frame_tree_node) { +scoped_refptr<RenderFrameDevToolsAgentHost> +RenderFrameDevToolsAgentHost::FindForDangling(FrameTreeNode* frame_tree_node) { return FindAgentHost(frame_tree_node); }
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h index 2b4bee8d..f796577 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.h +++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -65,9 +65,9 @@ // This method is called when new frame is created for an emebedded page // (portal or fenced frame) or local root navigation. - static scoped_refptr<DevToolsAgentHost> + static scoped_refptr<RenderFrameDevToolsAgentHost> CreateForLocalRootOrEmbeddedPageNavigation(NavigationRequest* request); - static scoped_refptr<DevToolsAgentHost> FindForDangling( + static scoped_refptr<RenderFrameDevToolsAgentHost> FindForDangling( FrameTreeNode* frame_tree_node); RenderFrameDevToolsAgentHost(const RenderFrameDevToolsAgentHost&) = delete;
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc index b5f5773..0f35c064 100644 --- a/content/browser/shared_storage/shared_storage_browsertest.cc +++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -1282,18 +1282,15 @@ ExecuteScriptInWorklet(shell(), R"( console.log(await sharedStorage.length()); console.log(await sharedStorage.get('key0')); - - // This won't be executed due to the error in the last get(). - console.log(await sharedStorage.length()); )"); EXPECT_EQ(2u, console_observer.messages().size()); EXPECT_EQ("0", base::UTF16ToUTF8(console_observer.messages()[0].message)); EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo, console_observer.messages()[0].log_level); - EXPECT_EQ("sharedStorage.get() failed", + EXPECT_EQ("undefined", base::UTF16ToUTF8(console_observer.messages()[1].message)); - EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kError, + EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo, console_observer.messages()[1].log_level); } @@ -1389,9 +1386,6 @@ console.log(await sharedStorage.length()); console.log(await sharedStorage.get('key0')); - - // This won't be executed due to the error in the last get(). - console.log(await sharedStorage.length()); )"); EXPECT_EQ(4u, console_observer.messages().size()); @@ -1399,7 +1393,7 @@ EXPECT_EQ("value0", base::UTF16ToUTF8(console_observer.messages()[1].message)); EXPECT_EQ("0", base::UTF16ToUTF8(console_observer.messages()[2].message)); - EXPECT_EQ("sharedStorage.get() failed", + EXPECT_EQ("undefined", base::UTF16ToUTF8(console_observer.messages()[3].message)); EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo, console_observer.messages()[0].log_level); @@ -1407,7 +1401,7 @@ console_observer.messages()[1].log_level); EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo, console_observer.messages()[2].log_level); - EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kError, + EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo, console_observer.messages()[3].log_level); }
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc index fdc89a88..d69921c 100644 --- a/content/browser/shared_storage/shared_storage_worklet_host.cc +++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -376,24 +376,33 @@ if (!IsSharedStorageAllowed()) { std::move(callback).Run( - /*success=*/false, + shared_storage_worklet::mojom::SharedStorageGetStatus::kError, /*error_message=*/kSharedStorageDisabledMessage, /*value=*/{}); return; } auto operation_completed_callback = base::BindOnce( [](SharedStorageGetCallback callback, GetResult result) { - // We consider either database error or missing key to be a failure. - if (result.result != OperationResult::kSuccess || !result.data) { + // If the key is not found but there is no other error, the worklet will + // resolve the promise to undefined. + if (result.result == OperationResult::kKeyNotFound) { std::move(callback).Run( - /*success=*/false, + shared_storage_worklet::mojom::SharedStorageGetStatus::kNotFound, + /*error_message=*/"sharedStorage.get() could not find key", + /*value=*/{}); + return; + } + + if (result.result != OperationResult::kSuccess) { + std::move(callback).Run( + shared_storage_worklet::mojom::SharedStorageGetStatus::kError, /*error_message=*/"sharedStorage.get() failed", /*value=*/{}); return; } std::move(callback).Run( - /*success=*/true, - /*error_message=*/{}, /*value=*/*result.data); + shared_storage_worklet::mojom::SharedStorageGetStatus::kSuccess, + /*error_message=*/{}, /*value=*/result.data); }, std::move(callback));
diff --git a/content/browser/speculation_rules/prefetch/prefetch_network_context.cc b/content/browser/speculation_rules/prefetch/prefetch_network_context.cc index 809a4f0..581b1dfb 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_network_context.cc +++ b/content/browser/speculation_rules/prefetch/prefetch_network_context.cc
@@ -12,6 +12,7 @@ #include "content/browser/speculation_rules/prefetch/prefetch_type.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/network_service_instance.h" +#include "content/public/browser/prefetch_service_delegate.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_switches.h" @@ -82,21 +83,23 @@ network_context_.reset(); url_loader_factory_.reset(); + PrefetchServiceDelegate* delegate = + prefetch_service_->GetPrefetchServiceDelegate(); + auto context_params = network::mojom::NetworkContextParams::New(); context_params->user_agent = content::GetReducedUserAgent( base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseMobileUserAgent), - ""); + delegate ? delegate->GetMajorVersionNumber() : ""); context_params->cert_verifier_params = GetCertVerifierParams( cert_verifier::mojom::CertVerifierCreationParams::New()); context_params->cors_exempt_header_list = {kCorsExemptPurposeHeaderName}; context_params->cookie_manager_params = network::mojom::CookieManagerParams::New(); - // TODO(https://crbug.com/1299059): Get major version of Chrome when - // constructing the user agent. This will require a delegate. - // TODO(https://crbug.com/1299059): Add the accept languages stored in prefs. - // This will require a delegate. + if (delegate) { + context_params->accept_language = delegate->GetAcceptLanguageHeader(); + } context_params->http_cache_enabled = true; DCHECK(!context_params->http_cache_directory); @@ -104,6 +107,7 @@ if (prefetch_type_.IsProxyRequired()) { PrefetchProxyConfigurator* prefetch_proxy_configurator = prefetch_service_->GetPrefetchProxyConfigurator(); + DCHECK(prefetch_proxy_configurator); context_params->initial_custom_proxy_config = prefetch_proxy_configurator->CreateCustomProxyConfig();
diff --git a/content/browser/speculation_rules/prefetch/prefetch_params.cc b/content/browser/speculation_rules/prefetch/prefetch_params.cc index d440fca..05c6934 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_params.cc +++ b/content/browser/speculation_rules/prefetch/prefetch_params.cc
@@ -8,6 +8,7 @@ #include "base/metrics/field_trial_params.h" #include "base/rand_util.h" #include "content/browser/speculation_rules/prefetch/prefetch_features.h" +#include "content/public/browser/prefetch_service_delegate.h" namespace content { @@ -15,7 +16,7 @@ return base::FeatureList::IsEnabled(features::kPrefetchUseContentRefactor); } -GURL PrefetchProxyHost() { +GURL PrefetchProxyHost(const GURL& default_proxy_url) { // Command line overrides take priority. std::string cmd_line_value = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( @@ -34,9 +35,7 @@ return url; } - // TODO(https://crbug.com/1299059): Get default URL of the prefetch proxy - // server via a delegate. - return GURL(""); + return default_proxy_url; } std::string PrefetchProxyHeaderKey() { @@ -53,12 +52,27 @@ features::kPrefetchUseContentRefactor, "server_experiment_group"); } +bool PrefetchAllowAllDomains() { + return base::GetFieldTrialParamByFeatureAsBool( + features::kPrefetchUseContentRefactor, "allow_all_domains", + false) || + base::CommandLine::ForCurrentProcess()->HasSwitch( + "isolated-prerender-allow-all-domains"); +} + +bool PrefetchAllowAllDomainsForExtendedPreloading() { + return base::GetFieldTrialParamByFeatureAsBool( + features::kPrefetchUseContentRefactor, + "allow_all_domains_for_extended_preloading", false); +} + int PrefetchServiceMaximumNumberOfConcurrentPrefetches() { return base::GetFieldTrialParamByFeatureAsInt( features::kPrefetchUseContentRefactor, "max_concurrent_prefetches", 1); } -bool PrefetchServiceSendDecoyRequestForIneligblePrefetch() { +bool PrefetchServiceSendDecoyRequestForIneligblePrefetch( + bool disabled_based_on_user_settings) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( "prefetch-proxy-never-send-decoy-requests-for-testing")) { return false; @@ -68,9 +82,12 @@ return true; } - // TODO(https://crbug.com/1299059): Check if the user has opted-in to Make - // Search and Browsing Better. If so, then we don't need to send decoys. Doing - // this will require a delegate. + if (base::GetFieldTrialParamByFeatureAsBool( + features::kPrefetchUseContentRefactor, + "disable_decoys_based_on_user_settings", true) && + disabled_based_on_user_settings) { + return false; + } double probability = base::GetFieldTrialParamByFeatureAsDouble( features::kPrefetchUseContentRefactor,
diff --git a/content/browser/speculation_rules/prefetch/prefetch_params.h b/content/browser/speculation_rules/prefetch/prefetch_params.h index 0e8ad75..713310d 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_params.h +++ b/content/browser/speculation_rules/prefetch/prefetch_params.h
@@ -15,7 +15,7 @@ bool PrefetchContentRefactorIsEnabled(); // The url of the tunnel proxy. -CONTENT_EXPORT GURL PrefetchProxyHost(); +CONTENT_EXPORT GURL PrefetchProxyHost(const GURL& default_proxy_url); // The header name used to connect to the tunnel proxy. std::string PrefetchProxyHeaderKey(); @@ -26,6 +26,14 @@ // group, this will return an empty string. std::string PrefetchProxyServerExperimentGroup(); +// Returns true if any domain can issue private prefetches using the prefetch +// proxy. +bool PrefetchAllowAllDomains(); + +// Returns true if any domain can issue private prefetches using the prefetch +// proxy, so long as the user opted-in to extended preloading. +bool PrefetchAllowAllDomainsForExtendedPreloading(); + // The maximum number of mainframes allowed to be prefetched at the same time. int PrefetchServiceMaximumNumberOfConcurrentPrefetches(); @@ -33,7 +41,8 @@ // but not cached, to disguise the presence of cookies (or other criteria). The // return value is randomly decided based on variation params since always // sending the decoy request is expensive from a data use perspective. -CONTENT_EXPORT bool PrefetchServiceSendDecoyRequestForIneligblePrefetch(); +CONTENT_EXPORT bool PrefetchServiceSendDecoyRequestForIneligblePrefetch( + bool disabled_based_on_user_settings); // The amount of time to allow a prefetch to take before considering it a // timeout error.
diff --git a/content/browser/speculation_rules/prefetch/prefetch_params_unittest.cc b/content/browser/speculation_rules/prefetch/prefetch_params_unittest.cc index 949a87b..acfe700f 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_params_unittest.cc +++ b/content/browser/speculation_rules/prefetch/prefetch_params_unittest.cc
@@ -20,7 +20,8 @@ {{"ineligible_decoy_request_probability", "-1"}}); for (size_t i = 0; i < 100; i++) { - EXPECT_FALSE(PrefetchServiceSendDecoyRequestForIneligblePrefetch()); + EXPECT_FALSE(PrefetchServiceSendDecoyRequestForIneligblePrefetch( + /* disabled_based_on_user_settings=*/false)); } } @@ -31,7 +32,8 @@ {{"ineligible_decoy_request_probability", "2"}}); for (size_t i = 0; i < 100; i++) { - EXPECT_TRUE(PrefetchServiceSendDecoyRequestForIneligblePrefetch()); + EXPECT_TRUE(PrefetchServiceSendDecoyRequestForIneligblePrefetch( + /* disabled_based_on_user_settings=*/false)); } }
diff --git a/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.cc b/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.cc index 524cf891..29ce863 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.cc +++ b/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.cc
@@ -19,19 +19,28 @@ namespace content { -PrefetchProxyConfigurator::PrefetchProxyConfigurator() - : prefetch_proxy_server_(net::ProxyServer( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), - net::HostPortPair::FromURL(PrefetchProxyHost()))), +// static +std::unique_ptr<PrefetchProxyConfigurator> +PrefetchProxyConfigurator::MaybeCreatePrefetchProxyConfigurator( + const GURL& proxy_url, + const std::string& api_key) { + if (!proxy_url.is_valid()) + return nullptr; + + return std::make_unique<PrefetchProxyConfigurator>(proxy_url, api_key); +} + +PrefetchProxyConfigurator::PrefetchProxyConfigurator(const GURL& proxy_url, + const std::string api_key) + : prefetch_proxy_server_(net::GetSchemeFromUriScheme(proxy_url.scheme()), + net::HostPortPair::FromURL(proxy_url)), clock_(base::DefaultClock::GetInstance()) { - DCHECK(PrefetchProxyHost().is_valid()); + DCHECK(proxy_url.is_valid()); std::string server_experiment_group = PrefetchProxyServerExperimentGroup(); - - // TODO(https://crbug.com/1299059): Add API key to header. Need a delegate for - // this. std::string header_value = - server_experiment_group != "" ? "exp=" + server_experiment_group : ""; + "key=" + api_key + + (server_experiment_group != "" ? ",exp=" + server_experiment_group : ""); connect_tunnel_headers_.SetHeader(PrefetchProxyHeaderKey(), header_value); }
diff --git a/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.h b/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.h index ee94555..2503ec60 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.h +++ b/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_SPECULATION_RULES_PREFETCH_PREFETCH_PROXY_CONFIGURATOR_H_ #define CONTENT_BROWSER_SPECULATION_RULES_PREFETCH_PREFETCH_PROXY_CONFIGURATOR_H_ +#include <string> + #include "base/memory/raw_ptr.h" #include "base/sequence_checker.h" #include "base/time/clock.h" @@ -27,7 +29,14 @@ class CONTENT_EXPORT PrefetchProxyConfigurator : public network::mojom::CustomProxyConnectionObserver { public: - PrefetchProxyConfigurator(); + // Creates an instance of |PrefetchProxyConfigurator| when given a valid + // |proxy_url|. + static std::unique_ptr<PrefetchProxyConfigurator> + MaybeCreatePrefetchProxyConfigurator(const GURL& proxy_url, + const std::string& api_key); + + explicit PrefetchProxyConfigurator(const GURL& proxy_url, + const std::string api_key); ~PrefetchProxyConfigurator() override; PrefetchProxyConfigurator(const PrefetchProxyConfigurator&) = delete;
diff --git a/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator_unittest.cc b/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator_unittest.cc index d08e63f4..789160a 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator_unittest.cc +++ b/content/browser/speculation_rules/prefetch/prefetch_proxy_configurator_unittest.cc
@@ -25,6 +25,8 @@ namespace content { namespace { +const char kApiKey[] = "APIKEY"; + class TestCustomProxyConfigClient : public network::mojom::CustomProxyConfigClient { public: @@ -57,6 +59,8 @@ return std::move(config_client_->config_); } + GURL prefetch_proxy_url() { return GURL("https://prefetchproxy.com"); } + void VerifyLatestProxyConfig(const GURL& proxy_url, const net::HttpRequestHeaders& headers) { auto config = LatestProxyConfig(); @@ -81,7 +85,8 @@ PrefetchProxyConfigurator* configurator() { if (!configurator_) { // Lazy construct and init so that any changed field trials can be used. - configurator_ = std::make_unique<PrefetchProxyConfigurator>(); + configurator_ = std::make_unique<PrefetchProxyConfigurator>( + prefetch_proxy_url(), kApiKey); mojo::Remote<network::mojom::CustomProxyConfigClient> client_remote; config_client_ = std::make_unique<TestCustomProxyConfigClient>( client_remote.BindNewPipeAndPassReceiver()); @@ -109,8 +114,6 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndDisableFeature( features::kPrefetchUseContentRefactor); - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - "isolated-prerender-tunnel-proxy", "https://testproxyhost.com"); base::RunLoop loop; configurator()->UpdateCustomProxyConfig(loop.QuitClosure()); @@ -120,32 +123,29 @@ } TEST_F(PrefetchProxyConfiguratorTest, ExperimentOverrides) { - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeatureWithParameters( features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}, {"proxy_header_key", "test-header"}}); + {{"proxy_header_key", "test-header"}}); base::RunLoop loop; configurator()->UpdateCustomProxyConfig(loop.QuitClosure()); loop.Run(); net::HttpRequestHeaders headers; - headers.SetHeader("test-header", ""); - VerifyLatestProxyConfig(proxy_url, headers); + headers.SetHeader("test-header", "key=" + std::string(kApiKey)); + VerifyLatestProxyConfig(prefetch_proxy_url(), headers); } TEST_F(PrefetchProxyConfiguratorTest, Fallback_DoesRandomBackoff_ErrFailed) { base::HistogramTester histogram_tester; - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}}); + scoped_feature_list.InitAndEnableFeature( + features::kPrefetchUseContentRefactor); net::ProxyServer proxy( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), - net::HostPortPair::FromURL(PrefetchProxyHost())); + net::GetSchemeFromUriScheme(prefetch_proxy_url().scheme()), + net::HostPortPair::FromURL(prefetch_proxy_url())); EXPECT_TRUE(configurator()->IsPrefetchProxyAvailable()); @@ -161,15 +161,13 @@ TEST_F(PrefetchProxyConfiguratorTest, FallbackDoesRandomBackoff_ErrOK) { base::HistogramTester histogram_tester; - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}}); + scoped_feature_list.InitAndEnableFeature( + features::kPrefetchUseContentRefactor); net::ProxyServer proxy( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), - net::HostPortPair::FromURL(PrefetchProxyHost())); + net::GetSchemeFromUriScheme(prefetch_proxy_url().scheme()), + net::HostPortPair::FromURL(prefetch_proxy_url())); EXPECT_TRUE(configurator()->IsPrefetchProxyAvailable()); @@ -185,14 +183,12 @@ TEST_F(PrefetchProxyConfiguratorTest, Fallback_DifferentProxy) { base::HistogramTester histogram_tester; - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}}); + scoped_feature_list.InitAndEnableFeature( + features::kPrefetchUseContentRefactor); net::ProxyServer proxy( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), + net::GetSchemeFromUriScheme(prefetch_proxy_url().scheme()), net::HostPortPair::FromURL(GURL("http://foo.com"))); EXPECT_TRUE(configurator()->IsPrefetchProxyAvailable()); @@ -204,15 +200,13 @@ TEST_F(PrefetchProxyConfiguratorTest, TunnelHeaders_200OK) { base::HistogramTester histogram_tester; - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}}); + scoped_feature_list.InitAndEnableFeature( + features::kPrefetchUseContentRefactor); net::ProxyServer proxy( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), - net::HostPortPair::FromURL(PrefetchProxyHost())); + net::GetSchemeFromUriScheme(prefetch_proxy_url().scheme()), + net::HostPortPair::FromURL(prefetch_proxy_url())); EXPECT_TRUE(configurator()->IsPrefetchProxyAvailable()); @@ -224,14 +218,12 @@ TEST_F(PrefetchProxyConfiguratorTest, TunnelHeaders_DifferentProxy) { base::HistogramTester histogram_tester; - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}}); + scoped_feature_list.InitAndEnableFeature( + features::kPrefetchUseContentRefactor); net::ProxyServer proxy( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), + net::GetSchemeFromUriScheme(prefetch_proxy_url().scheme()), net::HostPortPair::FromURL(GURL("http://foo.com"))); EXPECT_TRUE(configurator()->IsPrefetchProxyAvailable()); @@ -244,15 +236,13 @@ TEST_F(PrefetchProxyConfiguratorTest, TunnelHeaders_500NoRetryAfter) { base::HistogramTester histogram_tester; - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}}); + scoped_feature_list.InitAndEnableFeature( + features::kPrefetchUseContentRefactor); net::ProxyServer proxy( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), - net::HostPortPair::FromURL(PrefetchProxyHost())); + net::GetSchemeFromUriScheme(prefetch_proxy_url().scheme()), + net::HostPortPair::FromURL(prefetch_proxy_url())); EXPECT_TRUE(configurator()->IsPrefetchProxyAvailable()); @@ -268,15 +258,13 @@ TEST_F(PrefetchProxyConfiguratorTest, TunnelHeaders_500WithRetryAfter) { base::HistogramTester histogram_tester; - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}}); + scoped_feature_list.InitAndEnableFeature( + features::kPrefetchUseContentRefactor); net::ProxyServer proxy( - net::GetSchemeFromUriScheme(PrefetchProxyHost().scheme()), - net::HostPortPair::FromURL(PrefetchProxyHost())); + net::GetSchemeFromUriScheme(prefetch_proxy_url().scheme()), + net::HostPortPair::FromURL(prefetch_proxy_url())); EXPECT_TRUE(configurator()->IsPrefetchProxyAvailable()); @@ -296,12 +284,10 @@ } TEST_F(PrefetchProxyConfiguratorTest, ServerExperimentGroup) { - GURL proxy_url("https://proxy.com"); base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeatureWithParameters( features::kPrefetchUseContentRefactor, - {{"proxy_host", proxy_url.spec()}, - {"proxy_header_key", "test-header"}, + {{"proxy_header_key", "test-header"}, {"server_experiment_group", "test_group"}}); base::RunLoop loop; @@ -309,8 +295,9 @@ loop.Run(); net::HttpRequestHeaders headers; - headers.SetHeader("test-header", "exp=test_group"); - VerifyLatestProxyConfig(proxy_url, headers); + headers.SetHeader("test-header", + "key=" + std::string(kApiKey) + ",exp=test_group"); + VerifyLatestProxyConfig(prefetch_proxy_url(), headers); } } // namespace
diff --git a/content/browser/speculation_rules/prefetch/prefetch_service.cc b/content/browser/speculation_rules/prefetch/prefetch_service.cc index 55506e8..47e084091 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_service.cc +++ b/content/browser/speculation_rules/prefetch/prefetch_service.cc
@@ -22,6 +22,7 @@ #include "content/browser/speculation_rules/prefetch/prefetched_mainframe_response_container.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/prefetch_service_delegate.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/service_worker_context.h" @@ -173,8 +174,14 @@ PrefetchService::PrefetchService(BrowserContext* browser_context) : browser_context_(browser_context), + delegate_(GetContentClient()->browser()->CreatePrefetchServiceDelegate( + browser_context_)), prefetch_proxy_configurator_( - std::make_unique<PrefetchProxyConfigurator>()) {} + PrefetchProxyConfigurator::MaybeCreatePrefetchProxyConfigurator( + PrefetchProxyHost(delegate_ + ? delegate_->GetDefaultPrefetchProxyHost() + : GURL("")), + delegate_ ? delegate_->GetAPIKey() : "")) {} PrefetchService::~PrefetchService() = default; @@ -183,6 +190,24 @@ DCHECK(prefetch_container); auto prefetch_container_key = prefetch_container->GetPrefetchContainerKey(); + // If the user has disabled pre* actions, then don't prefetch. + if (delegate_ && !delegate_->IsSomePreloadingEnabled()) { + return; + } + + if (delegate_) { + bool allow_all_domains = PrefetchAllowAllDomains() || + (PrefetchAllowAllDomainsForExtendedPreloading() && + delegate_->IsExtendedPreloadingEnabled()); + if (!allow_all_domains && + !delegate_->IsDomainInPrefetchAllowList( + RenderFrameHost::FromID( + prefetch_container->GetReferringRenderFrameHostId()) + ->GetLastCommittedURL())) { + return; + } + } + DCHECK(all_prefetches_.find(prefetch_container_key) == all_prefetches_.end()); all_prefetches_[prefetch_container_key] = prefetch_container; @@ -248,7 +273,8 @@ } if (prefetch_container->GetPrefetchType().IsProxyRequired() && - !prefetch_proxy_configurator_->IsPrefetchProxyAvailable()) { + (!prefetch_proxy_configurator_ || + !prefetch_proxy_configurator_->IsPrefetchProxyAvailable())) { std::move(result_callback) .Run(prefetch_container, false, PrefetchStatus::kPrefetchProxyNotAvailable); @@ -268,9 +294,15 @@ return; } - // TODO(https://crbug.com/1299059): Add a delegate to get information from - // |PrefetchProxyOriginDecider| about whether or not we can prefetch the given - // origin. + // If we have recently received a "retry-after" for the origin, then don't + // send new prefetches. + if (delegate_ && delegate_->IsOriginOutsideRetryAfterWindow( + prefetch_container->GetURL())) { + std::move(result_callback) + .Run(prefetch_container, false, + PrefetchStatus::kPrefetchIneligibleRetryAfter); + return; + } // This service worker check assumes that the prefetch will only ever be // performed in a first-party context (main frame prefetch). At the moment @@ -363,12 +395,12 @@ if (status && prefetch_container) { prefetch_container->SetPrefetchStatus(status.value()); - // TODO(https://crbug.com/1299059): Check if we should send decoys based - // on prefs. This will need to be done via a delegate if (prefetch_container->GetPrefetchType().IsProxyRequired() && ShouldConsiderDecoyRequestForStatus( prefetch_container->GetPrefetchStatus()) && - PrefetchServiceSendDecoyRequestForIneligblePrefetch()) { + PrefetchServiceSendDecoyRequestForIneligblePrefetch( + delegate_ ? delegate_->DisableDecoysBasedOnUserSettings() + : false)) { prefetch_container->SetIsDecoy(true); prefetch_queue_.push_back(prefetch_container); prefetch_container->SetPrefetchStatus( @@ -722,9 +754,10 @@ if (head->headers->EnumerateHeader(nullptr, "Retry-After", &retry_after_string) && net::HttpUtil::ParseRetryAfterHeader( - retry_after_string, base::Time::Now(), &retry_after)) { - // TODO(https://crbug.com/1299059): Update |PrefetchProxyOriginDecider| - // of this response via a delegate. + retry_after_string, base::Time::Now(), &retry_after) && + delegate_) { + delegate_->ReportOriginRetryAfter(prefetch_container->GetURL(), + retry_after); } } return;
diff --git a/content/browser/speculation_rules/prefetch/prefetch_service.h b/content/browser/speculation_rules/prefetch/prefetch_service.h index 6a241ac..8577a49 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_service.h +++ b/content/browser/speculation_rules/prefetch/prefetch_service.h
@@ -31,6 +31,7 @@ class BrowserContext; class PrefetchProxyConfigurator; +class PrefetchServiceDelegate; class ServiceWorkerContext; // Manages all prefetches within a single BrowserContext. Responsible for @@ -53,6 +54,10 @@ BrowserContext* GetBrowserContext() const { return browser_context_; } + PrefetchServiceDelegate* GetPrefetchServiceDelegate() const { + return delegate_.get(); + } + PrefetchProxyConfigurator* GetPrefetchProxyConfigurator() const { return prefetch_proxy_configurator_.get(); } @@ -177,6 +182,10 @@ raw_ptr<BrowserContext> browser_context_; + // Delegate provided by embedder that controls specific behavior of |this|. + // May be nullptr if embedder doesn't provide a delegate. + std::unique_ptr<PrefetchServiceDelegate> delegate_; + // The custom proxy configurator for Prefetch Proxy. Only used on prefetches // that require the proxy. std::unique_ptr<PrefetchProxyConfigurator> prefetch_proxy_configurator_;
diff --git a/content/browser/speculation_rules/prefetch/prefetch_service_unittest.cc b/content/browser/speculation_rules/prefetch/prefetch_service_unittest.cc index 3ba40ea..725eaaa50 100644 --- a/content/browser/speculation_rules/prefetch/prefetch_service_unittest.cc +++ b/content/browser/speculation_rules/prefetch/prefetch_service_unittest.cc
@@ -13,7 +13,9 @@ #include "content/browser/speculation_rules/prefetch/prefetch_params.h" #include "content/browser/speculation_rules/prefetch/prefetch_status.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/prefetch_service_delegate.h" #include "content/public/browser/storage_partition.h" +#include "content/public/common/content_client.h" #include "content/public/test/fake_service_worker_context.h" #include "content/public/test/mock_navigation_handle.h" #include "content/public/test/test_renderer_host.h" @@ -25,6 +27,7 @@ #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/web_preferences/web_preferences.h" #include "url/gurl.h" @@ -32,6 +35,10 @@ namespace content { namespace { +const char kPrefetchProxyAddress[] = "https://testprefetchproxy.com"; + +const char kApiKey[] = "APIKEY"; + const int kTotalTimeDuration = 4321; const int kConnectTimeDuration = 123; @@ -45,6 +52,89 @@ <body></body> </html>)"; +class MockPrefetchServiceDelegate : public PrefetchServiceDelegate { + public: + MockPrefetchServiceDelegate() { + // Sets default behavior for the delegate. + ON_CALL(*this, GetDefaultPrefetchProxyHost) + .WillByDefault(testing::Return(GURL(kPrefetchProxyAddress))); + ON_CALL(*this, GetAPIKey).WillByDefault(testing::Return(kApiKey)); + ON_CALL(*this, IsOriginOutsideRetryAfterWindow(testing::_)) + .WillByDefault(testing::Return(false)); + ON_CALL(*this, DisableDecoysBasedOnUserSettings) + .WillByDefault(testing::Return(false)); + ON_CALL(*this, IsSomePreloadingEnabled) + .WillByDefault(testing::Return(true)); + ON_CALL(*this, IsExtendedPreloadingEnabled) + .WillByDefault(testing::Return(false)); + ON_CALL(*this, IsDomainInPrefetchAllowList(testing::_)) + .WillByDefault(testing::Return(true)); + } + + ~MockPrefetchServiceDelegate() override = default; + + MockPrefetchServiceDelegate(const MockPrefetchServiceDelegate&) = delete; + MockPrefetchServiceDelegate& operator=(const MockPrefetchServiceDelegate) = + delete; + + // PrefetchServiceDelegate. + MOCK_METHOD(std::string, GetMajorVersionNumber, (), (override)); + MOCK_METHOD(std::string, GetAcceptLanguageHeader, (), (override)); + MOCK_METHOD(GURL, GetDefaultPrefetchProxyHost, (), (override)); + MOCK_METHOD(std::string, GetAPIKey, (), (override)); + MOCK_METHOD(void, + ReportOriginRetryAfter, + (const GURL&, base::TimeDelta), + (override)); + MOCK_METHOD(bool, IsOriginOutsideRetryAfterWindow, (const GURL&), (override)); + MOCK_METHOD(void, ClearData, (), (override)); + MOCK_METHOD(bool, DisableDecoysBasedOnUserSettings, (), (override)); + MOCK_METHOD(bool, IsSomePreloadingEnabled, (), (override)); + MOCK_METHOD(bool, IsExtendedPreloadingEnabled, (), (override)); + MOCK_METHOD(bool, IsDomainInPrefetchAllowList, (const GURL&), (override)); +}; + +class ScopedPrefetchServiceContentBrowserClient + : public TestContentBrowserClient { + public: + explicit ScopedPrefetchServiceContentBrowserClient( + std::unique_ptr<MockPrefetchServiceDelegate> + mock_prefetch_service_delegate) + : mock_prefetch_service_delegate_( + std::move(mock_prefetch_service_delegate)) { + old_browser_client_ = SetBrowserClientForTesting(this); + } + + ~ScopedPrefetchServiceContentBrowserClient() override { + EXPECT_EQ(this, SetBrowserClientForTesting(old_browser_client_)); + } + + void SetDataSaverEnabledForTesting(bool data_saver_enabled) { + data_saver_enabled_ = data_saver_enabled; + } + + // ContentBrowserClient. + std::unique_ptr<PrefetchServiceDelegate> CreatePrefetchServiceDelegate( + content::BrowserContext*) override { + return std::move(mock_prefetch_service_delegate_); + } + + bool IsDataSaverEnabled(BrowserContext*) override { + return data_saver_enabled_; + } + + void OverrideWebkitPrefs(WebContents*, + blink::web_pref::WebPreferences* prefs) override { + prefs->data_saver_enabled = data_saver_enabled_; + } + + private: + raw_ptr<ContentBrowserClient> old_browser_client_; + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate_; + + bool data_saver_enabled_{false}; +}; + class PrefetchServiceTest : public RenderViewHostTestHarness { public: PrefetchServiceTest() @@ -69,10 +159,6 @@ [](base::StringPiece) { return false; }); PrefetchService::SetServiceWorkerContextForTesting( &service_worker_context_); - - prefetch_service_ = PrefetchService::CreateIfPossible(browser_context()); - PrefetchDocumentManager::SetPrefetchServiceForTesting( - prefetch_service_.get()); } void TearDown() override { @@ -81,17 +167,28 @@ PrefetchService::SetHostNonUniqueFilterForTesting(nullptr); PrefetchService::SetServiceWorkerContextForTesting(nullptr); PrefetchService::SetURLLoaderFactoryForTesting(nullptr); + test_content_browser_client_.reset(); RenderViewHostTestHarness::TearDown(); } virtual void InitScopedFeatureList() { scoped_feature_list_.InitAndEnableFeatureWithParameters( content::features::kPrefetchUseContentRefactor, - {{"proxy_host", "https://testproxyhost.com"}, - {"ineligible_decoy_request_probability", "0"}, + {{"ineligible_decoy_request_probability", "0"}, {"prefetch_container_lifetime_s", "-1"}}); } + void MakePrefetchService(std::unique_ptr<MockPrefetchServiceDelegate> + mock_prefetch_service_delegate) { + test_content_browser_client_ = + std::make_unique<ScopedPrefetchServiceContentBrowserClient>( + std::move(mock_prefetch_service_delegate)); + + prefetch_service_ = PrefetchService::CreateIfPossible(browser_context()); + PrefetchDocumentManager::SetPrefetchServiceForTesting( + prefetch_service_.get()); + } + // Creates a prefetch request for |url| on the current main frame. void MakePrefetchOnMainFrame(const GURL& url, const PrefetchType& prefetch_type) { @@ -161,11 +258,13 @@ head->load_timing.connect_timing.connect_end - base::Milliseconds(kConnectTimeDuration); - head->proxy_server = use_prefetch_proxy - ? net::ProxyServer::FromSchemeHostAndPort( - net::ProxyServer::Scheme::SCHEME_HTTPS, - PrefetchProxyHost().spec(), absl::nullopt) - : net::ProxyServer::Direct(); + head->proxy_server = + use_prefetch_proxy + ? net::ProxyServer::FromSchemeHostAndPort( + net::ProxyServer::Scheme::SCHEME_HTTPS, + PrefetchProxyHost(GURL(kPrefetchProxyAddress)).spec(), + absl::nullopt) + : net::ProxyServer::Direct(); head->mime_type = mime_type; for (const auto& header : headers) { @@ -221,6 +320,10 @@ prefetch_document_manager->DidStartNavigation(&handle); } + ScopedPrefetchServiceContentBrowserClient* test_content_browser_client() { + return test_content_browser_client_.get(); + } + protected: FakeServiceWorkerContext service_worker_context_; mojo::Remote<network::mojom::CookieManager> cookie_manager_; @@ -231,15 +334,17 @@ base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<PrefetchService> prefetch_service_; + + std::unique_ptr<ScopedPrefetchServiceContentBrowserClient> + test_content_browser_client_; }; TEST_F(PrefetchServiceTest, CreateServiceWhenFeatureEnabled) { // Enable feature, which means that we should be able to create a // PrefetchService instance. base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - content::features::kPrefetchUseContentRefactor, - {{"proxy_host", "https://testproxyhost.com"}}); + scoped_feature_list.InitAndEnableFeature( + content::features::kPrefetchUseContentRefactor); EXPECT_TRUE(PrefetchService::CreateIfPossible(browser_context())); } @@ -257,6 +362,9 @@ TEST_F(PrefetchServiceTest, SuccessCase) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/true)); @@ -302,9 +410,290 @@ prefetch_iter->second->GetPrefetchContainerKey()); } +TEST_F(PrefetchServiceTest, NoPrefetchingPreloadingDisabled) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + // When preloading is disabled, then |PrefetchService| doesn't take the + // prefetch at all. + EXPECT_CALL(*mock_prefetch_service_delegate, IsSomePreloadingEnabled) + .Times(1) + .WillOnce(testing::Return(false)); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(RequestCount(), 0); + + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); + + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.RespCode", + 0); + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.NetError", + 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", 0); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 0U); + + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + prefetch_service_->GetPrefetchToServe(GURL("https://example.com")); + EXPECT_FALSE(serveable_prefetch_container); +} + +TEST_F(PrefetchServiceTest, NoPrefetchingDomainNotInAllowList) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + // When referring page is not in allow list, then |PrefetchService| doesn't + // take the prefetch at all. + EXPECT_CALL(*mock_prefetch_service_delegate, + IsDomainInPrefetchAllowList(testing::_)) + .Times(1) + .WillOnce(testing::Return(false)); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(RequestCount(), 0); + + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); + + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.RespCode", + 0); + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.NetError", + 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", 0); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 0U); + + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + prefetch_service_->GetPrefetchToServe(GURL("https://example.com")); + EXPECT_FALSE(serveable_prefetch_container); +} + +class PrefetchServiceAllowAllDomainsTest : public PrefetchServiceTest { + public: + void InitScopedFeatureList() override { + scoped_feature_list_.InitAndEnableFeatureWithParameters( + content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "0"}, + {"prefetch_container_lifetime_s", "-1"}, + {"allow_all_domains", "true"}}); + } +}; + +TEST_F(PrefetchServiceAllowAllDomainsTest, AllowAllDomains) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + // When "allow_all_domains" is set to true, then we can prefetch from all + // domains, not just those in the allow list. + EXPECT_CALL(*mock_prefetch_service_delegate, + IsDomainInPrefetchAllowList(testing::_)) + .Times(0); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + VerifyCommonRequestState(GURL("https://example.com"), + /*use_prefetch_proxy=*/true); + MakeResponseAndWait(net::HTTP_OK, net::OK, kHTMLMimeType, + /*use_prefetch_proxy=*/true, + {{"X-Testing", "Hello World"}}, kHTMLBody); + + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); + + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.RespCode", net::HTTP_OK, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.NetError", net::OK, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", std::size(kHTMLBody), 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", kTotalTimeDuration, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", kConnectTimeDuration, 1); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 1U); + + auto prefetch_iter = all_prefetches.find( + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://example.com"))); + ASSERT_TRUE(prefetch_iter != all_prefetches.end()); + + EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); + EXPECT_EQ(prefetch_iter->second->GetPrefetchStatus(), + PrefetchStatus::kPrefetchSuccessful); + EXPECT_TRUE(prefetch_iter->second->HasValidPrefetchedResponse( + base::TimeDelta::Max())); + + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + prefetch_service_->GetPrefetchToServe(prefetch_iter->second->GetURL()); + ASSERT_TRUE(serveable_prefetch_container); + EXPECT_EQ(serveable_prefetch_container->GetPrefetchContainerKey(), + prefetch_iter->second->GetPrefetchContainerKey()); +} + +class PrefetchServiceAllowAllDomainsForExtendedPreloadingTest + : public PrefetchServiceTest { + public: + void InitScopedFeatureList() override { + scoped_feature_list_.InitAndEnableFeatureWithParameters( + content::features::kPrefetchUseContentRefactor, + {{"ineligible_decoy_request_probability", "0"}, + {"prefetch_container_lifetime_s", "-1"}, + {"allow_all_domains_for_extended_preloading", "true"}}); + } +}; + +TEST_F(PrefetchServiceAllowAllDomainsForExtendedPreloadingTest, + ExtendedPreloadingEnabled) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + // Allow all domains if and only if extended preloading is enabled. + EXPECT_CALL(*mock_prefetch_service_delegate, IsExtendedPreloadingEnabled) + .Times(1) + .WillOnce(testing::Return(true)); + EXPECT_CALL(*mock_prefetch_service_delegate, + IsDomainInPrefetchAllowList(testing::_)) + .Times(0); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + VerifyCommonRequestState(GURL("https://example.com"), + /*use_prefetch_proxy=*/true); + MakeResponseAndWait(net::HTTP_OK, net::OK, kHTMLMimeType, + /*use_prefetch_proxy=*/true, + {{"X-Testing", "Hello World"}}, kHTMLBody); + + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); + + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.RespCode", net::HTTP_OK, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.NetError", net::OK, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", std::size(kHTMLBody), 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", kTotalTimeDuration, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", kConnectTimeDuration, 1); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 1U); + + auto prefetch_iter = all_prefetches.find( + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://example.com"))); + ASSERT_TRUE(prefetch_iter != all_prefetches.end()); + + EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); + EXPECT_EQ(prefetch_iter->second->GetPrefetchStatus(), + PrefetchStatus::kPrefetchSuccessful); + EXPECT_TRUE(prefetch_iter->second->HasValidPrefetchedResponse( + base::TimeDelta::Max())); + + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + prefetch_service_->GetPrefetchToServe(prefetch_iter->second->GetURL()); + ASSERT_TRUE(serveable_prefetch_container); + EXPECT_EQ(serveable_prefetch_container->GetPrefetchContainerKey(), + prefetch_iter->second->GetPrefetchContainerKey()); +} + +TEST_F(PrefetchServiceAllowAllDomainsForExtendedPreloadingTest, + ExtendedPreloadingDisabled) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + // If extended preloading is disabled, then we check the allow list. + EXPECT_CALL(*mock_prefetch_service_delegate, IsExtendedPreloadingEnabled) + .Times(1) + .WillOnce(testing::Return(false)); + EXPECT_CALL(*mock_prefetch_service_delegate, + IsDomainInPrefetchAllowList(testing::_)) + .Times(1) + .WillOnce(testing::Return(false)); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(RequestCount(), 0); + + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); + + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.RespCode", + 0); + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.NetError", + 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", 0); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 0U); + + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + prefetch_service_->GetPrefetchToServe(GURL("https://example.com")); + EXPECT_FALSE(serveable_prefetch_container); +} + TEST_F(PrefetchServiceTest, NotEligibleHostnameNonUnique) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + PrefetchService::SetHostNonUniqueFilterForTesting( [](base::StringPiece) { return true; }); @@ -347,31 +736,12 @@ EXPECT_FALSE(serveable_prefetch_container); } -namespace { - -class DataSaverContentBrowserClient : public TestContentBrowserClient { - public: - explicit DataSaverContentBrowserClient(bool data_saver_enabled) - : data_saver_enabled_(data_saver_enabled) {} - - bool IsDataSaverEnabled(BrowserContext*) override { - return data_saver_enabled_; - } - void OverrideWebkitPrefs(WebContents*, - blink::web_pref::WebPreferences* prefs) override { - prefs->data_saver_enabled = data_saver_enabled_; - } - - private: - bool data_saver_enabled_; -}; - -} // namespace - TEST_F(PrefetchServiceTest, NotEligibleDataSaverEnabled) { base::HistogramTester histogram_tester; - DataSaverContentBrowserClient browser_client(true); - ScopedContentBrowserClientSetting replace_browser_client(&browser_client); + + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + test_content_browser_client()->SetDataSaverEnabledForTesting(true); MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, @@ -409,6 +779,9 @@ TEST_F(PrefetchServiceTest, NotEligibleNonHttps) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + MakePrefetchOnMainFrame(GURL("http://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/true)); @@ -448,21 +821,80 @@ EXPECT_FALSE(serveable_prefetch_container); } -TEST_F(PrefetchServiceTest, EligibleNonHttpsNonProxiedPotentiallyTrustworthy) { +TEST_F(PrefetchServiceTest, NotEligiblePrefetchProxyNotAvailable) { base::HistogramTester histogram_tester; - MakePrefetchOnMainFrame(GURL("http://localhost"), + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + // If the prefetch proxy URL is invalid, then we can't make prefetches that + // require the proxy. However, non-proxied prefetches are fine. + EXPECT_CALL(*mock_prefetch_service_delegate, GetDefaultPrefetchProxyHost) + .Times(1) + .WillOnce(testing::Return(GURL(""))); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(RequestCount(), 0); + + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.RespCode", + 0); + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.NetError", + 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", 0); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 1U); + + auto prefetch_iter = all_prefetches.find( + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://example.com"))); + ASSERT_TRUE(prefetch_iter != all_prefetches.end()); + + EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); + EXPECT_EQ(prefetch_iter->second->GetPrefetchStatus(), + PrefetchStatus::kPrefetchProxyNotAvailable); + EXPECT_FALSE(prefetch_iter->second->HasValidPrefetchedResponse( + base::TimeDelta::Max())); +} + +TEST_F(PrefetchServiceTest, + EligiblePrefetchProxyNotAvailableNonProxiedPrefetch) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + // If the prefetch proxy URL is invalid, then we can't make prefetches that + // require the proxy. However, non-proxied prefetches are fine. + EXPECT_CALL(*mock_prefetch_service_delegate, GetDefaultPrefetchProxyHost) + .Times(1) + .WillOnce(testing::Return(GURL(""))); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/false)); base::RunLoop().RunUntilIdle(); - VerifyCommonRequestState(GURL("http://localhost"), + VerifyCommonRequestState(GURL("https://example.com"), /*use_prefetch_proxy=*/false); MakeResponseAndWait(net::HTTP_OK, net::OK, kHTMLMimeType, /*use_prefetch_proxy=*/false, {{"X-Testing", "Hello World"}}, kHTMLBody); - Navigate(GURL("http://localhost"), main_rfh()->GetGlobalId()); + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); histogram_tester.ExpectUniqueSample( "PrefetchProxy.Prefetch.Mainframe.RespCode", net::HTTP_OK, 1); @@ -480,7 +912,7 @@ EXPECT_EQ(all_prefetches.size(), 1U); auto prefetch_iter = all_prefetches.find( - std::make_pair(main_rfh()->GetGlobalId(), GURL("http://localhost"))); + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://example.com"))); ASSERT_TRUE(prefetch_iter != all_prefetches.end()); EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); @@ -490,7 +922,104 @@ base::TimeDelta::Max())); base::WeakPtr<PrefetchContainer> serveable_prefetch_container = - prefetch_service_->GetPrefetchToServe(GURL("http://localhost")); + prefetch_service_->GetPrefetchToServe(prefetch_iter->second->GetURL()); + ASSERT_TRUE(serveable_prefetch_container); + EXPECT_EQ(serveable_prefetch_container->GetPrefetchContainerKey(), + prefetch_iter->second->GetPrefetchContainerKey()); +} + +TEST_F(PrefetchServiceTest, NotEligibleOriginWithinRetryAfterWindow) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + EXPECT_CALL(*mock_prefetch_service_delegate, + IsOriginOutsideRetryAfterWindow(GURL("https://example.com"))) + .Times(1) + .WillOnce(testing::Return(true)); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(RequestCount(), 0); + + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.RespCode", + 0); + histogram_tester.ExpectTotalCount("PrefetchProxy.Prefetch.Mainframe.NetError", + 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", 0); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 1U); + + auto prefetch_iter = all_prefetches.find( + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://example.com"))); + ASSERT_TRUE(prefetch_iter != all_prefetches.end()); + + EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); + EXPECT_EQ(prefetch_iter->second->GetPrefetchStatus(), + PrefetchStatus::kPrefetchIneligibleRetryAfter); + EXPECT_FALSE(prefetch_iter->second->HasValidPrefetchedResponse( + base::TimeDelta::Max())); +} + +TEST_F(PrefetchServiceTest, EligibleNonHttpsNonProxiedPotentiallyTrustworthy) { + base::HistogramTester histogram_tester; + + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + + MakePrefetchOnMainFrame(GURL("https://localhost"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/false)); + base::RunLoop().RunUntilIdle(); + + VerifyCommonRequestState(GURL("https://localhost"), + /*use_prefetch_proxy=*/false); + MakeResponseAndWait(net::HTTP_OK, net::OK, kHTMLMimeType, + /*use_prefetch_proxy=*/false, + {{"X-Testing", "Hello World"}}, kHTMLBody); + + Navigate(GURL("https://localhost"), main_rfh()->GetGlobalId()); + + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.RespCode", net::HTTP_OK, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.NetError", net::OK, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", std::size(kHTMLBody), 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", kTotalTimeDuration, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", kConnectTimeDuration, 1); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 1U); + + auto prefetch_iter = all_prefetches.find( + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://localhost"))); + ASSERT_TRUE(prefetch_iter != all_prefetches.end()); + + EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); + EXPECT_EQ(prefetch_iter->second->GetPrefetchStatus(), + PrefetchStatus::kPrefetchSuccessful); + EXPECT_TRUE(prefetch_iter->second->HasValidPrefetchedResponse( + base::TimeDelta::Max())); + + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + prefetch_service_->GetPrefetchToServe(GURL("https://localhost")); ASSERT_TRUE(serveable_prefetch_container); EXPECT_EQ(serveable_prefetch_container->GetPrefetchContainerKey(), prefetch_iter->second->GetPrefetchContainerKey()); @@ -499,6 +1028,9 @@ TEST_F(PrefetchServiceTest, NotEligibleServiceWorkerRegistered) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + service_worker_context_.AddRegistrationToRegisteredStorageKeys( blink::StorageKey(url::Origin::Create(GURL("https://example.com")))); @@ -544,6 +1076,9 @@ TEST_F(PrefetchServiceTest, EligibleServiceWorkerNotRegistered) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + service_worker_context_.AddRegistrationToRegisteredStorageKeys( blink::StorageKey(url::Origin::Create(GURL("https://other.com")))); @@ -595,6 +1130,9 @@ TEST_F(PrefetchServiceTest, NotEligibleUserHasCookies) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + ASSERT_TRUE(SetCookie(GURL("https://example.com"), "testing")); MakePrefetchOnMainFrame(GURL("https://example.com"), @@ -639,6 +1177,9 @@ TEST_F(PrefetchServiceTest, EligibleUserHasCookiesForDifferentUrl) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + ASSERT_TRUE(SetCookie(GURL("https://other.com"), "testing")); MakePrefetchOnMainFrame(GURL("https://example.com"), @@ -689,6 +1230,9 @@ TEST_F(PrefetchServiceTest, EligibleSameOriginPrefetchCanHaveExistingCookies) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + ASSERT_TRUE(SetCookie(GURL("https://example.com"), "testing")); MakePrefetchOnMainFrame(GURL("https://example.com"), @@ -739,6 +1283,9 @@ TEST_F(PrefetchServiceTest, FailedNon2XXResponseCode) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/true)); @@ -785,6 +1332,9 @@ TEST_F(PrefetchServiceTest, FailedNetError) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/true)); @@ -829,9 +1379,72 @@ EXPECT_FALSE(serveable_prefetch_container); } +TEST_F(PrefetchServiceTest, HandleRetryAfterResponse) { + base::HistogramTester histogram_tester; + + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + EXPECT_CALL( + *mock_prefetch_service_delegate, + ReportOriginRetryAfter(GURL("https://example.com"), base::Seconds(1234))) + .Times(1); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + VerifyCommonRequestState(GURL("https://example.com"), + /*use_prefetch_proxy=*/true); + + // Simulate the origin responding with a "retry-after" header. + MakeResponseAndWait(net::HTTP_SERVICE_UNAVAILABLE, net::OK, kHTMLMimeType, + /*use_prefetch_proxy=*/true, + {{"Retry-After", "1234"}, {"X-Testing", "Hello World"}}, + ""); + + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); + + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.RespCode", + net::HTTP_SERVICE_UNAVAILABLE, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.NetError", net::OK, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.BodyLength", 0, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.TotalTime", kTotalTimeDuration, 1); + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.Mainframe.ConnectTime", kConnectTimeDuration, 1); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 1U); + + auto prefetch_iter = all_prefetches.find( + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://example.com"))); + ASSERT_TRUE(prefetch_iter != all_prefetches.end()); + + EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); + EXPECT_EQ(prefetch_iter->second->GetPrefetchStatus(), + PrefetchStatus::kPrefetchFailedNon2XX); + EXPECT_FALSE(prefetch_iter->second->HasValidPrefetchedResponse( + base::TimeDelta::Max())); + + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + prefetch_service_->GetPrefetchToServe(GURL("https://example.com")); + EXPECT_FALSE(serveable_prefetch_container); +} + TEST_F(PrefetchServiceTest, SuccessNonHTML) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/true)); @@ -882,6 +1495,9 @@ TEST_F(PrefetchServiceTest, NotServeableNavigationInDifferentRenderFrameHost) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/true)); @@ -936,8 +1552,7 @@ void InitScopedFeatureList() override { scoped_feature_list_.InitAndEnableFeatureWithParameters( content::features::kPrefetchUseContentRefactor, - {{"proxy_host", "https://testproxyhost.com"}, - {"ineligible_decoy_request_probability", "0"}, + {{"ineligible_decoy_request_probability", "0"}, {"prefetch_container_lifetime_s", "-1"}, {"html_only", "true"}}); } @@ -946,6 +1561,9 @@ TEST_F(PrefetchServiceWithHTMLOnlyTest, FailedNonHTMLWithHTMLOnly) { base::HistogramTester histogram_tester; + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + MakePrefetchOnMainFrame(GURL("https://example.com"), PrefetchType(/*use_isolated_network_context=*/true, /*use_prefetch_proxy=*/true)); @@ -996,13 +1614,15 @@ void InitScopedFeatureList() override { scoped_feature_list_.InitAndEnableFeatureWithParameters( content::features::kPrefetchUseContentRefactor, - {{"proxy_host", "https://testproxyhost.com"}, - {"ineligible_decoy_request_probability", "1"}, + {{"ineligible_decoy_request_probability", "1"}, {"prefetch_container_lifetime_s", "-1"}}); } }; TEST_F(PrefetchServiceAlwaysMakeDecoyRequestTest, DecoyRequest) { + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>()); + ASSERT_TRUE(SetCookie(GURL("https://example.com"), "testing")); MakePrefetchOnMainFrame(GURL("https://example.com"), @@ -1037,6 +1657,43 @@ EXPECT_FALSE(serveable_prefetch_container); } +TEST_F(PrefetchServiceAlwaysMakeDecoyRequestTest, + NoDecoyRequestDisableDecoysBasedOnUserSettings) { + std::unique_ptr<MockPrefetchServiceDelegate> mock_prefetch_service_delegate = + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>(); + + EXPECT_CALL(*mock_prefetch_service_delegate, DisableDecoysBasedOnUserSettings) + .Times(1) + .WillOnce(testing::Return(true)); + + MakePrefetchService(std::move(mock_prefetch_service_delegate)); + + ASSERT_TRUE(SetCookie(GURL("https://example.com"), "testing")); + + MakePrefetchOnMainFrame(GURL("https://example.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(RequestCount(), 0); + + Navigate(GURL("https://example.com"), main_rfh()->GetGlobalId()); + + auto all_prefetches = prefetch_service_->GetAllPrefetchesForTesting(); + + EXPECT_EQ(all_prefetches.size(), 1U); + + auto prefetch_iter = all_prefetches.find( + std::make_pair(main_rfh()->GetGlobalId(), GURL("https://example.com"))); + ASSERT_TRUE(prefetch_iter != all_prefetches.end()); + + EXPECT_TRUE(prefetch_iter->second->HasPrefetchStatus()); + EXPECT_EQ(prefetch_iter->second->GetPrefetchStatus(), + PrefetchStatus::kPrefetchNotEligibleUserHasCookies); + EXPECT_FALSE(prefetch_iter->second->HasValidPrefetchedResponse( + base::TimeDelta::Max())); +} + // TODO(https://crbug.com/1299059): Add test for incognito mode. } // namespace
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 63e6075..69df47d 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -2634,6 +2634,20 @@ bluetooth_allowed_devices_map_->Clear(); } +void StoragePartitionImpl::ResetAttributionManagerForTesting( + base::OnceCallback<void(bool)> callback) { + DCHECK(initialized_); + + // Reset the existing manager first to ensure that the underlying DB is only + // accessed by one instance at a time. + attribution_manager_.reset(); + + attribution_manager_ = AttributionManagerImpl::CreateWithNewDbForTesting( + this, partition_path_, special_storage_policy_); + + std::move(callback).Run(/*success=*/!!attribution_manager_); +} + void StoragePartitionImpl::AddObserver(DataRemovalObserver* observer) { data_removal_observers_.AddObserver(observer); }
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 1b836b6..b0ddd571 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -236,6 +236,8 @@ void SetNetworkContextForTesting( mojo::PendingRemote<network::mojom::NetworkContext> network_context_remote) override; + void ResetAttributionManagerForTesting( + base::OnceCallback<void(bool)> callback) override; base::WeakPtr<StoragePartition> GetWeakPtr(); BackgroundFetchContext* GetBackgroundFetchContext();
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 1470df4..ee5067b9 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1356,15 +1356,6 @@ return ftn->current_frame_host(); } -void WebContentsImpl::ForEachFrame( - const base::RepeatingCallback<void(RenderFrameHost*)>& on_frame) { - OPTIONAL_TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"), - "WebContentsImpl::ForEachFrame"); - for (FrameTreeNode* node : primary_frame_tree_.Nodes()) { - on_frame.Run(node->current_frame_host()); - } -} - void WebContentsImpl::ForEachRenderFrameHost( RenderFrameHost::FrameIterationCallback on_frame) { ForEachRenderFrameHost(RenderFrameHostImpl::FrameIterationWrapper(on_frame));
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 9af9ea4..592533a 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -339,8 +339,6 @@ bool IsPrerenderedFrame(int frame_tree_node_id) override; RenderFrameHostImpl* UnsafeFindFrameByFrameTreeNodeId( int frame_tree_node_id) override; - void ForEachFrame( - const base::RepeatingCallback<void(RenderFrameHost*)>& on_frame) override; void ForEachRenderFrameHost( RenderFrameHost::FrameIterationCallback on_frame) override; void ForEachRenderFrameHost(
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index abd02c0..56b5719 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -287,6 +287,8 @@ "picture_in_picture_window_controller.h", "platform_notification_context.h", "platform_notification_service.h", + "prefetch_service_delegate.cc", + "prefetch_service_delegate.h", "preloading.h", "preloading_data.h", "prerender_handle.h",
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 9a593698..2324162 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -37,6 +37,7 @@ #include "content/public/browser/network_service_instance.h" #include "content/public/browser/overlay_window.h" #include "content/public/browser/page_navigator.h" +#include "content/public/browser/prefetch_service_delegate.h" #include "content/public/browser/quota_permission_context.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/sms_fetcher.h" @@ -1326,6 +1327,12 @@ return nullptr; } +std::unique_ptr<PrefetchServiceDelegate> +ContentBrowserClient::CreatePrefetchServiceDelegate( + BrowserContext* browser_context) { + return nullptr; +} + void ContentBrowserClient::ShowDirectSocketsConnectionDialog( content::RenderFrameHost* owner, const std::string& address,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 58755b9..d18856a 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -216,6 +216,7 @@ class NavigationHandle; class NavigationThrottle; class NavigationUIData; +class PrefetchServiceDelegate; class QuotaPermissionContext; class ReceiverPresentationServiceDelegate; class RenderFrameHost; @@ -2220,6 +2221,11 @@ virtual std::unique_ptr<SpeculationHostDelegate> CreateSpeculationHostDelegate(RenderFrameHost& render_frame_host); + // Allows the embedder to provide a PrefetchServiceDelegate that will be used + // to make prefetches. + virtual std::unique_ptr<PrefetchServiceDelegate> + CreatePrefetchServiceDelegate(BrowserContext* browser_context); + // Allows the embedder to show a dialog that will be used to control whether a // connection through the Direct Sockets API is permitted. If the connection // is permitted, the remote address and port that the user input will be sent
diff --git a/content/public/browser/prefetch_service_delegate.cc b/content/public/browser/prefetch_service_delegate.cc new file mode 100644 index 0000000..11d9d49f --- /dev/null +++ b/content/public/browser/prefetch_service_delegate.cc
@@ -0,0 +1,28 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/browser/prefetch_service_delegate.h" + +#include "content/browser/browser_context_impl.h" +#include "content/browser/speculation_rules/prefetch/prefetch_service.h" +#include "content/public/browser/browser_context.h" + +namespace content { + +// static +void PrefetchServiceDelegate::ClearData(BrowserContext* browser_context) { + PrefetchService* prefetch_service = + BrowserContextImpl::From(browser_context)->GetPrefetchService(); + if (!prefetch_service) + return; + + PrefetchServiceDelegate* prefetch_service_delegate = + prefetch_service->GetPrefetchServiceDelegate(); + if (!prefetch_service_delegate) + return; + + prefetch_service_delegate->ClearData(); +} + +} // namespace content \ No newline at end of file
diff --git a/content/public/browser/prefetch_service_delegate.h b/content/public/browser/prefetch_service_delegate.h new file mode 100644 index 0000000..8f4618a --- /dev/null +++ b/content/public/browser/prefetch_service_delegate.h
@@ -0,0 +1,67 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_PREFETCH_SERVICE_DELEGATE_H_ +#define CONTENT_PUBLIC_BROWSER_PREFETCH_SERVICE_DELEGATE_H_ + +#include <string> + +#include "base/time/time.h" +#include "content/common/content_export.h" +#include "url/gurl.h" + +namespace content { + +class BrowserContext; + +// Allows embedders to control certain aspects of |PrefetchService|. +class CONTENT_EXPORT PrefetchServiceDelegate { + public: + virtual ~PrefetchServiceDelegate() = default; + + // Clears data for delegate associated with given |browser_context|. + static void ClearData(BrowserContext* browser_context); + + // Gets the major version of the embedder. Only the major version of embedder + // is included in the user agent for prefetch requests. + virtual std::string GetMajorVersionNumber() = 0; + + // Gets the accept language header to be included in prefetch requests. + virtual std::string GetAcceptLanguageHeader() = 0; + + // Gets the default host of the prefetch proxy. + virtual GURL GetDefaultPrefetchProxyHost() = 0; + + // Gets API key for making prefetching requests. + virtual std::string GetAPIKey() = 0; + + // Reports that a 503 response with a "Retry-After" header was received from + // |url|. Indicates that we shouldn't send new prefetch requests to that + // origin for |retry_after| amount of time. + virtual void ReportOriginRetryAfter(const GURL& url, + base::TimeDelta retry_after) = 0; + + // Returns whether or not the URL is eligible for prefetch based on previous + // responses with a "Retry-After" header. + virtual bool IsOriginOutsideRetryAfterWindow(const GURL& url) = 0; + + // Clears any browsing data associated with the delegate, specifically any + // information about "Retry-Afters" received. + virtual void ClearData() = 0; + + // Checks if we can disable sending decoy prefetches based on the user's + // settings. + virtual bool DisableDecoysBasedOnUserSettings() = 0; + + // Get the state of the user's preloading settings. + virtual bool IsSomePreloadingEnabled() = 0; + virtual bool IsExtendedPreloadingEnabled() = 0; + + // Checks if the referring page is in the allow list to make prefetches. + virtual bool IsDomainInPrefetchAllowList(const GURL& referring_url) = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_PREFETCH_SERVICE_DELEGATE_H_ \ No newline at end of file
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h index add16c58..c828d24 100644 --- a/content/public/browser/storage_partition.h +++ b/content/public/browser/storage_partition.h
@@ -325,6 +325,11 @@ virtual leveldb_proto::ProtoDatabaseProvider* GetProtoDatabaseProviderForTesting() = 0; + // Resets all state associated with the Attribution Reporting API for use in + // hermetic tests. + virtual void ResetAttributionManagerForTesting( + base::OnceCallback<void(bool success)> callback) = 0; + // The value pointed to by |settings| should remain valid until the // the function is called again with a new value or a nullptr. static void SetDefaultQuotaSettingsForTesting(
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 92a0750..64e7a35 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -417,15 +417,6 @@ virtual RenderFrameHost* UnsafeFindFrameByFrameTreeNodeId( int frame_tree_node_id) = 0; - // TODO(1208438): Migrate to |ForEachRenderFrameHost|. - // Calls |on_frame| for each frame in the currently active view. - // Note: The RenderFrameHost parameter is not guaranteed to have a live - // RenderFrame counterpart in the renderer process. Callbacks should check - // IsRenderFrameLive(), as sending IPC messages to it in this case will fail - // silently. - virtual void ForEachFrame( - const base::RepeatingCallback<void(RenderFrameHost*)>& on_frame) = 0; - // Calls |on_frame| for every RenderFrameHost in this WebContents. Note that // this includes RenderFrameHosts that are not descended from the primary main // frame (e.g. bfcached pages and prerendered pages). The order of traversal
diff --git a/content/public/test/test_storage_partition.cc b/content/public/test/test_storage_partition.cc index c436909..31f567f4 100644 --- a/content/public/test/test_storage_partition.cc +++ b/content/public/test/test_storage_partition.cc
@@ -229,6 +229,11 @@ void TestStoragePartition::ClearBluetoothAllowedDevicesMapForTesting() {} +void TestStoragePartition::ResetAttributionManagerForTesting( + base::OnceCallback<void(bool)> callback) { + std::move(callback).Run(/*success=*/true); +} + void TestStoragePartition::FlushNetworkInterfaceForTesting() {} void TestStoragePartition::WaitForDeletionTasksForTesting() {}
diff --git a/content/public/test/test_storage_partition.h b/content/public/test/test_storage_partition.h index 3d4382a4..86e128a 100644 --- a/content/public/test/test_storage_partition.h +++ b/content/public/test/test_storage_partition.h
@@ -215,6 +215,8 @@ int GetDataRemovalObserverCount(); void ClearBluetoothAllowedDevicesMapForTesting() override; + void ResetAttributionManagerForTesting( + base::OnceCallback<void(bool)> callback) override; void FlushNetworkInterfaceForTesting() override; void WaitForDeletionTasksForTesting() override; void WaitForCodeCacheShutdownForTesting() override;
diff --git a/content/services/shared_storage_worklet/public/mojom/shared_storage_worklet_service.mojom b/content/services/shared_storage_worklet/public/mojom/shared_storage_worklet_service.mojom index 8b8c6820..5a21be65 100644 --- a/content/services/shared_storage_worklet/public/mojom/shared_storage_worklet_service.mojom +++ b/content/services/shared_storage_worklet/public/mojom/shared_storage_worklet_service.mojom
@@ -13,6 +13,12 @@ import "url/mojom/origin.mojom"; import "url/mojom/url.mojom"; +enum SharedStorageGetStatus { + kSuccess, + kNotFound, + kError, +}; + // Used by the shared storage worklet environment to access the shared storage, // log messages, etc. interface SharedStorageWorkletServiceClient { @@ -41,7 +47,8 @@ // Handle sharedStorage.get(): get the entry at `key`, or an empty string if // `key` is not present. SharedStorageGet(blink.mojom.SharedStorageKeyArgument key) - => (bool success, string error_message, mojo_base.mojom.String16 value); + => (SharedStorageGetStatus status, string error_message, + mojo_base.mojom.String16 value); // Returns (potentially in batches) the keys of the shared storage. SharedStorageKeys(pending_remote<SharedStorageEntriesListener> listener);
diff --git a/content/services/shared_storage_worklet/shared_storage.cc b/content/services/shared_storage_worklet/shared_storage.cc index 2bb6f0f..8b27110 100644 --- a/content/services/shared_storage_worklet/shared_storage.cc +++ b/content/services/shared_storage_worklet/shared_storage.cc
@@ -297,18 +297,25 @@ void SharedStorage::OnStringRetrievalOperationFinished( v8::Isolate* isolate, v8::Global<v8::Promise::Resolver> global_resolver, - bool success, + shared_storage_worklet::mojom::SharedStorageGetStatus status, const std::string& error_message, const std::u16string& result) { WorkletV8Helper::HandleScope scope(isolate); v8::Local<v8::Promise::Resolver> resolver = global_resolver.Get(isolate); v8::Local<v8::Context> context = resolver->GetCreationContextChecked(); - if (success) { + if (status == + shared_storage_worklet::mojom::SharedStorageGetStatus::kSuccess) { resolver->Resolve(context, gin::ConvertToV8(isolate, result)).ToChecked(); return; } + if (status == + shared_storage_worklet::mojom::SharedStorageGetStatus::kNotFound) { + resolver->Resolve(context, v8::Undefined(isolate)).ToChecked(); + return; + } + resolver->Reject(context, gin::StringToV8(isolate, error_message)) .ToChecked(); }
diff --git a/content/services/shared_storage_worklet/shared_storage.h b/content/services/shared_storage_worklet/shared_storage.h index 45e2f10..cd4c35f 100644 --- a/content/services/shared_storage_worklet/shared_storage.h +++ b/content/services/shared_storage_worklet/shared_storage.h
@@ -47,7 +47,7 @@ void OnStringRetrievalOperationFinished( v8::Isolate* isolate, v8::Global<v8::Promise::Resolver> global_resolver, - bool success, + shared_storage_worklet::mojom::SharedStorageGetStatus status, const std::string& error_message, const std::u16string& result);
diff --git a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc index 086ed89..ae300b8 100644 --- a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc +++ b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc
@@ -116,7 +116,7 @@ FROM_HERE, base::BindLambdaForTesting([callback = std::move(callback)]() mutable { std::move(callback).Run( - /*success=*/true, + shared_storage_worklet::mojom::SharedStorageGetStatus::kSuccess, /*error_message=*/{}, /*value=*/u"test-value"); }));
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index cccba399..62eb22a 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -2062,6 +2062,7 @@ "../browser/attribution_reporting/attribution_cookie_checker_impl_unittest.cc", "../browser/attribution_reporting/attribution_data_host_manager_impl_unittest.cc", "../browser/attribution_reporting/attribution_filter_data_unittest.cc", + "../browser/attribution_reporting/attribution_header_utils_unittest.cc", "../browser/attribution_reporting/attribution_host_unittest.cc", "../browser/attribution_reporting/attribution_insecure_random_generator_unittest.cc", "../browser/attribution_reporting/attribution_interop_parser_unittest.cc",
diff --git a/content/test/data/accessibility/html/math-expected-uia-win.txt b/content/test/data/accessibility/html/math-expected-uia-win.txt index 9d36f33..3685e00 100644 --- a/content/test/data/accessibility/html/math-expected-uia-win.txt +++ b/content/test/data/accessibility/html/math-expected-uia-win.txt
@@ -1,6 +1,6 @@ Document ++Group IsControlElement=false -++++Group IsControlElement=false +++++Group ++++++Group IsControlElement=false ++++++++Group IsControlElement=false ++++++++++Group IsControlElement=false
diff --git a/content/test/data/accessibility/mathml/math-node-expected-uia-win.txt b/content/test/data/accessibility/mathml/math-node-expected-uia-win.txt new file mode 100644 index 0000000..e566496 --- /dev/null +++ b/content/test/data/accessibility/mathml/math-node-expected-uia-win.txt
@@ -0,0 +1 @@ +Group
diff --git a/content/test/data/accessibility/mathml/math.html b/content/test/data/accessibility/mathml/math.html index 5a63295..d3c9351 100644 --- a/content/test/data/accessibility/mathml/math.html +++ b/content/test/data/accessibility/mathml/math.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <!-- @AURALINUX-ALLOW:tag:* +@UIA-WIN-ALLOW:ControlType='UIA_GroupControlTypeId' --> <math class="test"> </math>
diff --git a/content/test/data/attribution_reporting/register_source_navigation_redirect.html b/content/test/data/attribution_reporting/register_source_navigation_redirect.html new file mode 100644 index 0000000..b15cf00 --- /dev/null +++ b/content/test/data/attribution_reporting/register_source_navigation_redirect.html
@@ -0,0 +1 @@ +Registers a source by providing headers and performs a redirect to another registration endpoint.
diff --git a/content/test/data/attribution_reporting/register_source_navigation_redirect.html.mock-http-headers b/content/test/data/attribution_reporting/register_source_navigation_redirect.html.mock-http-headers new file mode 100644 index 0000000..e4fc46e --- /dev/null +++ b/content/test/data/attribution_reporting/register_source_navigation_redirect.html.mock-http-headers
@@ -0,0 +1,3 @@ +HTTP/1.1 301 Yo +Attribution-Reporting-Register-Source:{"source_event_id":"1","destination":"https://d.test"} +Location: /page_with_conversion_redirect.html
diff --git a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt index ff196a2..97ede12 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
@@ -97,6 +97,7 @@ crbug.com/1336713 WebCodecs_texture_expired_from_destroyed_device_hw_decoder [ Failure ] crbug.com/1336713 WebCodecs_texture_expired_from_destroyed_device_offscreen [ Failure ] crbug.com/1336713 WebCodecs_texture_expired_from_destroyed_device_sw_decoder [ Failure ] +crbug.com/1336713 WebCodecs_texture_expired_from_destroyed_device_camera [ Failure ] crbug.com/1311091 WebCodecs_WebRTCPeerConnection_* [ Skip ]
diff --git a/content/web_test/BUILD.gn b/content/web_test/BUILD.gn index 1319db8..5c35546 100644 --- a/content/web_test/BUILD.gn +++ b/content/web_test/BUILD.gn
@@ -97,6 +97,8 @@ "browser/mojo_web_test_helper.h", "browser/test_info_extractor.cc", "browser/test_info_extractor.h", + "browser/web_test_attribution_manager.cc", + "browser/web_test_attribution_manager.h", "browser/web_test_background_fetch_delegate.cc", "browser/web_test_background_fetch_delegate.h", "browser/web_test_bluetooth_adapter_provider.cc",
diff --git a/content/web_test/browser/web_test_attribution_manager.cc b/content/web_test/browser/web_test_attribution_manager.cc new file mode 100644 index 0000000..eace883 --- /dev/null +++ b/content/web_test/browser/web_test_attribution_manager.cc
@@ -0,0 +1,21 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/web_test/browser/web_test_attribution_manager.h" + +#include <utility> + +#include "content/public/browser/storage_partition.h" + +namespace content { + +WebTestAttributionManager::WebTestAttributionManager( + StoragePartition& storage_partition) + : storage_partition_(&storage_partition) {} + +void WebTestAttributionManager::Reset(ResetCallback callback) { + storage_partition_->ResetAttributionManagerForTesting(std::move(callback)); +} + +} // namespace content
diff --git a/content/web_test/browser/web_test_attribution_manager.h b/content/web_test/browser/web_test_attribution_manager.h new file mode 100644 index 0000000..284c787 --- /dev/null +++ b/content/web_test/browser/web_test_attribution_manager.h
@@ -0,0 +1,39 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_WEB_TEST_BROWSER_WEB_TEST_ATTRIBUTION_MANAGER_H_ +#define CONTENT_WEB_TEST_BROWSER_WEB_TEST_ATTRIBUTION_MANAGER_H_ + +#include "third_party/blink/public/mojom/conversions/attribution_reporting_automation.mojom.h" + +#include "base/memory/raw_ptr.h" + +namespace content { + +class StoragePartition; + +// Provides privileged access to a storage partition's `AttributionManager` in +// order to support test-specific behavior. +class WebTestAttributionManager + : public blink::test::mojom::AttributionReportingAutomation { + public: + explicit WebTestAttributionManager(StoragePartition& storage_partition); + + ~WebTestAttributionManager() override = default; + + WebTestAttributionManager(const WebTestAttributionManager&) = delete; + + WebTestAttributionManager& operator=(const WebTestAttributionManager&) = + delete; + + // blink::test::mojom::AttributionReportingAutomation: + void Reset(ResetCallback) override; + + private: + const base::raw_ptr<StoragePartition> storage_partition_; +}; + +} // namespace content + +#endif // CONTENT_WEB_TEST_BROWSER_WEB_TEST_ATTRIBUTION_MANAGER_H_
diff --git a/content/web_test/browser/web_test_content_browser_client.cc b/content/web_test/browser/web_test_content_browser_client.cc index 2e7c332..e757a73 100644 --- a/content/web_test/browser/web_test_content_browser_client.cc +++ b/content/web_test/browser/web_test_content_browser_client.cc
@@ -43,6 +43,7 @@ #include "content/web_test/browser/fake_bluetooth_delegate.h" #include "content/web_test/browser/mojo_echo.h" #include "content/web_test/browser/mojo_web_test_helper.h" +#include "content/web_test/browser/web_test_attribution_manager.h" #include "content/web_test/browser/web_test_bluetooth_fake_adapter_setter_impl.h" #include "content/web_test/browser/web_test_browser_context.h" #include "content/web_test/browser/web_test_browser_main_parts.h" @@ -70,6 +71,7 @@ #include "storage/browser/quota/quota_settings.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/common/web_preferences/web_preferences.h" +#include "third_party/blink/public/mojom/conversions/attribution_reporting_automation.mojom.h" #include "ui/base/ui_base_switches.h" #include "url/origin.h" @@ -471,6 +473,10 @@ map->Add<blink::test::mojom::CookieManagerAutomation>(base::BindRepeating( &WebTestContentBrowserClient::BindCookieManagerAutomation, base::Unretained(this))); + map->Add<blink::test::mojom::AttributionReportingAutomation>( + base::BindRepeating( + &WebTestContentBrowserClient::BindAttributionReportingAutomation, + base::Unretained(this))); } bool WebTestContentBrowserClient::CanAcceptUntrustedExchangesIfNeeded() { @@ -523,6 +529,16 @@ std::move(receiver)); } +void WebTestContentBrowserClient::BindAttributionReportingAutomation( + RenderFrameHost* render_frame_host, + mojo::PendingReceiver<blink::test::mojom::AttributionReportingAutomation> + receiver) { + attribution_reporting_receivers_.Add( + std::make_unique<WebTestAttributionManager>( + *GetWebTestBrowserContext()->GetDefaultStoragePartition()), + std::move(receiver)); +} + std::unique_ptr<LoginDelegate> WebTestContentBrowserClient::CreateLoginDelegate( const net::AuthChallengeInfo& auth_info, content::WebContents* web_contents,
diff --git a/content/web_test/browser/web_test_content_browser_client.h b/content/web_test/browser/web_test_content_browser_client.h index 00e2a8c..4805dd03 100644 --- a/content/web_test/browser/web_test_content_browser_client.h +++ b/content/web_test/browser/web_test_content_browser_client.h
@@ -20,6 +20,7 @@ #include "services/service_manager/public/cpp/binder_registry.h" #include "third_party/blink/public/mojom/badging/badging.mojom.h" #include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h" +#include "third_party/blink/public/mojom/conversions/attribution_reporting_automation.mojom-forward.h" #include "third_party/blink/public/mojom/cookie_manager/cookie_manager_automation.mojom-forward.h" #include "third_party/blink/public/mojom/permissions/permission_automation.mojom-forward.h" #include "third_party/blink/public/mojom/storage_access/storage_access_automation.mojom-forward.h" @@ -143,6 +144,11 @@ mojo::PendingReceiver<blink::test::mojom::CookieManagerAutomation> receiver); + void BindAttributionReportingAutomation( + RenderFrameHost* render_frame_host, + mojo::PendingReceiver<blink::test::mojom::AttributionReportingAutomation> + receiver); + void BindWebTestControlHost( int render_process_id, mojo::PendingAssociatedReceiver<mojom::WebTestControlHost> receiver); @@ -157,6 +163,8 @@ std::unique_ptr<MockBadgeService> mock_badge_service_; mojo::UniqueReceiverSet<blink::test::mojom::CookieManagerAutomation> cookie_managers_; + mojo::UniqueReceiverSet<blink::test::mojom::AttributionReportingAutomation> + attribution_reporting_receivers_; }; } // namespace content
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc index df72dad..7420e65 100644 --- a/device/bluetooth/bluetooth_adapter_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -708,8 +708,7 @@ } // TODO(scheib): Enable BluetoothTest fixture tests on all platforms. -// Flaky on Mac. See crbug.com/1334462 -#if BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) #define MAYBE_ConstructDefaultAdapter ConstructDefaultAdapter #else #define MAYBE_ConstructDefaultAdapter DISABLED_ConstructDefaultAdapter @@ -721,24 +720,14 @@ TEST_F(BluetoothTest, MAYBE_ConstructDefaultAdapter) { #endif InitWithDefaultAdapter(); - if (!adapter_->IsPresent()) { - LOG(WARNING) << "Bluetooth adapter not present; skipping unit test."; + if (!adapter_->IsPresent() || !adapter_->IsPowered()) { + LOG(WARNING) + << "Bluetooth adapter not present or not powered; skipping unit test."; return; } - bool expected = false; -// MacOS returns empty for name and address if the adapter is off. -#if BUILDFLAG(IS_MAC) - expected = !adapter_->IsPowered(); -#endif // BUILDFLAG(IS_MAC) - - EXPECT_EQ(expected, adapter_->GetAddress().empty()); - EXPECT_EQ(expected, adapter_->GetName().empty()); - - EXPECT_TRUE(adapter_->IsPresent()); - // Don't know on test machines if adapter will be powered or not, but - // the call should be safe to make and consistent. - EXPECT_EQ(adapter_->IsPowered(), adapter_->IsPowered()); + EXPECT_FALSE(adapter_->GetAddress().empty()); + EXPECT_FALSE(adapter_->GetName().empty()); EXPECT_FALSE(adapter_->IsDiscoverable()); EXPECT_FALSE(adapter_->IsDiscovering()); } // namespace device
diff --git a/extensions/common/constants.cc b/extensions/common/constants.cc index 6141448..6b5ad91 100644 --- a/extensions/common/constants.cc +++ b/extensions/common/constants.cc
@@ -174,6 +174,13 @@ const char kSigninProfileTestExtensionId[] = "mecfefiddjlmabpeilblgegnbioikfmp"; const char kGuestModeTestExtensionId[] = "behllobkkfkfnphdnhnkndlbkcpglgmj"; +const char kStagingAttractLoopAppId[] = "aefaeciooibphdopnjjmgjdlckdcfbae"; +const char kStagingHighlightsAppId[] = "glochkamldfopmdlegmcnjmgkopfiplb"; +// 2022 Attract Loop App ID +const char kNewAttractLoopAppId[] = "igilkdghcdehjdcpndaodgnjgdggiemm"; +// 2022 Highlights App ID +const char kNewHighlightsAppId[] = "enchmnkoajljphdmahljlebfmpkkbnkj"; + bool IsSystemUIApp(base::StringPiece extension_id) { static const char* const kApps[] = { // clang-format off @@ -191,6 +198,18 @@ } return false; } + +bool IsDemoModeChromeApp(base::StringPiece extension_id) { + static const char* const kDemoModeApps[] = { + kHighlightsAppId, kScreensaverAppId, kStagingAttractLoopAppId, + kStagingHighlightsAppId, kNewAttractLoopAppId, kNewHighlightsAppId, + }; + for (const char* id : kDemoModeApps) { + if (extension_id == id) + return true; + } + return false; +} #endif // BUILDFLAG(IS_CHROMEOS_ASH) bool IsQuickOfficeExtension(const std::string& id) {
diff --git a/extensions/common/constants.h b/extensions/common/constants.h index 78e2d70..947997d6 100644 --- a/extensions/common/constants.h +++ b/extensions/common/constants.h
@@ -353,6 +353,10 @@ // that that on other operating systems would be considered part of the OS, // for example the file manager. EXTENSIONS_EXPORT bool IsSystemUIApp(base::StringPiece extension_id); + +// Returns true if this app is one of Demo Mode Chrome Apps, including +// attract loop and highlights apps. +EXTENSIONS_EXPORT bool IsDemoModeChromeApp(base::StringPiece extension_id); #endif // True if the id matches any of the QuickOffice extension ids.
diff --git a/fuchsia_web/webengine/browser/frame_impl.cc b/fuchsia_web/webengine/browser/frame_impl.cc index 5b804b3ad..6aeae53 100644 --- a/fuchsia_web/webengine/browser/frame_impl.cc +++ b/fuchsia_web/webengine/browser/frame_impl.cc
@@ -607,16 +607,17 @@ void FrameImpl::MaybeStartCastStreaming( content::NavigationHandle* navigation_handle) { - if (!context_->has_cast_streaming_enabled() || !receiver_session_client_) + if (!context_->has_cast_streaming_enabled() || !receiver_session_client_ || + receiver_session_client_->HasReceiverSession()) { return; + } mojo::AssociatedRemote<cast_streaming::mojom::DemuxerConnector> demuxer_connector; navigation_handle->GetRenderFrameHost() ->GetRemoteAssociatedInterfaces() ->GetInterface(&demuxer_connector); - receiver_session_client_->SetCastStreamingReceiver( - std::move(demuxer_connector)); + receiver_session_client_->SetDemuxerConnector(std::move(demuxer_connector)); } void FrameImpl::UpdateRenderViewZoomLevel(
diff --git a/fuchsia_web/webengine/browser/receiver_session_client.cc b/fuchsia_web/webengine/browser/receiver_session_client.cc index 31317059..8b04089 100644 --- a/fuchsia_web/webengine/browser/receiver_session_client.cc +++ b/fuchsia_web/webengine/browser/receiver_session_client.cc
@@ -20,7 +20,7 @@ ReceiverSessionClient::~ReceiverSessionClient() = default; -void ReceiverSessionClient::SetCastStreamingReceiver( +void ReceiverSessionClient::SetDemuxerConnector( mojo::AssociatedRemote<cast_streaming::mojom::DemuxerConnector> demuxer_connector) { DCHECK(message_port_request_); @@ -49,3 +49,7 @@ std::move(message_port_request_))); receiver_session_->StartStreamingAsync(std::move(demuxer_connector)); } + +bool ReceiverSessionClient::HasReceiverSession() { + return !!receiver_session_; +}
diff --git a/fuchsia_web/webengine/browser/receiver_session_client.h b/fuchsia_web/webengine/browser/receiver_session_client.h index 831e4a19..4b5dd54 100644 --- a/fuchsia_web/webengine/browser/receiver_session_client.h +++ b/fuchsia_web/webengine/browser/receiver_session_client.h
@@ -24,16 +24,18 @@ ReceiverSessionClient& operator=(const ReceiverSessionClient&) = delete; - void SetCastStreamingReceiver( + void SetDemuxerConnector( mojo::AssociatedRemote<cast_streaming::mojom::DemuxerConnector> demuxer_connector); + bool HasReceiverSession(); + private: // Populated in the ctor, and removed when |receiver_session_| is created in - // SetCastStreamingReceiver(). + // SetDemuxerConnector(). fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request_; - // Created in SetCastStreamingReceiver(), and empty prior to that call. + // Created in SetDemuxerConnector(), and empty prior to that call. std::unique_ptr<cast_streaming::ReceiverSession> receiver_session_; const bool video_only_receiver_;
diff --git a/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc b/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc index 247ea3b..2c9bb37 100644 --- a/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc +++ b/fuchsia_web/webengine/browser/web_engine_permission_delegate.cc
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/check_op.h" #include "base/notreached.h" +#include "components/permissions/permission_util.h" #include "content/public/browser/permission_controller.h" #include "fuchsia_web/webengine/browser/frame_impl.h" #include "third_party/blink/public/common/permissions/permission_utils.h" @@ -64,6 +65,21 @@ bool user_gesture, base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback) { + std::vector<std::string> permission_strings; + permission_strings.reserve(permissions.size()); + for (const auto& permission : permissions) { + permission_strings.push_back( + permissions::PermissionUtil::GetPermissionString( + permissions::PermissionUtil::PermissionTypeToContentSetting( + permission))); + } + + // TODO(crbug.com/1063094): Clean up this warning once the permission + // API is implemented. + LOG(WARNING) << "Denied permissions that were not previously granted by " + << "SetPermissionState: " + << base::JoinString(permission_strings, ", "); + FrameImpl* frame = FrameImpl::FromRenderFrameHost(render_frame_host); DCHECK(frame); frame->permission_controller()->RequestPermissions(
diff --git a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc index fc1e946..633b4caa 100644 --- a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc +++ b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
@@ -52,7 +52,7 @@ // out by the OS scheduler. The task on windows is simiulated by reading // TimeTicks instead of Sleep(). void SimpleTask(base::TimeDelta duration, base::TimeDelta extra_time) { -#if BUILDFLAG(IS_WIN) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) auto start_timetick = base::TimeTicks::Now(); do { } while ((base::TimeTicks::Now() - start_timetick) < duration); @@ -146,7 +146,7 @@ // model_ver_str = "MacBookProXX,X", model_ver_str = "XX,X" std::string model_ver_str = model_str.substr(model_version_pos); int major_model_ver = std::atoi(model_ver_str.c_str()); - // For version < 14,1 + // For model version < 14,1 if (major_model_ver < 14) { timeout_type = kSlow; }
diff --git a/infra/config/generated/builders/try/linux-rel/properties.json b/infra/config/generated/builders/try/linux-rel/properties.json index ed2efae5..534966c 100644 --- a/infra/config/generated/builders/try/linux-rel/properties.json +++ b/infra/config/generated/builders/try/linux-rel/properties.json
@@ -161,9 +161,6 @@ ], "use_clang_coverage": true }, - "$build/flakiness": { - "check_for_flakiness": true - }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 008fb99f..247eeec 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -68984,7 +68984,7 @@ dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" dimensions: "pool:luci.chromium.try" - dimensions: "ssd:0" + dimensions: "ssd:1" exe { cipd_package: "infra/chromium/bootstrapper/${platform}" cipd_version: "latest"
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star index 0a03cc99..36d492e 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -225,7 +225,7 @@ name = "linux-rel", compilator = "linux-rel-compilator", branch_selector = branches.STANDARD_MILESTONE, - check_for_flakiness = True, + check_for_flakiness = False, mirrors = [ "ci/Linux Builder", "ci/Linux Tests", @@ -378,6 +378,7 @@ # TODO(crbug/1144484): Remove this timeout once we figure out the # regression in compiler or toolchain. execution_timeout = 7 * time.hour, + ssd = True, ) try_.builder(
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 0b615ae..40bb1ca6 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -3678,9 +3678,8 @@ _keyCommandsProvider.canDismissModals = NO; [_sideSwipeController setEnabled:YES]; - if (self.isNTPActiveForCurrentWebState) { - [_ntpCoordinator locationBarDidResignFirstResponder]; - } + [_ntpCoordinator locationBarDidResignFirstResponder]; + [UIView animateWithDuration:0.3 animations:^{ [self.typingShield setAlpha:0.0];
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc index bb551528..dc1b731 100644 --- a/media/gpu/vaapi/vaapi_wrapper.cc +++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -2325,9 +2325,12 @@ // when AMD supports it. // TODO(b/233924862): use the DRM_PRIME_2 API with protected content. // TODO(b/233929647): use the DRM_PRIME_2 API with the i965 driver. + // TODO(b/236746283): remove the kNoModifier check once the modifier is + // plumbed for JPEG decoding and encoding. const bool use_drm_prime_2 = GetImplementationType() == VAImplementation::kIntelIHD && - !protected_content; + !protected_content && + pixmap->GetBufferFormatModifier() != gfx::NativePixmapHandle::kNoModifier; union { VADRMPRIMESurfaceDescriptor descriptor;
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index 713f7e6c..3a48729 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -2494,10 +2494,10 @@ base::Value::Dict dict; source.AddToEventParameters(dict); dict.Set("host", ToLogStringValue(key_.host)); - std::vector<base::Value> query_types_list; + base::Value::List query_types_list; for (DnsQueryType query_type : key_.query_types) - query_types_list.emplace_back(kDnsQueryTypes.at(query_type)); - dict.Set("dns_query_types", base::Value(std::move(query_types_list))); + query_types_list.Append(kDnsQueryTypes.at(query_type)); + dict.Set("dns_query_types", std::move(query_types_list)); dict.Set("secure_dns_mode", base::strict_cast<int>(key_.secure_dns_mode)); dict.Set("network_isolation_key", key_.network_isolation_key.ToDebugString());
diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc index 576cfb1..01809ad 100644 --- a/net/http/http_auth_controller.cc +++ b/net/http/http_auth_controller.cc
@@ -32,10 +32,10 @@ namespace { base::Value ControllerParamsToValue(HttpAuth::Target target, const GURL& url) { - base::Value params(base::Value::Type::DICTIONARY); - params.SetStringPath("target", HttpAuth::GetAuthTargetString(target)); - params.SetStringPath("url", url.spec()); - return params; + base::Value::Dict params; + params.Set("target", HttpAuth::GetAuthTargetString(target)); + params.Set("url", url.spec()); + return base::Value(std::move(params)); } } // namespace
diff --git a/net/http/http_auth_gssapi_posix.cc b/net/http/http_auth_gssapi_posix.cc index 59f738f9..e3ab2d7 100644 --- a/net/http/http_auth_gssapi_posix.cc +++ b/net/http/http_auth_gssapi_posix.cc
@@ -119,12 +119,12 @@ return 0 == memcmp(left->elements, right->elements, right->length); } -base::Value GetGssStatusCodeValue(GSSAPILibrary* gssapi_lib, - OM_uint32 status, - OM_uint32 status_code_type) { - base::Value rv{base::Value::Type::DICTIONARY}; +base::Value::Dict GetGssStatusCodeValue(GSSAPILibrary* gssapi_lib, + OM_uint32 status, + OM_uint32 status_code_type) { + base::Value::Dict rv; - rv.SetIntKey("status", status); + rv.Set("status", static_cast<int>(status)); // Message lookups aren't performed if there's no library or if the status // indicates success. @@ -149,7 +149,7 @@ // |kMaxMsgLength|. There's no real documented limit to work with here. constexpr size_t kMaxMsgLength = 4096; - base::Value messages{base::Value::Type::LIST}; + base::Value::List messages; do { gss_buffer_desc_struct message_buffer = GSS_C_EMPTY_BUFFER; ScopedBuffer message_buffer_releaser(&message_buffer, gssapi_lib); @@ -175,41 +175,40 @@ messages.Append(message_string); } while (message_context != 0 && ++iterations < kMaxDisplayIterations); - if (messages.GetListDeprecated().size() > 0) - rv.SetKey("message", std::move(messages)); + if (!messages.empty()) + rv.Set("message", std::move(messages)); return rv; } -base::Value GetGssStatusValue(GSSAPILibrary* gssapi_lib, - base::StringPiece method, - OM_uint32 major_status, - OM_uint32 minor_status) { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetStringKey("function", method); - params.SetKey("major_status", GetGssStatusCodeValue(gssapi_lib, major_status, - GSS_C_GSS_CODE)); - params.SetKey("minor_status", GetGssStatusCodeValue(gssapi_lib, minor_status, - GSS_C_MECH_CODE)); +base::Value::Dict GetGssStatusValue(GSSAPILibrary* gssapi_lib, + base::StringPiece method, + OM_uint32 major_status, + OM_uint32 minor_status) { + base::Value::Dict params; + params.Set("function", method); + params.Set("major_status", + GetGssStatusCodeValue(gssapi_lib, major_status, GSS_C_GSS_CODE)); + params.Set("minor_status", + GetGssStatusCodeValue(gssapi_lib, minor_status, GSS_C_MECH_CODE)); return params; } -base::Value OidToValue(gss_OID oid) { - base::Value params(base::Value::Type::DICTIONARY); +base::Value::Dict OidToValue(gss_OID oid) { + base::Value::Dict params; if (!oid || oid->length == 0) { - params.SetStringKey("oid", "<Empty OID>"); + params.Set("oid", "<Empty OID>"); return params; } - params.SetIntKey("length", oid->length); + params.Set("length", static_cast<int>(oid->length)); if (!oid->elements) return params; // Cap OID content at arbitrary limit 1k. constexpr OM_uint32 kMaxOidDataSize = 1024; - params.SetKey( - "bytes", - NetLogBinaryValue(oid->elements, std::min(kMaxOidDataSize, oid->length))); + params.Set("bytes", NetLogBinaryValue(oid->elements, std::min(kMaxOidDataSize, + oid->length))); // Based on RFC 2744 Appendix A. Hardcoding the OIDs in the list below to // avoid having a static dependency on the library. @@ -233,52 +232,51 @@ for (auto& well_known_oid : kWellKnownOIDs) { if (OidEquals(oid, const_cast<const gss_OID>(&well_known_oid.oid_desc))) - params.SetStringKey("oid", well_known_oid.symbolic_name); + params.Set("oid", well_known_oid.symbolic_name); } return params; } -base::Value GetDisplayNameValue(GSSAPILibrary* gssapi_lib, - const gss_name_t gss_name) { +base::Value::Dict GetDisplayNameValue(GSSAPILibrary* gssapi_lib, + const gss_name_t gss_name) { OM_uint32 major_status = 0; OM_uint32 minor_status = 0; gss_buffer_desc_struct name = GSS_C_EMPTY_BUFFER; gss_OID name_type = GSS_C_NO_OID; - base::Value rv{base::Value::Type::DICTIONARY}; + base::Value::Dict rv; major_status = gssapi_lib->display_name(&minor_status, gss_name, &name, &name_type); ScopedBuffer scoped_output_name(&name, gssapi_lib); if (major_status != GSS_S_COMPLETE) { - rv.SetKey("error", GetGssStatusValue(gssapi_lib, "gss_display_name", - major_status, minor_status)); + rv.Set("error", GetGssStatusValue(gssapi_lib, "gss_display_name", + major_status, minor_status)); return rv; } auto name_string = base::StringPiece(reinterpret_cast<const char*>(name.value), name.length); - rv.SetKey("name", base::IsStringUTF8(name_string) - ? NetLogStringValue(name_string) - : NetLogBinaryValue(name.value, name.length)); - rv.SetKey("type", OidToValue(name_type)); + rv.Set("name", base::IsStringUTF8(name_string) + ? NetLogStringValue(name_string) + : NetLogBinaryValue(name.value, name.length)); + rv.Set("type", OidToValue(name_type)); return rv; } -base::Value ContextFlagsToValue(OM_uint32 flags) { - base::Value rv{base::Value::Type::DICTIONARY}; - rv.SetStringKey("value", base::StringPrintf("0x%08x", flags)); - rv.SetBoolKey("delegated", (flags & GSS_C_DELEG_FLAG) == GSS_C_DELEG_FLAG); - rv.SetBoolKey("mutual", (flags & GSS_C_MUTUAL_FLAG) == GSS_C_MUTUAL_FLAG); +base::Value::Dict ContextFlagsToValue(OM_uint32 flags) { + base::Value::Dict rv; + rv.Set("value", base::StringPrintf("0x%08x", flags)); + rv.Set("delegated", (flags & GSS_C_DELEG_FLAG) == GSS_C_DELEG_FLAG); + rv.Set("mutual", (flags & GSS_C_MUTUAL_FLAG) == GSS_C_MUTUAL_FLAG); return rv; } base::Value GetContextStateAsValue(GSSAPILibrary* gssapi_lib, const gss_ctx_id_t context_handle) { - base::Value rv{base::Value::Type::DICTIONARY}; + base::Value::Dict rv; if (context_handle == GSS_C_NO_CONTEXT) { - rv.SetKey("error", - GetGssStatusValue(nullptr, "<none>", GSS_S_NO_CONTEXT, 0)); - return rv; + rv.Set("error", GetGssStatusValue(nullptr, "<none>", GSS_S_NO_CONTEXT, 0)); + return base::Value(std::move(rv)); } OM_uint32 major_status = 0; @@ -300,22 +298,22 @@ &locally_initiated, &open); if (major_status != GSS_S_COMPLETE) { - rv.SetKey("error", GetGssStatusValue(gssapi_lib, "gss_inquire_context", - major_status, minor_status)); - return rv; + rv.Set("error", GetGssStatusValue(gssapi_lib, "gss_inquire_context", + major_status, minor_status)); + return base::Value(std::move(rv)); } ScopedName scoped_src_name(src_name, gssapi_lib); ScopedName scoped_targ_name(targ_name, gssapi_lib); - rv.SetKey("source", GetDisplayNameValue(gssapi_lib, src_name)); - rv.SetKey("target", GetDisplayNameValue(gssapi_lib, targ_name)); + rv.Set("source", GetDisplayNameValue(gssapi_lib, src_name)); + rv.Set("target", GetDisplayNameValue(gssapi_lib, targ_name)); // lifetime_rec is a uint32, while base::Value only takes ints. On 32 bit // platforms uint32 doesn't fit on an int. - rv.SetStringKey("lifetime", base::NumberToString(lifetime_rec)); - rv.SetKey("mechanism", OidToValue(mech_type)); - rv.SetKey("flags", ContextFlagsToValue(ctx_flags)); - rv.SetBoolKey("open", !!open); - return rv; + rv.Set("lifetime", base::NumberToString(lifetime_rec)); + rv.Set("mechanism", OidToValue(mech_type)); + rv.Set("flags", ContextFlagsToValue(ctx_flags)); + rv.Set("open", !!open); + return base::Value(std::move(rv)); } namespace { @@ -323,11 +321,11 @@ // Return a NetLog value for the result of loading a library. base::Value LibraryLoadResultParams(base::StringPiece library_name, base::StringPiece load_result) { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetStringKey("library_name", library_name); + base::Value::Dict params; + params.Set("library_name", library_name); if (!load_result.empty()) - params.SetStringKey("load_result", load_result); - return params; + params.Set("load_result", load_result); + return base::Value(std::move(params)); } } // namespace @@ -425,10 +423,10 @@ base::Value BindFailureParams(base::StringPiece library_name, base::StringPiece method) { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetStringKey("library_name", library_name); - params.SetStringKey("method", method); - return params; + base::Value::Dict params; + params.Set("library_name", library_name); + params.Set("method", method); + return base::Value(std::move(params)); } void* BindUntypedMethod(base::NativeLibrary lib, @@ -806,25 +804,25 @@ base::StringPiece spn, OM_uint32 major_status, OM_uint32 minor_status) { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetStringKey("spn", spn); + base::Value::Dict params; + params.Set("spn", spn); if (major_status != GSS_S_COMPLETE) - params.SetKey("status", GetGssStatusValue(library, "import_name", - major_status, minor_status)); - return params; + params.Set("status", GetGssStatusValue(library, "import_name", major_status, + minor_status)); + return base::Value(std::move(params)); } base::Value InitSecContextErrorParams(GSSAPILibrary* library, gss_ctx_id_t context, OM_uint32 major_status, OM_uint32 minor_status) { - base::Value params{base::Value::Type::DICTIONARY}; + base::Value::Dict params; if (major_status != GSS_S_COMPLETE) - params.SetKey("status", GetGssStatusValue(library, "gss_init_sec_context", - major_status, minor_status)); + params.Set("status", GetGssStatusValue(library, "gss_init_sec_context", + major_status, minor_status)); if (context != GSS_C_NO_CONTEXT) - params.SetKey("context", GetContextStateAsValue(library, context)); - return params; + params.Set("context", GetContextStateAsValue(library, context)); + return base::Value(std::move(params)); } } // anonymous namespace
diff --git a/net/http/http_auth_gssapi_posix.h b/net/http/http_auth_gssapi_posix.h index 33a3b4a..3acd8bc 100644 --- a/net/http/http_auth_gssapi_posix.h +++ b/net/http/http_auth_gssapi_posix.h
@@ -256,8 +256,8 @@ // Diagnostics -// GetGssStatusCodeValue constructs a base::Value containing a status code and a -// message. +// GetGssStatusCodeValue constructs a base::Value::Dict containing a status code +// and a message. // // { // "status" : <status value as a number>, @@ -274,12 +274,12 @@ // identified to look up messages if |status_code_type| is |GSS_C_MECH_CODE|. // Since no mechanism OIDs are passed in, mechanism specific status codes will // likely not have messages. -NET_EXPORT_PRIVATE base::Value GetGssStatusCodeValue( +NET_EXPORT_PRIVATE base::Value::Dict GetGssStatusCodeValue( GSSAPILibrary* gssapi_lib, OM_uint32 status, OM_uint32 status_code_type); -// Given major and minor GSSAPI status codes, returns a base::Value +// Given major and minor GSSAPI status codes, returns a base::Value::Dict // encapsulating the codes as well as their meanings as expanded via // gss_display_status(). // @@ -304,21 +304,22 @@ // returned value will be missing the "message" fields. The same is true if the // message lookup failed for some reason, or if the lookups succeeded but // yielded an empty message. -NET_EXPORT_PRIVATE base::Value GetGssStatusValue(GSSAPILibrary* gssapi_lib, - base::StringPiece method, - OM_uint32 major_status, - OM_uint32 minor_status); +NET_EXPORT_PRIVATE base::Value::Dict GetGssStatusValue( + GSSAPILibrary* gssapi_lib, + base::StringPiece method, + OM_uint32 major_status, + OM_uint32 minor_status); -// OidToValue returns a base::Value representing an OID. The structure of the -// value is: +// OidToValue returns a base::Value::Dict representing an OID. The structure of +// the value is: // { // "oid": <symbolic name of OID if it is known> // "length": <length in bytes of serialized OID>, // "bytes": <hexdump of up to 1024 bytes of serialized OID> // } -NET_EXPORT_PRIVATE base::Value OidToValue(const gss_OID oid); +NET_EXPORT_PRIVATE base::Value::Dict OidToValue(const gss_OID oid); -// GetDisplayNameValue returns a base::Value representing a gss_name_t. It +// GetDisplayNameValue returns a base::Value::Dict representing a gss_name_t. It // invokes |gss_display_name()| via |gssapi_lib| to determine the display name // associated with |gss_name|. // @@ -336,8 +337,9 @@ // // Note that |gss_name_t| is platform dependent. If |gss_display_name| fails, // there's no good value to display in its stead. -NET_EXPORT_PRIVATE base::Value GetDisplayNameValue(GSSAPILibrary* gssapi_lib, - const gss_name_t gss_name); +NET_EXPORT_PRIVATE base::Value::Dict GetDisplayNameValue( + GSSAPILibrary* gssapi_lib, + const gss_name_t gss_name); // GetContextStateAsValue returns a base::Value that describes the state of a // GSSAPI context. The structure of the value is:
diff --git a/net/http/http_auth_handler_factory.cc b/net/http/http_auth_handler_factory.cc index 05e0a44..7583a2a 100644 --- a/net/http/http_auth_handler_factory.cc +++ b/net/http/http_auth_handler_factory.cc
@@ -38,16 +38,16 @@ const url::SchemeHostPort& scheme_host_port, const absl::optional<bool>& allows_default_credentials, net::NetLogCaptureMode capture_mode) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("scheme", net::NetLogStringValue(scheme)); + base::Value::Dict dict; + dict.Set("scheme", net::NetLogStringValue(scheme)); if (net::NetLogCaptureIncludesSensitive(capture_mode)) - dict.SetKey("challenge", net::NetLogStringValue(challenge)); - dict.SetStringKey("origin", scheme_host_port.Serialize()); + dict.Set("challenge", net::NetLogStringValue(challenge)); + dict.Set("origin", scheme_host_port.Serialize()); if (allows_default_credentials) - dict.SetBoolKey("allows_default_credentials", *allows_default_credentials); + dict.Set("allows_default_credentials", *allows_default_credentials); if (net_error < 0) - dict.SetIntKey("net_error", net_error); - return dict; + dict.Set("net_error", net_error); + return base::Value(std::move(dict)); } } // namespace
diff --git a/net/http/http_auth_handler_factory_unittest.cc b/net/http/http_auth_handler_factory_unittest.cc index ac993f0fe..71551c8 100644 --- a/net/http/http_auth_handler_factory_unittest.cc +++ b/net/http/http_auth_handler_factory_unittest.cc
@@ -378,10 +378,12 @@ auto entries = net_log_observer.GetEntriesWithType( NetLogEventType::AUTH_HANDLER_CREATE_RESULT); ASSERT_EQ(1u, entries.size()); - const std::string* scheme = entries[0].params.FindStringKey("scheme"); + const std::string* scheme = + entries[0].params.GetDict().FindString("scheme"); ASSERT_NE(nullptr, scheme); EXPECT_STRCASEEQ(test_case.expected_scheme, scheme->data()); - absl::optional<int> net_error = entries[0].params.FindIntKey("net_error"); + absl::optional<int> net_error = + entries[0].params.GetDict().FindInt("net_error"); if (test_case.expected_net_error) { ASSERT_TRUE(net_error.has_value()); EXPECT_EQ(test_case.expected_net_error, net_error.value()); @@ -391,7 +393,7 @@ // The challenge should be logged only when sensitive logging is enabled. const std::string* challenge = - entries[0].params.FindStringKey("challenge"); + entries[0].params.GetDict().FindString("challenge"); if (capture_mode == NetLogCaptureMode::kDefault) { ASSERT_EQ(nullptr, challenge); } else {
diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc index bab8b1b..e4b83d5 100644 --- a/net/http/http_auth_handler_negotiate.cc +++ b/net/http/http_auth_handler_negotiate.cc
@@ -40,13 +40,13 @@ base::Value NetLogParameterChannelBindings( const std::string& channel_binding_token, NetLogCaptureMode capture_mode) { - base::Value dict(base::Value::Type::DICTIONARY); + base::Value::Dict dict; if (!NetLogCaptureIncludesSocketBytes(capture_mode)) - return dict; + return base::Value(std::move(dict)); - dict.SetStringKey("token", base::HexEncode(channel_binding_token.data(), - channel_binding_token.size())); - return dict; + dict.Set("token", base::HexEncode(channel_binding_token.data(), + channel_binding_token.size())); + return base::Value(std::move(dict)); } // Uses |negotiate_auth_system_factory| to create the auth system, otherwise
diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc index e55a34e..02ce74d 100644 --- a/net/http/http_auth_sspi_win.cc +++ b/net/http/http_auth_sspi_win.cc
@@ -28,47 +28,45 @@ namespace { base::Value SecurityStatusToValue(Error mapped_error, SECURITY_STATUS status) { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetIntKey("net_error", mapped_error); - params.SetIntKey("security_status", status); - return params; + base::Value::Dict params; + params.Set("net_error", mapped_error); + params.Set("security_status", static_cast<int>(status)); + return base::Value(std::move(params)); } base::Value AcquireCredentialsHandleParams(const std::u16string* domain, const std::u16string* user, Error result, SECURITY_STATUS status) { - base::Value params{base::Value::Type::DICTIONARY}; + base::Value::Dict params; if (domain && user) { - params.SetStringKey("domain", base::UTF16ToUTF8(*domain)); - params.SetStringKey("user", base::UTF16ToUTF8(*user)); + params.Set("domain", base::UTF16ToUTF8(*domain)); + params.Set("user", base::UTF16ToUTF8(*user)); } - params.SetKey("status", SecurityStatusToValue(result, status)); - return params; + params.Set("status", SecurityStatusToValue(result, status)); + return base::Value(std::move(params)); } base::Value ContextFlagsToValue(DWORD flags) { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetStringKey("value", base::StringPrintf("0x%08lx", flags)); - params.SetBoolKey("delegated", - (flags & ISC_RET_DELEGATE) == ISC_RET_DELEGATE); - params.SetBoolKey("mutual", - (flags & ISC_RET_MUTUAL_AUTH) == ISC_RET_MUTUAL_AUTH); - return params; + base::Value::Dict params; + params.Set("value", base::StringPrintf("0x%08lx", flags)); + params.Set("delegated", (flags & ISC_RET_DELEGATE) == ISC_RET_DELEGATE); + params.Set("mutual", (flags & ISC_RET_MUTUAL_AUTH) == ISC_RET_MUTUAL_AUTH); + return base::Value(std::move(params)); } base::Value ContextAttributesToValue(SSPILibrary* library, PCtxtHandle handle, DWORD attributes) { - base::Value params{base::Value::Type::DICTIONARY}; + base::Value::Dict params; SecPkgContext_NativeNames native_names = {0}; auto qc_result = library->QueryContextAttributesEx( handle, SECPKG_ATTR_NATIVE_NAMES, &native_names, sizeof(native_names)); if (qc_result == SEC_E_OK && native_names.sClientName && native_names.sServerName) { - params.SetStringKey("source", base::as_u16cstr(native_names.sClientName)); - params.SetStringKey("target", base::as_u16cstr(native_names.sServerName)); + params.Set("source", base::as_u16cstr(native_names.sClientName)); + params.Set("target", base::as_u16cstr(native_names.sServerName)); } SecPkgContext_NegotiationInfo negotiation_info = {0}; @@ -77,22 +75,21 @@ sizeof(negotiation_info)); if (qc_result == SEC_E_OK && negotiation_info.PackageInfo && negotiation_info.PackageInfo->Name) { - params.SetStringKey("mechanism", - base::as_u16cstr(negotiation_info.PackageInfo->Name)); - params.SetBoolKey("open", negotiation_info.NegotiationState != - SECPKG_NEGOTIATION_COMPLETE); + params.Set("mechanism", + base::as_u16cstr(negotiation_info.PackageInfo->Name)); + params.Set("open", negotiation_info.NegotiationState != + SECPKG_NEGOTIATION_COMPLETE); } SecPkgContext_Authority authority = {0}; qc_result = library->QueryContextAttributesEx(handle, SECPKG_ATTR_AUTHORITY, &authority, sizeof(authority)); if (qc_result == SEC_E_OK && authority.sAuthorityName) { - params.SetStringKey("authority", - base::as_u16cstr(authority.sAuthorityName)); + params.Set("authority", base::as_u16cstr(authority.sAuthorityName)); } - params.SetKey("flags", ContextFlagsToValue(attributes)); - return params; + params.Set("flags", ContextFlagsToValue(attributes)); + return base::Value(std::move(params)); } base::Value InitializeSecurityContextParams(SSPILibrary* library, @@ -100,12 +97,13 @@ Error result, SECURITY_STATUS status, DWORD attributes) { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetKey("status", SecurityStatusToValue(result, status)); - if (result == OK) - params.SetKey("context", - ContextAttributesToValue(library, handle, attributes)); - return params; + base::Value::Dict params; + params.Set("status", SecurityStatusToValue(result, status)); + if (result == OK) { + params.Set("context", + ContextAttributesToValue(library, handle, attributes)); + } + return base::Value(std::move(params)); } Error MapAcquireCredentialsStatusToError(SECURITY_STATUS status) { @@ -548,10 +546,10 @@ context_flags |= (ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH); net_log.BeginEvent(NetLogEventType::AUTH_LIBRARY_INIT_SEC_CTX, [&] { - base::Value params{base::Value::Type::DICTIONARY}; - params.SetStringKey("spn", spn); - params.SetKey("flags", ContextFlagsToValue(context_flags)); - return params; + base::Value::Dict params; + params.Set("spn", spn); + params.Set("flags", ContextFlagsToValue(context_flags)); + return base::Value(std::move(params)); }); // This returns a token that is passed to the remote server.
diff --git a/net/http/http_cache_lookup_manager.cc b/net/http/http_cache_lookup_manager.cc index 6ed9cd0..cfcf6c84 100644 --- a/net/http/http_cache_lookup_manager.cc +++ b/net/http/http_cache_lookup_manager.cc
@@ -19,10 +19,10 @@ base::Value NetLogPushLookupTransactionParams( const NetLogSource& net_log, const ServerPushDelegate::ServerPushHelper* push_helper) { - base::Value dict(base::Value::Type::DICTIONARY); - net_log.AddToEventParameters(&dict); - dict.SetStringKey("push_url", push_helper->GetURL().possibly_invalid_spec()); - return dict; + base::Value::Dict dict; + net_log.AddToEventParameters(dict); + dict.Set("push_url", push_helper->GetURL().possibly_invalid_spec()); + return base::Value(std::move(dict)); } HttpCacheLookupManager::LookupTransaction::LookupTransaction(
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 6c81586..66ea212 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -193,7 +193,7 @@ std::string GetHeaders(const base::Value& params) { if (!params.is_dict()) return ""; - const base::Value* header_list = params.FindListKey("headers"); + const base::Value::List* header_list = params.GetDict().FindList("headers"); if (!header_list) return ""; std::string headers;
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc index ea36ce6..a19608b 100644 --- a/net/http/http_request_headers.cc +++ b/net/http/http_request_headers.cc
@@ -198,17 +198,17 @@ base::Value HttpRequestHeaders::NetLogParams( const std::string& request_line, NetLogCaptureMode capture_mode) const { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("line", NetLogStringValue(request_line)); - base::Value headers(base::Value::Type::LIST); + base::Value::Dict dict; + dict.Set("line", NetLogStringValue(request_line)); + base::Value::List headers; for (const auto& header : headers_) { std::string log_value = ElideHeaderValueForNetLog(capture_mode, header.key, header.value); headers.Append( NetLogStringValue(base::StrCat({header.key, ": ", log_value}))); } - dict.SetKey("headers", std::move(headers)); - return dict; + dict.Set("headers", std::move(headers)); + return base::Value(std::move(dict)); } HttpRequestHeaders::HeaderVector::iterator HttpRequestHeaders::FindHeader(
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index 727cebf..08597856 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc
@@ -1373,8 +1373,8 @@ base::Value HttpResponseHeaders::NetLogParams( NetLogCaptureMode capture_mode) const { - base::Value dict(base::Value::Type::DICTIONARY); - base::Value headers(base::Value::Type::LIST); + base::Value::Dict dict; + base::Value::List headers; headers.Append(NetLogStringValue(GetStatusLine())); size_t iterator = 0; std::string name; @@ -1384,8 +1384,8 @@ ElideHeaderValueForNetLog(capture_mode, name, value); headers.Append(NetLogStringValue(base::StrCat({name, ": ", log_value}))); } - dict.SetKey("headers", std::move(headers)); - return dict; + dict.Set("headers", std::move(headers)); + return base::Value(std::move(dict)); } bool HttpResponseHeaders::IsChunkEncoded() const {
diff --git a/net/http/http_server_properties.cc b/net/http/http_server_properties.cc index 3adcc93..c0cae1b 100644 --- a/net/http/http_server_properties.cc +++ b/net/http/http_server_properties.cc
@@ -378,11 +378,11 @@ base::Value HttpServerProperties::GetAlternativeServiceInfoAsValue() const { const base::Time now = clock_->Now(); const base::TimeTicks now_ticks = tick_clock_->NowTicks(); - base::Value dict_list(base::Value::Type::LIST); + base::Value::List dict_list; for (const auto& server_info : server_info_map_) { if (!server_info.second.alternative_services.has_value()) continue; - base::Value alternative_service_list(base::Value::Type::LIST); + base::Value::List alternative_service_list; const ServerInfoMapKey& key = server_info.first; for (const AlternativeServiceInfo& alternative_service_info : server_info.second.alternative_services.value()) { @@ -415,16 +415,16 @@ } alternative_service_list.Append(std::move(alternative_service_string)); } - if (alternative_service_list.GetListDeprecated().empty()) + if (alternative_service_list.empty()) continue; - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("server", key.server.Serialize()); - dict.SetStringKey("network_isolation_key", - key.network_isolation_key.ToDebugString()); - dict.SetKey("alternative_service", std::move(alternative_service_list)); + base::Value::Dict dict; + dict.Set("server", key.server.Serialize()); + dict.Set("network_isolation_key", + key.network_isolation_key.ToDebugString()); + dict.Set("alternative_service", std::move(alternative_service_list)); dict_list.Append(std::move(dict)); } - return dict_list; + return base::Value(std::move(dict_list)); } bool HttpServerProperties::WasLastLocalAddressWhenQuicWorked(
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index f0a2edc..93ff6b8 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -78,24 +78,23 @@ bool expect_spdy, bool using_quic, RequestPriority priority) { - base::Value dict(base::Value::Type::DICTIONARY); + base::Value::Dict dict; if (source.IsValid()) - source.AddToEventParameters(&dict); - dict.SetStringKey("original_url", - original_url.DeprecatedGetOriginAsURL().spec()); - dict.SetStringKey("url", url.DeprecatedGetOriginAsURL().spec()); - dict.SetBoolKey("expect_spdy", expect_spdy); - dict.SetBoolKey("using_quic", using_quic); - dict.SetStringKey("priority", RequestPriorityToString(priority)); - return dict; + source.AddToEventParameters(dict); + dict.Set("original_url", original_url.DeprecatedGetOriginAsURL().spec()); + dict.Set("url", url.DeprecatedGetOriginAsURL().spec()); + dict.Set("expect_spdy", expect_spdy); + dict.Set("using_quic", using_quic); + dict.Set("priority", RequestPriorityToString(priority)); + return base::Value(std::move(dict)); } // Returns parameters associated with the ALPN protocol of a HTTP stream. base::Value NetLogHttpStreamProtoParams(NextProto negotiated_protocol) { - base::Value dict(base::Value::Type::DICTIONARY); + base::Value::Dict dict; - dict.SetStringKey("proto", NextProtoToString(negotiated_protocol)); - return dict; + dict.Set("proto", NextProtoToString(negotiated_protocol)); + return base::Value(std::move(dict)); } HttpStreamFactory::Job::Job(Delegate* delegate,
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc index 19dd80b..a1eddbb 100644 --- a/net/http/http_stream_factory_job_controller.cc +++ b/net/http/http_stream_factory_job_controller.cc
@@ -44,13 +44,12 @@ // Returns parameters associated with the proxy resolution. base::Value NetLogHttpStreamJobProxyServerResolved( const ProxyServer& proxy_server) { - base::Value dict(base::Value::Type::DICTIONARY); + base::Value::Dict dict; - dict.SetStringKey("proxy_server", - proxy_server.is_valid() - ? ProxyServerToPacResultElement(proxy_server) - : std::string()); - return dict; + dict.Set("proxy_server", proxy_server.is_valid() + ? ProxyServerToPacResultElement(proxy_server) + : std::string()); + return base::Value(std::move(dict)); } GURL CreateAltSvcUrl(const GURL& origin_url, @@ -103,21 +102,20 @@ base::Value NetLogJobControllerParams(const HttpRequestInfo& request_info, bool is_preconnect) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("url", request_info.url.possibly_invalid_spec()); - dict.SetBoolKey("is_preconnect", is_preconnect); - dict.SetStringKey("privacy_mode", - PrivacyModeToDebugString(request_info.privacy_mode)); + base::Value::Dict dict; + dict.Set("url", request_info.url.possibly_invalid_spec()); + dict.Set("is_preconnect", is_preconnect); + dict.Set("privacy_mode", PrivacyModeToDebugString(request_info.privacy_mode)); - return dict; + return base::Value(std::move(dict)); } base::Value NetLogAltSvcParams(const AlternativeServiceInfo* alt_svc_info, bool is_broken) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("alt_svc", alt_svc_info->ToString()); - dict.SetBoolKey("is_broken", is_broken); - return dict; + base::Value::Dict dict; + dict.Set("alt_svc", alt_svc_info->ToString()); + dict.Set("is_broken", is_broken); + return base::Value(std::move(dict)); } HttpStreamFactory::JobController::JobController(
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc index e11997a..95f3515c 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_unittest.cc
@@ -1039,9 +1039,9 @@ int count = 0; base::Value dict = pool->GetInfoAsValue("", ""); EXPECT_TRUE(dict.is_dict()); - const base::Value* groups = dict.FindDictKey("groups"); + const base::Value::Dict* groups = dict.GetDict().FindDict("groups"); if (groups) { - count = groups->DictSize(); + count = groups->size(); } return count; } @@ -1052,14 +1052,14 @@ session->spdy_session_pool()->SpdySessionPoolInfoToValue()); if (!value || !value->is_list()) return -1; - return value->GetListDeprecated().size(); + return value->GetList().size(); } // Return count of sockets handed out by a given socket pool. int GetHandedOutSocketCount(ClientSocketPool* pool) { base::Value dict = pool->GetInfoAsValue("", ""); EXPECT_TRUE(dict.is_dict()); - return dict.FindIntKey("handed_out_socket_count").value_or(-1); + return dict.GetDict().FindInt("handed_out_socket_count").value_or(-1); } // Return count of distinct QUIC sessions.
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index 7a0e8f0e4..3b7c4b3 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -57,11 +57,11 @@ base::Value NetLogSendRequestBodyParams(uint64_t length, bool is_chunked, bool did_merge) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetIntKey("length", static_cast<int>(length)); - dict.SetBoolKey("is_chunked", is_chunked); - dict.SetBoolKey("did_merge", did_merge); - return dict; + base::Value::Dict dict; + dict.Set("length", static_cast<int>(length)); + dict.Set("is_chunked", is_chunked); + dict.Set("did_merge", did_merge); + return base::Value(std::move(dict)); } void NetLogSendRequestBody(const NetLogWithSource& net_log,
diff --git a/net/http/transport_security_persister.cc b/net/http/transport_security_persister.cc index 2b3d0dc..9a33e56 100644 --- a/net/http/transport_security_persister.cc +++ b/net/http/transport_security_persister.cc
@@ -103,32 +103,32 @@ // Serializes STS data from |state| to a Value. base::Value SerializeSTSData(const TransportSecurityState* state) { - base::Value sts_list(base::Value::Type::LIST); + base::Value::List sts_list; TransportSecurityState::STSStateIterator sts_iterator(*state); for (; sts_iterator.HasNext(); sts_iterator.Advance()) { const TransportSecurityState::STSState& sts_state = sts_iterator.domain_state(); - base::Value serialized(base::Value::Type::DICTIONARY); - serialized.SetStringKey( - kHostname, HashedDomainToExternalString(sts_iterator.hostname())); - serialized.SetBoolKey(kStsIncludeSubdomains, sts_state.include_subdomains); - serialized.SetDoubleKey(kStsObserved, sts_state.last_observed.ToDoubleT()); - serialized.SetDoubleKey(kExpiry, sts_state.expiry.ToDoubleT()); + base::Value::Dict serialized; + serialized.Set(kHostname, + HashedDomainToExternalString(sts_iterator.hostname())); + serialized.Set(kStsIncludeSubdomains, sts_state.include_subdomains); + serialized.Set(kStsObserved, sts_state.last_observed.ToDoubleT()); + serialized.Set(kExpiry, sts_state.expiry.ToDoubleT()); switch (sts_state.upgrade_mode) { case TransportSecurityState::STSState::MODE_FORCE_HTTPS: - serialized.SetStringKey(kMode, kForceHTTPS); + serialized.Set(kMode, kForceHTTPS); break; case TransportSecurityState::STSState::MODE_DEFAULT: - serialized.SetStringKey(kMode, kDefault); + serialized.Set(kMode, kDefault); break; } sts_list.Append(std::move(serialized)); } - return sts_list; + return base::Value(std::move(sts_list)); } // Deserializes STS data from a Value created by the above method. @@ -139,16 +139,17 @@ base::Time current_time(base::Time::Now()); - for (const base::Value& sts_entry : sts_list.GetListDeprecated()) { - if (!sts_entry.is_dict()) + for (const base::Value& sts_entry : sts_list.GetList()) { + const base::Value::Dict* sts_dict = sts_entry.GetIfDict(); + if (!sts_dict) continue; - const std::string* hostname = sts_entry.FindStringKey(kHostname); + const std::string* hostname = sts_dict->FindString(kHostname); absl::optional<bool> sts_include_subdomains = - sts_entry.FindBoolKey(kStsIncludeSubdomains); - absl::optional<double> sts_observed = sts_entry.FindDoubleKey(kStsObserved); - absl::optional<double> expiry = sts_entry.FindDoubleKey(kExpiry); - const std::string* mode = sts_entry.FindStringKey(kMode); + sts_dict->FindBool(kStsIncludeSubdomains); + absl::optional<double> sts_observed = sts_dict->FindDouble(kStsObserved); + absl::optional<double> expiry = sts_dict->FindDouble(kExpiry); + const std::string* mode = sts_dict->FindString(kMode); if (!hostname || !sts_include_subdomains.has_value() || !sts_observed.has_value() || !expiry.has_value() || !mode) { @@ -182,17 +183,17 @@ // Serializes Expect-CT data from |state| to a Value. base::Value SerializeExpectCTData(TransportSecurityState* state) { - base::Value ct_list(base::Value::Type::LIST); + base::Value::List ct_list; if (!IsDynamicExpectCTEnabled()) - return ct_list; + return base::Value(std::move(ct_list)); TransportSecurityState::ExpectCTStateIterator expect_ct_iterator(*state); for (; expect_ct_iterator.HasNext(); expect_ct_iterator.Advance()) { const TransportSecurityState::ExpectCTState& expect_ct_state = expect_ct_iterator.domain_state(); - base::Value ct_entry(base::Value::Type::DICTIONARY); + base::Value::Dict ct_entry; base::Value network_isolation_key_value; // Don't serialize entries with transient NetworkIsolationKeys. @@ -200,22 +201,19 @@ &network_isolation_key_value)) { continue; } - ct_entry.SetKey(kNetworkIsolationKey, - std::move(network_isolation_key_value)); + ct_entry.Set(kNetworkIsolationKey, std::move(network_isolation_key_value)); - ct_entry.SetStringKey( - kHostname, HashedDomainToExternalString(expect_ct_iterator.hostname())); - ct_entry.SetDoubleKey(kExpectCTObserved, - expect_ct_state.last_observed.ToDoubleT()); - ct_entry.SetDoubleKey(kExpectCTExpiry, expect_ct_state.expiry.ToDoubleT()); - ct_entry.SetBoolKey(kExpectCTEnforce, expect_ct_state.enforce); - ct_entry.SetStringKey(kExpectCTReportUri, - expect_ct_state.report_uri.spec()); + ct_entry.Set(kHostname, + HashedDomainToExternalString(expect_ct_iterator.hostname())); + ct_entry.Set(kExpectCTObserved, expect_ct_state.last_observed.ToDoubleT()); + ct_entry.Set(kExpectCTExpiry, expect_ct_state.expiry.ToDoubleT()); + ct_entry.Set(kExpectCTEnforce, expect_ct_state.enforce); + ct_entry.Set(kExpectCTReportUri, expect_ct_state.report_uri.spec()); ct_list.Append(std::move(ct_entry)); } - return ct_list; + return base::Value(std::move(ct_list)); } // Deserializes Expect-CT data from a Value created by the above method. @@ -228,21 +226,22 @@ const base::Time current_time(base::Time::Now()); - for (const base::Value& ct_entry : ct_list.GetListDeprecated()) { - if (!ct_entry.is_dict()) + for (const base::Value& ct_entry : ct_list.GetList()) { + const base::Value::Dict* ct_dict = ct_entry.GetIfDict(); + if (!ct_dict) continue; - const std::string* hostname = ct_entry.FindStringKey(kHostname); + const std::string* hostname = ct_dict->FindString(kHostname); const base::Value* network_isolation_key_value = - ct_entry.FindKey(kNetworkIsolationKey); + ct_dict->Find(kNetworkIsolationKey); absl::optional<double> expect_ct_last_observed = - ct_entry.FindDoubleKey(kExpectCTObserved); + ct_dict->FindDouble(kExpectCTObserved); absl::optional<double> expect_ct_expiry = - ct_entry.FindDoubleKey(kExpectCTExpiry); + ct_dict->FindDouble(kExpectCTExpiry); absl::optional<bool> expect_ct_enforce = - ct_entry.FindBoolKey(kExpectCTEnforce); + ct_dict->FindBool(kExpectCTEnforce); const std::string* expect_ct_report_uri = - ct_entry.FindStringKey(kExpectCTReportUri); + ct_dict->FindString(kExpectCTReportUri); if (!hostname || !network_isolation_key_value || !expect_ct_last_observed.has_value() || !expect_ct_expiry.has_value() || @@ -351,11 +350,10 @@ bool TransportSecurityPersister::SerializeData(std::string* output) { DCHECK(foreground_runner_->RunsTasksInCurrentSequence()); - base::Value toplevel(base::Value::Type::DICTIONARY); - toplevel.SetIntKey(kVersionKey, kCurrentVersionValue); - toplevel.SetKey(kSTSKey, SerializeSTSData(transport_security_state_)); - toplevel.SetKey(kExpectCTKey, - SerializeExpectCTData(transport_security_state_)); + base::Value::Dict toplevel; + toplevel.Set(kVersionKey, kCurrentVersionValue); + toplevel.Set(kSTSKey, SerializeSTSData(transport_security_state_)); + toplevel.Set(kExpectCTKey, SerializeExpectCTData(transport_security_state_)); base::JSONWriter::Write(toplevel, output); return true; @@ -374,18 +372,19 @@ if (!value || !value->is_dict()) return; - absl::optional<int> version = value->FindIntKey(kVersionKey); + base::Value::Dict& dict = value->GetDict(); + absl::optional<int> version = dict.FindInt(kVersionKey); // Stop if the data is out of date (or in the previous format that didn't have // a version number). if (!version || *version != kCurrentVersionValue) return; - base::Value* sts_value = value->FindKey(kSTSKey); + base::Value* sts_value = dict.Find(kSTSKey); if (sts_value) DeserializeSTSData(*sts_value, state); - base::Value* expect_ct_value = value->FindKey(kExpectCTKey); + base::Value* expect_ct_value = dict.Find(kExpectCTKey); if (expect_ct_value) DeserializeExpectCTData(*expect_ct_value, state); }
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc index 25c3764df..cbe5d84 100644 --- a/net/http/transport_security_state.cc +++ b/net/http/transport_security_state.cc
@@ -79,16 +79,16 @@ if (!cert_chain) return base::Value(base::Value::Type::LIST); - base::Value result(base::Value::Type::LIST); + base::Value::List result; std::vector<std::string> pem_encoded_chain; cert_chain->GetPEMEncodedChain(&pem_encoded_chain); for (const std::string& cert : pem_encoded_chain) result.Append(cert); - return result; + return base::Value(std::move(result)); } -bool HashReportForCache(const base::Value& report, +bool HashReportForCache(const base::Value::Dict& report, const GURL& report_uri, std::string* cache_key) { char hashed[crypto::kSHA256Length]; @@ -112,23 +112,23 @@ if (pkp_state.report_uri.is_empty()) return false; - base::Value report(base::Value::Type::DICTIONARY); + base::Value::Dict report; base::Time now = base::Time::Now(); - report.SetStringKey("hostname", host_port_pair.host()); - report.SetIntKey("port", host_port_pair.port()); - report.SetBoolKey("include-subdomains", pkp_state.include_subdomains); - report.SetStringKey("noted-hostname", pkp_state.domain); + report.Set("hostname", host_port_pair.host()); + report.Set("port", host_port_pair.port()); + report.Set("include-subdomains", pkp_state.include_subdomains); + report.Set("noted-hostname", pkp_state.domain); auto served_certificate_chain_list = GetPEMEncodedChainAsList(served_certificate_chain); auto validated_certificate_chain_list = GetPEMEncodedChainAsList(validated_certificate_chain); - report.SetKey("served-certificate-chain", - std::move(served_certificate_chain_list)); - report.SetKey("validated-certificate-chain", - std::move(validated_certificate_chain_list)); + report.Set("served-certificate-chain", + std::move(served_certificate_chain_list)); + report.Set("validated-certificate-chain", + std::move(validated_certificate_chain_list)); - base::Value known_pin_list(base::Value::Type::LIST); + base::Value::List known_pin_list; for (const auto& hash_value : pkp_state.spki_hashes) { std::string known_pin; @@ -152,7 +152,7 @@ known_pin_list.Append(known_pin); } - report.SetKey("known-pins", std::move(known_pin_list)); + report.Set("known-pins", std::move(known_pin_list)); // For the sent reports cache, do not include the effective expiration // date. The expiration date will likely change every time the user @@ -163,9 +163,9 @@ return false; } - report.SetStringKey("date-time", base::TimeToISO8601(now)); - report.SetStringKey("effective-expiration-date", - base::TimeToISO8601(pkp_state.expiry)); + report.Set("date-time", base::TimeToISO8601(now)); + report.Set("effective-expiration-date", + base::TimeToISO8601(pkp_state.expiry)); if (!base::JSONWriter::Write(report, serialized_report)) { LOG(ERROR) << "Failed to serialize HPKP violation report."; return false; @@ -433,14 +433,13 @@ base::Value TransportSecurityState::NetLogUpgradeToSSLParam( const std::string& host) { STSState sts_state; - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("host", host); - dict.SetBoolKey("get_sts_state_result", GetSTSState(host, &sts_state)); - dict.SetBoolKey("should_upgrade_to_ssl", sts_state.ShouldUpgradeToSSL()); - dict.SetBoolKey( - "host_found_in_hsts_bypass_list", - hsts_host_bypass_list_.find(host) != hsts_host_bypass_list_.end()); - return dict; + base::Value::Dict dict; + dict.Set("host", host); + dict.Set("get_sts_state_result", GetSTSState(host, &sts_state)); + dict.Set("should_upgrade_to_ssl", sts_state.ShouldUpgradeToSSL()); + dict.Set("host_found_in_hsts_bypass_list", + hsts_host_bypass_list_.find(host) != hsts_host_bypass_list_.end()); + return base::Value(std::move(dict)); } bool TransportSecurityState::ShouldUpgradeToSSL(
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc index 72ea47e..2065ebd3 100644 --- a/net/http/transport_security_state_unittest.cc +++ b/net/http/transport_security_state_unittest.cc
@@ -255,11 +255,10 @@ ASSERT_TRUE(cert_list->is_list()); std::vector<std::string> pem_encoded_chain; cert_chain->GetPEMEncodedChain(&pem_encoded_chain); - ASSERT_EQ(pem_encoded_chain.size(), cert_list->GetListDeprecated().size()); + ASSERT_EQ(pem_encoded_chain.size(), cert_list->GetList().size()); for (size_t i = 0; i < pem_encoded_chain.size(); i++) { - const std::string& list_cert = - cert_list->GetListDeprecated()[i].GetString(); + const std::string& list_cert = cert_list->GetList()[i].GetString(); EXPECT_EQ(pem_encoded_chain[i], list_cert); } } @@ -274,46 +273,46 @@ const HashValueVector& known_pins) { absl::optional<base::Value> value = base::JSONReader::Read(report); ASSERT_TRUE(value.has_value()); - const base::Value& report_dict = value.value(); - ASSERT_TRUE(report_dict.is_dict()); + const base::Value::Dict* report_dict = value.value().GetIfDict(); + ASSERT_TRUE(report_dict); - const std::string* report_hostname = report_dict.FindStringKey("hostname"); + const std::string* report_hostname = report_dict->FindString("hostname"); ASSERT_TRUE(report_hostname); EXPECT_EQ(host_port_pair.host(), *report_hostname); - absl::optional<int> report_port = report_dict.FindIntKey("port"); + absl::optional<int> report_port = report_dict->FindInt("port"); ASSERT_TRUE(report_port.has_value()); EXPECT_EQ(host_port_pair.port(), report_port.value()); absl::optional<bool> report_include_subdomains = - report_dict.FindBoolKey("include-subdomains"); + report_dict->FindBool("include-subdomains"); ASSERT_TRUE(report_include_subdomains.has_value()); EXPECT_EQ(include_subdomains, report_include_subdomains.value()); const std::string* report_noted_hostname = - report_dict.FindStringKey("noted-hostname"); + report_dict->FindString("noted-hostname"); ASSERT_TRUE(report_noted_hostname); EXPECT_EQ(noted_hostname, *report_noted_hostname); // TODO(estark): check times in RFC3339 format. const std::string* report_expiration = - report_dict.FindStringKey("effective-expiration-date"); + report_dict->FindString("effective-expiration-date"); ASSERT_TRUE(report_expiration); EXPECT_FALSE(report_expiration->empty()); - const std::string* report_date = report_dict.FindStringKey("date-time"); + const std::string* report_date = report_dict->FindString("date-time"); ASSERT_TRUE(report_date); EXPECT_FALSE(report_date->empty()); const base::Value* report_served_certificate_chain = - report_dict.FindKey("served-certificate-chain"); + report_dict->Find("served-certificate-chain"); ASSERT_TRUE(report_served_certificate_chain); ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList( served_certificate_chain, report_served_certificate_chain)); const base::Value* report_validated_certificate_chain = - report_dict.FindKey("validated-certificate-chain"); + report_dict->Find("validated-certificate-chain"); ASSERT_TRUE(report_validated_certificate_chain); ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList( validated_certificate_chain, report_validated_certificate_chain));
diff --git a/net/third_party/uri_template/OWNERS b/net/third_party/uri_template/OWNERS index 53e68eb7..e69de29 100644 --- a/net/third_party/uri_template/OWNERS +++ b/net/third_party/uri_template/OWNERS
@@ -1 +0,0 @@ -mmenke@chromium.org
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index 5d1d82237..3112e52 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -285,6 +285,12 @@ // handled instead by DesktopSessionAgent. monitor->Start(); } + + // Re-send the extended layout information so the client has information + // needed to identify each stream. + // TODO(crbug.com/1326339): Remove this line when legacy VideoLayout + // messages are fully deprecated and no longer sent. + OnDesktopDisplayChanged(desktop_display_info_.GetVideoLayoutProto()); } VLOG(1) << "Client capabilities: " << *client_capabilities_;
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc index d4f63ca..c2537061 100644 --- a/services/network/cors/cors_url_loader_factory.cc +++ b/services/network/cors/cors_url_loader_factory.cc
@@ -46,10 +46,10 @@ // where these operations are permitted (as specified by // URLLoaderFactoryParams::trust_token_redemption_policy). bool VerifyTrustTokenParamsIntegrityIfPresent( - const ResourceRequest& url_request, + const ResourceRequest& resource_request, const NetworkContext* context, mojom::TrustTokenRedemptionPolicy trust_token_redemption_policy) { - if (!url_request.trust_token_params) + if (!resource_request.trust_token_params) return true; if (!context->trust_token_store()) { @@ -70,7 +70,7 @@ if (trust_token_redemption_policy == mojom::TrustTokenRedemptionPolicy::kForbid && DoesTrustTokenOperationRequirePermissionsPolicy( - url_request.trust_token_params->type)) { + resource_request.trust_token_params->type)) { // Got a request configured for Trust Tokens redemption or signing from // a context in which this operation is prohibited. mojo::ReportBadMessage(
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 42fe6cfa..f7ca736 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -8327,15 +8327,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8361,7 +8361,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -8837,15 +8837,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M103/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8871,7 +8871,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 0d1939f..af7b26f6 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -46457,15 +46457,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46491,7 +46491,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -46967,15 +46967,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M103/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47001,7 +47001,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47481,15 +47481,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47515,7 +47515,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -47991,15 +47991,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M103/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48025,7 +48025,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -48573,15 +48573,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48607,7 +48607,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49083,15 +49083,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M103/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49117,7 +49117,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -49665,15 +49665,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49699,7 +49699,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -50175,15 +50175,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", + "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--test-expectations", - "../../weblayer/browser/android/javatests/skew/expectations.txt", - "--webview-apk-path=apks/SystemWebView.apk", "--implementation-outdir", "../../weblayer_instrumentation_test_M103/out/Release", + "--test-expectations", + "../../weblayer/browser/android/javatests/skew/expectations.txt", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -50209,7 +50209,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M103", - "revision": "version:103.0.5060.60" + "revision": "version:103.0.5060.61" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/filters/fuchsia.lsan.extensions_unittests.filter b/testing/buildbot/filters/fuchsia.lsan.extensions_unittests.filter index 8718c97..9eb49ad 100644 --- a/testing/buildbot/filters/fuchsia.lsan.extensions_unittests.filter +++ b/testing/buildbot/filters/fuchsia.lsan.extensions_unittests.filter
@@ -5,6 +5,8 @@ -APILastErrorTest* -APIRequestHandlerTest.SettingLastError -All/ResponseValidationNativeExtensionBindingsSystemUnittest.ResponseValidation* +-All/SignatureValidationNativeExtensionBindingsSystemUnittest.EventArgumentValidation* +-All/SignatureValidationNativeExtensionBindingsSystemUnittest.ResponseValidation* -DeclarativeEventTest.TestRulesSchema -DeclarativeEventWithSchemaTest.TestAllMethods -EventEmitterUnittest.ListenersDestroyingContext
diff --git a/testing/buildbot/filters/linux-lacros.browser_tests.filter b/testing/buildbot/filters/linux-lacros.browser_tests.filter index 64e21fa..fd74bbb0 100644 --- a/testing/buildbot/filters/linux-lacros.browser_tests.filter +++ b/testing/buildbot/filters/linux-lacros.browser_tests.filter
@@ -27,7 +27,6 @@ -All/HostedOrWebAppTest.CtrlClickLink/WebApp -AudioFocusWebContentsObserverBrowserTest.PlatformAppHasDifferentAudioFocus -ContentSettingsTest.AllowCookiesForASessionUsingExceptions --CustomTabBarViewBrowserTest.BackToAppButtonIsNotVisibleInOutOfScopePopups -DevToolsTest.TestDispatchKeyEventShowsAutoFill # #TODO (b/235882005): These tests fail due to a NOT_IMPLEMENTED_LOG_ONCE() # within the wayland_surface.cc implementation. This implementation is
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json index e13826d..397a5a4 100644 --- a/testing/buildbot/internal.chromeos.fyi.json +++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1039,48 +1039,48 @@ "args": [], "cros_board": "octopus", "cros_img": "octopus-release/R105-14916.0.0", - "name": "lacros_all_tast_tests_informational OCTOPUS_RELEASE_LKGM", + "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_LKGM", "swarming": {}, - "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && informational)", - "test": "lacros_all_tast_tests_informational", - "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests_informational/", - "timeout_sec": 25200, + "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")", + "test": "lacros_fyi_tast_tests", + "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/", + "timeout_sec": 10800, "variant_id": "OCTOPUS_RELEASE_LKGM" }, { "args": [], "cros_board": "octopus", "cros_img": "octopus-release/R104-14909.7.0", - "name": "lacros_all_tast_tests_informational OCTOPUS_RELEASE_DEV", + "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_DEV", "swarming": {}, - "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && informational)", - "test": "lacros_all_tast_tests_informational", - "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests_informational/", - "timeout_sec": 25200, + "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")", + "test": "lacros_fyi_tast_tests", + "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/", + "timeout_sec": 10800, "variant_id": "OCTOPUS_RELEASE_DEV" }, { "args": [], "cros_board": "octopus", "cros_img": "octopus-release/R103-14816.64.0", - "name": "lacros_all_tast_tests_informational OCTOPUS_RELEASE_BETA", + "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_BETA", "swarming": {}, - "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && informational)", - "test": "lacros_all_tast_tests_informational", - "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests_informational/", - "timeout_sec": 25200, + "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")", + "test": "lacros_fyi_tast_tests", + "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/", + "timeout_sec": 10800, "variant_id": "OCTOPUS_RELEASE_BETA" }, { "args": [], "cros_board": "octopus", "cros_img": "octopus-release/R102-14695.85.0", - "name": "lacros_all_tast_tests_informational OCTOPUS_RELEASE_STABLE", + "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_STABLE", "swarming": {}, - "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && informational)", - "test": "lacros_all_tast_tests_informational", - "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests_informational/", - "timeout_sec": 25200, + "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")", + "test": "lacros_fyi_tast_tests", + "test_id_prefix": "ninja://chromeos/lacros:lacros_fyi_tast_tests/", + "timeout_sec": 10800, "variant_id": "OCTOPUS_RELEASE_STABLE" }, {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index c79e4c8..8cfa5eb 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3947,9 +3947,9 @@ }, 'lacros_skylab_amd64_fyi': { - 'lacros_all_tast_tests_informational': { - 'tast_expr': '("group:mainline" && "dep:lacros" && informational)', - 'timeout_sec': 25200, + 'lacros_fyi_tast_tests': { + 'tast_expr': '("group:mainline" && "dep:lacros" && !informational || "name:lacros.VariationSmoke")', + 'timeout_sec': 10800, }, 'ozone_unittests': { 'timeout_sec': 3600,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 530e98720..258abb6 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -517,16 +517,16 @@ }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ + '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--test-expectations', - '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--implementation-outdir', '../../weblayer_instrumentation_test_M103/out/Release', - '--impl-version=103' + '--test-expectations', + '../../weblayer/browser/android/javatests/skew/expectations.txt', + '--impl-version=103', ], 'identifier': 'with_impl_from_103', 'swarming': { @@ -534,10 +534,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.60' + 'revision': 'version:103.0.5060.61', } - ] - } + ], + }, }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -661,16 +661,16 @@ }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ + '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--test-expectations', - '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--webview-apk-path=apks/SystemWebView.apk', '--implementation-outdir', '../../weblayer_instrumentation_test_M103/out/Release', - '--impl-version=103' + '--test-expectations', + '../../weblayer/browser/android/javatests/skew/expectations.txt', + '--impl-version=103', ], 'identifier': 'with_impl_from_103', 'swarming': { @@ -678,10 +678,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.60' + 'revision': 'version:103.0.5060.61', } - ] - } + ], + }, }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -805,16 +805,16 @@ }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ + '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', + '--client-outdir', + '../../weblayer_instrumentation_test_M103/out/Release', '--implementation-outdir', '.', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--webview-apk-path=apks/SystemWebView.apk', - '--client-outdir', - '../../weblayer_instrumentation_test_M103/out/Release', - '--client-version=103' + '--client-version=103', ], 'identifier': 'with_client_from_103', 'swarming': { @@ -822,10 +822,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.60' + 'revision': 'version:103.0.5060.61', } - ] - } + ], + }, }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [
diff --git a/testing/merge_scripts/code_coverage/merge_lib.py b/testing/merge_scripts/code_coverage/merge_lib.py index 1699e958..d95fc3f 100644 --- a/testing/merge_scripts/code_coverage/merge_lib.py +++ b/testing/merge_scripts/code_coverage/merge_lib.py
@@ -9,6 +9,7 @@ import re import shutil import subprocess +import sys _DIR_SOURCE_ROOT = os.path.normpath( os.path.join(os.path.dirname(__file__), '..', '..', '..')) @@ -108,6 +109,10 @@ cpu_count = multiprocessing.cpu_count() counts = max(10, cpu_count - 5) # Use 10+ processes, but leave 5 cpu cores. + if sys.platform == 'win32': + # TODO(crbug.com/1190269) - we can't use more than 56 child processes on + # Windows or Python3 may hang. + counts = min(counts, 56) pool = multiprocessing.Pool(counts) output_profdata_files = multiprocessing.Manager().list() invalid_profraw_files = multiprocessing.Manager().list()
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 8e8178e..58ab8287 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3171,6 +3171,30 @@ ] } ], + "DesktopOmniboxRichAutocompletion": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "RichAutocompletionAutocompleteNonPrefixAll": "true", + "RichAutocompletionAutocompleteTitles": "true" + }, + "enable_features": [ + "OmniboxRichAutocompletion", + "OmniboxShortcutExpanding" + ] + } + ] + } + ], "DesktopReadingListAddFromDialog": [ { "platforms": [ @@ -5724,8 +5748,6 @@ "OmniboxBookmarkPathsUiDynamicReplaceUrl": "true", "OmniboxLocalZeroSuggestAgeThreshold": "60", "OmniboxMaxURLMatches": "7", - "RichAutocompletionAutocompleteNonPrefixAll": "true", - "RichAutocompletionAutocompleteTitles": "true", "ShortBookmarkSuggestionsByTotalInputLengthThreshold": "3", "UIMaxAutocompleteMatches": "8", "ZeroSuggestCacheCounterfactual": "true", @@ -5745,7 +5767,6 @@ "OmniboxMaxZeroSuggestMatches", "OmniboxPreserveLongerShortcutsText", "OmniboxRemoveSuggestionsFromClipboard", - "OmniboxRichAutocompletion", "OmniboxShortBookmarkSuggestionsByTotalInputLength", "OmniboxUIExperimentMaxAutocompleteMatches", "ZeroSuggestPrefetching" @@ -6599,6 +6620,31 @@ ] } ], + "PrecompileInlineScripts": [ + { + "platforms": [ + "android", + "android_weblayer", + "android_webview", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "FirstScriptLazy_20220609", + "params": { + "compile-strategy": "first-script-lazy" + }, + "enable_features": [ + "PrecompileInlineScripts" + ] + } + ] + } + ], "PreconnectToSearchDesktop": [ { "platforms": [ @@ -6622,6 +6668,24 @@ ] } ], + "PrefetchFontLookupTables": [ + { + "platforms": [ + "android", + "android_weblayer", + "android_webview", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "PrefetchFontLookupTables" + ] + } + ] + } + ], "PreloadCookies": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index fb96dcf3..31bc729 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -65,7 +65,7 @@ // Used as a binding for controlling the runtime enabled blink feature // "FixedElementsDontOverscroll". This is needed for experimentation. const base::Feature kFixedElementsDontOverscroll{ - "FixedElementsDontOverscroll", base::FEATURE_DISABLED_BY_DEFAULT}; + "FixedElementsDontOverscroll", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kGMSCoreEmoji{"GMSCoreEmoji", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 1ed8a5b..a5031fa 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -48,6 +48,7 @@ "content_index/content_index.mojom", "context_menu/context_menu.mojom", "conversions/attribution_data_host.mojom", + "conversions/attribution_reporting_automation.mojom", "conversions/conversions.mojom", "cookie_manager/cookie_manager_automation.mojom", "cookie_store/cookie_store.mojom",
diff --git a/third_party/blink/public/mojom/conversions/attribution_reporting_automation.mojom b/third_party/blink/public/mojom/conversions/attribution_reporting_automation.mojom new file mode 100644 index 0000000..9331061 --- /dev/null +++ b/third_party/blink/public/mojom/conversions/attribution_reporting_automation.mojom
@@ -0,0 +1,14 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module blink.test.mojom; + +// Provides privileged access to the Attribution Reporting API +// +// https://wicg.github.io/attribution-reporting-api/ +interface AttributionReportingAutomation { + // Resets all state associated with the Attribution Reporting API for use in + // hermetic tests. + Reset() => (bool success); +};
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index f50223df..b0172da 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -755,6 +755,7 @@ "//third_party/blink/renderer/core/testing/internal_settings.idl", "//third_party/blink/renderer/core/testing/internals.idl", "//third_party/blink/renderer/core/testing/internals_delete_all_cookies.idl", + "//third_party/blink/renderer/core/testing/attribution_reporting_automation.idl", "//third_party/blink/renderer/core/testing/origin_trials_test.idl", "//third_party/blink/renderer/core/testing/origin_trials_test_dictionary.idl", "//third_party/blink/renderer/core/testing/origin_trials_test_partial.idl",
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 1f6eb3db..e4562ca 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -430,6 +430,8 @@ "fetch/testing/worker_internals_fetch.h", "html/forms/mock_file_chooser.h", "streams/test_underlying_source.h", + "testing/attribution_reporting_automation.cc", + "testing/attribution_reporting_automation.h", "testing/callback_function_test.cc", "testing/callback_function_test.h", "testing/color_scheme_helper.cc",
diff --git a/third_party/blink/renderer/core/dom/attribute.h b/third_party/blink/renderer/core/dom/attribute.h index 1869c50..eff6042a 100644 --- a/third_party/blink/renderer/core/dom/attribute.h +++ b/third_party/blink/renderer/core/dom/attribute.h
@@ -41,6 +41,8 @@ public: Attribute(const QualifiedName& name, const AtomicString& value) : name_(name), value_(value) {} + Attribute(QualifiedName&& name, AtomicString&& value) + : name_(std::move(name)), value_(std::move(value)) {} // NOTE: The references returned by these functions are only valid for as long // as the Attribute stays in place. For example, calling a function that
diff --git a/third_party/blink/renderer/core/dom/element_data.h b/third_party/blink/renderer/core/dom/element_data.h index 937c4fa..bfae665 100644 --- a/third_party/blink/renderer/core/dom/element_data.h +++ b/third_party/blink/renderer/core/dom/element_data.h
@@ -138,6 +138,7 @@ private: friend class Element; friend class HTMLImageElement; + friend class HTMLQuoteElement; friend class ShareableElementData; friend class UniqueElementData; friend class SVGElement;
diff --git a/third_party/blink/renderer/core/dom/qualified_name.h b/third_party/blink/renderer/core/dom/qualified_name.h index c4634c33..f094fb9 100644 --- a/third_party/blink/renderer/core/dom/qualified_name.h +++ b/third_party/blink/renderer/core/dom/qualified_name.h
@@ -113,6 +113,8 @@ impl_ = other.impl_; return *this; } + QualifiedName(QualifiedName&& other) = default; + QualifiedName& operator=(QualifiedName&& other) = default; bool operator==(const QualifiedName& other) const { return impl_ == other.impl_;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index deeeab3..ed1ee90 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1250,7 +1250,7 @@ gfx::Size old_size = frame_view->Size(); UpdateICBAndResizeViewport(visible_viewport_size); gfx::Size new_size = frame_view->Size(); - frame_view->MarkViewportConstrainedObjectsForLayout( + frame_view->MarkFixedPositionObjectsForLayout( old_size.width() != new_size.width(), old_size.height() != new_size.height()); }
diff --git a/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto b/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto index 2814043a..c5c8b4df 100644 --- a/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto +++ b/third_party/blink/renderer/core/frame/attribution_src/attribution_trigger_registration_corpus/all_params.textproto
@@ -195,7 +195,9 @@ name: "a" value { number_value { - integer_value: 123 + integer_value { + value: 123 + } } } } @@ -203,7 +205,9 @@ name: "b" value { number_value { - integer_value: 456 + integer_value { + value: 456 + } } } }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index ec9c683d..3b62399 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -268,7 +268,6 @@ visually_non_empty_character_count_(0), visually_non_empty_pixel_count_(0), is_visually_non_empty_(false), - sticky_position_object_count_(0), layout_size_fixed_to_frame_size_(true), needs_update_geometries_(false), root_layer_did_scroll_(false), @@ -328,7 +327,7 @@ visitor->Trace(scroll_anchoring_scrollable_areas_); visitor->Trace(animating_scrollable_areas_); visitor->Trace(user_scrollable_areas_); - visitor->Trace(viewport_constrained_objects_); + visitor->Trace(fixed_position_objects_); visitor->Trace(background_attachment_fixed_objects_); visitor->Trace(auto_size_info_); visitor->Trace(plugins_); @@ -487,7 +486,7 @@ // are missed. It would be good to understand how/why that happens, but in the // mean time, it's not safe to keep pointers around to defunct LayoutObjects. orthogonal_writing_mode_root_list_.Clear(); - viewport_constrained_objects_.Clear(); + fixed_position_objects_.Clear(); background_attachment_fixed_objects_.clear(); // Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing @@ -894,9 +893,8 @@ gfx::Size new_size(Size()); if (old_size != new_size) { - MarkViewportConstrainedObjectsForLayout( - old_size.width() != new_size.width(), - old_size.height() != new_size.height()); + MarkFixedPositionObjectsForLayout(old_size.width() != new_size.width(), + old_size.height() != new_size.height()); } if (frame_->IsMainFrame()) { @@ -1258,35 +1256,15 @@ return true; } -void LocalFrameView::AddViewportConstrainedObject( - LayoutObject& object, - ViewportConstrainedType constrained_reason) { - if (!viewport_constrained_objects_) - viewport_constrained_objects_ = MakeGarbageCollected<ObjectSet>(); - - auto result = viewport_constrained_objects_->insert(&object); - if (constrained_reason == ViewportConstrainedType::kSticky) { - if (result.is_new_entry) { - sticky_position_object_count_++; - } - DCHECK_LE(sticky_position_object_count_, - viewport_constrained_objects_->size()); - } +void LocalFrameView::AddFixedPositionObject(LayoutObject& object) { + if (!fixed_position_objects_) + fixed_position_objects_ = MakeGarbageCollected<ObjectSet>(); + fixed_position_objects_->insert(&object); } -void LocalFrameView::RemoveViewportConstrainedObject( - LayoutObject& object, - ViewportConstrainedType constrained_reason) { - if (viewport_constrained_objects_) { - auto it = viewport_constrained_objects_->find(&object); - if (it != viewport_constrained_objects_->end()) { - viewport_constrained_objects_->erase(it); - if (constrained_reason == ViewportConstrainedType::kSticky) { - DCHECK_GT(sticky_position_object_count_, 0U); - sticky_position_object_count_--; - } - } - } +void LocalFrameView::RemoveFixedPositionObject(LayoutObject& object) { + if (fixed_position_objects_) + fixed_position_objects_->erase(&object); } void LocalFrameView::ViewportSizeChanged(bool width_changed, @@ -1326,19 +1304,18 @@ layout_view->SetShouldCheckForPaintInvalidation(); if (GetFrame().GetDocument() && !IsInPerformLayout()) - MarkViewportConstrainedObjectsForLayout(width_changed, height_changed); + MarkFixedPositionObjectsForLayout(width_changed, height_changed); if (GetPaintTimingDetector().Visualizer()) GetPaintTimingDetector().Visualizer()->OnViewportChanged(); } -void LocalFrameView::MarkViewportConstrainedObjectsForLayout( - bool width_changed, - bool height_changed) { - if (!HasViewportConstrainedObjects() || !(width_changed || height_changed)) +void LocalFrameView::MarkFixedPositionObjectsForLayout(bool width_changed, + bool height_changed) { + if (!HasFixedPositionObjects() || !(width_changed || height_changed)) return; - for (const auto& layout_object : *viewport_constrained_objects_) { + for (const auto& layout_object : *fixed_position_objects_) { const ComputedStyle& style = layout_object->StyleRef(); if (width_changed) { if (style.Width().IsFixed() &&
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index d0e1196..fba1485 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -296,33 +296,22 @@ void DidChangeScrollOffset(); void ViewportSizeChanged(bool width_changed, bool height_changed); - void MarkViewportConstrainedObjectsForLayout(bool width_changed, - bool height_changed); + void MarkFixedPositionObjectsForLayout(bool width_changed, + bool height_changed); void DynamicViewportUnitsChanged(); AtomicString MediaType() const; void SetMediaType(const AtomicString&); void AdjustMediaTypeForPrinting(bool printing); - // For any viewport-constrained object, we need to know if it's due to fixed - // or sticky so that we can support HasStickyViewportConstrainedObject(). - enum ViewportConstrainedType { kFixed = 0, kSticky = 1 }; - // Fixed-position and viewport-constrained sticky-position objects. typedef HeapHashSet<Member<LayoutObject>> ObjectSet; - void AddViewportConstrainedObject(LayoutObject&, ViewportConstrainedType); - void RemoveViewportConstrainedObject(LayoutObject&, ViewportConstrainedType); - const ObjectSet* ViewportConstrainedObjects() const { - return viewport_constrained_objects_; + void AddFixedPositionObject(LayoutObject&); + void RemoveFixedPositionObject(LayoutObject&); + const ObjectSet* FixedPositionObjects() const { + return fixed_position_objects_; } - bool HasViewportConstrainedObjects() const { - return viewport_constrained_objects_ && - viewport_constrained_objects_->size() > 0; - } - // Returns true if any of the objects in viewport_constrained_objects_ are - // sticky position. - bool HasStickyViewportConstrainedObject() const { - DCHECK(!sticky_position_object_count_ || HasViewportConstrainedObjects()); - return sticky_position_object_count_ > 0; + bool HasFixedPositionObjects() const { + return fixed_position_objects_ && fixed_position_objects_->size() > 0; } // Objects with background-attachment:fixed. @@ -1099,9 +1088,7 @@ Member<ScrollableAreaSet> animating_scrollable_areas_; // Scrollable areas which are user-scrollable, whether they overflow or not. Member<ScrollableAreaSet> user_scrollable_areas_; - Member<ObjectSet> viewport_constrained_objects_; - // Number of entries in viewport_constrained_objects_ that are sticky. - unsigned sticky_position_object_count_; + Member<ObjectSet> fixed_position_objects_; ObjectSet background_attachment_fixed_objects_; Member<FrameViewAutoSizeInfo> auto_size_info_;
diff --git a/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc b/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc index 1b18604..dd87e1b 100644 --- a/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc +++ b/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
@@ -45,7 +45,7 @@ // 'style' is now the ComputedStyle for the object whose position depends // on the document. - if (style->HasViewportConstrainedPosition() || + if (style->GetPosition() == EPosition::kFixed || style->HasStickyConstrainedPosition()) { return true; }
diff --git a/third_party/blink/renderer/core/html/closewatcher/close_watcher.cc b/third_party/blink/renderer/core/html/closewatcher/close_watcher.cc index c283b82a..64102d54 100644 --- a/third_party/blink/renderer/core/html/closewatcher/close_watcher.cc +++ b/third_party/blink/renderer/core/html/closewatcher/close_watcher.cc
@@ -91,13 +91,12 @@ } // static -CloseWatcher* CloseWatcher::Create(LocalDOMWindow* window, - CloseWatcherOptions* options) { +CloseWatcher* CloseWatcher::Create(LocalDOMWindow* window) { if (!window->GetFrame()) return nullptr; WatcherStack& stack = *window->closewatcher_stack(); - return CreateInternal(window, stack, options); + return CreateInternal(window, stack, nullptr); } // static
diff --git a/third_party/blink/renderer/core/html/closewatcher/close_watcher.h b/third_party/blink/renderer/core/html/closewatcher/close_watcher.h index 078abef..19d14b6 100644 --- a/third_party/blink/renderer/core/html/closewatcher/close_watcher.h +++ b/third_party/blink/renderer/core/html/closewatcher/close_watcher.h
@@ -28,10 +28,7 @@ CloseWatcherOptions*, ExceptionState&); - // TODO(domenic): remove the CloseWatcherOptions* from this overload. This is - // meant to be used by Chromium-internal callers, who will not want to pass an - // AbortSignal. - static CloseWatcher* Create(LocalDOMWindow*, CloseWatcherOptions*); + static CloseWatcher* Create(LocalDOMWindow*); explicit CloseWatcher(LocalDOMWindow*); void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index c65d649..c93d961 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -528,11 +528,22 @@ const AtomicString& attribution_src_value = FastGetAttribute(html_names::kAttributionsrcAttr); - if (!attribution_src_value.IsNull()) { + if (!attribution_src_value.IsEmpty()) { frame_request.SetImpression( frame->GetAttributionSrcLoader()->RegisterNavigation( GetDocument().CompleteURL(attribution_src_value), this)); } + + // If the impression could not be set, or if the value was null, mark that + // the frame request is eligible for attribution by adding an impression. + if (!frame_request.Impression() && + CanRegisterAttributionInContext( + frame, this, + /*request_id=*/absl::nullopt, + AttributionSrcLoader::RegisterContext::kAttributionSrc, + /*log_issues=*/false)) { + frame_request.SetImpression(blink::Impression()); + } } Frame* target_frame =
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.cc b/third_party/blink/renderer/core/html/html_dialog_element.cc index d10168b..c8bfd1b 100644 --- a/third_party/blink/renderer/core/html/html_dialog_element.cc +++ b/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -162,8 +162,10 @@ previously_focused_element->Focus(focus_options); } - if (close_watcher_) + if (close_watcher_) { close_watcher_->destroy(); + close_watcher_ = nullptr; + } } void HTMLDialogElement::SetIsModal(bool is_modal) { @@ -206,7 +208,7 @@ if (!dialog_) return; if (event->type() == event_type_names::kCancel) - dialog_->CloseWatcherFiredCancel(); + dialog_->CloseWatcherFiredCancel(event); if (event->type() == event_type_names::kClose) dialog_->CloseWatcherFiredClose(); } @@ -263,7 +265,7 @@ if (RuntimeEnabledFeatures::CloseWatcherEnabled()) { if (LocalDOMWindow* window = GetDocument().domWindow()) { - close_watcher_ = CloseWatcher::Create(window, /*options=*/nullptr); + close_watcher_ = CloseWatcher::Create(window); if (close_watcher_) { auto* event_listener = MakeGarbageCollected<DialogCloseWatcherEventListener>(this); @@ -284,6 +286,11 @@ HTMLElement::RemovedFrom(insertion_point); InertSubtreesChanged(document, old_modal_dialog); SetIsModal(false); + + if (close_watcher_) { + close_watcher_->destroy(); + close_watcher_ = nullptr; + } } void HTMLDialogElement::DefaultEventHandler(Event& event) { @@ -296,21 +303,18 @@ HTMLElement::DefaultEventHandler(event); } -void HTMLDialogElement::CloseWatcherFiredCancel() { - cancel_fired_since_last_close_ = true; +void HTMLDialogElement::CloseWatcherFiredCancel(Event* close_watcher_event) { + // https://wicg.github.io/close-watcher/#patch-dialog cancelAction + + Event* dialog_event = Event::CreateCancelable(event_type_names::kCancel); + DispatchEvent(*dialog_event); + if (dialog_event->defaultPrevented()) + close_watcher_event->preventDefault(); + dialog_event->SetDefaultHandled(); } void HTMLDialogElement::CloseWatcherFiredClose() { - // https://wicg.github.io/close-watcher/#cancel-the-dialog - if (cancel_fired_since_last_close_) { - cancel_fired_since_last_close_ = false; - - Event* cancel_event = Event::CreateCancelable(event_type_names::kCancel); - DispatchEvent(*cancel_event); - if (cancel_event->defaultPrevented()) - return; - cancel_event->SetDefaultHandled(); - } + // https://wicg.github.io/close-watcher/#patch-dialog closeAction close(); }
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.h b/third_party/blink/renderer/core/html/html_dialog_element.h index de9df798..304613f 100644 --- a/third_party/blink/renderer/core/html/html_dialog_element.h +++ b/third_party/blink/renderer/core/html/html_dialog_element.h
@@ -56,7 +56,7 @@ return_value_ = return_value; } - void CloseWatcherFiredCancel(); + void CloseWatcherFiredCancel(Event*); void CloseWatcherFiredClose(); private: @@ -74,7 +74,6 @@ WeakMember<Element> previously_focused_element_; Member<CloseWatcher> close_watcher_; - bool cancel_fired_since_last_close_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index ccfd16d..e56d613c 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -69,6 +69,7 @@ #include "third_party/blink/renderer/core/html/html_dimension.h" #include "third_party/blink/renderer/core/html/html_document.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" +#include "third_party/blink/renderer/core/html/html_quote_element.h" #include "third_party/blink/renderer/core/html/html_slot_element.h" #include "third_party/blink/renderer/core/html/html_template_element.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" @@ -253,6 +254,12 @@ void HTMLElement::MapLanguageAttributeToLocale( const AtomicString& value, MutableCSSPropertyValueSet* style) { + // HTMLQuoteElement should ignore own lang attribute and use lang of parent. + // This is handled in CollectExtraStyleForPresentationAttribute(). + // https://github.com/w3c/csswg-drafts/issues/5478 + if (IsA<HTMLQuoteElement>(this)) { + return; + } if (!value.IsEmpty()) { // Have to quote so the locale id is treated as a string instead of as a CSS // keyword.
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index f8b2285f..06fa1c5f 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -244,9 +244,18 @@ return allowed_websites; } +// Checks if the passed url is the same origin with the document. +// This is called in order to limit LazyEmbeds/Ads to apply only cross-origin +// frames. +// We're not sure if this is 100% needed, and we should move the check closer +// to context->GetSecurityOrigin()->CanAccess check. +bool AreSameOrigin(const Document& document, const KURL& url) { + return SecurityOrigin::AreSameOrigin(url, document.Url()); +} + // Checks if the passed `url` is in the allowlist for automatic // lazy-loading. Returns true if the url is in the list. -bool IsEligibleForLazyEmbeds(KURL url) { +bool IsEligibleForLazyEmbeds(const KURL& url, const Document& document) { #if DCHECK_IS_ON() if (base::FeatureList::IsEnabled( features::kAutomaticLazyFrameLoadingToEmbeds)) { @@ -257,6 +266,12 @@ } #endif // DCHECK_IS_ON() + // LazyEmbeds targets are third-party frames. + // Not eligible if the frame url is a same-origin as the parent url. + if (AreSameOrigin(document, url)) { + return false; + } + scoped_refptr<const SecurityOrigin> origin = SecurityOrigin::Create(url); for (const auto& it : AllowedWebsitesForLazyLoading()) { // TODO(sisidovski): IsSameOriginWith is more strict but we skip the port @@ -664,13 +679,14 @@ if (CheckAndRecordIfShouldLazilyLoadFrame( GetDocument(), /*is_loading_attr_lazy=*/loading_lazy_set, - /*is_eligible_for_lazy_embeds=*/IsEligibleForLazyEmbeds(url), - /*is_eligible_for_lazy_ads=*/IsAdRelated(), + /*is_eligible_for_lazy_embeds=*/ + IsEligibleForLazyEmbeds(url, GetDocument()), + /*is_eligible_for_lazy_ads=*/IsEligibleForLazyAds(url), /*record_uma=*/true)) { lazy_load_frame_observer_->DeferLoadUntilNearViewport(request, frame_load_type); MaybeSetTimeoutToStartAdFrameLoading( - /*is_loading_attr_lazy=*/loading_lazy_set); + url, /*is_loading_attr_lazy=*/loading_lazy_set); return true; } @@ -872,13 +888,20 @@ LoadImmediatelyIfLazy(); } +bool HTMLFrameOwnerElement::IsEligibleForLazyAds(const KURL& url) { + // LazyAds targets are third-party frames. + // Not eligible if the frame url is a same-origin as the parent url. + return IsAdRelated() && !AreSameOrigin(GetDocument(), url); +} + void HTMLFrameOwnerElement::MaybeSetTimeoutToStartAdFrameLoading( + const KURL& url, bool is_loading_attr_lazy) { if (!base::FeatureList::IsEnabled( features::kAutomaticLazyFrameLoadingToAds)) { return; } - if (!IsAdRelated()) { + if (!IsEligibleForLazyAds(url)) { return; } // Even if the frame is ad related, respect the explicit loading="lazy"
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h index 6248c41..0410332 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.h +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -199,7 +199,9 @@ is_swapping_frames_ = is_swapping; } - void MaybeSetTimeoutToStartAdFrameLoading(bool is_loading_attr_lazy); + bool IsEligibleForLazyAds(const KURL& url); + void MaybeSetTimeoutToStartAdFrameLoading(const KURL& url, + bool is_loading_attr_lazy); // This function is used for the call back of idle task. // Trigger loading if the frame is lazy-loaded but not started yet. void LoadIfLazyOnIdle(base::TimeTicks deadline);
diff --git a/third_party/blink/renderer/core/html/html_quote_element.cc b/third_party/blink/renderer/core/html/html_quote_element.cc index e85d6a1..41913ab 100644 --- a/third_party/blink/renderer/core/html/html_quote_element.cc +++ b/third_party/blink/renderer/core/html/html_quote_element.cc
@@ -22,6 +22,8 @@ #include "third_party/blink/renderer/core/html/html_quote_element.h" +#include "third_party/blink/renderer/core/css/css_markup.h" +#include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/html_names.h" @@ -32,6 +34,7 @@ : HTMLElement(tag_name, document) { DCHECK(HasTagName(html_names::kQTag) || HasTagName(html_names::kBlockquoteTag)); + SetHasCustomStyleCallbacks(); } bool HTMLQuoteElement::IsURLAttribute(const Attribute& attribute) const { @@ -48,4 +51,27 @@ return html_names::kCiteAttr; } +void HTMLQuoteElement::WillRecalcStyle(const StyleRecalcChange change) { + EnsureUniqueElementData().SetPresentationAttributeStyleIsDirty(true); +} + +void HTMLQuoteElement::CollectExtraStyleForPresentationAttribute( + MutableCSSPropertyValueSet* style) { + HTMLElement::CollectExtraStyleForPresentationAttribute(style); + + // <q> should ignore its own lang attribute and use lang of parent. + // https://github.com/w3c/csswg-drafts/issues/5478 + Element* parent = parentElement(); + if (parent) { + if (const AtomicString lang = parent->ComputeInheritedLanguage()) { + AddPropertyToPresentationAttributeStyle( + style, CSSPropertyID::kWebkitLocale, SerializeString(lang)); + return; + } + } + // The empty string means the language is explicitly unknown. + AddPropertyToPresentationAttributeStyle(style, CSSPropertyID::kWebkitLocale, + CSSValueID::kAuto); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_quote_element.h b/third_party/blink/renderer/core/html/html_quote_element.h index aa6585f..bfaf467 100644 --- a/third_party/blink/renderer/core/html/html_quote_element.h +++ b/third_party/blink/renderer/core/html/html_quote_element.h
@@ -39,6 +39,9 @@ bool IsURLAttribute(const Attribute&) const override; bool HasLegalLinkAttribute(const QualifiedName&) const override; const QualifiedName& SubResourceAttributeName() const override; + void WillRecalcStyle(const StyleRecalcChange) override; + void CollectExtraStyleForPresentationAttribute( + MutableCSSPropertyValueSet*) override; }; inline bool IsHTMLQuoteElement(const HTMLElement& element) {
diff --git a/third_party/blink/renderer/core/html/parser/atomic_html_token.h b/third_party/blink/renderer/core/html/parser/atomic_html_token.h index 4558746..8a6391c 100644 --- a/third_party/blink/renderer/core/html/parser/atomic_html_token.h +++ b/third_party/blink/renderer/core/html/parser/atomic_html_token.h
@@ -199,19 +199,21 @@ if (attribute.NameIsEmpty()) continue; +#if DCHECK_IS_ON() attribute.NameRange().CheckValid(); attribute.ValueRange().CheckValid(); +#endif - AtomicString value(attribute.GetValue()); // The string pointer in |value| is null for attributes with no values, but // the null atom is used to represent absence of attributes; attributes with // no values have the value set to an empty atom instead. - if (value == g_null_atom) { - value = g_empty_atom; - } - const QualifiedName& name = NameForAttribute(attribute); + QualifiedName name = NameForAttribute(attribute); if (added_attributes.insert(name.LocalName()).is_new_entry) { - attributes_.push_back(Attribute(name, value)); + AtomicString value(attribute.GetValue()); + if (value.IsNull()) { + value = g_empty_atom; + } + attributes_.UncheckedAppend(Attribute(std::move(name), std::move(value))); } else { duplicate_attribute_ = true; }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index bf4a67b..d869003 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -503,6 +503,7 @@ if (IsOutOfFlowPositioned()) LayoutBlock::RemovePositionedObject(this); + RemoveFromPercentHeightContainer(); if (IsOrthogonalWritingModeRoot() && !DocumentBeingDestroyed()) UnmarkOrthogonalWritingModeRoot(); @@ -515,6 +516,8 @@ .GetFrame() ->GetInputMethodController() .LayoutObjectWillBeDestroyed(*this); + if (IsFixedPositioned()) + GetFrameView()->RemoveFixedPositionObject(*this); } SetSnapContainer(nullptr); @@ -779,6 +782,19 @@ } } + if (LocalFrameView* frame_view = View()->GetFrameView()) { + bool new_style_is_fixed_position = + StyleRef().GetPosition() == EPosition::kFixed; + bool old_style_is_fixed_position = + old_style && old_style->GetPosition() == EPosition::kFixed; + if (new_style_is_fixed_position != old_style_is_fixed_position) { + if (new_style_is_fixed_position && Layer()) + frame_view->AddFixedPositionObject(*this); + else + frame_view->RemoveFixedPositionObject(*this); + } + } + // Update the script style map, from the new computed style. if (IsCustomItem()) GetCustomLayoutChild()->styleMap()->UpdateStyle(GetDocument(), StyleRef());
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index 70e2f9b..2d14a8d 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -161,22 +161,6 @@ // A continuation of this LayoutObject should be destroyed at subclasses. DCHECK(!Continuation()); - if (IsPositioned()) { - // Don't use view() because the document's layoutView has been set to - // 0 during destruction. - if (LocalFrame* frame = GetFrame()) { - if (LocalFrameView* frame_view = frame->View()) { - if (StyleRef().HasViewportConstrainedPosition()) { - frame_view->RemoveViewportConstrainedObject( - *this, LocalFrameView::ViewportConstrainedType::kFixed); - } else if (StyleRef().HasStickyConstrainedPosition()) { - frame_view->RemoveViewportConstrainedObject( - *this, LocalFrameView::ViewportConstrainedType::kSticky); - } - } - } - } - LayoutObject::WillBeDestroyed(); if (HasLayer()) @@ -368,43 +352,6 @@ } } - if (LocalFrameView* frame_view = View()->GetFrameView()) { - bool new_style_is_viewport_constained = - StyleRef().GetPosition() == EPosition::kFixed; - bool old_style_is_viewport_constrained = - old_style && old_style->GetPosition() == EPosition::kFixed; - bool new_style_is_sticky = StyleRef().HasStickyConstrainedPosition(); - bool old_style_is_sticky = - old_style && old_style->HasStickyConstrainedPosition(); - - if (old_style_is_sticky && !new_style_is_sticky) { - // This may get re-added to viewport constrained objects if the object - // went from sticky to fixed. - frame_view->RemoveViewportConstrainedObject( - *this, LocalFrameView::ViewportConstrainedType::kSticky); - - // Remove sticky constraints for this layer. - if (Layer()) { - if (const PaintLayer* ancestor_scroll_container_layer = - Layer()->AncestorScrollContainerLayer()) { - if (PaintLayerScrollableArea* scrollable_area = - ancestor_scroll_container_layer->GetScrollableArea()) - scrollable_area->InvalidateStickyConstraintsFor(Layer()); - } - } - } - - if (new_style_is_viewport_constained != old_style_is_viewport_constrained) { - if (new_style_is_viewport_constained && Layer()) { - frame_view->AddViewportConstrainedObject( - *this, LocalFrameView::ViewportConstrainedType::kFixed); - } else { - frame_view->RemoveViewportConstrainedObject( - *this, LocalFrameView::ViewportConstrainedType::kFixed); - } - } - } - if (old_style && old_style->BackfaceVisibility() != StyleRef().BackfaceVisibility()) { SetNeedsPaintPropertyUpdate();
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc b/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc index b1c18a6d..1985a60 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
@@ -414,6 +414,90 @@ ->scroll_container_relative_sticky_box_rect.X()); } +TEST_P(LayoutBoxModelObjectTest, StickyPositionStatusChange) { + SetBodyInnerHTML(R"HTML( + <style> + #scroller { overflow: auto; height: 200px; } + #sticky { position: sticky; top: 0; } + </style> + <div id='scroller'> + <div id='sticky'></div> + <div style='height: 500px'></div> + </div> + )HTML"); + auto* scrollable_area = + GetLayoutBoxModelObjectByElementId("scroller")->GetScrollableArea(); + auto* sticky = GetDocument().getElementById("sticky"); + auto* sticky_layer = sticky->GetLayoutBox()->Layer(); + ASSERT_TRUE(sticky_layer); + EXPECT_TRUE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); + + // Change top to auto which effectively makes the object no longer sticky + // constrained and removed from the scrollable area's sticky constraints map. + sticky->setAttribute(html_names::kStyleAttr, "top: auto"); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + EXPECT_FALSE( + sticky->GetLayoutObject()->StyleRef().HasStickyConstrainedPosition()); + ASSERT_EQ(sticky_layer, sticky->GetLayoutBox()->Layer()); + EXPECT_FALSE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); + + // Change top back to 0. |sticky| should be back to sticky constrained. + sticky->setAttribute(html_names::kStyleAttr, ""); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + EXPECT_TRUE( + sticky->GetLayoutObject()->StyleRef().HasStickyConstrainedPosition()); + ASSERT_EQ(sticky_layer, sticky->GetLayoutBox()->Layer()); + EXPECT_TRUE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); + + // Change position to relative. The sticky layer should be removed from the + // scrollable area's sticky constraints map. + sticky->setAttribute(html_names::kStyleAttr, "position: relative"); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + ASSERT_EQ(sticky_layer, sticky->GetLayoutBox()->Layer()); + EXPECT_FALSE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); + + // Change position back to sticky. + sticky->setAttribute(html_names::kStyleAttr, ""); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + ASSERT_EQ(sticky_layer, sticky->GetLayoutBox()->Layer()); + EXPECT_TRUE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); + + // Change position to static, which removes the layer. There should be no + // dangling pointer in the sticky constraints map. + sticky->setAttribute(html_names::kStyleAttr, "position: static"); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + ASSERT_FALSE(sticky->GetLayoutBox()->Layer()); + EXPECT_FALSE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); + + // Change position back to sticky. + sticky->setAttribute(html_names::kStyleAttr, ""); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + sticky_layer = sticky->GetLayoutBox()->Layer(); + EXPECT_TRUE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); + + // Remove the layout object. There should be no dangling pointer in the + // sticky constraints map. + sticky->setAttribute(html_names::kStyleAttr, "display: none"); + GetDocument().View()->UpdateLifecycleToLayoutClean( + DocumentUpdateReason::kTest); + ASSERT_FALSE(sticky->GetLayoutObject()); + EXPECT_FALSE( + scrollable_area->GetStickyConstraintsMap().Contains(sticky_layer)); +} + // Verifies that the correct sticky-box shifting ancestor is found when // computing the sticky constraints. Any such ancestor is the first sticky // element between you and your containing block (exclusive). @@ -1051,53 +1135,6 @@ target->Layer()->CompositingContainer()); } -// Tests that when a sticky object is removed from the root scroller it -// correctly clears its viewport constrained position: https://crbug.com/755307. -TEST_P(LayoutBoxModelObjectTest, StickyRemovedFromRootScrollableArea) { - SetBodyInnerHTML(R"HTML( - <style> - body { height: 5000px; } - #scroller { height: 100px; } - #sticky { position: sticky; top: 0; height: 50px; width: 50px; } - </style> - <div id='scroller'> - <div id='sticky'></div> - </div> - )HTML"); - - auto* sticky = GetLayoutBoxModelObjectByElementId("sticky"); - auto* scroller = GetLayoutBoxModelObjectByElementId("scroller"); - - // The 'scroller' starts as as a non-scroll container, so the sticky - // element's ancestor overflow layer should be the outer scroller. - EXPECT_TRUE(sticky->Layer()->AncestorScrollContainerLayer()->IsRootLayer()); - - // We need the sticky element to not be a PaintLayer child of the scroller, - // so that it is later reparented under the scroller's PaintLayer - EXPECT_FALSE(scroller->Layer()); - - // Now make the scroller into an actual scroller. This will reparent the - // sticky element to be a child of the scroller, and will set its previous - // overflow layer to nullptr. - To<Element>(scroller->GetNode()) - ->SetInlineStyleProperty(CSSPropertyID::kOverflow, "scroll"); - UpdateAllLifecyclePhasesForTest(); - - // The sticky element should no longer be viewport constrained. - EXPECT_FALSE(GetDocument().View()->HasViewportConstrainedObjects()); - - // Making the scroller have visible overflow but still have a PaintLayer - // (in this case by making it position: relative) will cause us to need to - // recompute the sticky element's ancestor overflow layer. - To<Element>(scroller->GetNode()) - ->SetInlineStyleProperty(CSSPropertyID::kPosition, "relative"); - To<Element>(scroller->GetNode()) - ->SetInlineStyleProperty(CSSPropertyID::kOverflow, "visible"); - - // Now try to scroll to the sticky element, this used to crash. - GetDocument().GetFrame()->DomWindow()->scrollTo(0, 500); -} - TEST_P(LayoutBoxModelObjectTest, BackfaceVisibilityChange) { AtomicString base_style = "width: 100px; height: 100px; background: blue; position: absolute";
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc index 5748f2b7..d409ff80 100644 --- a/third_party/blink/renderer/core/layout/scroll_anchor.cc +++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -150,11 +150,9 @@ static bool CandidateMayMoveWithScroller(const LayoutObject* candidate, const ScrollableArea* scroller) { - if (const ComputedStyle* style = candidate->Style()) { - if (style->HasViewportConstrainedPosition() || - style->HasStickyConstrainedPosition()) - return false; - } + if (candidate->IsFixedPositioned() || + candidate->StyleRef().HasStickyConstrainedPosition()) + return false; LayoutObject::AncestorSkipInfo skip_info(ScrollerLayoutBox(scroller)); candidate->Container(&skip_info);
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index 1912c1f..568beb3 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -205,9 +205,24 @@ // characters, such as '='. const String decoded = DecodeURLEscapeSequences(value_string.ToString(), DecodeURLMode::kUTF8); - window_features.impression = - dom_window->GetFrame()->GetAttributionSrcLoader()->RegisterNavigation( - dom_window->CompleteURL(decoded)); + + if (!decoded.IsEmpty()) { + window_features.impression = + dom_window->GetFrame() + ->GetAttributionSrcLoader() + ->RegisterNavigation(dom_window->CompleteURL(decoded)); + } + + // If the impression could not be set, or if the value was empty, mark + // attribution eligibility by adding an impression. + if (!window_features.impression && + CanRegisterAttributionInContext( + dom_window->GetFrame(), /*element=*/nullptr, + /*request_id=*/absl::nullopt, + AttributionSrcLoader::RegisterContext::kAttributionSrc, + /*log_issues=*/false)) { + window_features.impression = blink::Impression(); + } } }
diff --git a/third_party/blink/renderer/core/paint/cull_rect_updater.cc b/third_party/blink/renderer/core/paint/cull_rect_updater.cc index 47d6972..6e23fa4 100644 --- a/third_party/blink/renderer/core/paint/cull_rect_updater.cc +++ b/third_party/blink/renderer/core/paint/cull_rect_updater.cc
@@ -474,20 +474,14 @@ if (object.HasLayer()) { To<LayoutBoxModelObject>(object).Layer()->SetNeedsCullRectUpdate(); if (object.IsLayoutView() && - object.GetFrameView()->HasViewportConstrainedObjects()) { + object.GetFrameView()->HasFixedPositionObjects()) { // Fixed-position cull rects depend on view clip. See // ComputeFragmentCullRect(). if (const auto* clip_node = object.FirstFragment().PaintProperties()->OverflowClip()) { if (clip_node->NodeChanged() != PaintPropertyChangeType::kUnchanged) { - for (auto constrained : - *object.GetFrameView()->ViewportConstrainedObjects()) { - if (constrained->IsFixedPositioned()) { - To<LayoutBoxModelObject>(constrained.Get()) - ->Layer() - ->SetNeedsCullRectUpdate(); - } - } + for (auto fixed : *object.GetFrameView()->FixedPositionObjects()) + To<LayoutBox>(fixed.Get())->Layer()->SetNeedsCullRectUpdate(); } } }
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 56aec320..79590d8 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -290,31 +290,13 @@ if (enclosing_scroller && GetLayoutObject().StyleRef().HasStickyConstrainedPosition() && GetLayoutObject().NeedsPaintPropertyUpdate()) { - if (enclosing_scroller != previous_enclosing_scroller) { - // Old ancestor scroller should no longer have these constraints. - DCHECK(!previous_enclosing_scroller || - !previous_enclosing_scroller->GetScrollableArea() || - !previous_enclosing_scroller->GetScrollableArea() - ->GetStickyConstraintsMap() - .Contains(this)); - - // If our ancestor scroller has changed and the previous one was the - // root layer, we are no longer viewport constrained. - if (previous_enclosing_scroller && - previous_enclosing_scroller->IsRootLayer()) { - GetLayoutObject() - .View() - ->GetFrameView() - ->RemoveViewportConstrainedObject( - GetLayoutObject(), - LocalFrameView::ViewportConstrainedType::kSticky); - } - } - - if (enclosing_scroller->IsRootLayer()) { - GetLayoutObject().View()->GetFrameView()->AddViewportConstrainedObject( - GetLayoutObject(), LocalFrameView::ViewportConstrainedType::kSticky); - } + // Old ancestor scroller should no longer have these constraints. + DCHECK(enclosing_scroller == previous_enclosing_scroller || + !previous_enclosing_scroller || + !previous_enclosing_scroller->GetScrollableArea() || + !previous_enclosing_scroller->GetScrollableArea() + ->GetStickyConstraintsMap() + .Contains(this)); GetLayoutObject().UpdateStickyPositionConstraints(); // Sticky position constraints and ancestor overflow scroller affect @@ -2532,18 +2514,6 @@ } if (AncestorScrollContainerLayer()) { - // If the previous AncestorScrollContainerLayer is the root and this object - // is a sticky viewport constrained object, it is no longer known to be - // constrained by the root. - if (AncestorScrollContainerLayer()->IsRootLayer() && - GetLayoutObject().StyleRef().HasStickyConstrainedPosition()) { - if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView()) { - frame_view->RemoveViewportConstrainedObject( - GetLayoutObject(), - LocalFrameView::ViewportConstrainedType::kSticky); - } - } - if (PaintLayerScrollableArea* ancestor_scrollable_area = AncestorScrollContainerLayer()->GetScrollableArea()) { // TODO(pdr): We will need to invalidate the scroll paint property subtree
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 037806dd..466ae8e 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -4100,8 +4100,7 @@ // we can limit the following condition to IsA<LayoutView>(object_), // i.e. exclude subscrollers. auto* frame_view = object_.GetFrameView(); - // TODO(crbug.com/1310584): This should be HasFixedPositionObjects(). - if (frame_view->HasViewportConstrainedObjects() && + if (frame_view->HasFixedPositionObjects() && !object_.View()->FirstFragment().PaintProperties()->Scroll()) { frame_view->SetPaintArtifactCompositorNeedsUpdate(); } else if (!object_.IsStackingContext() &&
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 9e4bcf2..bb5622f 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1228,7 +1228,8 @@ if (is_document_element || is_in_top_layer || is_svg_stacking || StyleType() == kPseudoIdBackdrop || HasTransformRelatedProperty() || HasStackingGroupingProperty(BoxReflect()) || - HasViewportConstrainedPosition() || GetPosition() == EPosition::kSticky || + GetPosition() == EPosition::kFixed || + GetPosition() == EPosition::kSticky || HasPropertyThatCreatesStackingContext(WillChangeProperties()) || /* TODO(882625): This becomes unnecessary when will-change correctly takes into account active animations. */
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 9aef5feec..c4c8546 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2013,9 +2013,6 @@ return GetPosition() == EPosition::kRelative || GetPosition() == EPosition::kSticky; } - bool HasViewportConstrainedPosition() const { - return GetPosition() == EPosition::kFixed; - } bool HasStickyConstrainedPosition() const { return GetPosition() == EPosition::kSticky && (!Top().IsAuto() || !Left().IsAuto() || !Right().IsAuto() ||
diff --git a/third_party/blink/renderer/core/testing/attribution_reporting_automation.cc b/third_party/blink/renderer/core/testing/attribution_reporting_automation.cc new file mode 100644 index 0000000..fde7648 --- /dev/null +++ b/third_party/blink/renderer/core/testing/attribution_reporting_automation.cc
@@ -0,0 +1,56 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/testing/attribution_reporting_automation.h" + +#include <utility> + +#include "base/check.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/public/mojom/conversions/attribution_reporting_automation.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" +#include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/heap/persistent.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" + +namespace blink { + +// static +ScriptPromise AttributionReportingAutomation::resetAttributionReporting( + ScriptState* script_state, + Internals&) { + LocalDOMWindow* window = LocalDOMWindow::From(script_state); + mojo::Remote<test::mojom::blink::AttributionReportingAutomation> automation; + window->GetBrowserInterfaceBroker().GetInterface( + automation.BindNewPipeAndPassReceiver()); + DCHECK(automation.is_bound()); + + ScriptPromiseResolver* resolver = + MakeGarbageCollected<ScriptPromiseResolver>(script_state); + ScriptPromise promise = resolver->Promise(); + + test::mojom::blink::AttributionReportingAutomation* raw_automation = + automation.get(); + + raw_automation->Reset(WTF::Bind( + [](ScriptPromiseResolver* resolver, + mojo::Remote<test::mojom::blink::AttributionReportingAutomation>, + bool success) { + if (success) { + resolver->Resolve(); + } else { + resolver->Reject(); + } + }, + WrapPersistent(resolver), + // Keep `automation` alive to wait for callback. + std::move(automation))); + + return promise; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/testing/attribution_reporting_automation.h b/third_party/blink/renderer/core/testing/attribution_reporting_automation.h new file mode 100644 index 0000000..804ffce --- /dev/null +++ b/third_party/blink/renderer/core/testing/attribution_reporting_automation.h
@@ -0,0 +1,26 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ATTRIBUTION_REPORTING_AUTOMATION_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ATTRIBUTION_REPORTING_AUTOMATION_H_ + +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +namespace blink { + +class Internals; +class ScriptPromise; +class ScriptState; + +class AttributionReportingAutomation { + STATIC_ONLY(AttributionReportingAutomation); + + public: + static ScriptPromise resetAttributionReporting(ScriptState* script_state, + Internals& internals); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ATTRIBUTION_REPORTING_AUTOMATION_H_
diff --git a/third_party/blink/renderer/core/testing/attribution_reporting_automation.idl b/third_party/blink/renderer/core/testing/attribution_reporting_automation.idl new file mode 100644 index 0000000..17d49c4 --- /dev/null +++ b/third_party/blink/renderer/core/testing/attribution_reporting_automation.idl
@@ -0,0 +1,9 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + ImplementedAs=AttributionReportingAutomation +] partial interface Internals { + [CallWith=ScriptState] Promise<void> resetAttributionReporting(); +};
diff --git a/third_party/blink/renderer/platform/blob/blob_data.cc b/third_party/blink/renderer/platform/blob/blob_data.cc index 5c83345..e1e3a80 100644 --- a/third_party/blink/renderer/platform/blob/blob_data.cc +++ b/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -333,7 +333,7 @@ BlobDataHandle::BlobDataHandle(std::unique_ptr<BlobData> data, uint64_t size) : uuid_(WTF::CreateCanonicalUUIDString()), - type_(data->ContentType().IsolatedCopy()), + type_(data->ContentType()), size_(size), is_single_unknown_size_file_(data->IsSingleUnknownSizeFile()) { auto elements = data->ReleaseElements(); @@ -346,8 +346,8 @@ BlobDataHandle::BlobDataHandle(const String& uuid, const String& type, uint64_t size) - : uuid_(uuid.IsolatedCopy()), - type_(IsValidBlobType(type) ? type.IsolatedCopy() : ""), + : uuid_(uuid), + type_(IsValidBlobType(type) ? type : ""), size_(size), is_single_unknown_size_file_(false) { GetThreadSpecificRegistry()->GetBlobFromUUID( @@ -359,8 +359,8 @@ const String& type, uint64_t size, mojo::PendingRemote<mojom::blink::Blob> blob_remote) - : uuid_(uuid.IsolatedCopy()), - type_(IsValidBlobType(type) ? type.IsolatedCopy() : ""), + : uuid_(uuid), + type_(IsValidBlobType(type) ? type : ""), size_(size), is_single_unknown_size_file_(false), blob_remote_(std::move(blob_remote)) {
diff --git a/third_party/blink/renderer/platform/blob/blob_data.h b/third_party/blink/renderer/platform/blob/blob_data.h index 99d4c07..ab237cf 100644 --- a/third_party/blink/renderer/platform/blob/blob_data.h +++ b/third_party/blink/renderer/platform/blob/blob_data.h
@@ -208,8 +208,8 @@ uint64_t size, mojo::PendingRemote<mojom::blink::Blob>); - String Uuid() const { return uuid_.IsolatedCopy(); } - String GetType() const { return type_.IsolatedCopy(); } + String Uuid() const { return uuid_; } + String GetType() const { return type_; } uint64_t size() const { return size_; } bool IsSingleUnknownSizeFile() const { return is_single_unknown_size_file_; }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index b6c952e..3917be4f 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1099,7 +1099,7 @@ }, { name: "FixedElementsDontOverscroll", - status: "test", + status: "stable", }, { name: "Fledge",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index a4e2af8..d3733d1 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1811,7 +1811,6 @@ crbug.com/753671 [ Mac12-arm64 ] external/wpt/css/css-content/quotes-020.html [ Failure ] crbug.com/753671 external/wpt/css/css-content/quotes-021.html [ Failure ] crbug.com/753671 external/wpt/css/css-content/quotes-022.html [ Failure ] -crbug.com/753671 external/wpt/css/css-content/quotes-030.html [ Failure ] crbug.com/1067277 external/wpt/css/css-content/element-replacement-on-replaced-element.tentative.html [ Failure ] crbug.com/1335893 external/wpt/css/css-content/content-none-root-columns.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html b/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html index 095c37fe..2c793ea 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html +++ b/third_party/blink/web_tests/external/wpt/css/css-content/quotes-030.html
@@ -12,6 +12,9 @@ body { font: 32px Arial, Helvetica, Noto Sans, DejaVu Sans, FreeSans, sans-serif; quotes: auto; } </style> <body> -<p>Test passes if the quote marks in both lines match: +<p>Test passes if the quote marks in each pair of lines match: <p>One <q>two <q lang="ja">three <q lang="fr">four</q></q></q> <p>One “two <span lang="ja">‘three <span lang="fr">『four』</span>’</span>” + +<p>One <q>two <q lang="ja">three <q>four</q></q></q> +<p>One “two <span lang="ja">‘three 『four』’</span>”
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html b/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html index c06d85b..36608c3 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-content/reference/quotes-030-ref.html
@@ -7,6 +7,9 @@ body { font: 32px Arial, Helvetica, Noto Sans, DejaVu Sans, FreeSans, sans-serif; quotes: auto; } </style> <body> -<p>Test passes if the quote marks in both lines match: +<p>Test passes if the quote marks in each pair of lines match: <p>One “two <span lang="ja">‘three <span lang="fr">『four』</span>’</span>” <p>One “two <span lang="ja">‘three <span lang="fr">『four』</span>’</span>” + +<p>One “two <span lang="ja">‘three 『four』’</span>” +<p>One “two <span lang="ja">‘three 『four』’</span>”
diff --git a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html index 3417d15..0279fe9e 100644 --- a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html +++ b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang-expected.html
@@ -160,152 +160,152 @@ <!-- Custom quotes are inlined to make this test fail if you don't implement CSS quotes. --> <div lang="custom">ACcustomDB</div> -<q><q>default</q></q> -<q lang="af"><q>af</q></q> -<q lang="agq"><q>agq</q></q> -<q lang="ak"><q>ak</q></q> -<q lang="am"><q>am</q></q> -<q lang="ar"><q>ar</q></q> -<q lang="asa"><q>asa</q></q> -<q lang="az-Cyrl"><q>az-Cyrl</q></q> -<q lang="bas"><q>bas</q></q> -<q lang="bem"><q>bem</q></q> -<q lang="bez"><q>bez</q></q> -<q lang="bg"><q>bg</q></q> -<q lang="bm"><q>bm</q></q> -<q lang="bn"><q>bn</q></q> -<q lang="br"><q>br</q></q> -<q lang="brx"><q>brx</q></q> -<q lang="bs-Cyrl"><q>bs-Cyrl</q></q> -<q lang="ca"><q>ca</q></q> -<q lang="cgg"><q>cgg</q></q> -<q lang="chr"><q>chr</q></q> -<q lang="cs"><q>cs</q></q> -<q lang="da"><q>da</q></q> -<q lang="dav"><q>dav</q></q> -<q lang="de"><q>de</q></q> -<q lang="de-CH"><q>de-CH</q></q> -<q lang="dje"><q>dje</q></q> -<q lang="dua"><q>dua</q></q> -<q lang="dyo"><q>dyo</q></q> -<q lang="dz"><q>dz</q></q> -<q lang="ebu"><q>ebu</q></q> -<q lang="ee"><q>ee</q></q> -<q lang="el"><q>el</q></q> -<q lang="en"><q>en</q></q> -<q lang="en-GB"><q>en-GB</q></q> -<q lang="es"><q>es</q></q> -<q lang="et"><q>et</q></q> -<q lang="eu"><q>eu</q></q> -<q lang="ewo"><q>ewo</q></q> -<q lang="fa"><q>fa</q></q> -<q lang="ff"><q>ff</q></q> -<q lang="fi"><q>fi</q></q> -<q lang="fr"><q>fr</q></q> -<q lang="fr-CA"><q>fr-CA</q></q> -<q lang="fr-CH"><q>fr-CH</q></q> -<q lang="gsw"><q>gsw</q></q> -<q lang="gu"><q>gu</q></q> -<q lang="guz"><q>guz</q></q> -<q lang="ha"><q>ha</q></q> -<q lang="he"><q>he</q></q> -<q lang="hi"><q>hi</q></q> -<q lang="hr"><q>hr</q></q> -<q lang="hu"><q>hu</q></q> -<q lang="id"><q>id</q></q> -<q lang="ig"><q>ig</q></q> -<q lang="it"><q>it</q></q> -<q lang="ja"><q>ja</q></q> -<q lang="jgo"><q>jgo</q></q> -<q lang="jmc"><q>jmc</q></q> -<q lang="kab"><q>kab</q></q> -<q lang="kam"><q>kam</q></q> -<q lang="kde"><q>kde</q></q> -<q lang="kea"><q>kea</q></q> -<q lang="khq"><q>khq</q></q> -<q lang="ki"><q>ki</q></q> -<q lang="kkj"><q>kkj</q></q> -<q lang="kln"><q>kln</q></q> -<q lang="km"><q>km</q></q> -<q lang="kn"><q>kn</q></q> -<q lang="ko"><q>ko</q></q> -<q lang="ksb"><q>ksb</q></q> -<q lang="ksf"><q>ksf</q></q> -<q lang="lag"><q>lag</q></q> -<q lang="lg"><q>lg</q></q> -<q lang="ln"><q>ln</q></q> -<q lang="lo"><q>lo</q></q> -<q lang="lt"><q>lt</q></q> -<q lang="lu"><q>lu</q></q> -<q lang="luo"><q>luo</q></q> -<q lang="luy"><q>luy</q></q> -<q lang="lv"><q>lv</q></q> -<q lang="mas"><q>mas</q></q> -<q lang="mer"><q>mer</q></q> -<q lang="mfe"><q>mfe</q></q> -<q lang="mg"><q>mg</q></q> -<q lang="mgo"><q>mgo</q></q> -<q lang="mk"><q>mk</q></q> -<q lang="ml"><q>ml</q></q> -<q lang="mr"><q>mr</q></q> -<q lang="ms"><q>ms</q></q> -<q lang="mua"><q>mua</q></q> -<q lang="my"><q>my</q></q> -<q lang="naq"><q>naq</q></q> -<q lang="nb"><q>nb</q></q> -<q lang="nd"><q>nd</q></q> -<q lang="nl"><q>nl</q></q> -<q lang="nmg"><q>nmg</q></q> -<q lang="nn"><q>nn</q></q> -<q lang="nnh"><q>nnh</q></q> -<q lang="nus"><q>nus</q></q> -<q lang="nyn"><q>nyn</q></q> -<q lang="pl"><q>pl</q></q> -<q lang="pt"><q>pt</q></q> -<q lang="pt-PT"><q>pt-PT</q></q> -<q lang="rn"><q>rn</q></q> -<q lang="ro"><q>ro</q></q> -<q lang="rof"><q>rof</q></q> -<q lang="ru"><q>ru</q></q> -<q lang="rw"><q>rw</q></q> -<q lang="rwk"><q>rwk</q></q> -<q lang="saq"><q>saq</q></q> -<q lang="sbp"><q>sbp</q></q> -<q lang="seh"><q>seh</q></q> -<q lang="ses"><q>ses</q></q> -<q lang="sg"><q>sg</q></q> -<q lang="shi"><q>shi</q></q> -<q lang="shi-Tfng"><q>shi-Tfng</q></q> -<q lang="si"><q>si</q></q> -<q lang="sk"><q>sk</q></q> -<q lang="sl"><q>sl</q></q> -<q lang="sn"><q>sn</q></q> -<q lang="so"><q>so</q></q> -<q lang="sq"><q>sq</q></q> -<q lang="sr"><q>sr</q></q> -<q lang="sr-Latn"><q>sr-Latn</q></q> -<q lang="sv"><q>sv</q></q> -<q lang="sw"><q>sw</q></q> -<q lang="swc"><q>swc</q></q> -<q lang="ta"><q>ta</q></q> -<q lang="te"><q>te</q></q> -<q lang="teo"><q>teo</q></q> -<q lang="th"><q>th</q></q> -<q lang="ti-ER"><q>ti-ER</q></q> -<q lang="to"><q>to</q></q> -<q lang="tr"><q>tr</q></q> -<q lang="twq"><q>twq</q></q> -<q lang="tzm"><q>tzm</q></q> -<q lang="uk"><q>uk</q></q> -<q lang="ur"><q>ur</q></q> -<q lang="vai"><q>vai</q></q> -<q lang="vai-Latn"><q>vai-Latn</q></q> -<q lang="vi"><q>vi</q></q> -<q lang="vun"><q>vun</q></q> -<q lang="xh"><q>xh</q></q> -<q lang="xog"><q>xog</q></q> -<q lang="yav"><q>yav</q></q> -<q lang="yo"><q>yo</q></q> -<q lang="zh"><q>zh</q></q> -<q lang="zh-Hant"><q>zh-Hant</q></q> -<q lang="zu"><q>zu</q></q> +<div><q><q>default</q></q></div> +<div lang="af"><q><q>af</q></q></div> +<div lang="agq"><q><q>agq</q></q></div> +<div lang="ak"><q><q>ak</q></q></div> +<div lang="am"><q><q>am</q></q></div> +<div lang="ar"><q><q>ar</q></q></div> +<div lang="asa"><q><q>asa</q></q></div> +<div lang="az-Cyrl"><q><q>az-Cyrl</q></q></div> +<div lang="bas"><q><q>bas</q></q></div> +<div lang="bem"><q><q>bem</q></q></div> +<div lang="bez"><q><q>bez</q></q></div> +<div lang="bg"><q><q>bg</q></q></div> +<div lang="bm"><q><q>bm</q></q></div> +<div lang="bn"><q><q>bn</q></q></div> +<div lang="br"><q><q>br</q></q></div> +<div lang="brx"><q><q>brx</q></q></div> +<div lang="bs-Cyrl"><q><q>bs-Cyrl</q></q></div> +<div lang="ca"><q><q>ca</q></q></div> +<div lang="cgg"><q><q>cgg</q></q></div> +<div lang="chr"><q><q>chr</q></q></div> +<div lang="cs"><q><q>cs</q></q></div> +<div lang="da"><q><q>da</q></q></div> +<div lang="dav"><q><q>dav</q></q></div> +<div lang="de"><q><q>de</q></q></div> +<div lang="de-CH"><q><q>de-CH</q></q></div> +<div lang="dje"><q><q>dje</q></q></div> +<div lang="dua"><q><q>dua</q></q></div> +<div lang="dyo"><q><q>dyo</q></q></div> +<div lang="dz"><q><q>dz</q></q></div> +<div lang="ebu"><q><q>ebu</q></q></div> +<div lang="ee"><q><q>ee</q></q></div> +<div lang="el"><q><q>el</q></q></div> +<div lang="en"><q><q>en</q></q></div> +<div lang="en-GB"><q><q>en-GB</q></q></div> +<div lang="es"><q><q>es</q></q></div> +<div lang="et"><q><q>et</q></q></div> +<div lang="eu"><q><q>eu</q></q></div> +<div lang="ewo"><q><q>ewo</q></q></div> +<div lang="fa"><q><q>fa</q></q></div> +<div lang="ff"><q><q>ff</q></q></div> +<div lang="fi"><q><q>fi</q></q></div> +<div lang="fr"><q><q>fr</q></q></div> +<div lang="fr-CA"><q><q>fr-CA</q></q></div> +<div lang="fr-CH"><q><q>fr-CH</q></q></div> +<div lang="gsw"><q><q>gsw</q></q></div> +<div lang="gu"><q><q>gu</q></q></div> +<div lang="guz"><q><q>guz</q></q></div> +<div lang="ha"><q><q>ha</q></q></div> +<div lang="he"><q><q>he</q></q></div> +<div lang="hi"><q><q>hi</q></q></div> +<div lang="hr"><q><q>hr</q></q></div> +<div lang="hu"><q><q>hu</q></q></div> +<div lang="id"><q><q>id</q></q></div> +<div lang="ig"><q><q>ig</q></q></div> +<div lang="it"><q><q>it</q></q></div> +<div lang="ja"><q><q>ja</q></q></div> +<div lang="jgo"><q><q>jgo</q></q></div> +<div lang="jmc"><q><q>jmc</q></q></div> +<div lang="kab"><q><q>kab</q></q></div> +<div lang="kam"><q><q>kam</q></q></div> +<div lang="kde"><q><q>kde</q></q></div> +<div lang="kea"><q><q>kea</q></q></div> +<div lang="khq"><q><q>khq</q></q></div> +<div lang="ki"><q><q>ki</q></q></div> +<div lang="kkj"><q><q>kkj</q></q></div> +<div lang="kln"><q><q>kln</q></q></div> +<div lang="km"><q><q>km</q></q></div> +<div lang="kn"><q><q>kn</q></q></div> +<div lang="ko"><q><q>ko</q></q></div> +<div lang="ksb"><q><q>ksb</q></q></div> +<div lang="ksf"><q><q>ksf</q></q></div> +<div lang="lag"><q><q>lag</q></q></div> +<div lang="lg"><q><q>lg</q></q></div> +<div lang="ln"><q><q>ln</q></q></div> +<div lang="lo"><q><q>lo</q></q></div> +<div lang="lt"><q><q>lt</q></q></div> +<div lang="lu"><q><q>lu</q></q></div> +<div lang="luo"><q><q>luo</q></q></div> +<div lang="luy"><q><q>luy</q></q></div> +<div lang="lv"><q><q>lv</q></q></div> +<div lang="mas"><q><q>mas</q></q></div> +<div lang="mer"><q><q>mer</q></q></div> +<div lang="mfe"><q><q>mfe</q></q></div> +<div lang="mg"><q><q>mg</q></q></div> +<div lang="mgo"><q><q>mgo</q></q></div> +<div lang="mk"><q><q>mk</q></q></div> +<div lang="ml"><q><q>ml</q></q></div> +<div lang="mr"><q><q>mr</q></q></div> +<div lang="ms"><q><q>ms</q></q></div> +<div lang="mua"><q><q>mua</q></q></div> +<div lang="my"><q><q>my</q></q></div> +<div lang="naq"><q><q>naq</q></q></div> +<div lang="nb"><q><q>nb</q></q></div> +<div lang="nd"><q><q>nd</q></q></div> +<div lang="nl"><q><q>nl</q></q></div> +<div lang="nmg"><q><q>nmg</q></q></div> +<div lang="nn"><q><q>nn</q></q></div> +<div lang="nnh"><q><q>nnh</q></q></div> +<div lang="nus"><q><q>nus</q></q></div> +<div lang="nyn"><q><q>nyn</q></q></div> +<div lang="pl"><q><q>pl</q></q></div> +<div lang="pt"><q><q>pt</q></q></div> +<div lang="pt-PT"><q><q>pt-PT</q></q></div> +<div lang="rn"><q><q>rn</q></q></div> +<div lang="ro"><q><q>ro</q></q></div> +<div lang="rof"><q><q>rof</q></q></div> +<div lang="ru"><q><q>ru</q></q></div> +<div lang="rw"><q><q>rw</q></q></div> +<div lang="rwk"><q><q>rwk</q></q></div> +<div lang="saq"><q><q>saq</q></q></div> +<div lang="sbp"><q><q>sbp</q></q></div> +<div lang="seh"><q><q>seh</q></q></div> +<div lang="ses"><q><q>ses</q></q></div> +<div lang="sg"><q><q>sg</q></q></div> +<div lang="shi"><q><q>shi</q></q></div> +<div lang="shi-Tfng"><q><q>shi-Tfng</q></q></div> +<div lang="si"><q><q>si</q></q></div> +<div lang="sk"><q><q>sk</q></q></div> +<div lang="sl"><q><q>sl</q></q></div> +<div lang="sn"><q><q>sn</q></q></div> +<div lang="so"><q><q>so</q></q></div> +<div lang="sq"><q><q>sq</q></q></div> +<div lang="sr"><q><q>sr</q></q></div> +<div lang="sr-Latn"><q><q>sr-Latn</q></q></div> +<div lang="sv"><q><q>sv</q></q></div> +<div lang="sw"><q><q>sw</q></q></div> +<div lang="swc"><q><q>swc</q></q></div> +<div lang="ta"><q><q>ta</q></q></div> +<div lang="te"><q><q>te</q></q></div> +<div lang="teo"><q><q>teo</q></q></div> +<div lang="th"><q><q>th</q></q></div> +<div lang="ti-ER"><q><q>ti-ER</q></q></div> +<div lang="to"><q><q>to</q></q></div> +<div lang="tr"><q><q>tr</q></q></div> +<div lang="twq"><q><q>twq</q></q></div> +<div lang="tzm"><q><q>tzm</q></q></div> +<div lang="uk"><q><q>uk</q></q></div> +<div lang="ur"><q><q>ur</q></q></div> +<div lang="vai"><q><q>vai</q></q></div> +<div lang="vai-Latn"><q><q>vai-Latn</q></q></div> +<div lang="vi"><q><q>vi</q></q></div> +<div lang="vun"><q><q>vun</q></q></div> +<div lang="xh"><q><q>xh</q></q></div> +<div lang="xog"><q><q>xog</q></q></div> +<div lang="yav"><q><q>yav</q></q></div> +<div lang="yo"><q><q>yo</q></q></div> +<div lang="zh"><q><q>zh</q></q></div> +<div lang="zh-Hant"><q><q>zh-Hant</q></q></div> +<div lang="zu"><q><q>zu</q></q></div>
diff --git a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html index 4806c8e9..c9277942 100644 --- a/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html +++ b/third_party/blink/web_tests/fast/css-generated-content/quotes-lang.html
@@ -12,152 +12,152 @@ </p> <div lang="custom"><q><q>custom</q></q></div> -<q><q>default</q></q> -<q lang="af"><q>af</q></q> -<q lang="agq"><q>agq</q></q> -<q lang="ak"><q>ak</q></q> -<q lang="am"><q>am</q></q> -<q lang="ar"><q>ar</q></q> -<q lang="asa"><q>asa</q></q> -<q lang="az-Cyrl"><q>az-Cyrl</q></q> -<q lang="bas"><q>bas</q></q> -<q lang="bem"><q>bem</q></q> -<q lang="bez"><q>bez</q></q> -<q lang="bg"><q>bg</q></q> -<q lang="bm"><q>bm</q></q> -<q lang="bn"><q>bn</q></q> -<q lang="br"><q>br</q></q> -<q lang="brx"><q>brx</q></q> -<q lang="bs-Cyrl"><q>bs-Cyrl</q></q> -<q lang="ca"><q>ca</q></q> -<q lang="cgg"><q>cgg</q></q> -<q lang="chr"><q>chr</q></q> -<q lang="cs"><q>cs</q></q> -<q lang="da"><q>da</q></q> -<q lang="dav"><q>dav</q></q> -<q lang="de"><q>de</q></q> -<q lang="de-CH"><q>de-CH</q></q> -<q lang="dje"><q>dje</q></q> -<q lang="dua"><q>dua</q></q> -<q lang="dyo"><q>dyo</q></q> -<q lang="dz"><q>dz</q></q> -<q lang="ebu"><q>ebu</q></q> -<q lang="ee"><q>ee</q></q> -<q lang="el"><q>el</q></q> -<q lang="en"><q>en</q></q> -<q lang="en-GB"><q>en-GB</q></q> -<q lang="es"><q>es</q></q> -<q lang="et"><q>et</q></q> -<q lang="eu"><q>eu</q></q> -<q lang="ewo"><q>ewo</q></q> -<q lang="fa"><q>fa</q></q> -<q lang="ff"><q>ff</q></q> -<q lang="fi"><q>fi</q></q> -<q lang="fr"><q>fr</q></q> -<q lang="fr-CA"><q>fr-CA</q></q> -<q lang="fr-CH"><q>fr-CH</q></q> -<q lang="gsw"><q>gsw</q></q> -<q lang="gu"><q>gu</q></q> -<q lang="guz"><q>guz</q></q> -<q lang="ha"><q>ha</q></q> -<q lang="he"><q>he</q></q> -<q lang="hi"><q>hi</q></q> -<q lang="hr"><q>hr</q></q> -<q lang="hu"><q>hu</q></q> -<q lang="id"><q>id</q></q> -<q lang="ig"><q>ig</q></q> -<q lang="it"><q>it</q></q> -<q lang="ja"><q>ja</q></q> -<q lang="jgo"><q>jgo</q></q> -<q lang="jmc"><q>jmc</q></q> -<q lang="kab"><q>kab</q></q> -<q lang="kam"><q>kam</q></q> -<q lang="kde"><q>kde</q></q> -<q lang="kea"><q>kea</q></q> -<q lang="khq"><q>khq</q></q> -<q lang="ki"><q>ki</q></q> -<q lang="kkj"><q>kkj</q></q> -<q lang="kln"><q>kln</q></q> -<q lang="km"><q>km</q></q> -<q lang="kn"><q>kn</q></q> -<q lang="ko"><q>ko</q></q> -<q lang="ksb"><q>ksb</q></q> -<q lang="ksf"><q>ksf</q></q> -<q lang="lag"><q>lag</q></q> -<q lang="lg"><q>lg</q></q> -<q lang="ln"><q>ln</q></q> -<q lang="lo"><q>lo</q></q> -<q lang="lt"><q>lt</q></q> -<q lang="lu"><q>lu</q></q> -<q lang="luo"><q>luo</q></q> -<q lang="luy"><q>luy</q></q> -<q lang="lv"><q>lv</q></q> -<q lang="mas"><q>mas</q></q> -<q lang="mer"><q>mer</q></q> -<q lang="mfe"><q>mfe</q></q> -<q lang="mg"><q>mg</q></q> -<q lang="mgo"><q>mgo</q></q> -<q lang="mk"><q>mk</q></q> -<q lang="ml"><q>ml</q></q> -<q lang="mr"><q>mr</q></q> -<q lang="ms"><q>ms</q></q> -<q lang="mua"><q>mua</q></q> -<q lang="my"><q>my</q></q> -<q lang="naq"><q>naq</q></q> -<q lang="nb"><q>nb</q></q> -<q lang="nd"><q>nd</q></q> -<q lang="nl"><q>nl</q></q> -<q lang="nmg"><q>nmg</q></q> -<q lang="nn"><q>nn</q></q> -<q lang="nnh"><q>nnh</q></q> -<q lang="nus"><q>nus</q></q> -<q lang="nyn"><q>nyn</q></q> -<q lang="pl"><q>pl</q></q> -<q lang="pt"><q>pt</q></q> -<q lang="pt-PT"><q>pt-PT</q></q> -<q lang="rn"><q>rn</q></q> -<q lang="ro"><q>ro</q></q> -<q lang="rof"><q>rof</q></q> -<q lang="ru"><q>ru</q></q> -<q lang="rw"><q>rw</q></q> -<q lang="rwk"><q>rwk</q></q> -<q lang="saq"><q>saq</q></q> -<q lang="sbp"><q>sbp</q></q> -<q lang="seh"><q>seh</q></q> -<q lang="ses"><q>ses</q></q> -<q lang="sg"><q>sg</q></q> -<q lang="shi"><q>shi</q></q> -<q lang="shi-Tfng"><q>shi-Tfng</q></q> -<q lang="si"><q>si</q></q> -<q lang="sk"><q>sk</q></q> -<q lang="sl"><q>sl</q></q> -<q lang="sn"><q>sn</q></q> -<q lang="so"><q>so</q></q> -<q lang="sq"><q>sq</q></q> -<q lang="sr"><q>sr</q></q> -<q lang="sr-Latn"><q>sr-Latn</q></q> -<q lang="sv"><q>sv</q></q> -<q lang="sw"><q>sw</q></q> -<q lang="swc"><q>swc</q></q> -<q lang="ta"><q>ta</q></q> -<q lang="te"><q>te</q></q> -<q lang="teo"><q>teo</q></q> -<q lang="th"><q>th</q></q> -<q lang="ti-ER"><q>ti-ER</q></q> -<q lang="to"><q>to</q></q> -<q lang="tr"><q>tr</q></q> -<q lang="twq"><q>twq</q></q> -<q lang="tzm"><q>tzm</q></q> -<q lang="uk"><q>uk</q></q> -<q lang="ur"><q>ur</q></q> -<q lang="vai"><q>vai</q></q> -<q lang="vai-Latn"><q>vai-Latn</q></q> -<q lang="vi"><q>vi</q></q> -<q lang="vun"><q>vun</q></q> -<q lang="xh"><q>xh</q></q> -<q lang="xog"><q>xog</q></q> -<q lang="yav"><q>yav</q></q> -<q lang="yo"><q>yo</q></q> -<q lang="zh"><q>zh</q></q> -<q lang="zh-Hant"><q>zh-Hant</q></q> -<q lang="zu"><q>zu</q></q> +<div><q><q>default</q></q></div> +<div lang="af"><q><q>af</q></q></div> +<div lang="agq"><q><q>agq</q></q></div> +<div lang="ak"><q><q>ak</q></q></div> +<div lang="am"><q><q>am</q></q></div> +<div lang="ar"><q><q>ar</q></q></div> +<div lang="asa"><q><q>asa</q></q></div> +<div lang="az-Cyrl"><q><q>az-Cyrl</q></q></div> +<div lang="bas"><q><q>bas</q></q></div> +<div lang="bem"><q><q>bem</q></q></div> +<div lang="bez"><q><q>bez</q></q></div> +<div lang="bg"><q><q>bg</q></q></div> +<div lang="bm"><q><q>bm</q></q></div> +<div lang="bn"><q><q>bn</q></q></div> +<div lang="br"><q><q>br</q></q></div> +<div lang="brx"><q><q>brx</q></q></div> +<div lang="bs-Cyrl"><q><q>bs-Cyrl</q></q></div> +<div lang="ca"><q><q>ca</q></q></div> +<div lang="cgg"><q><q>cgg</q></q></div> +<div lang="chr"><q><q>chr</q></q></div> +<div lang="cs"><q><q>cs</q></q></div> +<div lang="da"><q><q>da</q></q></div> +<div lang="dav"><q><q>dav</q></q></div> +<div lang="de"><q><q>de</q></q></div> +<div lang="de-CH"><q><q>de-CH</q></q></div> +<div lang="dje"><q><q>dje</q></q></div> +<div lang="dua"><q><q>dua</q></q></div> +<div lang="dyo"><q><q>dyo</q></q></div> +<div lang="dz"><q><q>dz</q></q></div> +<div lang="ebu"><q><q>ebu</q></q></div> +<div lang="ee"><q><q>ee</q></q></div> +<div lang="el"><q><q>el</q></q></div> +<div lang="en"><q><q>en</q></q></div> +<div lang="en-GB"><q><q>en-GB</q></q></div> +<div lang="es"><q><q>es</q></q></div> +<div lang="et"><q><q>et</q></q></div> +<div lang="eu"><q><q>eu</q></q></div> +<div lang="ewo"><q><q>ewo</q></q></div> +<div lang="fa"><q><q>fa</q></q></div> +<div lang="ff"><q><q>ff</q></q></div> +<div lang="fi"><q><q>fi</q></q></div> +<div lang="fr"><q><q>fr</q></q></div> +<div lang="fr-CA"><q><q>fr-CA</q></q></div> +<div lang="fr-CH"><q><q>fr-CH</q></q></div> +<div lang="gsw"><q><q>gsw</q></q></div> +<div lang="gu"><q><q>gu</q></q></div> +<div lang="guz"><q><q>guz</q></q></div> +<div lang="ha"><q><q>ha</q></q></div> +<div lang="he"><q><q>he</q></q></div> +<div lang="hi"><q><q>hi</q></q></div> +<div lang="hr"><q><q>hr</q></q></div> +<div lang="hu"><q><q>hu</q></q></div> +<div lang="id"><q><q>id</q></q></div> +<div lang="ig"><q><q>ig</q></q></div> +<div lang="it"><q><q>it</q></q></div> +<div lang="ja"><q><q>ja</q></q></div> +<div lang="jgo"><q><q>jgo</q></q></div> +<div lang="jmc"><q><q>jmc</q></q></div> +<div lang="kab"><q><q>kab</q></q></div> +<div lang="kam"><q><q>kam</q></q></div> +<div lang="kde"><q><q>kde</q></q></div> +<div lang="kea"><q><q>kea</q></q></div> +<div lang="khq"><q><q>khq</q></q></div> +<div lang="ki"><q><q>ki</q></q></div> +<div lang="kkj"><q><q>kkj</q></q></div> +<div lang="kln"><q><q>kln</q></q></div> +<div lang="km"><q><q>km</q></q></div> +<div lang="kn"><q><q>kn</q></q></div> +<div lang="ko"><q><q>ko</q></q></div> +<div lang="ksb"><q><q>ksb</q></q></div> +<div lang="ksf"><q><q>ksf</q></q></div> +<div lang="lag"><q><q>lag</q></q></div> +<div lang="lg"><q><q>lg</q></q></div> +<div lang="ln"><q><q>ln</q></q></div> +<div lang="lo"><q><q>lo</q></q></div> +<div lang="lt"><q><q>lt</q></q></div> +<div lang="lu"><q><q>lu</q></q></div> +<div lang="luo"><q><q>luo</q></q></div> +<div lang="luy"><q><q>luy</q></q></div> +<div lang="lv"><q><q>lv</q></q></div> +<div lang="mas"><q><q>mas</q></q></div> +<div lang="mer"><q><q>mer</q></q></div> +<div lang="mfe"><q><q>mfe</q></q></div> +<div lang="mg"><q><q>mg</q></q></div> +<div lang="mgo"><q><q>mgo</q></q></div> +<div lang="mk"><q><q>mk</q></q></div> +<div lang="ml"><q><q>ml</q></q></div> +<div lang="mr"><q><q>mr</q></q></div> +<div lang="ms"><q><q>ms</q></q></div> +<div lang="mua"><q><q>mua</q></q></div> +<div lang="my"><q><q>my</q></q></div> +<div lang="naq"><q><q>naq</q></q></div> +<div lang="nb"><q><q>nb</q></q></div> +<div lang="nd"><q><q>nd</q></q></div> +<div lang="nl"><q><q>nl</q></q></div> +<div lang="nmg"><q><q>nmg</q></q></div> +<div lang="nn"><q><q>nn</q></q></div> +<div lang="nnh"><q><q>nnh</q></q></div> +<div lang="nus"><q><q>nus</q></q></div> +<div lang="nyn"><q><q>nyn</q></q></div> +<div lang="pl"><q><q>pl</q></q></div> +<div lang="pt"><q><q>pt</q></q></div> +<div lang="pt-PT"><q><q>pt-PT</q></q></div> +<div lang="rn"><q><q>rn</q></q></div> +<div lang="ro"><q><q>ro</q></q></div> +<div lang="rof"><q><q>rof</q></q></div> +<div lang="ru"><q><q>ru</q></q></div> +<div lang="rw"><q><q>rw</q></q></div> +<div lang="rwk"><q><q>rwk</q></q></div> +<div lang="saq"><q><q>saq</q></q></div> +<div lang="sbp"><q><q>sbp</q></q></div> +<div lang="seh"><q><q>seh</q></q></div> +<div lang="ses"><q><q>ses</q></q></div> +<div lang="sg"><q><q>sg</q></q></div> +<div lang="shi"><q><q>shi</q></q></div> +<div lang="shi-Tfng"><q><q>shi-Tfng</q></q></div> +<div lang="si"><q><q>si</q></q></div> +<div lang="sk"><q><q>sk</q></q></div> +<div lang="sl"><q><q>sl</q></q></div> +<div lang="sn"><q><q>sn</q></q></div> +<div lang="so"><q><q>so</q></q></div> +<div lang="sq"><q><q>sq</q></q></div> +<div lang="sr"><q><q>sr</q></q></div> +<div lang="sr-Latn"><q><q>sr-Latn</q></q></div> +<div lang="sv"><q><q>sv</q></q></div> +<div lang="sw"><q><q>sw</q></q></div> +<div lang="swc"><q><q>swc</q></q></div> +<div lang="ta"><q><q>ta</q></q></div> +<div lang="te"><q><q>te</q></q></div> +<div lang="teo"><q><q>teo</q></q></div> +<div lang="th"><q><q>th</q></q></div> +<div lang="ti-ER"><q><q>ti-ER</q></q></div> +<div lang="to"><q><q>to</q></q></div> +<div lang="tr"><q><q>tr</q></q></div> +<div lang="twq"><q><q>twq</q></q></div> +<div lang="tzm"><q><q>tzm</q></q></div> +<div lang="uk"><q><q>uk</q></q></div> +<div lang="ur"><q><q>ur</q></q></div> +<div lang="vai"><q><q>vai</q></q></div> +<div lang="vai-Latn"><q><q>vai-Latn</q></q></div> +<div lang="vi"><q><q>vi</q></q></div> +<div lang="vun"><q><q>vun</q></q></div> +<div lang="xh"><q><q>xh</q></q></div> +<div lang="xog"><q><q>xog</q></q></div> +<div lang="yav"><q><q>yav</q></q></div> +<div lang="yo"><q><q>yo</q></q></div> +<div lang="zh"><q><q>zh</q></q></div> +<div lang="zh-Hant"><q><q>zh-Hant</q></q></div> +<div lang="zu"><q><q>zu</q></q></div>
diff --git a/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-name.html b/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-name.html index 3a1971b..92617ebf 100644 --- a/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-name.html +++ b/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-name.html
@@ -9,7 +9,7 @@ <input id="filetype" type="file"> <script type="module"> -import '/wpt_internal/forms/resources/mock-file-chooser.js'; +import '/resources/mock-file-chooser.js'; async_test((t) => { testRunner.waitUntilDone();
diff --git a/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-with-axpress.html b/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-with-axpress.html index 91dd77d..8c29f4e 100644 --- a/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-with-axpress.html +++ b/third_party/blink/web_tests/http/tests/accessibility/file-upload-button-with-axpress.html
@@ -10,7 +10,7 @@ <div id="console"></div> <script type="module"> -import {mockFileChooserFactory} from '/wpt_internal/forms/resources/mock-file-chooser.js'; +import {mockFileChooserFactory} from '/resources/mock-file-chooser.js'; promise_test(async () => { const inputFile = document.getElementById('filetype');
diff --git a/third_party/blink/web_tests/http/tests/custom-elements/form-submission-file.html b/third_party/blink/web_tests/http/tests/custom-elements/form-submission-file.html index cd52523b..1a7ed377 100644 --- a/third_party/blink/web_tests/http/tests/custom-elements/form-submission-file.html +++ b/third_party/blink/web_tests/http/tests/custom-elements/form-submission-file.html
@@ -5,7 +5,7 @@ <div id="container"></div> <input type=file multiple> <script type="module"> -import {mockFileChooserFactory} from '/wpt_internal/forms/resources/mock-file-chooser.js'; +import {mockFileChooserFactory} from '/resources/mock-file-chooser.js'; class MyControl extends HTMLElement { static get formAssociated() { return true; } @@ -53,7 +53,7 @@ } promise_test(async t => { - $('container').innerHTML = '<form action="../external/wpt/common/blank.html" target="if1">' + + $('container').innerHTML = '<form action="/resources/blank.html" target="if1">' + '<input name=name-pd1 value="value-pd1">' + '<my-control name=ce1></my-control>' + '</form>' + @@ -66,7 +66,7 @@ }, 'Single value - A file value'); promise_test(async t => { - $('container').innerHTML = '<form action="../external/wpt/common/blank.html" target="if1">' + + $('container').innerHTML = '<form action="/resources/blank.html" target="if1">' + '<my-control name=ce1></my-control>' + '</form>' + '<iframe name="if1"></iframe>';
diff --git a/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js b/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js index 222d849..25dda85 100644 --- a/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js +++ b/third_party/blink/web_tests/http/tests/devtools/device-orientation-success.js
@@ -15,7 +15,7 @@ async function setUpDeviceOrientation() { const {sensorMocks, setMockSensorDataForType} = - await import('/wpt_internal/orientation-event/resources/sensor-helpers.js'); + await import('/resources/sensor-helpers.js'); sensorProvider = sensorMocks(); let mockDataPromise = setMockSensorDataForType( sensorProvider,
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only.js index df723b8..709d441 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only.js
@@ -15,9 +15,9 @@ return lineNumberDiff || a.params.issue.details.contentSecurityPolicyIssueDetails.sourceCodeLocation.columnNumber - b.params.issue.details.contentSecurityPolicyIssueDetails.sourceCodeLocation.columnNumber; }); for (const issue of issues) { - testRunner.log(issue.params, "Inspector issue: ", ["violatingNodeId"]); + testRunner.log(issue.params, "Inspector issue: ", ["violatingNodeId", "scriptId"]); } testRunner.completeTest(); } }); - }) \ No newline at end of file + })
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-wait-for-debugger-2-sessions.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-wait-for-debugger-2-sessions.js new file mode 100644 index 0000000..49e541b --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-wait-for-debugger-2-sessions.js
@@ -0,0 +1,19 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank( + `Tests that setAutoAttach honors updated waitForDebuggerOnStart.`); + + await dp.Target.setAutoAttach( + {autoAttach: true, waitForDebuggerOnStart: false, flatten: true}); + + const dp2 = (await page.createSession()).protocol; + await dp2.Target.setAutoAttach( + {autoAttach: true, waitForDebuggerOnStart: true, flatten: true}); + + session.navigate(testRunner.url('../resources/site_per_process_main.html')); + const attached = await Promise.all([ + dp.Target.onceAttachedToTarget(), + dp2.Target.onceAttachedToTarget() + ]); + testRunner.log(attached); + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/resources/blank.html b/third_party/blink/web_tests/http/tests/resources/blank.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/resources/blank.html
diff --git a/third_party/blink/web_tests/http/tests/resources/mock-file-chooser.js b/third_party/blink/web_tests/http/tests/resources/mock-file-chooser.js new file mode 100644 index 0000000..60b9325 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/resources/mock-file-chooser.js
@@ -0,0 +1,95 @@ +import {FileChooser, FileChooserParams_Mode, FileChooserReceiver} from '/gen/third_party/blink/public/mojom/choosers/file_chooser.mojom.m.js'; + +class MockFileChooserFactory extends EventTarget { + constructor() { + super(); + this.paths_ = []; + this.baseDir_ = undefined; + this.receiver_ = undefined; + this.interceptor_ = + new MojoInterfaceInterceptor(FileChooser.$interfaceName); + this.interceptor_.oninterfacerequest = e => { + this.receiver_ = new FileChooserReceiver( + new MockFileChooser(this, this.paths_, this.baseDir_)); + this.receiver_.$.bindHandle(e.handle); + this.paths_ = []; + }; + this.interceptor_.start(); + } + + setPathsToBeChosen(paths, opt_baseDir) { + internals.disableReferencedFilePathsVerification(); + // TODO(tkent): Need to ensure each of paths is an absolute path. + this.paths_ = paths; + this.baseDir_ = opt_baseDir; + } +} + +function modeToString(mode) { + let Mode = FileChooserParams_Mode; + switch (mode) { + case Mode.kOpen: + return 'kOpen'; + case Mode.kOpenMultiple: + return 'kOpenMultiple'; + case Mode.kUploadFolder: + return 'kUploadFolder'; + case Mode.kSave: + return 'kSave'; + default: + return `Unknown ${mode}`; + } +} + +class MockFileChooser { + constructor(factory, paths, baseDir) { + this.factory_ = factory; + this.paths_ = paths; + this.baseDir_ = baseDir; + } + + openFileChooser(params) { + this.params_ = params; + + this.factory_.dispatchEvent( + new CustomEvent('open', {detail: modeToString(params.mode)})); + return new Promise((resolve, reject) => { + setTimeout(() => this.chooseFiles_(resolve), 1); + }); + } + + enumerateChosenDirectory(directoryPath) { + console.log('MockFileChooserFactory::EnumerateChosenDirectory() is not implemented.'); + } + + chooseFiles_(resolve) { + const file_info_list = []; + for (const path of this.paths_) { + const nativeFile = {filePath: toFilePath(path), displayName: {data: []}}; + file_info_list.push({nativeFile}); + } + const basePath = this.baseDir_ || ''; + resolve({result: {files: file_info_list, + baseDirectory: toFilePath(basePath)}}); + } +} + +function toFilePath(path) { + if (!navigator.platform.startsWith('Win')) { + // We assume `path` is absolute, and it is therefore fine as-is on + // non-Windows systems. + return {path} + } + + // On Windows, we rewrite / to \ and return as an array of character codes, + // since the path's mojom representation on Windows is an array<uint16> + // instead of a string. + const winPath = path.replace(/\//g, '\\'); + const string16Path = []; + for (let i = 0; i < winPath.length; ++i) { + string16Path.push(winPath.charCodeAt(i)); + } + return {path: string16Path}; +} + +export const mockFileChooserFactory = new MockFileChooserFactory();
diff --git a/third_party/blink/web_tests/http/tests/resources/sensor-helpers.js b/third_party/blink/web_tests/http/tests/resources/sensor-helpers.js new file mode 100644 index 0000000..a2a033bb --- /dev/null +++ b/third_party/blink/web_tests/http/tests/resources/sensor-helpers.js
@@ -0,0 +1,531 @@ +import {ReportingMode, Sensor, SensorClientRemote, SensorReceiver, SensorRemote, SensorType} from '/gen/services/device/public/mojom/sensor.mojom.m.js'; +import {SensorCreationResult, SensorInitParams_READ_BUFFER_SIZE_FOR_TESTS, SensorProvider, SensorProviderReceiver} from '/gen/services/device/public/mojom/sensor_provider.mojom.m.js'; + +// Default sensor frequency in default configurations. +const DEFAULT_FREQUENCY = 5; + +// A "sliding window" that iterates over |data| and returns one item at a +// time, advancing and wrapping around as needed. |data| must be an array of +// arrays. +class RingBuffer { + constructor(data) { + this.bufferPosition_ = 0; + // Validate |data|'s format and deep-copy every element. + this.data_ = Array.from(data, element => { + if (!Array.isArray(element)) { + throw new TypeError('Every |data| element must be an array.'); + } + return Array.from(element); + }) + } + + next() { + const value = this.data_[this.bufferPosition_]; + this.bufferPosition_ = (this.bufferPosition_ + 1) % this.data_.length; + return { done: false, value: value }; + } + + [Symbol.iterator]() { + return this; + } +} + +export function sensorMocks() { + // Class that mocks Sensor interface defined in sensor.mojom + class MockSensor { + constructor(sensorRequest, buffer, reportingMode) { + this.client_ = null; + this.startShouldFail_ = false; + this.notifyOnReadingChange_ = true; + this.reportingMode_ = reportingMode; + this.sensorReadingTimerId_ = null; + this.readingData_ = null; + this.suspendCalled_ = null; + this.resumeCalled_ = null; + this.addConfigurationCalled_ = null; + this.removeConfigurationCalled_ = null; + this.requestedFrequencies_ = []; + this.buffer_ = buffer; + this.resetBuffer(); + this.receiver_ = new SensorReceiver(this); + this.receiver_.$.bindHandle(sensorRequest.handle); + } + + // device.mojom.Sensor implementation + // Mojo functions that return a value must be async and return an object + // whose keys match the names declared in Mojo. + + // GetDefaultConfiguration() => (SensorConfiguration configuration) + // Returns default configuration. + async getDefaultConfiguration() { + return { frequency: DEFAULT_FREQUENCY }; + } + + // AddConfiguration(SensorConfiguration configuration) => (bool success) + // Adds configuration for the sensor and starts reporting fake data + // through setSensorReading function. + async addConfiguration(configuration) { + assert_not_equals(configuration, null, "Invalid sensor configuration."); + + this.requestedFrequencies_.push(configuration.frequency); + // Sort using descending order. + this.requestedFrequencies_.sort( + (first, second) => { return second - first }); + + if (!this.startShouldFail_ ) + this.startReading(); + + if (this.addConfigurationCalled_ != null) + this.addConfigurationCalled_(this); + + return { success: !this.startShouldFail_ }; + } + + // RemoveConfiguration(SensorConfiguration configuration) + // Removes sensor configuration from the list of active configurations and + // stops notification about sensor reading changes if + // requestedFrequencies_ is empty. + removeConfiguration(configuration) { + if (this.removeConfigurationCalled_ != null) { + this.removeConfigurationCalled_(this); + } + + const index = this.requestedFrequencies_.indexOf(configuration.frequency); + if (index == -1) + return; + + this.requestedFrequencies_.splice(index, 1); + if (this.requestedFrequencies_.length === 0) + this.stopReading(); + } + + // Suspend() + suspend() { + this.stopReading(); + if (this.suspendCalled_ != null) { + this.suspendCalled_(this); + } + } + + // Resume() + resume() { + assert_equals(this.sensorReadingTimerId_, null); + this.startReading(); + if (this.resumeCalled_ != null) { + this.resumeCalled_(this); + } + } + + // ConfigureReadingChangeNotifications(bool enabled) + // Configures whether to report a reading change when in ON_CHANGE + // reporting mode. + configureReadingChangeNotifications(notifyOnReadingChange) { + this.notifyOnReadingChange_ = notifyOnReadingChange; + } + + // Mock functions + + // Resets mock Sensor state. + reset() { + this.stopReading(); + + this.startShouldFail_ = false; + this.notifyOnReadingChange_ = true; + this.readingData_ = null; + this.requestedFrequencies_ = []; + this.suspendCalled_ = null; + this.resumeCalled_ = null; + this.addConfigurationCalled_ = null; + this.removeConfigurationCalled_ = null; + this.resetBuffer(); + this.receiver_.$.close(); + } + + // Zeroes shared buffer. + resetBuffer() { + this.buffer_.fill(0); + } + + // Sets fake data that is used to deliver sensor reading updates. + async setSensorReading(readingData) { + this.readingData_ = new RingBuffer(readingData); + return this; + } + + // Sets flag that forces sensor to fail when addConfiguration is invoked. + setStartShouldFail(shouldFail) { + this.startShouldFail_ = shouldFail; + } + + // Returns resolved promise if suspend() was called, rejected otherwise. + suspendCalled() { + return new Promise(resolve => { + this.suspendCalled_ = resolve; + }); + } + + // Returns resolved promise if resume() was called, rejected otherwise. + resumeCalled() { + return new Promise(resolve => { + this.resumeCalled_ = resolve; + }); + } + + // Resolves promise when addConfiguration() is called. + addConfigurationCalled() { + return new Promise(resolve => { + this.addConfigurationCalled_ = resolve; + }); + } + + // Resolves promise when removeConfiguration() is called. + removeConfigurationCalled() { + return new Promise(resolve => { + this.removeConfigurationCalled_ = resolve; + }); + } + + startReading() { + if (this.readingData_ != null) { + this.stopReading(); + const maxFrequencyUsed = this.requestedFrequencies_[0]; + const timeout = (1 / maxFrequencyUsed) * 1000; + this.sensorReadingTimerId_ = window.setInterval(() => { + if (this.readingData_) { + // |buffer_| is a TypedArray, so we need to make sure we pass an + // array to set(). + const reading = this.readingData_.next().value; + assert_true(Array.isArray(reading), "The readings passed to " + + "setSensorReading() must arrays."); + this.buffer_.set(reading, 2); + + // For all tests sensor reading should have monotonically + // increasing timestamp in seconds. + this.buffer_[1] = window.performance.now() * 0.001; + } + if (this.reportingMode_ === ReportingMode.ON_CHANGE && + this.notifyOnReadingChange_) { + this.client_.sensorReadingChanged(); + } + }, timeout); + } + } + + stopReading() { + if (this.sensorReadingTimerId_ != null) { + window.clearInterval(this.sensorReadingTimerId_); + this.sensorReadingTimerId_ = null; + } + } + + getSamplingFrequency() { + assert_true(this.requestedFrequencies_.length > 0); + return this.requestedFrequencies_[0]; + } + } + + // This class aggregates information about a given sensor type that is used by + // MockSensorProvider when it is asked to create a new MockSensor. + class SensorTypeSettings { + constructor(mojoSensorType) { + this.mojoSensorType_ = mojoSensorType; + assert_greater_than_equal(mojoSensorType, SensorType.MIN_VALUE); + assert_less_than_equal(mojoSensorType, SensorType.MAX_VALUE); + + this.shouldDenyRequests_ = false; + this.unavailable_ = false; + } + + get mojoSensorType() { + return this.mojoSensorType_; + } + + get shouldDenyRequests() { + return this.shouldDenyRequests_; + } + + set shouldDenyRequests(deny) { + this.shouldDenyRequests_ = deny; + } + + get unavailable() { + return this.unavailable_; + } + + set unavailable(is_unavailable) { + this.unavailable_ = is_unavailable; + } + } + + // Maps a given device.mojom.SensorType enum value to a suitable name as a + // string. + function getSensorTypeName(mojoSensorType) { + switch (mojoSensorType) { + case SensorType.ACCELEROMETER: + return 'Accelerometer'; + case SensorType.LINEAR_ACCELERATION: + return 'LinearAccelerationSensor'; + case SensorType.AMBIENT_LIGHT: + return 'AmbientLightSensor'; + case SensorType.GRAVITY: + return 'GravitySensor'; + case SensorType.GYROSCOPE: + return 'Gyroscope'; + case SensorType.MAGNETOMETER: + return 'Magnetometer'; + case SensorType.ABSOLUTE_ORIENTATION_QUATERNION: + return 'AbsoluteOrientationSensor'; + case SensorType.ABSOLUTE_ORIENTATION_EULER_ANGLES: + return 'AbsoluteOrientationEulerAngles'; + case SensorType.RELATIVE_ORIENTATION_QUATERNION: + return 'RelativeOrientationSensor'; + case SensorType.RELATIVE_ORIENTATION_EULER_ANGLES: + return 'RelativeOrientationEulerAngles'; + } + } + + // Class that mocks SensorProvider interface defined in + // sensor_provider.mojom + class MockSensorProvider { + constructor() { + this.readingSizeInBytes_ = + Number(SensorInitParams_READ_BUFFER_SIZE_FOR_TESTS); + this.sharedBufferSizeInBytes_ = + this.readingSizeInBytes_ * (SensorType.MAX_VALUE + 1); + let rv = Mojo.createSharedBuffer(this.sharedBufferSizeInBytes_); + assert_equals( + rv.result, Mojo.RESULT_OK, 'Failed to create shared buffer'); + const handle = rv.handle; + rv = handle.mapBuffer(0, this.sharedBufferSizeInBytes_); + assert_equals(rv.result, Mojo.RESULT_OK, 'Failed to map shared buffer'); + this.shmemArrayBuffer_ = rv.buffer; + rv = handle.duplicateBufferHandle({readOnly: true}); + assert_equals( + rv.result, Mojo.RESULT_OK, 'Failed to duplicate shared buffer'); + this.readOnlySharedBufferHandle_ = rv.handle; + this.activeSensors_ = new Map(); + this.resolveFuncs_ = new Map(); + this.isContinuous_ = false; + this.maxFrequency_ = 60; + this.minFrequency_ = 1; + this.resetSensorTypeSettings(); + this.receiver_ = new SensorProviderReceiver(this); + this.interceptor_ = + new MojoInterfaceInterceptor(SensorProvider.$interfaceName); + this.interceptor_.oninterfacerequest = + e => this.receiver_.$.bindHandle(e.handle); + this.interceptor_.start(); + } + + // device.mojom.SensorProvider implementation + // Mojo functions that return a value must be async and return an object + // whose keys match the names declared in Mojo. + + // GetSensor(SensorType type) => (SensorCreationResult result, + // SensorInitParams? init_params) + // Returns initialized Sensor proxy to the client. + async getSensor(mojoSensorType) { + const sensorSettings = this.sensorTypeSettings_.get(getSensorTypeName(mojoSensorType)); + if (sensorSettings.unavailable) { + return {result: SensorCreationResult.ERROR_NOT_AVAILABLE, + initParams: null}; + } + if (sensorSettings.shouldDenyRequests) { + return {result: SensorCreationResult.ERROR_NOT_ALLOWED, + initParams: null}; + } + + const offset = mojoSensorType * this.readingSizeInBytes_; + const reportingMode = this.isContinuous_ ? + ReportingMode.CONTINUOUS : ReportingMode.ON_CHANGE; + + const sensorPtr = new SensorRemote(); + if (!this.activeSensors_.has(mojoSensorType)) { + const shmemView = new Float64Array( + this.shmemArrayBuffer_, offset, + this.readingSizeInBytes_ / Float64Array.BYTES_PER_ELEMENT); + const mockSensor = new MockSensor( + sensorPtr.$.bindNewPipeAndPassReceiver(), shmemView, reportingMode); + this.activeSensors_.set(mojoSensorType, mockSensor); + this.activeSensors_.get(mojoSensorType).client_ = new SensorClientRemote(); + } + + const rv = this.readOnlySharedBufferHandle_.duplicateBufferHandle( + {readOnly: true}); + + assert_equals(rv.result, Mojo.RESULT_OK); + + const defaultConfig = { frequency: DEFAULT_FREQUENCY }; + // Consider sensor traits to meet assertions in C++ code (see + // services/device/public/cpp/generic_sensor/sensor_traits.h) + if (mojoSensorType == SensorType.AMBIENT_LIGHT || + mojoSensorType == SensorType.MAGNETOMETER) { + this.maxFrequency_ = Math.min(10, this.maxFrequency_); + } + + const client = this.activeSensors_.get(mojoSensorType).client_; + const initParams = { + sensor: sensorPtr, + clientReceiver: client.$.bindNewPipeAndPassReceiver(), + memory: {buffer: rv.handle}, + bufferOffset: BigInt(offset), + mode: reportingMode, + defaultConfiguration: defaultConfig, + minimumFrequency: this.minFrequency_, + maximumFrequency: this.maxFrequency_ + }; + + if (this.resolveFuncs_.has(mojoSensorType)) { + for (let resolveFunc of this.resolveFuncs_.get(mojoSensorType)) { + resolveFunc(this.activeSensors_.get(mojoSensorType)); + } + this.resolveFuncs_.delete(mojoSensorType); + } + + return {result: SensorCreationResult.SUCCESS, initParams}; + } + + // Mock functions + + // Returns a SensorTypeSettings instance corresponding to the name |type|, a + // string. + getSensorTypeSettings(type) { + return this.sensorTypeSettings_.get(type); + } + + // Recreates |this.sensorTypeSettings_| with a new map and values reset to + // their defaults. + resetSensorTypeSettings() { + this.sensorTypeSettings_ = new Map([ + ['Accelerometer', new SensorTypeSettings(SensorType.ACCELEROMETER)], + ['LinearAccelerationSensor', new SensorTypeSettings(SensorType.LINEAR_ACCELERATION)], + ['AmbientLightSensor', new SensorTypeSettings(SensorType.AMBIENT_LIGHT)], + ['GravitySensor', new SensorTypeSettings(SensorType.GRAVITY)], + ['Gyroscope', new SensorTypeSettings(SensorType.GYROSCOPE)], + ['Magnetometer', new SensorTypeSettings(SensorType.MAGNETOMETER)], + ['AbsoluteOrientationSensor', new SensorTypeSettings(SensorType.ABSOLUTE_ORIENTATION_QUATERNION)], + ['AbsoluteOrientationEulerAngles', new SensorTypeSettings(SensorType.ABSOLUTE_ORIENTATION_EULER_ANGLES)], + ['RelativeOrientationSensor', new SensorTypeSettings(SensorType.RELATIVE_ORIENTATION_QUATERNION)], + ['RelativeOrientationEulerAngles', new SensorTypeSettings(SensorType.RELATIVE_ORIENTATION_EULER_ANGLES)] + ]); + } + + // Resets state of mock SensorProvider between test runs. + reset() { + for (const sensor of this.activeSensors_.values()) { + sensor.reset(); + } + this.activeSensors_.clear(); + this.resolveFuncs_.clear(); + this.resetSensorTypeSettings(); + this.maxFrequency_ = 60; + this.minFrequency_ = 1; + this.isContinuous_ = false; + this.receiver_.$.close(); + this.interceptor_.stop(); + } + + // Returns mock sensor that was created in getSensor to the layout test. + getCreatedSensor(sensorName) { + const type = this.sensorTypeSettings_.get(sensorName).mojoSensorType; + + if (this.activeSensors_.has(type)) { + return Promise.resolve(this.activeSensors_.get(type)); + } + + return new Promise(resolve => { + if (!this.resolveFuncs_.has(type)) { + this.resolveFuncs_.set(type, []); + } + this.resolveFuncs_.get(type).push(resolve); + }); + } + + // Forces sensor to use |reportingMode| as an update mode. + setContinuousReportingMode() { + this.isContinuous_ = true; + } + + // Sets the maximum frequency for a concrete sensor. + setMaximumSupportedFrequency(frequency) { + this.maxFrequency_ = frequency; + } + + // Sets the minimum frequency for a concrete sensor. + setMinimumSupportedFrequency(frequency) { + this.minFrequency_ = frequency; + } + } + + return new MockSensorProvider(); +} + +export function sensor_test(func, name, properties) { + promise_test(async t => { + const sensorProvider = sensorMocks(); + + // Clean up and reset mock sensor stubs asynchronously, so that the blink + // side closes its proxies and notifies JS sensor objects before new test is + // started. + try { + await func(t, sensorProvider); + } finally { + sensorProvider.reset(); + await new Promise(resolve => { setTimeout(resolve, 0); }); + }; + }, name, properties); +} + +export async function setMockSensorDataForType(sensorProvider, sensorType, mockDataArray) { + const createdSensor = await sensorProvider.getCreatedSensor(sensorType); + return createdSensor.setSensorReading([mockDataArray]); +} + +// Returns a promise that will be resolved when an event equal to the given +// event is fired. +export function waitForEvent(expectedEvent, targetWindow = window) { + const stringify = (thing, targetWindow) => { + if (thing instanceof targetWindow.Object && thing.constructor !== targetWindow.Object) { + let str = '{'; + for (let key of Object.keys(Object.getPrototypeOf(thing))) { + str += JSON.stringify(key) + ': ' + stringify(thing[key], targetWindow) + ', '; + } + return str + '}'; + } else if (thing instanceof Number) { + return thing.toFixed(6); + } + return JSON.stringify(thing); + }; + + return new Promise((resolve, reject) => { + let events = []; + let timeoutId = null; + + const expectedEventString = stringify(expectedEvent, window); + function listener(event) { + const eventString = stringify(event, targetWindow); + if (eventString === expectedEventString) { + targetWindow.clearTimeout(timeoutId); + targetWindow.removeEventListener(expectedEvent.type, listener); + resolve(); + } else { + events.push(eventString); + } + } + targetWindow.addEventListener(expectedEvent.type, listener); + + timeoutId = targetWindow.setTimeout(() => { + targetWindow.removeEventListener(expectedEvent.type, listener); + let errorMessage = 'Timeout waiting for expected event: ' + expectedEventString; + if (events.length == 0) { + errorMessage += ', no events were fired'; + } else { + errorMessage += ', received events: ' + for (let event of events) { + errorMessage += event + ', '; + } + } + reject(errorMessage); + }, 500); + }); +}
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only-expected.txt index 00de596..9d869c2 100644 --- a/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only-expected.txt +++ b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/issues/content-security-policy-issue-report-only-expected.txt
@@ -28,7 +28,7 @@ sourceCodeLocation : { columnNumber : 13 lineNumber : 4 - scriptId : 4 + scriptId : <string> url : https://devtools.test:8443/inspector-protocol/resources/content-security-policy-issue-report-only.php } violatedDirective : script-src
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/target/auto-attach-wait-for-debugger-2-sessions-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/target/auto-attach-wait-for-debugger-2-sessions-expected.txt new file mode 100644 index 0000000..a1eaed04 --- /dev/null +++ b/third_party/blink/web_tests/platform/generic/http/tests/inspector-protocol/target/auto-attach-wait-for-debugger-2-sessions-expected.txt
@@ -0,0 +1,38 @@ +Tests that setAutoAttach honors updated waitForDebuggerOnStart. +[ + [0] : { + method : Target.attachedToTarget + params : { + sessionId : <string> + targetInfo : { + attached : true + browserContextId : <string> + canAccessOpener : false + targetId : <string> + title : + type : iframe + url : + } + waitingForDebugger : false + } + sessionId : <string> + } + [1] : { + method : Target.attachedToTarget + params : { + sessionId : <string> + targetInfo : { + attached : true + browserContextId : <string> + canAccessOpener : false + targetId : <string> + title : + type : iframe + url : + } + waitingForDebugger : true + } + sessionId : <string> + } +] +
diff --git a/third_party/blink/web_tests/platform/generic/virtual/shared-storage-fenced-frame-shadow-dom/wpt_internal/shared_storage/verify-get-undefined.https-expected.txt b/third_party/blink/web_tests/platform/generic/virtual/shared-storage-fenced-frame-shadow-dom/wpt_internal/shared_storage/verify-get-undefined.https-expected.txt new file mode 100644 index 0000000..022cdc0 --- /dev/null +++ b/third_party/blink/web_tests/platform/generic/virtual/shared-storage-fenced-frame-shadow-dom/wpt_internal/shared_storage/verify-get-undefined.https-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = ResizeObserver loop limit exceeded +PASS verify-get-undefined-url-selection-operation +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js index aa4ab54..f1ab48d 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/resources/helpers.js
@@ -2,6 +2,13 @@ * Helper functions for attribution reporting API tests. */ +attribution_reporting_promise_test = f => promise_test(async t => { + t.add_cleanup(() => internals.resetAttributionReporting()); + t.add_cleanup(() => resetEventLevelReports()); + t.add_cleanup(() => resetAggregatableReports()); + return f(t); +}); + const eventLevelReportsUrl = '/.well-known/attribution-reporting/report-event-attribution'; const aggregatableReportsUrl =
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-aggregatable-report-test.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-aggregatable-report-test.sub.https.html index 198fa7f9..99493eb8 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-aggregatable-report-test.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-aggregatable-report-test.sub.https.html
@@ -4,7 +4,7 @@ <script src="/resources/testharnessreport.js"></script> <script src="resources/helpers.js"></script> <script> -promise_test(async t => { +attribution_reporting_promise_test(async t => { const source = { source_event_id: '9153495207648170476', destination: `https://{{host}}`, @@ -29,7 +29,7 @@ geoValue: 1664, }, }; - await resetAggregatableReports(); + registerAttributionSrc( 'Attribution-Reporting-Register-Source', source, 'foo=bar;Secure;HttpOnly;Path=/');
diff --git a/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-event-level-report-test.sub.https.html b/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-event-level-report-test.sub.https.html index 2ce4628..d7071ff 100644 --- a/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-event-level-report-test.sub.https.html +++ b/third_party/blink/web_tests/wpt_internal/attribution-reporting/simple-event-level-report-test.sub.https.html
@@ -4,13 +4,13 @@ <script src="/resources/testharnessreport.js"></script> <script src="resources/helpers.js"></script> <script> -promise_test(async t => { +attribution_reporting_promise_test(async t => { const sourceEvent = { source_event_id: '9153495207648170476', destination: `https://{{host}}`, }; const trigger = {event_trigger_data: [{'trigger_data': '2'}]}; - await resetEventLevelReports(); + registerAttributionSrc( 'Attribution-Reporting-Register-Source', sourceEvent, 'foo=bar;Secure;HttpOnly;Path=/');
diff --git a/third_party/blink/web_tests/wpt_internal/shared_storage/resources/verify-get-undefined-module.js b/third_party/blink/web_tests/wpt_internal/shared_storage/resources/verify-get-undefined-module.js new file mode 100644 index 0000000..d98a392e --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/shared_storage/resources/verify-get-undefined-module.js
@@ -0,0 +1,16 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +class VerifyGetUndefinedURLSelectionOperation { + async run(urls, data) { + if (await sharedStorage.get('key-not-previously-set') === undefined) { + return 1; + } + + return -1; + } +} + +register("verify-get-undefined-url-selection-operation", + VerifyGetUndefinedURLSelectionOperation);
diff --git a/third_party/blink/web_tests/wpt_internal/shared_storage/verify-get-undefined.https.html b/third_party/blink/web_tests/wpt_internal/shared_storage/verify-get-undefined.https.html new file mode 100644 index 0000000..72090bf --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/shared_storage/verify-get-undefined.https.html
@@ -0,0 +1,36 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/utils.js"></script> +<script src="/common/utils.js"></script> +<script src="../fenced_frame/resources/utils.js"></script> + +<body> +<script> +'use strict'; + +promise_test(async () => { + const ancestor_key = token(); + let url0 = generateURL("resources/frame0.html", [ancestor_key]); + let url1 = generateURL("resources/frame1.html", [ancestor_key]); + + await sharedStorage.worklet.addModule("resources/verify-get-undefined-module.js"); + + let uuid1 = await sharedStorage.selectURL( + "verify-get-undefined-url-selection-operation", + [{url: url0, + reporting_metadata: {'click': "resources/frame0.html"}}, + {url: url1, + reporting_metadata: + {'mouse interaction': "resources/frame1.html", + 'click': "resources/frame2.html"}}]); + + attachFencedFrame(uuid1, 'opaque-ads'); + + // frame1_loaded implies that the operation was successful. + assert_equals(await nextValueFromServer(ancestor_key), "frame1_loaded"); + +}, 'verify-get-undefined-url-selection-operation'); + +</script> +</body>
diff --git a/third_party/closure_compiler/externs/terminal_private.js b/third_party/closure_compiler/externs/terminal_private.js index aa89101..a216c49 100644 --- a/third_party/closure_compiler/externs/terminal_private.js +++ b/third_party/closure_compiler/externs/terminal_private.js
@@ -111,6 +111,7 @@ * Returns an object containing info about ChromeOS settings that affect the * Terminal, e.g. which feature flags are enabled. * @param {function({ + * alternative_renderer: boolean, * multi_profile: boolean, * tmux_integration: boolean * }): void} callback Callback that will be called with the info object.
diff --git a/third_party/libevent/BUILD.gn b/third_party/libevent/BUILD.gn new file mode 100644 index 0000000..755a6a6e --- /dev/null +++ b/third_party/libevent/BUILD.gn
@@ -0,0 +1,69 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/nacl/config.gni") + +static_library("libevent") { + sources = [ + "buffer.c", + "evbuffer.c", + "evdns.c", + "evdns.h", + "event-config.h", + "event-internal.h", + "event.c", + "event.h", + "event_tagging.c", + "evhttp.h", + "evrpc-internal.h", + "evrpc.c", + "evrpc.h", + "evsignal.h", + "evutil.c", + "evutil.h", + "http-internal.h", + "http.c", + "log.c", + "log.h", + "min_heap.h", + "poll.c", + "select.c", + "signal.c", + "strlcpy-internal.h", + "strlcpy.c", + ] + + defines = [ "HAVE_CONFIG_H" ] + + if (is_apple) { + sources += [ + "kqueue.c", + "mac/config.h", + "mac/event-config.h", + ] + include_dirs = [ "mac" ] + } else if (is_linux || is_chromeos) { + sources += [ + "epoll.c", + "linux/config.h", + "linux/event-config.h", + ] + include_dirs = [ "linux" ] + } else if (is_android) { + sources += [ + "android/config.h", + "android/event-config.h", + "epoll.c", + ] + include_dirs = [ "android" ] + } + + if (!is_debug) { + configs -= [ "//build/config/compiler:default_optimization" ] + configs += [ "//build/config/compiler:optimize_max" ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +}
diff --git a/base/third_party/libevent/ChangeLog b/third_party/libevent/ChangeLog similarity index 100% rename from base/third_party/libevent/ChangeLog rename to third_party/libevent/ChangeLog
diff --git a/base/third_party/libevent/Doxyfile b/third_party/libevent/Doxyfile similarity index 100% rename from base/third_party/libevent/Doxyfile rename to third_party/libevent/Doxyfile
diff --git a/base/third_party/libevent/LICENSE b/third_party/libevent/LICENSE similarity index 100% rename from base/third_party/libevent/LICENSE rename to third_party/libevent/LICENSE
diff --git a/base/third_party/libevent/Makefile.am b/third_party/libevent/Makefile.am similarity index 100% rename from base/third_party/libevent/Makefile.am rename to third_party/libevent/Makefile.am
diff --git a/base/third_party/libevent/Makefile.nmake b/third_party/libevent/Makefile.nmake similarity index 100% rename from base/third_party/libevent/Makefile.nmake rename to third_party/libevent/Makefile.nmake
diff --git a/base/third_party/libevent/README b/third_party/libevent/README similarity index 100% rename from base/third_party/libevent/README rename to third_party/libevent/README
diff --git a/base/third_party/libevent/README.chromium b/third_party/libevent/README.chromium similarity index 100% rename from base/third_party/libevent/README.chromium rename to third_party/libevent/README.chromium
diff --git a/base/third_party/libevent/aix/config.h b/third_party/libevent/aix/config.h similarity index 100% rename from base/third_party/libevent/aix/config.h rename to third_party/libevent/aix/config.h
diff --git a/base/third_party/libevent/aix/event-config.h b/third_party/libevent/aix/event-config.h similarity index 100% rename from base/third_party/libevent/aix/event-config.h rename to third_party/libevent/aix/event-config.h
diff --git a/base/third_party/libevent/android/config.h b/third_party/libevent/android/config.h similarity index 100% rename from base/third_party/libevent/android/config.h rename to third_party/libevent/android/config.h
diff --git a/base/third_party/libevent/android/event-config.h b/third_party/libevent/android/event-config.h similarity index 100% rename from base/third_party/libevent/android/event-config.h rename to third_party/libevent/android/event-config.h
diff --git a/base/third_party/libevent/autogen.sh b/third_party/libevent/autogen.sh similarity index 100% rename from base/third_party/libevent/autogen.sh rename to third_party/libevent/autogen.sh
diff --git a/base/third_party/libevent/buffer.c b/third_party/libevent/buffer.c similarity index 100% rename from base/third_party/libevent/buffer.c rename to third_party/libevent/buffer.c
diff --git a/base/third_party/libevent/chromium.patch b/third_party/libevent/chromium.patch similarity index 100% rename from base/third_party/libevent/chromium.patch rename to third_party/libevent/chromium.patch
diff --git a/base/third_party/libevent/compat/sys/_libevent_time.h b/third_party/libevent/compat/sys/_libevent_time.h similarity index 100% rename from base/third_party/libevent/compat/sys/_libevent_time.h rename to third_party/libevent/compat/sys/_libevent_time.h
diff --git a/base/third_party/libevent/compat/sys/queue.h b/third_party/libevent/compat/sys/queue.h similarity index 100% rename from base/third_party/libevent/compat/sys/queue.h rename to third_party/libevent/compat/sys/queue.h
diff --git a/base/third_party/libevent/configure.in b/third_party/libevent/configure.in similarity index 100% rename from base/third_party/libevent/configure.in rename to third_party/libevent/configure.in
diff --git a/base/third_party/libevent/devpoll.c b/third_party/libevent/devpoll.c similarity index 100% rename from base/third_party/libevent/devpoll.c rename to third_party/libevent/devpoll.c
diff --git a/base/third_party/libevent/epoll.c b/third_party/libevent/epoll.c similarity index 100% rename from base/third_party/libevent/epoll.c rename to third_party/libevent/epoll.c
diff --git a/base/third_party/libevent/epoll_sub.c b/third_party/libevent/epoll_sub.c similarity index 100% rename from base/third_party/libevent/epoll_sub.c rename to third_party/libevent/epoll_sub.c
diff --git a/base/third_party/libevent/evbuffer.c b/third_party/libevent/evbuffer.c similarity index 100% rename from base/third_party/libevent/evbuffer.c rename to third_party/libevent/evbuffer.c
diff --git a/base/third_party/libevent/evdns.3 b/third_party/libevent/evdns.3 similarity index 100% rename from base/third_party/libevent/evdns.3 rename to third_party/libevent/evdns.3
diff --git a/base/third_party/libevent/evdns.c b/third_party/libevent/evdns.c similarity index 100% rename from base/third_party/libevent/evdns.c rename to third_party/libevent/evdns.c
diff --git a/base/third_party/libevent/evdns.h b/third_party/libevent/evdns.h similarity index 100% rename from base/third_party/libevent/evdns.h rename to third_party/libevent/evdns.h
diff --git a/third_party/libevent/event-config.h b/third_party/libevent/event-config.h new file mode 100644 index 0000000..82e6d2a --- /dev/null +++ b/third_party/libevent/event-config.h
@@ -0,0 +1,22 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is Chromium-specific, and brings in the appropriate +// event-config.h depending on your platform. + +#if defined(__APPLE__) +#include "third_party/libevent/mac/event-config.h" +#elif defined(ANDROID) +#include "third_party/libevent/android/event-config.h" +#elif defined(__linux__) +#include "third_party/libevent/linux/event-config.h" +#elif defined(__FreeBSD__) +#include "third_party/libevent/freebsd/event-config.h" +#elif defined(__sun) +#include "third_party/libevent/solaris/event-config.h" +#elif defined(_AIX) +#include "third_party/libevent/aix/event-config.h" +#else +#error generate event-config.h for your platform +#endif
diff --git a/base/third_party/libevent/event-internal.h b/third_party/libevent/event-internal.h similarity index 100% rename from base/third_party/libevent/event-internal.h rename to third_party/libevent/event-internal.h
diff --git a/base/third_party/libevent/event.3 b/third_party/libevent/event.3 similarity index 100% rename from base/third_party/libevent/event.3 rename to third_party/libevent/event.3
diff --git a/base/third_party/libevent/event.c b/third_party/libevent/event.c similarity index 100% rename from base/third_party/libevent/event.c rename to third_party/libevent/event.c
diff --git a/third_party/libevent/event.h b/third_party/libevent/event.h new file mode 100644 index 0000000..f0887b96 --- /dev/null +++ b/third_party/libevent/event.h
@@ -0,0 +1,1212 @@ +/* + * Copyright (c) 2000-2007 Niels Provos <provos@citi.umich.edu> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _EVENT_H_ +#define _EVENT_H_ + +/** @mainpage + + @section intro Introduction + + libevent is an event notification library for developing scalable network + servers. The libevent API provides a mechanism to execute a callback + function when a specific event occurs on a file descriptor or after a + timeout has been reached. Furthermore, libevent also support callbacks due + to signals or regular timeouts. + + libevent is meant to replace the event loop found in event driven network + servers. An application just needs to call event_dispatch() and then add or + remove events dynamically without having to change the event loop. + + Currently, libevent supports /dev/poll, kqueue(2), select(2), poll(2) and + epoll(4). It also has experimental support for real-time signals. The + internal event mechanism is completely independent of the exposed event API, + and a simple update of libevent can provide new functionality without having + to redesign the applications. As a result, Libevent allows for portable + application development and provides the most scalable event notification + mechanism available on an operating system. Libevent can also be used for + multi-threaded aplications; see Steven Grimm's explanation. Libevent should + compile on Linux, *BSD, Mac OS X, Solaris and Windows. + + @section usage Standard usage + + Every program that uses libevent must include the <event.h> header, and pass + the -levent flag to the linker. Before using any of the functions in the + library, you must call event_init() or event_base_new() to perform one-time + initialization of the libevent library. + + @section event Event notification + + For each file descriptor that you wish to monitor, you must declare an event + structure and call event_set() to initialize the members of the structure. + To enable notification, you add the structure to the list of monitored + events by calling event_add(). The event structure must remain allocated as + long as it is active, so it should be allocated on the heap. Finally, you + call event_dispatch() to loop and dispatch events. + + @section bufferevent I/O Buffers + + libevent provides an abstraction on top of the regular event callbacks. This + abstraction is called a buffered event. A buffered event provides input and + output buffers that get filled and drained automatically. The user of a + buffered event no longer deals directly with the I/O, but instead is reading + from input and writing to output buffers. + + Once initialized via bufferevent_new(), the bufferevent structure can be + used repeatedly with bufferevent_enable() and bufferevent_disable(). + Instead of reading and writing directly to a socket, you would call + bufferevent_read() and bufferevent_write(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + @section timers Timers + + libevent can also be used to create timers that invoke a callback after a + certain amount of time has expired. The evtimer_set() function prepares an + event struct to be used as a timer. To activate the timer, call + evtimer_add(). Timers can be deactivated by calling evtimer_del(). + + @section timeouts Timeouts + + In addition to simple timers, libevent can assign timeout events to file + descriptors that are triggered whenever a certain amount of time has passed + with no activity on a file descriptor. The timeout_set() function + initializes an event struct for use as a timeout. Once initialized, the + event must be activated by using timeout_add(). To cancel the timeout, call + timeout_del(). + + @section evdns Asynchronous DNS resolution + + libevent provides an asynchronous DNS resolver that should be used instead + of the standard DNS resolver functions. These functions can be imported by + including the <evdns.h> header in your program. Before using any of the + resolver functions, you must call evdns_init() to initialize the library. To + convert a hostname to an IP address, you call the evdns_resolve_ipv4() + function. To perform a reverse lookup, you would call the + evdns_resolve_reverse() function. All of these functions use callbacks to + avoid blocking while the lookup is performed. + + @section evhttp Event-driven HTTP servers + + libevent provides a very simple event-driven HTTP server that can be + embedded in your program and used to service HTTP requests. + + To use this capability, you need to include the <evhttp.h> header in your + program. You create the server by calling evhttp_new(). Add addresses and + ports to listen on with evhttp_bind_socket(). You then register one or more + callbacks to handle incoming requests. Each URI can be assigned a callback + via the evhttp_set_cb() function. A generic callback function can also be + registered via evhttp_set_gencb(); this callback will be invoked if no other + callbacks have been registered for a given URI. + + @section evrpc A framework for RPC servers and clients + + libevents provides a framework for creating RPC servers and clients. It + takes care of marshaling and unmarshaling all data structures. + + @section api API Reference + + To browse the complete documentation of the libevent API, click on any of + the following links. + + event.h + The primary libevent header + + evdns.h + Asynchronous DNS resolution + + evhttp.h + An embedded libevent-based HTTP server + + evrpc.h + A framework for creating RPC servers and clients + + */ + +/** @file event.h + + A library for writing event-driven network servers + + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "event-config.h" +#ifdef _EVENT_HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef _EVENT_HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef _EVENT_HAVE_STDINT_H +#include <stdint.h> +#endif +#include <stdarg.h> + +/* For int types. */ +#include "evutil.h" + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN +typedef unsigned char u_char; +typedef unsigned short u_short; +#endif + +#define EVLIST_TIMEOUT 0x01 +#define EVLIST_INSERTED 0x02 +#define EVLIST_SIGNAL 0x04 +#define EVLIST_ACTIVE 0x08 +#define EVLIST_INTERNAL 0x10 +#define EVLIST_INIT 0x80 + +/* EVLIST_X_ Private space: 0x1000-0xf000 */ +#define EVLIST_ALL (0xf000 | 0x9f) + +#define EV_TIMEOUT 0x01 +#define EV_READ 0x02 +#define EV_WRITE 0x04 +#define EV_SIGNAL 0x08 +#define EV_PERSIST 0x10 /* Persistant event */ + +/* Fix so that ppl dont have to run with <sys/queue.h> */ +#ifndef TAILQ_ENTRY +#define _EVENT_DEFINED_TQENTRY +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ + +struct event_base; +#ifndef EVENT_NO_STRUCT +struct event { + TAILQ_ENTRY (event) ev_next; + TAILQ_ENTRY (event) ev_active_next; + TAILQ_ENTRY (event) ev_signal_next; + unsigned int min_heap_idx; /* for managing timeouts */ + + struct event_base *ev_base; + + int ev_fd; + short ev_events; + short ev_ncalls; + short *ev_pncalls; /* Allows deletes in callback */ + + struct timeval ev_timeout; + + int ev_pri; /* smaller numbers are higher priority */ + + void (*ev_callback)(int, short, void *arg); + void *ev_arg; + + int ev_res; /* result passed to event callback */ + int ev_flags; +}; +#else +struct event; +#endif + +#define EVENT_SIGNAL(ev) (int)(ev)->ev_fd +#define EVENT_FD(ev) (int)(ev)->ev_fd + +/* + * Key-Value pairs. Can be used for HTTP headers but also for + * query argument parsing. + */ +struct evkeyval { + TAILQ_ENTRY(evkeyval) next; + + char *key; + char *value; +}; + +#ifdef _EVENT_DEFINED_TQENTRY +#undef TAILQ_ENTRY +struct event_list; +struct evkeyvalq; +#undef _EVENT_DEFINED_TQENTRY +#else +TAILQ_HEAD (event_list, event); +TAILQ_HEAD (evkeyvalq, evkeyval); +#endif /* _EVENT_DEFINED_TQENTRY */ + +/** + Initialize the event API. + + Use event_base_new() to initialize a new event base, but does not set + the current_base global. If using only event_base_new(), each event + added must have an event base set with event_base_set() + + @see event_base_set(), event_base_free(), event_init() + */ +struct event_base *event_base_new(void); + +/** + Initialize the event API. + + The event API needs to be initialized with event_init() before it can be + used. Sets the current_base global representing the default base for + events that have no base associated with them. + + @see event_base_set(), event_base_new() + */ +struct event_base *event_init(void); + +/** + Reinitialized the event base after a fork + + Some event mechanisms do not survive across fork. The event base needs + to be reinitialized with the event_reinit() function. + + @param base the event base that needs to be re-initialized + @return 0 if successful, or -1 if some events could not be re-added. + @see event_base_new(), event_init() +*/ +int event_reinit(struct event_base *base); + +/** + Loop to process events. + + In order to process events, an application needs to call + event_dispatch(). This function only returns on error, and should + replace the event core of the application program. + + @see event_base_dispatch() + */ +int event_dispatch(void); + + +/** + Threadsafe event dispatching loop. + + @param eb the event_base structure returned by event_init() + @see event_init(), event_dispatch() + */ +int event_base_dispatch(struct event_base *); + + +/** + Get the kernel event notification mechanism used by libevent. + + @param eb the event_base structure returned by event_base_new() + @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) + */ +const char *event_base_get_method(struct event_base *); + + +/** + Deallocate all memory associated with an event_base, and free the base. + + Note that this function will not close any fds or free any memory passed + to event_set as the argument to callback. + + @param eb an event_base to be freed + */ +void event_base_free(struct event_base *); + + +#define _EVENT_LOG_DEBUG 0 +#define _EVENT_LOG_MSG 1 +#define _EVENT_LOG_WARN 2 +#define _EVENT_LOG_ERR 3 +typedef void (*event_log_cb)(int severity, const char *msg); +/** + Redirect libevent's log messages. + + @param cb a function taking two arguments: an integer severity between + _EVENT_LOG_DEBUG and _EVENT_LOG_ERR, and a string. If cb is NULL, + then the default log is used. + */ +void event_set_log_callback(event_log_cb cb); + +/** + Associate a different event base with an event. + + @param eb the event base + @param ev the event + */ +int event_base_set(struct event_base *, struct event *); + +/** + event_loop() flags + */ +/*@{*/ +#define EVLOOP_ONCE 0x01 /**< Block at most once. */ +#define EVLOOP_NONBLOCK 0x02 /**< Do not block. */ +/*@}*/ + +/** + Handle events. + + This is a more flexible version of event_dispatch(). + + @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK + @return 0 if successful, -1 if an error occurred, or 1 if no events were + registered. + @see event_loopexit(), event_base_loop() +*/ +int event_loop(int); + +/** + Handle events (threadsafe version). + + This is a more flexible version of event_base_dispatch(). + + @param eb the event_base structure returned by event_init() + @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK + @return 0 if successful, -1 if an error occurred, or 1 if no events were + registered. + @see event_loopexit(), event_base_loop() + */ +int event_base_loop(struct event_base *, int); + +/** + Exit the event loop after the specified time. + + The next event_loop() iteration after the given timer expires will + complete normally (handling all queued events) then exit without + blocking for events again. + + Subsequent invocations of event_loop() will proceed normally. + + @param tv the amount of time after which the loop should terminate. + @return 0 if successful, or -1 if an error occurred + @see event_loop(), event_base_loop(), event_base_loopexit() + */ +int event_loopexit(const struct timeval *); + + +/** + Exit the event loop after the specified time (threadsafe variant). + + The next event_base_loop() iteration after the given timer expires will + complete normally (handling all queued events) then exit without + blocking for events again. + + Subsequent invocations of event_base_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @param tv the amount of time after which the loop should terminate. + @return 0 if successful, or -1 if an error occurred + @see event_loopexit() + */ +int event_base_loopexit(struct event_base *, const struct timeval *); + +/** + Abort the active event_loop() immediately. + + event_loop() will abort the loop after the next event is completed; + event_loopbreak() is typically invoked from this event's callback. + This behavior is analogous to the "break;" statement. + + Subsequent invocations of event_loop() will proceed normally. + + @return 0 if successful, or -1 if an error occurred + @see event_base_loopbreak(), event_loopexit() + */ +int event_loopbreak(void); + +/** + Abort the active event_base_loop() immediately. + + event_base_loop() will abort the loop after the next event is completed; + event_base_loopbreak() is typically invoked from this event's callback. + This behavior is analogous to the "break;" statement. + + Subsequent invocations of event_loop() will proceed normally. + + @param eb the event_base structure returned by event_init() + @return 0 if successful, or -1 if an error occurred + @see event_base_loopexit + */ +int event_base_loopbreak(struct event_base *); + + +/** + Add a timer event. + + @param ev the event struct + @param tv timeval struct + */ +#define evtimer_add(ev, tv) event_add(ev, tv) + + +/** + Define a timer event. + + @param ev event struct to be modified + @param cb callback function + @param arg argument that will be passed to the callback function + */ +#define evtimer_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg) + + +/** + * Delete a timer event. + * + * @param ev the event struct to be disabled + */ +#define evtimer_del(ev) event_del(ev) +#define evtimer_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) +#define evtimer_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) + +/** + * Add a timeout event. + * + * @param ev the event struct to be disabled + * @param tv the timeout value, in seconds + */ +#define timeout_add(ev, tv) event_add(ev, tv) + + +/** + * Define a timeout event. + * + * @param ev the event struct to be defined + * @param cb the callback to be invoked when the timeout expires + * @param arg the argument to be passed to the callback + */ +#define timeout_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg) + + +/** + * Disable a timeout event. + * + * @param ev the timeout event to be disabled + */ +#define timeout_del(ev) event_del(ev) + +#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv) +#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) + +#define signal_add(ev, tv) event_add(ev, tv) +#define signal_set(ev, x, cb, arg) \ + event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg) +#define signal_del(ev) event_del(ev) +#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv) +#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) + +/** + Prepare an event structure to be added. + + The function event_set() prepares the event structure ev to be used in + future calls to event_add() and event_del(). The event will be prepared to + call the function specified by the fn argument with an int argument + indicating the file descriptor, a short argument indicating the type of + event, and a void * argument given in the arg argument. The fd indicates + the file descriptor that should be monitored for events. The events can be + either EV_READ, EV_WRITE, or both. Indicating that an application can read + or write from the file descriptor respectively without blocking. + + The function fn will be called with the file descriptor that triggered the + event and the type of event which will be either EV_TIMEOUT, EV_SIGNAL, + EV_READ, or EV_WRITE. The additional flag EV_PERSIST makes an event_add() + persistent until event_del() has been called. + + @param ev an event struct to be modified + @param fd the file descriptor to be monitored + @param event desired events to monitor; can be EV_READ and/or EV_WRITE + @param fn callback function to be invoked when the event occurs + @param arg an argument to be passed to the callback function + + @see event_add(), event_del(), event_once() + + */ +void event_set(struct event *, int, short, void (*)(int, short, void *), void *); + +/** + Schedule a one-time event to occur. + + The function event_once() is similar to event_set(). However, it schedules + a callback to be called exactly once and does not require the caller to + prepare an event structure. + + @param fd a file descriptor to monitor + @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ | + EV_WRITE + @param callback callback function to be invoked when the event occurs + @param arg an argument to be passed to the callback function + @param timeout the maximum amount of time to wait for the event, or NULL + to wait forever + @return 0 if successful, or -1 if an error occurred + @see event_set() + + */ +int event_once(int, short, void (*)(int, short, void *), void *, + const struct timeval *); + + +/** + Schedule a one-time event (threadsafe variant) + + The function event_base_once() is similar to event_set(). However, it + schedules a callback to be called exactly once and does not require the + caller to prepare an event structure. + + @param base an event_base returned by event_init() + @param fd a file descriptor to monitor + @param events event(s) to monitor; can be any of EV_TIMEOUT | EV_READ | + EV_WRITE + @param callback callback function to be invoked when the event occurs + @param arg an argument to be passed to the callback function + @param timeout the maximum amount of time to wait for the event, or NULL + to wait forever + @return 0 if successful, or -1 if an error occurred + @see event_once() + */ +int event_base_once(struct event_base *base, int fd, short events, + void (*callback)(int, short, void *), void *arg, + const struct timeval *timeout); + + +/** + Add an event to the set of monitored events. + + The function event_add() schedules the execution of the ev event when the + event specified in event_set() occurs or in at least the time specified in + the tv. If tv is NULL, no timeout occurs and the function will only be + called if a matching event occurs on the file descriptor. The event in the + ev argument must be already initialized by event_set() and may not be used + in calls to event_set() until it has timed out or been removed with + event_del(). If the event in the ev argument already has a scheduled + timeout, the old timeout will be replaced by the new one. + + @param ev an event struct initialized via event_set() + @param timeout the maximum amount of time to wait for the event, or NULL + to wait forever + @return 0 if successful, or -1 if an error occurred + @see event_del(), event_set() + */ +int event_add(struct event *ev, const struct timeval *timeout); + + +/** + Remove an event from the set of monitored events. + + The function event_del() will cancel the event in the argument ev. If the + event has already executed or has never been added the call will have no + effect. + + @param ev an event struct to be removed from the working set + @return 0 if successful, or -1 if an error occurred + @see event_add() + */ +int event_del(struct event *); + +void event_active(struct event *, int, short); + + +/** + Checks if a specific event is pending or scheduled. + + @param ev an event struct previously passed to event_add() + @param event the requested event type; any of EV_TIMEOUT|EV_READ| + EV_WRITE|EV_SIGNAL + @param tv an alternate timeout (FIXME - is this true?) + + @return 1 if the event is pending, or 0 if the event has not occurred + + */ +int event_pending(struct event *ev, short event, struct timeval *tv); + + +/** + Test if an event structure has been initialized. + + The event_initialized() macro can be used to check if an event has been + initialized. + + @param ev an event structure to be tested + @return 1 if the structure has been initialized, or 0 if it has not been + initialized + */ +#ifdef WIN32 +#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE) +#else +#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT) +#endif + + +/** + Get the libevent version number. + + @return a string containing the version number of libevent + */ +const char *event_get_version(void); + + +/** + Get the kernel event notification mechanism used by libevent. + + @return a string identifying the kernel event mechanism (kqueue, epoll, etc.) + */ +const char *event_get_method(void); + + +/** + Set the number of different event priorities. + + By default libevent schedules all active events with the same priority. + However, some time it is desirable to process some events with a higher + priority than others. For that reason, libevent supports strict priority + queues. Active events with a lower priority are always processed before + events with a higher priority. + + The number of different priorities can be set initially with the + event_priority_init() function. This function should be called before the + first call to event_dispatch(). The event_priority_set() function can be + used to assign a priority to an event. By default, libevent assigns the + middle priority to all events unless their priority is explicitly set. + + @param npriorities the maximum number of priorities + @return 0 if successful, or -1 if an error occurred + @see event_base_priority_init(), event_priority_set() + + */ +int event_priority_init(int); + + +/** + Set the number of different event priorities (threadsafe variant). + + See the description of event_priority_init() for more information. + + @param eb the event_base structure returned by event_init() + @param npriorities the maximum number of priorities + @return 0 if successful, or -1 if an error occurred + @see event_priority_init(), event_priority_set() + */ +int event_base_priority_init(struct event_base *, int); + + +/** + Assign a priority to an event. + + @param ev an event struct + @param priority the new priority to be assigned + @return 0 if successful, or -1 if an error occurred + @see event_priority_init() + */ +int event_priority_set(struct event *, int); + + +/* These functions deal with buffering input and output */ + +struct evbuffer { + u_char *buffer; + u_char *orig_buffer; + + size_t misalign; + size_t totallen; + size_t off; + + void (*cb)(struct evbuffer *, size_t, size_t, void *); + void *cbarg; +}; + +/* Just for error reporting - use other constants otherwise */ +#define EVBUFFER_READ 0x01 +#define EVBUFFER_WRITE 0x02 +#define EVBUFFER_EOF 0x10 +#define EVBUFFER_ERROR 0x20 +#define EVBUFFER_TIMEOUT 0x40 + +struct bufferevent; +typedef void (*evbuffercb)(struct bufferevent *, void *); +typedef void (*everrorcb)(struct bufferevent *, short what, void *); + +struct event_watermark { + size_t low; + size_t high; +}; + +#ifndef EVENT_NO_STRUCT +struct bufferevent { + struct event_base *ev_base; + + struct event ev_read; + struct event ev_write; + + struct evbuffer *input; + struct evbuffer *output; + + struct event_watermark wm_read; + struct event_watermark wm_write; + + evbuffercb readcb; + evbuffercb writecb; + everrorcb errorcb; + void *cbarg; + + int timeout_read; /* in seconds */ + int timeout_write; /* in seconds */ + + short enabled; /* events that are currently enabled */ +}; +#endif + +/** + Create a new bufferevent. + + libevent provides an abstraction on top of the regular event callbacks. + This abstraction is called a buffered event. A buffered event provides + input and output buffers that get filled and drained automatically. The + user of a buffered event no longer deals directly with the I/O, but + instead is reading from input and writing to output buffers. + + Once initialized, the bufferevent structure can be used repeatedly with + bufferevent_enable() and bufferevent_disable(). + + When read enabled the bufferevent will try to read from the file descriptor + and call the read callback. The write callback is executed whenever the + output buffer is drained below the write low watermark, which is 0 by + default. + + If multiple bases are in use, bufferevent_base_set() must be called before + enabling the bufferevent for the first time. + + @param fd the file descriptor from which data is read and written to. + This file descriptor is not allowed to be a pipe(2). + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param errorcb callback to invoke when there is an error on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @return a pointer to a newly allocated bufferevent struct, or NULL if an + error occurred + @see bufferevent_base_set(), bufferevent_free() + */ +struct bufferevent *bufferevent_new(int fd, + evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); + + +/** + Assign a bufferevent to a specific event_base. + + @param base an event_base returned by event_init() + @param bufev a bufferevent struct returned by bufferevent_new() + @return 0 if successful, or -1 if an error occurred + @see bufferevent_new() + */ +int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev); + + +/** + Assign a priority to a bufferevent. + + @param bufev a bufferevent struct + @param pri the priority to be assigned + @return 0 if successful, or -1 if an error occurred + */ +int bufferevent_priority_set(struct bufferevent *bufev, int pri); + + +/** + Deallocate the storage associated with a bufferevent structure. + + @param bufev the bufferevent structure to be freed. + */ +void bufferevent_free(struct bufferevent *bufev); + + +/** + Changes the callbacks for a bufferevent. + + @param bufev the bufferevent object for which to change callbacks + @param readcb callback to invoke when there is data to be read, or NULL if + no callback is desired + @param writecb callback to invoke when the file descriptor is ready for + writing, or NULL if no callback is desired + @param errorcb callback to invoke when there is an error on the file + descriptor + @param cbarg an argument that will be supplied to each of the callbacks + (readcb, writecb, and errorcb) + @see bufferevent_new() + */ +void bufferevent_setcb(struct bufferevent *bufev, + evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg); + +/** + Changes the file descriptor on which the bufferevent operates. + + @param bufev the bufferevent object for which to change the file descriptor + @param fd the file descriptor to operate on +*/ +void bufferevent_setfd(struct bufferevent *bufev, int fd); + +/** + Write data to a bufferevent buffer. + + The bufferevent_write() function can be used to write data to the file + descriptor. The data is appended to the output buffer and written to the + descriptor automatically as it becomes available for writing. + + @param bufev the bufferevent to be written to + @param data a pointer to the data to be written + @param size the length of the data, in bytes + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write_buffer() + */ +int bufferevent_write(struct bufferevent *bufev, + const void *data, size_t size); + + +/** + Write data from an evbuffer to a bufferevent buffer. The evbuffer is + being drained as a result. + + @param bufev the bufferevent to be written to + @param buf the evbuffer to be written + @return 0 if successful, or -1 if an error occurred + @see bufferevent_write() + */ +int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf); + + +/** + Read data from a bufferevent buffer. + + The bufferevent_read() function is used to read data from the input buffer. + + @param bufev the bufferevent to be read from + @param data pointer to a buffer that will store the data + @param size the size of the data buffer, in bytes + @return the amount of data read, in bytes. + */ +size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size); + +/** + Enable a bufferevent. + + @param bufev the bufferevent to be enabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_disable() + */ +int bufferevent_enable(struct bufferevent *bufev, short event); + + +/** + Disable a bufferevent. + + @param bufev the bufferevent to be disabled + @param event any combination of EV_READ | EV_WRITE. + @return 0 if successful, or -1 if an error occurred + @see bufferevent_enable() + */ +int bufferevent_disable(struct bufferevent *bufev, short event); + + +/** + Set the read and write timeout for a buffered event. + + @param bufev the bufferevent to be modified + @param timeout_read the read timeout + @param timeout_write the write timeout + */ +void bufferevent_settimeout(struct bufferevent *bufev, + int timeout_read, int timeout_write); + + +/** + Sets the watermarks for read and write events. + + On input, a bufferevent does not invoke the user read callback unless + there is at least low watermark data in the buffer. If the read buffer + is beyond the high watermark, the buffevent stops reading from the network. + + On output, the user write callback is invoked whenever the buffered data + falls below the low watermark. + + @param bufev the bufferevent to be modified + @param events EV_READ, EV_WRITE or both + @param lowmark the lower watermark to set + @param highmark the high watermark to set +*/ + +void bufferevent_setwatermark(struct bufferevent *bufev, short events, + size_t lowmark, size_t highmark); + +#define EVBUFFER_LENGTH(x) (x)->off +#define EVBUFFER_DATA(x) (x)->buffer +#define EVBUFFER_INPUT(x) (x)->input +#define EVBUFFER_OUTPUT(x) (x)->output + + +/** + Allocate storage for a new evbuffer. + + @return a pointer to a newly allocated evbuffer struct, or NULL if an error + occurred + */ +struct evbuffer *evbuffer_new(void); + + +/** + Deallocate storage for an evbuffer. + + @param pointer to the evbuffer to be freed + */ +void evbuffer_free(struct evbuffer *); + + +/** + Expands the available space in an event buffer. + + Expands the available space in the event buffer to at least datlen + + @param buf the event buffer to be expanded + @param datlen the new minimum length requirement + @return 0 if successful, or -1 if an error occurred +*/ +int evbuffer_expand(struct evbuffer *, size_t); + + +/** + Append data to the end of an evbuffer. + + @param buf the event buffer to be appended to + @param data pointer to the beginning of the data buffer + @param datlen the number of bytes to be copied from the data buffer + */ +int evbuffer_add(struct evbuffer *, const void *, size_t); + + + +/** + Read data from an event buffer and drain the bytes read. + + @param buf the event buffer to be read from + @param data the destination buffer to store the result + @param datlen the maximum size of the destination buffer + @return the number of bytes read + */ +int evbuffer_remove(struct evbuffer *, void *, size_t); + + +/** + * Read a single line from an event buffer. + * + * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. + * The returned buffer needs to be freed by the caller. + * + * @param buffer the evbuffer to read from + * @return pointer to a single line, or NULL if an error occurred + */ +char *evbuffer_readline(struct evbuffer *); + + +/** Used to tell evbuffer_readln what kind of line-ending to look for. + */ +enum evbuffer_eol_style { + /** Any sequence of CR and LF characters is acceptable as an EOL. */ + EVBUFFER_EOL_ANY, + /** An EOL is an LF, optionally preceded by a CR. This style is + * most useful for implementing text-based internet protocols. */ + EVBUFFER_EOL_CRLF, + /** An EOL is a CR followed by an LF. */ + EVBUFFER_EOL_CRLF_STRICT, + /** An EOL is a LF. */ + EVBUFFER_EOL_LF +}; + +/** + * Read a single line from an event buffer. + * + * Reads a line terminated by an EOL as determined by the evbuffer_eol_style + * argument. Returns a newly allocated nul-terminated string; the caller must + * free the returned value. The EOL is not included in the returned string. + * + * @param buffer the evbuffer to read from + * @param n_read_out if non-NULL, points to a size_t that is set to the + * number of characters in the returned string. This is useful for + * strings that can contain NUL characters. + * @param eol_style the style of line-ending to use. + * @return pointer to a single line, or NULL if an error occurred + */ +char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, + enum evbuffer_eol_style eol_style); + + +/** + Move data from one evbuffer into another evbuffer. + + This is a destructive add. The data from one buffer moves into + the other buffer. The destination buffer is expanded as needed. + + @param outbuf the output buffer + @param inbuf the input buffer + @return 0 if successful, or -1 if an error occurred + */ +int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *); + + +/** + Append a formatted string to the end of an evbuffer. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ... arguments that will be passed to printf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + */ +int evbuffer_add_printf(struct evbuffer *, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__((format(printf, 2, 3))) +#endif +; + + +/** + Append a va_list formatted string to the end of an evbuffer. + + @param buf the evbuffer that will be appended to + @param fmt a format string + @param ap a varargs va_list argument array that will be passed to vprintf(3) + @return The number of bytes added if successful, or -1 if an error occurred. + */ +int evbuffer_add_vprintf(struct evbuffer *, const char *fmt, va_list ap); + + +/** + Remove a specified number of bytes data from the beginning of an evbuffer. + + @param buf the evbuffer to be drained + @param len the number of bytes to drain from the beginning of the buffer + */ +void evbuffer_drain(struct evbuffer *, size_t); + + +/** + Write the contents of an evbuffer to a file descriptor. + + The evbuffer will be drained after the bytes have been successfully written. + + @param buffer the evbuffer to be written and drained + @param fd the file descriptor to be written to + @return the number of bytes written, or -1 if an error occurred + @see evbuffer_read() + */ +int evbuffer_write(struct evbuffer *, int); + + +/** + Read from a file descriptor and store the result in an evbuffer. + + @param buf the evbuffer to store the result + @param fd the file descriptor to read from + @param howmuch the number of bytes to be read + @return the number of bytes read, or -1 if an error occurred + @see evbuffer_write() + */ +int evbuffer_read(struct evbuffer *, int, int); + + +/** + Find a string within an evbuffer. + + @param buffer the evbuffer to be searched + @param what the string to be searched for + @param len the length of the search string + @return a pointer to the beginning of the search string, or NULL if the search failed. + */ +u_char *evbuffer_find(struct evbuffer *, const u_char *, size_t); + +/** + Set a callback to invoke when the evbuffer is modified. + + @param buffer the evbuffer to be monitored + @param cb the callback function to invoke when the evbuffer is modified + @param cbarg an argument to be provided to the callback function + */ +void evbuffer_setcb(struct evbuffer *, void (*)(struct evbuffer *, size_t, size_t, void *), void *); + +/* + * Marshaling tagged data - We assume that all tags are inserted in their + * numeric order - so that unknown tags will always be higher than the + * known ones - and we can just ignore the end of an event buffer. + */ + +void evtag_init(void); + +void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data, + ev_uint32_t len); + +/** + Encode an integer and store it in an evbuffer. + + We encode integer's by nibbles; the first nibble contains the number + of significant nibbles - 1; this allows us to encode up to 64-bit + integers. This function is byte-order independent. + + @param evbuf evbuffer to store the encoded number + @param number a 32-bit integer + */ +void encode_int(struct evbuffer *evbuf, ev_uint32_t number); + +void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, + ev_uint32_t integer); + +void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, + const char *string); + +void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, + struct timeval *tv); + +int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, + struct evbuffer *dst); +int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag); +int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength); +int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength); +int evtag_consume(struct evbuffer *evbuf); + +int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag, + ev_uint32_t *pinteger); + +int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, + void *data, size_t len); + +int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag, + char **pstring); + +int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag, + struct timeval *ptv); + +#ifdef __cplusplus +} +#endif + +#endif /* _EVENT_H_ */
diff --git a/base/third_party/libevent/event_rpcgen.py b/third_party/libevent/event_rpcgen.py similarity index 100% rename from base/third_party/libevent/event_rpcgen.py rename to third_party/libevent/event_rpcgen.py
diff --git a/base/third_party/libevent/event_tagging.c b/third_party/libevent/event_tagging.c similarity index 100% rename from base/third_party/libevent/event_tagging.c rename to third_party/libevent/event_tagging.c
diff --git a/base/third_party/libevent/evhttp.h b/third_party/libevent/evhttp.h similarity index 100% rename from base/third_party/libevent/evhttp.h rename to third_party/libevent/evhttp.h
diff --git a/base/third_party/libevent/evport.c b/third_party/libevent/evport.c similarity index 100% rename from base/third_party/libevent/evport.c rename to third_party/libevent/evport.c
diff --git a/base/third_party/libevent/evrpc-internal.h b/third_party/libevent/evrpc-internal.h similarity index 100% rename from base/third_party/libevent/evrpc-internal.h rename to third_party/libevent/evrpc-internal.h
diff --git a/base/third_party/libevent/evrpc.c b/third_party/libevent/evrpc.c similarity index 100% rename from base/third_party/libevent/evrpc.c rename to third_party/libevent/evrpc.c
diff --git a/base/third_party/libevent/evrpc.h b/third_party/libevent/evrpc.h similarity index 100% rename from base/third_party/libevent/evrpc.h rename to third_party/libevent/evrpc.h
diff --git a/base/third_party/libevent/evsignal.h b/third_party/libevent/evsignal.h similarity index 100% rename from base/third_party/libevent/evsignal.h rename to third_party/libevent/evsignal.h
diff --git a/base/third_party/libevent/evutil.c b/third_party/libevent/evutil.c similarity index 100% rename from base/third_party/libevent/evutil.c rename to third_party/libevent/evutil.c
diff --git a/base/third_party/libevent/evutil.h b/third_party/libevent/evutil.h similarity index 100% rename from base/third_party/libevent/evutil.h rename to third_party/libevent/evutil.h
diff --git a/base/third_party/libevent/freebsd/config.h b/third_party/libevent/freebsd/config.h similarity index 100% rename from base/third_party/libevent/freebsd/config.h rename to third_party/libevent/freebsd/config.h
diff --git a/base/third_party/libevent/freebsd/event-config.h b/third_party/libevent/freebsd/event-config.h similarity index 100% rename from base/third_party/libevent/freebsd/event-config.h rename to third_party/libevent/freebsd/event-config.h
diff --git a/base/third_party/libevent/http-internal.h b/third_party/libevent/http-internal.h similarity index 100% rename from base/third_party/libevent/http-internal.h rename to third_party/libevent/http-internal.h
diff --git a/base/third_party/libevent/http.c b/third_party/libevent/http.c similarity index 100% rename from base/third_party/libevent/http.c rename to third_party/libevent/http.c
diff --git a/base/third_party/libevent/kqueue.c b/third_party/libevent/kqueue.c similarity index 100% rename from base/third_party/libevent/kqueue.c rename to third_party/libevent/kqueue.c
diff --git a/base/third_party/libevent/linux/config.h b/third_party/libevent/linux/config.h similarity index 100% rename from base/third_party/libevent/linux/config.h rename to third_party/libevent/linux/config.h
diff --git a/base/third_party/libevent/linux/event-config.h b/third_party/libevent/linux/event-config.h similarity index 100% rename from base/third_party/libevent/linux/event-config.h rename to third_party/libevent/linux/event-config.h
diff --git a/base/third_party/libevent/log.c b/third_party/libevent/log.c similarity index 100% rename from base/third_party/libevent/log.c rename to third_party/libevent/log.c
diff --git a/base/third_party/libevent/log.h b/third_party/libevent/log.h similarity index 100% rename from base/third_party/libevent/log.h rename to third_party/libevent/log.h
diff --git a/base/third_party/libevent/m4/.dummy b/third_party/libevent/m4/.dummy similarity index 100% rename from base/third_party/libevent/m4/.dummy rename to third_party/libevent/m4/.dummy
diff --git a/base/third_party/libevent/mac/config.h b/third_party/libevent/mac/config.h similarity index 100% rename from base/third_party/libevent/mac/config.h rename to third_party/libevent/mac/config.h
diff --git a/base/third_party/libevent/mac/event-config.h b/third_party/libevent/mac/event-config.h similarity index 100% rename from base/third_party/libevent/mac/event-config.h rename to third_party/libevent/mac/event-config.h
diff --git a/base/third_party/libevent/min_heap.h b/third_party/libevent/min_heap.h similarity index 100% rename from base/third_party/libevent/min_heap.h rename to third_party/libevent/min_heap.h
diff --git a/base/third_party/libevent/poll.c b/third_party/libevent/poll.c similarity index 100% rename from base/third_party/libevent/poll.c rename to third_party/libevent/poll.c
diff --git a/base/third_party/libevent/sample/Makefile.am b/third_party/libevent/sample/Makefile.am similarity index 100% rename from base/third_party/libevent/sample/Makefile.am rename to third_party/libevent/sample/Makefile.am
diff --git a/base/third_party/libevent/sample/event-test.c b/third_party/libevent/sample/event-test.c similarity index 100% rename from base/third_party/libevent/sample/event-test.c rename to third_party/libevent/sample/event-test.c
diff --git a/base/third_party/libevent/sample/signal-test.c b/third_party/libevent/sample/signal-test.c similarity index 100% rename from base/third_party/libevent/sample/signal-test.c rename to third_party/libevent/sample/signal-test.c
diff --git a/base/third_party/libevent/sample/time-test.c b/third_party/libevent/sample/time-test.c similarity index 100% rename from base/third_party/libevent/sample/time-test.c rename to third_party/libevent/sample/time-test.c
diff --git a/base/third_party/libevent/select.c b/third_party/libevent/select.c similarity index 100% rename from base/third_party/libevent/select.c rename to third_party/libevent/select.c
diff --git a/base/third_party/libevent/signal.c b/third_party/libevent/signal.c similarity index 100% rename from base/third_party/libevent/signal.c rename to third_party/libevent/signal.c
diff --git a/base/third_party/libevent/solaris/config.h b/third_party/libevent/solaris/config.h similarity index 100% rename from base/third_party/libevent/solaris/config.h rename to third_party/libevent/solaris/config.h
diff --git a/base/third_party/libevent/solaris/event-config.h b/third_party/libevent/solaris/event-config.h similarity index 100% rename from base/third_party/libevent/solaris/event-config.h rename to third_party/libevent/solaris/event-config.h
diff --git a/base/third_party/libevent/stamp-h.in b/third_party/libevent/stamp-h.in similarity index 100% rename from base/third_party/libevent/stamp-h.in rename to third_party/libevent/stamp-h.in
diff --git a/base/third_party/libevent/strlcpy-internal.h b/third_party/libevent/strlcpy-internal.h similarity index 100% rename from base/third_party/libevent/strlcpy-internal.h rename to third_party/libevent/strlcpy-internal.h
diff --git a/base/third_party/libevent/strlcpy.c b/third_party/libevent/strlcpy.c similarity index 100% rename from base/third_party/libevent/strlcpy.c rename to third_party/libevent/strlcpy.c
diff --git a/base/third_party/libevent/test/Makefile.am b/third_party/libevent/test/Makefile.am similarity index 100% rename from base/third_party/libevent/test/Makefile.am rename to third_party/libevent/test/Makefile.am
diff --git a/base/third_party/libevent/test/Makefile.nmake b/third_party/libevent/test/Makefile.nmake similarity index 100% rename from base/third_party/libevent/test/Makefile.nmake rename to third_party/libevent/test/Makefile.nmake
diff --git a/base/third_party/libevent/test/bench.c b/third_party/libevent/test/bench.c similarity index 100% rename from base/third_party/libevent/test/bench.c rename to third_party/libevent/test/bench.c
diff --git a/base/third_party/libevent/test/regress.c b/third_party/libevent/test/regress.c similarity index 100% rename from base/third_party/libevent/test/regress.c rename to third_party/libevent/test/regress.c
diff --git a/base/third_party/libevent/test/regress.h b/third_party/libevent/test/regress.h similarity index 100% rename from base/third_party/libevent/test/regress.h rename to third_party/libevent/test/regress.h
diff --git a/base/third_party/libevent/test/regress.rpc b/third_party/libevent/test/regress.rpc similarity index 100% rename from base/third_party/libevent/test/regress.rpc rename to third_party/libevent/test/regress.rpc
diff --git a/base/third_party/libevent/test/regress_dns.c b/third_party/libevent/test/regress_dns.c similarity index 100% rename from base/third_party/libevent/test/regress_dns.c rename to third_party/libevent/test/regress_dns.c
diff --git a/base/third_party/libevent/test/regress_http.c b/third_party/libevent/test/regress_http.c similarity index 100% rename from base/third_party/libevent/test/regress_http.c rename to third_party/libevent/test/regress_http.c
diff --git a/base/third_party/libevent/test/regress_rpc.c b/third_party/libevent/test/regress_rpc.c similarity index 100% rename from base/third_party/libevent/test/regress_rpc.c rename to third_party/libevent/test/regress_rpc.c
diff --git a/base/third_party/libevent/test/test-eof.c b/third_party/libevent/test/test-eof.c similarity index 100% rename from base/third_party/libevent/test/test-eof.c rename to third_party/libevent/test/test-eof.c
diff --git a/base/third_party/libevent/test/test-init.c b/third_party/libevent/test/test-init.c similarity index 100% rename from base/third_party/libevent/test/test-init.c rename to third_party/libevent/test/test-init.c
diff --git a/base/third_party/libevent/test/test-time.c b/third_party/libevent/test/test-time.c similarity index 100% rename from base/third_party/libevent/test/test-time.c rename to third_party/libevent/test/test-time.c
diff --git a/base/third_party/libevent/test/test-weof.c b/third_party/libevent/test/test-weof.c similarity index 100% rename from base/third_party/libevent/test/test-weof.c rename to third_party/libevent/test/test-weof.c
diff --git a/base/third_party/libevent/test/test.sh b/third_party/libevent/test/test.sh similarity index 100% rename from base/third_party/libevent/test/test.sh rename to third_party/libevent/test/test.sh
diff --git a/base/third_party/libevent/whatsnew-14.txt b/third_party/libevent/whatsnew-14.txt similarity index 100% rename from base/third_party/libevent/whatsnew-14.txt rename to third_party/libevent/whatsnew-14.txt
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py index 0c96821..4b503ca 100755 --- a/tools/checklicenses/checklicenses.py +++ b/tools/checklicenses/checklicenses.py
@@ -114,9 +114,6 @@ 'base/third_party/icu': [ # http://crbug.com/98087 'UNKNOWN', ], - 'base/third_party/libevent': [ # http://crbug.com/98309 - 'UNKNOWN', - ], 'buildtools/third_party/libc++/trunk/test': [ # http://llvm.org/bugs/show_bug.cgi?id=25980 'UNKNOWN', @@ -402,6 +399,9 @@ 'third_party/lcov/contrib/galaxy/genflat.pl': [ 'GPL (v2 or later)', ], + 'third_party/libevent': [ # http://crbug.com/98309 + 'UNKNOWN', + ], 'third_party/libjpeg_turbo': [ # http://crbug.com/98314 'UNKNOWN', ],
diff --git a/tools/checkperms/checkperms.py b/tools/checkperms/checkperms.py index ddc275aa..37a1d0ed 100755 --- a/tools/checkperms/checkperms.py +++ b/tools/checkperms/checkperms.py
@@ -173,8 +173,6 @@ # # Case-insensitive, lower-case only. IGNORED_PATHS = ( - 'base/third_party/libevent/autogen.sh', - 'base/third_party/libevent/test/test.sh', 'native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/' '__init__.py', 'out/',
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py index 46fc466..132766e8 100755 --- a/tools/clang/scripts/build.py +++ b/tools/clang/scripts/build.py
@@ -720,16 +720,16 @@ cc = os.path.join(PINNED_CLANG_DIR, 'bin', 'clang') cxx = os.path.join(PINNED_CLANG_DIR, 'bin', 'clang++') - if sys.platform != 'darwin': - # The host clang has lld, but self-hosting with lld is still slightly - # broken on mac. - # TODO: check if this works now. - base_cmake_args.append('-DLLVM_ENABLE_LLD=ON') - if sys.platform.startswith('linux'): MaybeDownloadHostGcc(args) base_cmake_args += [ '-DLLVM_STATIC_LINK_CXX_STDLIB=ON' ] + if sys.platform != 'darwin': + # The host clang has lld, but self-hosting with lld is still slightly + # broken on mac. + # TODO: check if this works now. + base_cmake_args.append('-DLLVM_ENABLE_LLD=ON') + if sys.platform == 'darwin': # For libc++, we only want the headers. base_cmake_args.extend([ @@ -1092,11 +1092,8 @@ 'COMPILER_RT_ENABLE_IOS=ON', 'COMPILER_RT_ENABLE_WATCHOS=OFF', 'COMPILER_RT_ENABLE_TVOS=OFF', - # armv7 is A5 and earlier, armv7s is A6+ (2012 and later, before 64-bit - # iPhones). armv7k is Apple Watch, which we don't need. - 'DARWIN_ios_ARCHS=armv7;armv7s;arm64', - 'DARWIN_iossim_ARCHS=i386;x86_64;arm64', - # We don't need 32-bit intel support for macOS, we only ship 64-bit. + 'DARWIN_ios_ARCHS=arm64', + 'DARWIN_iossim_ARCHS=arm64;x86_64', 'DARWIN_osx_ARCHS=arm64;x86_64', ] + compiler_rt_cmake_flags(sanitizers=True, profile=True) # compiler-rt is built for all platforms/arches with a single
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 8bf1d96..c062997 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -36,7 +36,7 @@ # Reverting problematic clang rolls is safe, though. # This is the output of `git describe` and is usable as a commit-ish. CLANG_REVISION = 'llvmorg-15-init-13850-ge2913362' -CLANG_SUB_REVISION = 1 +CLANG_SUB_REVISION = 2 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION) RELEASE_VERSION = '15.0.0'
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 626187e..a1ab356 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -160,6 +160,10 @@ "META": {"sizes": {"includes": [10]}}, "includes": [1480], }, + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/notification_tester/resources.grd": { + "META": {"sizes": {"includes": [5]}}, + "includes": [1490], + }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/commander/commander_resources.grd": { "META": {"sizes": {"includes": [15]}}, "includes": [1500],
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 95ad7ee..d042223 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -3453,7 +3453,7 @@ ], 'updater_debug_bot_x86_reclient': [ - 'updater_on_win_mac', 'debug_static_bot_reclient', 'x86', + 'updater_on_win_mac', 'debug_static_bot_reclient', 'x86', 'no_symbols', ], 'updater_release_bot': [
diff --git a/tools/mb/mb_config_expectations/chromium.updater.json b/tools/mb/mb_config_expectations/chromium.updater.json index 255f1ea..3918ba5 100644 --- a/tools/mb/mb_config_expectations/chromium.updater.json +++ b/tools/mb/mb_config_expectations/chromium.updater.json
@@ -60,7 +60,7 @@ "enable_chromium_updater": true, "is_component_build": false, "is_debug": true, - "symbol_level": 1, + "symbol_level": 0, "target_cpu": "x86", "use_remoteexec": true }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 662be0a..30b06b6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2664,19 +2664,6 @@ <int value="2" label="RemoteException"/> </enum> -<enum name="AndroidWebViewInitType"> - <int value="0" label="Synchronous"> - Initialization is called from UI thread. - </int> - <int value="1" label="Asynchronous"> - Initialization is called from background thread. - </int> - <int value="2" label="Already started"> - Initialization is called from the UI thread, but had previously been - requested by a background thread. - </int> -</enum> - <enum name="AndroidWebViewNonEmbeddedMetricsParsingLogResult"> <int value="0" label="Success"/> <int value="1" label="Malformed protobuf"/> @@ -7121,6 +7108,8 @@ <int value="55" label="CreditCardSeamlessFillable :-( (all other scenarios = Partial fill)"/> + <int value="56" + label="Local suggestion of a deduped server card filled (once)"/> </enum> <enum name="AutofillFormSubmittedState"> @@ -98500,6 +98489,7 @@ <int value="731985139" label="Heritage - 3218288446354675"/> <int value="732594745" label="Collage - 6982402080145977"/> <int value="738877507" label="Leisure - 2226962756689987"/> + <int value="741269277" label="LGBTQ Artists - 459480637562653"/> <int value="766726480" label="Leisure - 18440296559765836112"/> <int value="791271562" label="Floral - 565819782846602"/> <int value="810052365" label="Landscapes - 1422584172800781"/> @@ -98542,7 +98532,9 @@ <int value="1206215167" label="Art - 18445129029773517311"/> <int value="1243872355" label="Heritage - 18443899384969296995"/> <int value="1250920293" label="Art - 18443102780212086629"/> + <int value="1253859916" label="LGBTQ Artists - 7464667299209804"/> <int value="1259225205" label="Composition - 18442882001721507957"/> + <int value="1279122789" label="LGBTQ Artists - 18442382398260632933"/> <int value="1280051538" label="Made by Canvas - 3143878686017874"/> <int value="1305614077" label="Leisure - 4907156060116733"/> <int value="1308519753" label="Art - 18438839853429714249"/> @@ -98598,6 +98590,7 @@ <int value="1824980809" label="Landscapes - 1364019013680969"/> <int value="1827600028" label="Art - 18444590905352451740"/> <int value="1828136429" label="Landscapes - 2607257430205933"/> + <int value="1832792896" label="LGBTQ Artists - 8351230732415808"/> <int value="1840610500" label="Composition - 7377364085734596"/> <int value="1873509802" label="Element - 251772856401322"/> <int value="1875798627" label="Landscapes - 5124387486198371"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml index 914cb2f2..7150682 100644 --- a/tools/metrics/histograms/metadata/accessibility/histograms.xml +++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -1109,7 +1109,7 @@ </histogram> <histogram name="Accessibility.LiveCaption" enum="BooleanEnabled" - expires_after="2022-11-27"> + expires_after="2023-06-13"> <owner>katie@chromium.org</owner> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> @@ -1121,7 +1121,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.AudioPropertyChanged" - enum="BooleanEnabled" expires_after="2022-07-26"> + enum="BooleanEnabled" expires_after="2023-06-13"> <owner>katie@chromium.org</owner> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> @@ -1145,7 +1145,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.Duration.CaptionBubble{Visibility}2" - units="ms" expires_after="2022-07-26"> + units="ms" expires_after="2023-06-13"> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> <owner>chrome-a11y-core@google.com</owner> @@ -1163,7 +1163,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.EnableFrom{Entrypoint}" - enum="BooleanEnabled" expires_after="2022-07-26"> + enum="BooleanEnabled" expires_after="2023-06-13"> <owner>katie@chromium.org</owner> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> @@ -1180,7 +1180,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.ExpandBubble" - enum="LiveCaptionExpandBubbleEvent" expires_after="2022-07-26"> + enum="LiveCaptionExpandBubbleEvent" expires_after="2023-06-13"> <owner>katie@chromium.org</owner> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> @@ -1191,7 +1191,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.FeatureEnabled" - enum="BooleanEnabled" expires_after="2022-11-27"> + enum="BooleanEnabled" expires_after="2023-06-13"> <owner>katie@chromium.org</owner> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> @@ -1203,7 +1203,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.LoadSodaErrorCode" - enum="WinGetLastError" expires_after="2022-12-26"> + enum="WinGetLastError" expires_after="2023-06-13"> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> <owner>chrome-a11y-core@google.com</owner> @@ -1231,7 +1231,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.LoadSodaResult" - enum="LoadSodaResult" expires_after="2022-11-27"> + enum="LoadSodaResult" expires_after="2023-06-13"> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> <owner>chrome-a11y-core@google.com</owner> @@ -1242,7 +1242,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.Session2" - enum="LiveCaptionSessionEvent" expires_after="2022-11-27"> + enum="LiveCaptionSessionEvent" expires_after="2023-06-13"> <owner>katie@chromium.org</owner> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> @@ -1259,7 +1259,7 @@ <histogram name="Accessibility.LiveCaption.SodaVerificationFailureMissingIndicatorFile" - enum="Boolean" expires_after="2022-09-25"> + enum="Boolean" expires_after="2023-06-13"> <owner>abigailbklein@google.com</owner> <owner>evliu@google.com</owner> <owner>chrome-a11y-core@google.com</owner> @@ -1271,7 +1271,7 @@ </histogram> <histogram name="Accessibility.LiveCaption.SpeechRecognitionServiceLanguage" - enum="SodaLanguageCode" expires_after="2022-07-26"> + enum="SodaLanguageCode" expires_after="2023-06-13"> <owner>evliu@google.com</owner> <owner>chrome-media-ux@google.com</owner> <owner>chrome-a11y-core@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index 7bb1c2e..c7db683 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -4466,16 +4466,6 @@ </summary> </histogram> -<histogram name="Android.WebView.Startup.InitType" - enum="AndroidWebViewInitType" expires_after="2022-06-21"> - <owner>torne@chromium.org</owner> - <owner>src/android_webview/OWNERS</owner> - <summary> - Records which thread WebView initialization started from. The metric is - recorded during the first startChromiumLocked call. - </summary> -</histogram> - <histogram name="Android.WebView.SupportLibrary.ClientIsCompat" enum="WebViewClientTypeEnum" expires_after="2022-10-06"> <owner>ntfschr@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml index 771d64a..f490a94 100644 --- a/tools/metrics/histograms/metadata/apps/histograms.xml +++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -425,9 +425,9 @@ <owner>jamescook@chromium.org</owner> <owner>tbarzic@chromium.org</owner> <summary> - Whether the user has hidden the productivity launcher "continue where - you left off" section using the right-click menu. Recorded once per - launcher open. Split by clamshell vs. tablet mode. + Whether the user has manually hidden the productivity launcher + "continue where you left off" section. Recorded once per launcher + open. Split by clamshell vs. tablet mode. </summary> <token key="TabletOrClamshell" variants="TabletOrClamshellMode"/> </histogram>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 2e2e9e0..481d2c1 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -1981,6 +1981,13 @@ </summary> </histogram> +<histogram name="Ash.DeskTemplate.ReplaceSaveAndRecall" enum="BooleanHit" + expires_after="2022-12-03"> + <owner>dandersson@chromium.org</owner> + <owner>janetmac@chromium.org</owner> + <summary>Recorded when the user replaces a Save and Recall desk.</summary> +</histogram> + <histogram name="Ash.DeskTemplate.ReplaceTemplate" enum="BooleanHit" expires_after="2022-07-14"> <owner>aprilzhou@chromium.org</owner> @@ -1999,6 +2006,18 @@ </summary> </histogram> +<histogram name="Ash.DeskTemplate.SaveAndRecallUnsupportedAppDialogShow" + units="count" expires_after="2022-12-03"> + <owner>dandersson@google.com</owner> + <owner>janetmac@chromium.org</owner> + <summary> + Records the number of times the unsupported Apps dialog shows. This event is + triggered when a user attempts to save a Save and Recall desk that contains + an unsupported app type. Currently the saved desk feature only supports + PWAs, Extensions, and browser instances. + </summary> +</histogram> + <histogram name="Ash.DeskTemplate.SaveAndRecallWindowAndTabCount" units="count" expires_after="2022-11-24"> <owner>dandersson@chromium.org</owner> @@ -2025,6 +2044,16 @@ <summary>Records the number of tabs in a template when it is saved.</summary> </histogram> +<histogram name="Ash.DeskTemplate.TimeBetweenSaveAndRecall" units="seconds" + expires_after="2022-12-03"> + <owner>dandersson@chromium.org</owner> + <owner>janetmac@chromium.org</owner> + <summary> + The number of seconds between the creation of a new Save and Recall desk and + its launch (and automatic deletion). + </summary> +</histogram> + <histogram name="Ash.DeskTemplate.TimeToLoadTemplate" units="ms" expires_after="2023-01-18"> <owner>avynn@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index 87d90f0..803981e 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -464,7 +464,7 @@ </histogram> <histogram name="Autofill.BetterAuth.CardUnmaskDuration.Fido" units="ms" - expires_after="2022-12-04"> + expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -476,7 +476,7 @@ <histogram name="Autofill.BetterAuth.CardUnmaskDuration.Fido.{CardType}.{Result}" - units="ms" expires_after="2022-08-01"> + units="ms" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -489,7 +489,7 @@ </histogram> <histogram name="Autofill.BetterAuth.CardUnmaskPreflightCalled" - enum="BooleanHit" expires_after="2022-10-04"> + enum="BooleanHit" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -506,7 +506,7 @@ </histogram> <histogram name="Autofill.BetterAuth.CardUnmaskPreflightDuration" units="ms" - expires_after="2022-10-04"> + expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -519,7 +519,7 @@ </histogram> <histogram name="Autofill.BetterAuth.CardUnmaskTypeDecision" - enum="AutofillCreditCardUnmaskDecisionMetric" expires_after="2022-10-04"> + enum="AutofillCreditCardUnmaskDecisionMetric" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -533,7 +533,7 @@ <histogram name="Autofill.BetterAuth.FlowEvents.{BetterAuthFlowType}.{CardType}" - enum="AutofillCreditCardAuthenticationEvents" expires_after="2022-08-01"> + enum="AutofillCreditCardAuthenticationEvents" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -548,7 +548,7 @@ <histogram name="Autofill.BetterAuth.FlowEvents{AutofillCreditCardAuthenticationFlows}" - enum="AutofillCreditCardAuthenticationEvents" expires_after="2022-08-01"> + enum="AutofillCreditCardAuthenticationEvents" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -569,7 +569,7 @@ <histogram name="Autofill.BetterAuth.OptInCalled{AutofillCreditCardWebauthnOptInOrigin}" - enum="AutofillCreditCardWebauthnOptInParameters" expires_after="2022-08-01"> + enum="AutofillCreditCardWebauthnOptInParameters" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -586,7 +586,7 @@ <histogram name="Autofill.BetterAuth.OptInPromoShown{AutofillCreditCardWebauthnOptInOrigin}" - enum="BooleanHit" expires_after="2022-08-01"> + enum="BooleanHit" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -609,7 +609,7 @@ <histogram name="Autofill.BetterAuth.OptInPromoUserDecision{AutofillCreditCardWebauthnOptInOrigin}" - enum="AutofillWebauthnOptInPromoUserDecision" expires_after="2022-08-01"> + enum="AutofillWebauthnOptInPromoUserDecision" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -625,7 +625,7 @@ </histogram> <histogram name="Autofill.BetterAuth.OptOutCalled.FromSettingsPage" - enum="BooleanHit" expires_after="2022-12-11"> + enum="BooleanHit" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -642,7 +642,7 @@ <histogram name="Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn.Duration" - units="ms" expires_after="2022-12-04"> + units="ms" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -658,7 +658,7 @@ <histogram name="Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn.TimedOutCvcFallback" enum="AutofillCreditCardUserPerceivedLatencyFollowUp" - expires_after="2022-12-04"> + expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -673,7 +673,7 @@ <histogram name="Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection{AutofillFidoAuthenticationEnabledState}" - enum="AutofillCreditCardPreflightCallEvent" expires_after="2022-08-01"> + enum="AutofillCreditCardPreflightCallEvent" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -691,7 +691,7 @@ </histogram> <histogram name="Autofill.BetterAuth.UserVerifiabilityCheckDuration" units="ms" - expires_after="2022-10-04"> + expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -704,7 +704,7 @@ <histogram name="Autofill.BetterAuth.WebauthnResult{AutofillFidoUserVerificationFlow}" - enum="AutofillCreditCardWebauthnResultMetric" expires_after="2022-08-01"> + enum="AutofillCreditCardWebauthnResultMetric" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <owner>autofill-auth-team@google.com</owner> @@ -1102,7 +1102,7 @@ </histogram> <histogram name="Autofill.ExpirationDateFixFlowPrompt.Events" - enum="AutofillExpirationDateFixFlowPromptEvent" expires_after="2022-08-01"> + enum="AutofillExpirationDateFixFlowPromptEvent" expires_after="2023-07-01"> <owner>siashah@google.com</owner> <owner>jsaul@google.com</owner> <owner>payments-autofill-team@google.com</owner> @@ -1114,7 +1114,7 @@ </histogram> <histogram name="Autofill.ExpirationDateFixFlowPromptShown" enum="Boolean" - expires_after="2022-08-01"> + expires_after="2023-07-01"> <owner>siashah@google.com</owner> <owner>jsaul@google.com</owner> <owner>payments-autofill-team@google.com</owner> @@ -3394,7 +3394,7 @@ <histogram name="Autofill.UnmaskPrompt.Duration{AutofillUnmaskPromptCloseReasonEvents}" - units="ms" expires_after="2022-08-01"> + units="ms" expires_after="2023-07-01"> <owner>jsaul@google.com</owner> <owner>siyua@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml index e040cca..dd5f557 100644 --- a/tools/metrics/histograms/metadata/tab/histograms.xml +++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1806,7 +1806,7 @@ </histogram> <histogram name="Tabs.PersistedTabData.Storage.Delete.File" - enum="BooleanSuccess" expires_after="2022-07-03"> + enum="BooleanSuccess" expires_after="2023-06-20"> <owner>yusufo@chromium.org</owner> <owner>nyquist@chromium.org</owner> <owner>dtrainor@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index b503ac19..9dc950a 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "53fc881fbd90c7b86c93038753e5a58e8dc280df", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/a15b969a82947fe647e30f9aea938a6bf11d3d68/trace_processor_shell.exe" + "hash": "87054fb59f5b8043323a2d3e9d7e91e1f46a0e38", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/fb9252f9498fb45f62665a83bfdbe59b39cbccbd/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "0222c03249c2ac97990c17ff2bf951c16d63c3b8", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/5c85522e6e4c1670e58b341f05b68892df56a3c7/trace_processor_shell" + "hash": "8f86d818de0a5224033257321e31d91f4599f7c9", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/3d3f58658fdecc553543e801076e44febf5490b5/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6", "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "695c35c4dc544a9359c100ffafa58d7322eb7633", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/ae42e46f238d58c259af6366aba90e18e975cfa5/trace_processor_shell" + "hash": "2981176e3649eceaf7e13b78bee2cda9d90eafbf", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/fb9252f9498fb45f62665a83bfdbe59b39cbccbd/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/traffic_annotation/auditor/chromeos/safe_list.txt b/tools/traffic_annotation/auditor/chromeos/safe_list.txt index 2f2fca50..d61897e 100644 --- a/tools/traffic_annotation/auditor/chromeos/safe_list.txt +++ b/tools/traffic_annotation/auditor/chromeos/safe_list.txt
@@ -2,7 +2,6 @@ # Please do not add any new safelist. # missing,chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.cc -missing,chrome/browser/ash/printing/server_printers_fetcher.cc missing,chrome/browser/ash/customization/customization_wallpaper_downloader.cc missing,ash/wallpaper/wallpaper_controller_impl.cc all,chromeos/printing/printer_config_cache.cc
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 08fc3236..ea0a214f 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -378,4 +378,5 @@ <item id="drivefs_http_client" added_in_milestone="104" content_hash_code="042b8f2c" os_list="chromeos" file_path="ash/components/drivefs/drivefs_http_client.cc" /> <item id="borealis_splash_logo_loader" added_in_milestone="104" content_hash_code="031855a1" os_list="chromeos" file_path="chrome/browser/ui/views/borealis/borealis_splash_screen_view.cc" /> <item id="pending_beacon_api" added_in_milestone="105" content_hash_code="02288864" os_list="linux,windows,android,chromeos" file_path="content/browser/renderer_host/pending_beacon_service.cc" /> + <item id="printing_server_printers_query" added_in_milestone="106" content_hash_code="06f4759c" os_list="chromeos" file_path="chrome/browser/ash/printing/server_printers_fetcher.cc" /> </annotations>
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index fdcb3648..84160c2 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -111,6 +111,7 @@ <annotation id="printing_oauth2_next_token_request"/> <annotation id="printing_oauth2_registration_request"/> <annotation id="printing_oauth2_token_exchange_request"/> + <annotation id="printing_server_printers_query"/> </sender> <sender name="Device Activity"> <annotation id="device_activity_client_health_check"/>
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index e155257..0cd1985 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -7287,6 +7287,10 @@ case ax::mojom::Role::kLabelText: case ax::mojom::Role::kListBoxOption: case ax::mojom::Role::kListItem: + // Treat the root of a MathML tree as content/control so that it is seen + // by UIA clients. The remainder of the tree remains as text for now until + // UIA mappings for MathML are defined (https://crbug.com/1260585). + case ax::mojom::Role::kMathMLMath: case ax::mojom::Role::kMeter: case ax::mojom::Role::kProgressIndicator: case ax::mojom::Role::kRow:
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn index bf93b8d..7173b66 100644 --- a/ui/file_manager/file_manager/background/js/BUILD.gn +++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -91,7 +91,7 @@ strict_error_checking_closure_args + [ "js_module_root=./gen/ui", "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "hide_warnings_for=third_party/", ] } @@ -112,7 +112,7 @@ strict_error_checking_closure_args + [ "js_module_root=./gen/ui", "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "hide_warnings_for=third_party/", ] } @@ -801,7 +801,7 @@ strict_error_checking_closure_args + [ "js_module_root=./gen/ui", "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "hide_warnings_for=third_party/", ] }
diff --git a/ui/file_manager/file_manager/background/js/crostini_unittest.m.js b/ui/file_manager/file_manager/background/js/crostini_unittest.m.js index 1f2ba6a..27f5a972 100644 --- a/ui/file_manager/file_manager/background/js/crostini_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/crostini_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import { assertFalse,assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {installMockChrome} from '../../common/js/mock_chrome.js'; import {MockDirectoryEntry, MockEntry, MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_manager/background/js/device_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/device_handler_unittest.m.js index d1cab376..eab1b80 100644 --- a/ui/file_manager/file_manager/background/js/device_handler_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/device_handler_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {importer} from '../../common/js/importer_common.js'; import {metrics} from '../../common/js/metrics.js';
diff --git a/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.m.js index a1badca..efe6daf 100644 --- a/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals,assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {installMockChrome} from '../../common/js/mock_chrome.js'; import {ProgressItemState} from '../../common/js/progress_center_common.js';
diff --git a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js index f6778bf..75a2cd6 100644 --- a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {importer} from '../../common/js/importer_common.js'; import {installMockChrome, MockCommandLinePrivate} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.m.js index c97408d..3b44c06 100644 --- a/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/file_operation_handler_unittest.m.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 {assertArrayEquals, assertEquals, assertGT, assertLT, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertEquals, assertGT, assertLT, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {FileOperationProgressEvent} from '../../common/js/file_operation_common.js'; import {installMockChrome} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.m.js b/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.m.js index a131605..15cb4ae1 100644 --- a/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/file_operation_manager_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertArrayEquals, assertEquals, assertFalse, assertLT, assertNotReached, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertEquals, assertFalse, assertLT, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {FileOperationError, FileOperationProgressEvent} from '../../common/js/file_operation_common.js'; import {installMockChrome} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/background/js/import_history_unittest.m.js b/ui/file_manager/file_manager/background/js/import_history_unittest.m.js index cfe8b6c..428a30c 100644 --- a/ui/file_manager/file_manager/background/js/import_history_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/import_history_unittest.m.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 { assertEquals,assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {importer} from '../../common/js/importer_common.js'; import {MockChromeStorageAPI} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js index 55438b5..5d27f503 100644 --- a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {importer} from '../../common/js/importer_common.js'; import {MockCommandLinePrivate} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js b/ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js index 675bfb3..0d69951 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/media_scanner_unittest.m.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 {assertEquals, assertFalse, assertThrows} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertThrows} from 'chrome://webui-test/chai_assert.js'; import {importer} from '../../common/js/importer_common.js'; import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/background/js/metadata_proxy_unittest.m.js b/ui/file_manager/file_manager/background/js/metadata_proxy_unittest.m.js index 4cd2c60c..e491a349 100644 --- a/ui/file_manager/file_manager/background/js/metadata_proxy_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/metadata_proxy_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {MockFileSystem} from '../../common/js/mock_entry.js'; import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/background/js/mock_media_scanner.js b/ui/file_manager/file_manager/background/js/mock_media_scanner.js index 0cf55ad5..54e9274 100644 --- a/ui/file_manager/file_manager/background/js/mock_media_scanner.js +++ b/ui/file_manager/file_manager/background/js/mock_media_scanner.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 {assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {importer} from '../../common/js/importer_common.js'; import {mediaScannerInterfaces} from '../../externs/background/media_scanner.js';
diff --git a/ui/file_manager/file_manager/background/js/mount_metrics_unittest.m.js b/ui/file_manager/file_manager/background/js/mount_metrics_unittest.m.js index a8f61f1..bb16ece 100644 --- a/ui/file_manager/file_manager/background/js/mount_metrics_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/mount_metrics_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {metrics} from '../../common/js/metrics.js'; import {installMockChrome, MockCommandLinePrivate} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/background/js/task_queue_unittest.m.js b/ui/file_manager/file_manager/background/js/task_queue_unittest.m.js index c72de61..3e020c8 100644 --- a/ui/file_manager/file_manager/background/js/task_queue_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/task_queue_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {importer} from '../../common/js/importer_common.js'; import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/background/js/test_import_history.js b/ui/file_manager/file_manager/background/js/test_import_history.js index 347c01d..0f56f286 100644 --- a/ui/file_manager/file_manager/background/js/test_import_history.js +++ b/ui/file_manager/file_manager/background/js/test_import_history.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertTrue} from 'chrome://test/chai_assert.js'; +import {assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {importer} from '../../common/js/importer_common.js'; import {importerHistoryInterfaces} from '../../externs/background/import_history.js';
diff --git a/ui/file_manager/file_manager/background/js/trash_unittest.m.js b/ui/file_manager/file_manager/background/js/trash_unittest.m.js index 4c6d41d..7ac59af 100644 --- a/ui/file_manager/file_manager/background/js/trash_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/trash_unittest.m.js
@@ -4,7 +4,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockDirectoryEntry, MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js'; import {TrashDirs} from '../../common/js/trash.js';
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_unittest.m.js b/ui/file_manager/file_manager/background/js/volume_manager_unittest.m.js index bbd7565..a162c93 100644 --- a/ui/file_manager/file_manager/background/js/volume_manager_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/volume_manager_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {installMockChrome, MockCommandLinePrivate} from '../../common/js/mock_chrome.js'; import {MockDirectoryEntry, MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_manager/common/js/BUILD.gn b/ui/file_manager/file_manager/common/js/BUILD.gn index 3d42f1f..f1d66162 100644 --- a/ui/file_manager/file_manager/common/js/BUILD.gn +++ b/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -104,7 +104,7 @@ strict_error_checking_closure_args + [ "js_module_root=./gen/ui", "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", ] } @@ -424,7 +424,7 @@ strict_error_checking_closure_args + [ "js_module_root=./gen/ui", "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "hide_warnings_for=third_party/", ] }
diff --git a/ui/file_manager/file_manager/common/js/file_type_unittest.m.js b/ui/file_manager/file_manager/common/js/file_type_unittest.m.js index 12e890a..0731351 100644 --- a/ui/file_manager/file_manager/common/js/file_type_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/file_type_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {FileType} from './file_type.js'; import {MockFileSystem} from './mock_entry.js';
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.m.js b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.m.js index 56d86124..78313eb3 100644 --- a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {VolumeInfo} from '../../externs/volume_info.js';
diff --git a/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.m.js b/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.m.js index a94ee2d..501e3c1 100644 --- a/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/filtered_volume_manager_unittest.m.js
@@ -4,7 +4,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js'; import {VolumeInfo} from '../../externs/volume_info.js';
diff --git a/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js b/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js index 54a5472..6ddd309 100644 --- a/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/importer_common_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js'; import {VolumeInfo} from '../../externs/volume_info.js';
diff --git a/ui/file_manager/file_manager/common/js/lru_cache_unittest.m.js b/ui/file_manager/file_manager/common/js/lru_cache_unittest.m.js index 5299dc9..459d401 100644 --- a/ui/file_manager/file_manager/common/js/lru_cache_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/lru_cache_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {LRUCache} from './lru_cache.js'; export function testLRUCache() {
diff --git a/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.m.js b/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.m.js index c11f153..486afbb 100644 --- a/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/recent_date_bucket_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {installMockChrome} from '../../common/js/mock_chrome.js';
diff --git a/ui/file_manager/file_manager/common/js/storage_adapter_unittest.m.js b/ui/file_manager/file_manager/common/js/storage_adapter_unittest.m.js index fef3886..7d660d5 100644 --- a/ui/file_manager/file_manager/common/js/storage_adapter_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/storage_adapter_unittest.m.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 {assertDeepEquals} from 'chrome://test/chai_assert.js'; +import {assertDeepEquals} from 'chrome://webui-test/chai_assert.js'; import {storage} from './storage_adapter.js'; import {waitUntil} from './test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/common/js/unittest_util.js b/ui/file_manager/file_manager/common/js/unittest_util.js index 65684203..aebabaa 100644 --- a/ui/file_manager/file_manager/common/js/unittest_util.js +++ b/ui/file_manager/file_manager/common/js/unittest_util.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 {assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; /** * Asserts that two lists contain the same set of Entries. Entries are deemed
diff --git a/ui/file_manager/file_manager/common/js/util_unittest.m.js b/ui/file_manager/file_manager/common/js/util_unittest.m.js index f67269d7..90f1c70 100644 --- a/ui/file_manager/file_manager/common/js/util_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/util_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
diff --git a/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.m.js b/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.m.js index b549024..8a49d17 100644 --- a/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/volume_manager_types_unittest.m.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 {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockFileEntry, MockFileSystem} from './mock_entry.js'; import {VolumeManagerCommon} from './volume_manager_types.js';
diff --git a/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/ui/file_manager/file_manager/foreground/elements/BUILD.gn index 9ba2e95..5fbcf2ec 100644 --- a/ui/file_manager/file_manager/foreground/elements/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -251,7 +251,7 @@ "generate_exports=false", "js_module_root=./gen/ui", "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "hide_warnings_for=third_party/", ] }
diff --git a/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.m.js index dbbc5c2a..241bdad 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/elements/files_password_dialog_unittest.m.js
@@ -7,8 +7,10 @@ import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertEquals, assertFalse, assertNotReached} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertNotReached} from 'chrome://webui-test/chai_assert.js'; + import {waitUntil} from '../../common/js/test_error_reporting.js'; + import {FilesPasswordDialog} from './files_password_dialog.js'; /** @type {!FilesPasswordDialog} */
diff --git a/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.m.js index 886349a0..faddf16 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/elements/files_toast_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {FilesToast} from './files_toast.js'; export function setUpPage() {
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.m.js index d5b7874f..571dde50 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.m.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 {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.m.js b/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.m.js index f4f8c8c..300d4d4 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {util} from '../../common/js/util.js';
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 603ffdb7..836bebf 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -1374,7 +1374,7 @@ "js_module_root=../../ui/file_manager/", "js_module_root=./gen/ui/file_manager/", "jscomp_off=duplicate", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", "hide_warnings_for=third_party/",
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.m.js index bb3fcd9..6fa827d 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.m.js
@@ -4,7 +4,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockDriveSyncHandler} from '../../background/js/mock_drive_sync_handler.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
diff --git a/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.m.js index 99164b5..14a993a4 100644 --- a/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.m.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 {assertDeepEquals, assertEquals} from 'chrome://test/chai_assert.js'; +import {assertDeepEquals, assertEquals} from 'chrome://webui-test/chai_assert.js'; import {MockChromeFileManagerPrivateDirectoryChanged, MockChromeStorageAPI} from '../../common/js/mock_chrome.js'; import {waitUntil} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/banner_util_unittest.m.js b/ui/file_manager/file_manager/foreground/js/banner_util_unittest.m.js index 9bf79d40..e4f181a9 100644 --- a/ui/file_manager/file_manager/foreground/js/banner_util_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/banner_util_unittest.m.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 {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js'; import {Banner} from '../../externs/banner.js';
diff --git a/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.m.js b/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.m.js index c80e78e0da..ddddd0f8 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.m.js
@@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals, assertFalse} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse} from 'chrome://webui-test/chai_assert.js'; + import {installMockChrome} from '../../common/js/mock_chrome.js'; import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js'; import {EntryLocation} from '../../externs/entry_location.js'; import {VolumeManager} from '../../externs/volume_manager.js'; + import {FileFilter} from './directory_contents.js'; /**
diff --git a/ui/file_manager/file_manager/foreground/js/directory_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/directory_model_unittest.m.js index 60358bf..0992630 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/directory_model_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockFileOperationManager} from '../../background/js/mock_file_operation_manager.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.m.js index 282623a..5a0fa8a0 100644 --- a/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/file_list_model_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertArrayEquals, assertEquals} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertEquals} from 'chrome://webui-test/chai_assert.js'; + import {FileListModel} from './file_list_model.js'; import {MetadataModel} from './metadata/metadata_model.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.m.js index 88390d2..d996efd 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js'; import {FakeEntryImpl} from '../../common/js/files_app_entry_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.m.js index 84329fb..0252423 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {createCrostiniForTest} from '../../background/js/mock_crostini.js'; import {MockProgressCenter} from '../../background/js/mock_progress_center.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.m.js index 5f46976..0b129e2 100644 --- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller_unittest.m.js
@@ -8,7 +8,7 @@ import {Command} from 'chrome://resources/js/cr/ui/command.m.js'; import {ListSelectionModel} from 'chrome://resources/js/cr/ui/list_selection_model.m.js'; import {queryRequiredElement} from 'chrome://resources/js/util.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js'; import {DialogType} from '../../common/js/dialog_type.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.m.js index 0cfd629f..4e94395 100644 --- a/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/file_type_filters_controller_unittest.m.js
@@ -4,7 +4,7 @@ import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {EntryList, FakeEntryImpl} from '../../common/js/files_app_entry_types.js'; import {metrics} from '../../common/js/metrics.js';
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.m.js index f26b575..b2e4fab 100644 --- a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {TestMediaScanner} from '../../background/js/mock_media_scanner.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.m.js b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.m.js index a53392bc..3adfe09 100644 --- a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.m.js
@@ -4,7 +4,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockDirectoryEntry, MockEntry, MockFileSystem} from '../../common/js/mock_entry.js'; import {reportPromise, waitUntil} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn index 6ce18d3..8e0e58a 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
@@ -377,7 +377,7 @@ "js_module_root=./gen/ui", "js_module_root=../../ui/file_manager/", "js_module_root=./gen/ui/file_manager/", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", "hide_warnings_for=third_party/",
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.m.js index 758be08..c6b8d34 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {reportPromise} from '../../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.m.js index 1ffe643..b64daebd 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.m.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 {assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {ExifEntry} from '../../../externs/exif_entry.js'; import {MetadataParserLogger} from '../../../externs/metadata_worker_window.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.m.js index 7a743a4..fb96d39 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/external_metadata_provider_unittest.m.js
@@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; + import {installMockChrome} from '../../../common/js/mock_chrome.js'; import {reportPromise} from '../../../common/js/test_error_reporting.js'; + import {ExternalMetadataProvider} from './external_metadata_provider.js'; import {MetadataRequest} from './metadata_request.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.m.js index a4e1ae3f..e75e13b 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.m.js
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {reportPromise} from '../../../common/js/test_error_reporting.js'; + import {FileSystemMetadataProvider} from './file_system_metadata_provider.js'; import {MetadataRequest} from './metadata_request.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.m.js index fe52e7a..1d1d9139 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/image_orientation_unittest.m.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 {assertDeepEquals, assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {ImageOrientation} from './image_orientation.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.m.js index c33bef11..a5c52e6 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_item_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals, assertFalse, assertThrows, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertThrows, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {MetadataCacheItem} from './metadata_cache_item.js'; import {MetadataItem} from './metadata_item.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.m.js index 78db477..51ef014 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {MetadataCacheSet, MetadataCacheSetStorageForObject} from './metadata_cache_set.js'; /** @const {!Entry} */
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.m.js index 3e0900a..bb5b86cb 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.m.js
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals, assertThrows} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertThrows} from 'chrome://webui-test/chai_assert.js'; + import {reportPromise} from '../../../common/js/test_error_reporting.js'; + import {MetadataModel} from './metadata_model.js'; import {MetadataProvider} from './metadata_provider.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.m.js index f1d4b50a..2f8867c 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.m.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 {assertArrayEquals, assertEquals, assertNotReached, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {reportPromise} from '../../../common/js/test_error_reporting.js'; import {VolumeManagerCommon} from '../../../common/js/volume_manager_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.m.js index 568c35f..465f620 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {reportPromise} from '../../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.m.js index 73080a2..b0c413c 100644 --- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.m.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 {assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js'; import {VolumeInfoImpl} from '../../background/js/volume_info_impl.js';
diff --git a/ui/file_manager/file_manager/foreground/js/path_component_unittest.m.js b/ui/file_manager/file_manager/foreground/js/path_component_unittest.m.js index 773ca343..3600dea0 100644 --- a/ui/file_manager/file_manager/foreground/js/path_component_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/path_component_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js'; import {MockFileSystem} from '../../common/js/mock_entry.js';
diff --git a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.m.js index a96e003..f6cf353b 100644 --- a/ui/file_manager/file_manager/foreground/js/providers_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/providers_model_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.js'; import {VolumeInfoImpl} from '../../background/js/volume_info_impl.js';
diff --git a/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.m.js index b1fc4c0..84a0e14 100644 --- a/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/spinner_controller_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js index 614e1c7b..223c4ee 100644 --- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.m.js
@@ -5,7 +5,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {decorate} from 'chrome://resources/js/cr/ui.m.js'; import {Command} from 'chrome://resources/js/cr/ui/command.m.js'; -import {assertNotReached} from 'chrome://test/chai_assert.js'; +import {assertNotReached} from 'chrome://webui-test/chai_assert.js'; import {createCrostiniForTest} from '../../background/js/mock_crostini.js'; import {DialogType} from '../../common/js/dialog_type.js';
diff --git a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.m.js b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.m.js index bf6ec16..a51c843 100644 --- a/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/thumbnail_loader_unittest.m.js
@@ -4,7 +4,7 @@ import {ImageLoaderClient} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/image_loader_client.js'; import {LoadImageRequest} from 'chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/load_image_request.js'; -import {assertEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockEntry, MockFileSystem} from '../../common/js/mock_entry.js'; import {reportPromise} from '../../common/js/test_error_reporting.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index 347f3fe..217853d 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -682,7 +682,7 @@ "js_module_root=../../ui/file_manager/", "js_module_root=./gen/ui/file_manager/", "jscomp_off=duplicate", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", "hide_warnings_for=third_party/",
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js index 362834a4..07c3b89d4 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js
@@ -4,7 +4,7 @@ import {assertInstanceof} from 'chrome://resources/js/assert.m.js'; import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {util} from '../../../common/js/util.js'; import {MockActionModel, MockActionsModel} from '../mock_actions_model.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn index 171b535..f8b6ba2a 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/banners/BUILD.gn
@@ -203,7 +203,7 @@ "js_module_root=../../ui/file_manager/", "js_module_root=./gen/ui/file_manager/", "jscomp_off=duplicate", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", "hide_warnings_for=third_party/",
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.m.js index 31c78f6..3dc87a44 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners/educational_banner_unittest.m.js
@@ -3,7 +3,8 @@ // found in the LICENSE file. import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; + import {mockUtilVisitURL} from '../../../../common/js/mock_util.js'; import {Banner} from '../../../../externs/banner.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.m.js index 1c7a906..76bd8d8 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners/state_banner_unittest.m.js
@@ -4,11 +4,11 @@ import {decorate} from 'chrome://resources/js/cr/ui.m.js'; import {Command} from 'chrome://resources/js/cr/ui/command.m.js'; -import {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; + import {mockUtilVisitURL} from '../../../../common/js/mock_util.js'; import {waitUntil} from '../../../../common/js/test_error_reporting.js'; - import {StateBanner} from './state_banner.js'; /** @type{!StateBanner} */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.m.js index 6ba7e93f..2b98098 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners/warning_banner_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {mockUtilVisitURL} from '../../../../common/js/mock_util.js'; import {Banner} from '../../../../externs/banner.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js index e45e63bd..0b22f2b 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {BreadCrumb} from './breadcrumb.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.m.js index b9ac5e021..65b7a3d 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertArrayEquals,assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../../background/js/mock_volume_manager.js'; import {EntryList} from '../../../common/js/files_app_entry_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.m.js index 8e02ac66..d7977883 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_list_selection_model_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertArrayEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {FileListSelectionModel} from './file_list_selection_model.js'; /** @type {!FileListSelectionModel} */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.m.js index 62e6a91..8e9b2e2 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base_unittest.m.js
@@ -3,8 +3,10 @@ // found in the LICENSE file. import {assertInstanceof} from 'chrome://resources/js/assert.m.js'; -import {assertFalse} from 'chrome://test/chai_assert.js'; +import {assertFalse} from 'chrome://webui-test/chai_assert.js'; + import {waitUntil} from '../../../common/js/test_error_reporting.js'; + import {FileManagerDialogBase} from './file_manager_dialog_base.js'; export function setUp() {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.m.js index 81f2147..dceddd2 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list_unittest.m.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 {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {MockVolumeManager} from '../../../background/js/mock_volume_manager.js'; import {FakeEntryImpl} from '../../../common/js/files_app_entry_types.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.m.js index 037e8e7..d29d5bc1 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {FileTableColumnModel} from './file_table.js'; import {TableColumn} from './table/table_column.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.m.js index acbe497..572a7b1 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_tap_handler_unittest.m.js
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; + import {reportPromise} from '../../../common/js/test_error_reporting.js'; + import {FileTapHandler} from './file_tap_handler.js'; /** @type {!FileTapHandler} handler the handler. */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js index 44226c2..1c63b2c 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js
@@ -4,7 +4,8 @@ import {assertInstanceof} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {InstallLinuxPackageDialog} from './install_linux_package_dialog.js'; export function testInstallButtonHiddenUntilInfoReady() {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.m.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.m.js index 0e884ae..1e7583f 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.m.js +++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu_unittest.m.js
@@ -7,7 +7,7 @@ import {Command} from 'chrome://resources/js/cr/ui/command.m.js'; import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {util} from '../../../common/js/util.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js index 79e6929..b7a6764b 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/splitter_unittest.js
@@ -5,7 +5,7 @@ // clang-format off import {decorate} from 'chrome://resources/js/cr/ui.m.js'; import {getRequiredElement} from 'chrome://resources/js/util.m.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {Splitter} from './splitter.js';
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn index 56678de..e55ba3a 100644 --- a/ui/file_manager/image_loader/BUILD.gn +++ b/ui/file_manager/image_loader/BUILD.gn
@@ -161,7 +161,7 @@ "js_module_root=./gen/ui", "js_module_root=../../ui/file_manager/", "js_module_root=./gen/ui/file_manager/", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", ] }
diff --git a/ui/file_manager/image_loader/cache_unittest.m.js b/ui/file_manager/image_loader/cache_unittest.m.js index 53a9b45..709057d 100644 --- a/ui/file_manager/image_loader/cache_unittest.m.js +++ b/ui/file_manager/image_loader/cache_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; + import {LoadImageRequest} from './load_image_request.js';
diff --git a/ui/file_manager/image_loader/image_loader_client_unittest.m.js b/ui/file_manager/image_loader/image_loader_client_unittest.m.js index b8b1154..00da7aa 100644 --- a/ui/file_manager/image_loader/image_loader_client_unittest.m.js +++ b/ui/file_manager/image_loader/image_loader_client_unittest.m.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. import {reportPromise} from 'chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/common/js/test_error_reporting.js'; -import {assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {ImageLoaderClient} from './image_loader_client.js'; import {LoadImageRequest, LoadImageResponse, LoadImageResponseStatus} from './load_image_request.js';
diff --git a/ui/file_manager/image_loader/image_loader_unittest.m.js b/ui/file_manager/image_loader/image_loader_unittest.m.js index 1b985f9..4d67ab3c 100644 --- a/ui/file_manager/image_loader/image_loader_unittest.m.js +++ b/ui/file_manager/image_loader/image_loader_unittest.m.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 {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; import {ImageLoaderUtil} from './image_loader_util.js'; import {ImageOrientation} from './image_orientation.js';
diff --git a/ui/file_manager/image_loader/scheduler_unittest.m.js b/ui/file_manager/image_loader/scheduler_unittest.m.js index 3ef24657d..bab46bf 100644 --- a/ui/file_manager/image_loader/scheduler_unittest.m.js +++ b/ui/file_manager/image_loader/scheduler_unittest.m.js
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assertEquals} from 'chrome://test/chai_assert.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; + import {ImageRequestTask} from './image_request_task.js'; import {Scheduler} from './scheduler.js';
diff --git a/ui/file_manager/integration_tests/BUILD.gn b/ui/file_manager/integration_tests/BUILD.gn index e0e4bc9..28ae6ac 100644 --- a/ui/file_manager/integration_tests/BUILD.gn +++ b/ui/file_manager/integration_tests/BUILD.gn
@@ -21,7 +21,7 @@ strict_error_checking_closure_args + [ "js_module_root=./gen/ui", "js_module_root=../../ui", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "hide_warnings_for=third_party/", ] }
diff --git a/ui/file_manager/integration_tests/file_manager/BUILD.gn b/ui/file_manager/integration_tests/file_manager/BUILD.gn index ac221321..753fdda 100644 --- a/ui/file_manager/integration_tests/file_manager/BUILD.gn +++ b/ui/file_manager/integration_tests/file_manager/BUILD.gn
@@ -60,7 +60,7 @@ strict_error_checking_closure_args + [ "js_module_root=gen/ui/file_manager/", "js_module_root=../../ui/file_manager/", - "browser_resolver_prefix_replacements=\"chrome://test/=./\"", + "browser_resolver_prefix_replacements=\"chrome://webui-test/=./\"", "hide_warnings_for=third_party/", ] }
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc index ca6fa06..e1b0323c 100644 --- a/ui/gtk/gtk_ui.cc +++ b/ui/gtk/gtk_ui.cc
@@ -487,11 +487,7 @@ std::unique_ptr<ui::LinuxInputMethodContext> GtkUi::CreateInputMethodContext( ui::LinuxInputMethodContextDelegate* delegate) const { - return std::make_unique<ui::LinuxInputMethodContextWrapper>( - std::make_unique<InputMethodContextImplGtk>(delegate, - /*is_simple=*/false), - std::make_unique<InputMethodContextImplGtk>(delegate, - /*is_simple=*/true)); + return std::make_unique<InputMethodContextImplGtk>(delegate); } gfx::FontRenderParams GtkUi::GetDefaultFontRenderParams() const {
diff --git a/ui/gtk/input_method_context_impl_gtk.cc b/ui/gtk/input_method_context_impl_gtk.cc index a1d0dcb6..5694965 100644 --- a/ui/gtk/input_method_context_impl_gtk.cc +++ b/ui/gtk/input_method_context_impl_gtk.cc
@@ -65,27 +65,36 @@ } // namespace InputMethodContextImplGtk::InputMethodContextImplGtk( - ui::LinuxInputMethodContextDelegate* delegate, - bool is_simple) - : delegate_(delegate), is_simple_(is_simple) { + ui::LinuxInputMethodContextDelegate* delegate) + : delegate_(delegate) { CHECK(delegate_); - gtk_context_ = - is_simple ? gtk_im_context_simple_new() : gtk_im_multicontext_new(); + gtk_context_ = gtk_im_multicontext_new(); + gtk_simple_context_ = gtk_im_context_simple_new(); g_signal_connect(gtk_context_, "commit", G_CALLBACK(OnCommitThunk), this); + g_signal_connect(gtk_simple_context_, "commit", G_CALLBACK(OnCommitThunk), + this); g_signal_connect(gtk_context_, "preedit-changed", G_CALLBACK(OnPreeditChangedThunk), this); + g_signal_connect(gtk_simple_context_, "preedit-changed", + G_CALLBACK(OnPreeditChangedThunk), this); g_signal_connect(gtk_context_, "preedit-end", G_CALLBACK(OnPreeditEndThunk), this); + g_signal_connect(gtk_simple_context_, "preedit-end", + G_CALLBACK(OnPreeditEndThunk), this); g_signal_connect(gtk_context_, "preedit-start", G_CALLBACK(OnPreeditStartThunk), this); + g_signal_connect(gtk_simple_context_, "preedit-start", + G_CALLBACK(OnPreeditStartThunk), this); // TODO(shuchen): Handle operations on surrounding text. // "delete-surrounding" and "retrieve-surrounding" signals should be // handled. - if (GtkCheckVersion(4)) + if (GtkCheckVersion(4)) { gtk_im_context_set_client_widget(gtk_context_, GetDummyWindow()); + gtk_im_context_set_client_widget(gtk_simple_context_, GetDummyWindow()); + } } InputMethodContextImplGtk::~InputMethodContextImplGtk() { @@ -93,12 +102,17 @@ g_object_unref(gtk_context_); gtk_context_ = nullptr; } + if (gtk_simple_context_) { + g_object_unref(gtk_simple_context_); + gtk_simple_context_ = nullptr; + } } // Overridden from ui::LinuxInputMethodContext bool InputMethodContextImplGtk::DispatchKeyEvent( const ui::KeyEvent& key_event) { - if (!gtk_context_) + auto* gtk_context = GetIMContext(); + if (!gtk_context) return false; GdkEvent* event = nullptr; @@ -115,13 +129,15 @@ return false; } - SetContextClientWindow(target_window); + SetContextClientWindow(target_window, gtk_context); } // Convert the last known caret bounds relative to the screen coordinates // to a GdkRectangle relative to the client window. aura::Window* window = static_cast<aura::Window*>(key_event.target()); - gfx::Rect caret_bounds = last_caret_bounds_; + gfx::Rect caret_bounds; + if (gtk_context == gtk_context_) + caret_bounds = last_caret_bounds_; caret_bounds -= window->GetBoundsInScreen().OffsetFromOrigin(); // Chrome's DIPs may be different from GTK's DIPs if @@ -131,11 +147,11 @@ GetDeviceScaleFactor() / gtk_widget_get_scale_factor(GetDummyWindow())); GdkRectangle gdk_rect = {caret_bounds.x(), caret_bounds.y(), caret_bounds.width(), caret_bounds.height()}; - gtk_im_context_set_cursor_location(gtk_context_, &gdk_rect); + gtk_im_context_set_cursor_location(gtk_context, &gdk_rect); if (!GtkCheckVersion(4)) { const bool handled = - GtkImContextFilterKeypress(gtk_context_, GdkEventToKey(event)); + GtkImContextFilterKeypress(gtk_context, GdkEventToKey(event)); gdk_event_free(event); return handled; } @@ -153,7 +169,7 @@ auto keycode = GetKeyEventProperty(key_event, ui::kPropertyKeyboardHwKeyCode); auto state = GtkUi::GetPlatform()->GetGdkKeyEventState(key_event); auto group = GtkUi::GetPlatform()->GetGdkKeyEventGroup(key_event); - return gtk_im_context_filter_key(gtk_context_, press, surface, device, time, + return gtk_im_context_filter_key(gtk_context, press, surface, device, time, keycode, state, group); } @@ -165,43 +181,34 @@ void InputMethodContextImplGtk::Reset() { gtk_im_context_reset(gtk_context_); + gtk_im_context_reset(gtk_simple_context_); // Some input methods may not honour the reset call. // Focusing out/in the to make sure it gets reset correctly. - if (!is_simple_ && has_focus_) { - Blur(); - Focus(); + if (type_ != ui::TEXT_INPUT_TYPE_NONE) { + gtk_im_context_focus_out(gtk_context_); + gtk_im_context_focus_in(gtk_context_); } } void InputMethodContextImplGtk::UpdateFocus(bool has_client, ui::TextInputType old_type, ui::TextInputType new_type) { - if (is_simple_) { - // simple context can be used in any textfield, including password box, and - // even if the focused text input client's text input type is - // ui::TEXT_INPUT_TYPE_NONE. - if (has_client) - Focus(); - else - Blur(); - } else { - // Otherwise We only focus when the focus is in a textfield. - if (old_type != ui::TEXT_INPUT_TYPE_NONE) - Blur(); - if (new_type != ui::TEXT_INPUT_TYPE_NONE) - Focus(); - } -} + type_ = new_type; -void InputMethodContextImplGtk::Focus() { - gtk_im_context_focus_in(gtk_context_); - has_focus_ = true; -} + // We only focus when the focus is in a textfield. + if (old_type != ui::TEXT_INPUT_TYPE_NONE) + gtk_im_context_focus_out(gtk_context_); + if (new_type != ui::TEXT_INPUT_TYPE_NONE) + gtk_im_context_focus_in(gtk_context_); -void InputMethodContextImplGtk::Blur() { - gtk_im_context_focus_out(gtk_context_); - has_focus_ = false; + // simple context can be used in any textfield, including password box, and + // even if the focused text input client's text input type is + // ui::TEXT_INPUT_TYPE_NONE. + if (has_client) + gtk_im_context_focus_in(gtk_simple_context_); + else + gtk_im_context_focus_out(gtk_simple_context_); } void InputMethodContextImplGtk::SetCursorLocation(const gfx::Rect& rect) { @@ -222,14 +229,14 @@ // GtkIMContext event handlers. void InputMethodContextImplGtk::OnCommit(GtkIMContext* context, gchar* text) { - if (context != gtk_context_) + if (context != GetIMContext()) return; delegate_->OnCommit(base::UTF8ToUTF16(text)); } void InputMethodContextImplGtk::OnPreeditChanged(GtkIMContext* context) { - if (context != gtk_context_) + if (context != GetIMContext()) return; gchar* str = nullptr; @@ -246,29 +253,36 @@ } void InputMethodContextImplGtk::OnPreeditEnd(GtkIMContext* context) { - if (context != gtk_context_) + if (context != GetIMContext()) return; delegate_->OnPreeditEnd(); } void InputMethodContextImplGtk::OnPreeditStart(GtkIMContext* context) { - if (context != gtk_context_) + if (context != GetIMContext()) return; delegate_->OnPreeditStart(); } -void InputMethodContextImplGtk::SetContextClientWindow(GdkWindow* window) { +void InputMethodContextImplGtk::SetContextClientWindow( + GdkWindow* window, + GtkIMContext* gtk_context) { + gpointer& gdk_last_set_client_window = + gtk_context == gtk_simple_context_ + ? gdk_last_set_client_window_for_simple_ + : gdk_last_set_client_window_; + DCHECK(!GtkCheckVersion(4)); - if (window == gdk_last_set_client_window_) + if (window == gdk_last_set_client_window) return; - gtk_im_context_set_client_window(gtk_context_, window); + gtk_im_context_set_client_window(gtk_context, window); // Prevent leaks when overriding last client window - if (gdk_last_set_client_window_) - g_object_unref(gdk_last_set_client_window_); - gdk_last_set_client_window_ = window; + if (gdk_last_set_client_window) + g_object_unref(gdk_last_set_client_window); + gdk_last_set_client_window = window; } void InputMethodContextImplGtk::SetContentType(ui::TextInputType type, @@ -283,4 +297,14 @@ return nullptr; } +GtkIMContext* InputMethodContextImplGtk::GetIMContext() { + switch (type_) { + case ui::TEXT_INPUT_TYPE_NONE: + case ui::TEXT_INPUT_TYPE_PASSWORD: + return gtk_simple_context_; + default: + return gtk_context_; + } +} + } // namespace gtk
diff --git a/ui/gtk/input_method_context_impl_gtk.h b/ui/gtk/input_method_context_impl_gtk.h index f287cdb..1d09752 100644 --- a/ui/gtk/input_method_context_impl_gtk.h +++ b/ui/gtk/input_method_context_impl_gtk.h
@@ -22,8 +22,8 @@ // (gtk-immodule) as a bridge from/to underlying IMEs. class InputMethodContextImplGtk : public ui::LinuxInputMethodContext { public: - InputMethodContextImplGtk(ui::LinuxInputMethodContextDelegate* delegate, - bool is_simple); + explicit InputMethodContextImplGtk( + ui::LinuxInputMethodContextDelegate* delegate); InputMethodContextImplGtk(const InputMethodContextImplGtk&) = delete; InputMethodContextImplGtk& operator=(const InputMethodContextImplGtk&) = @@ -68,33 +68,29 @@ OnPreeditStart, GtkIMContext*); - // Called on getting focus. - void Focus(); - - // Called on loosing focus. - void Blur(); - // Only used on GTK3. - void SetContextClientWindow(GdkWindow* window); + void SetContextClientWindow(GdkWindow* window, GtkIMContext* gtk_context); + + // Returns the IMContext depending on the currently connected input field + // type. + GtkIMContext* GetIMContext(); // A set of callback functions. Must not be nullptr. const raw_ptr<ui::LinuxInputMethodContextDelegate> delegate_; - // Input method context type flag. - // - true if it supports table-based input methods - // - false if it supports multiple, loadable input methods - const bool is_simple_; - - // Keeps track of current focus state. - bool has_focus_ = false; + // Tracks the input field type. + ui::TextInputType type_ = ui::TEXT_INPUT_TYPE_NONE; // IME's input GTK context. raw_ptr<GtkIMContext> gtk_context_ = nullptr; + raw_ptr<GtkIMContext> gtk_simple_context_ = nullptr; // Only used on GTK3. gpointer gdk_last_set_client_window_ = nullptr; + gpointer gdk_last_set_client_window_for_simple_ = nullptr; // Last known caret bounds relative to the screen coordinates, in DIPs. + // Effective only on non-simple context. gfx::Rect last_caret_bounds_; };
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 2d21f2e..6250efd 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -3231,6 +3231,28 @@ base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr()); bool handled = false; + if (event.type() == ui::ET_MOUSE_DRAGGED) { + POINT point; + point.x = event.x(); + point.y = event.y(); + ::ClientToScreen(hwnd(), &point); + // Windows sometimes sends spurious WM_MOUSEMOVEs at 0,0. If this happens + // after a mouse down on a tab, it can cause a detach of the tab to 0,0. + // In general, it would cause weird behavior while dragging, so ignore + // these events if they're fairly far from the cursor. + if (point.x == 0 && point.y == 0) { + POINT cursor_pos; + ::GetCursorPos(&cursor_pos); + constexpr int kMinSpuriousDistance = 200; + auto distance = sqrt(pow(static_cast<float>(abs(cursor_pos.x)), 2) + + pow(static_cast<float>(abs(cursor_pos.y)), 2)); + if (distance > kMinSpuriousDistance) { + SetMsgHandled(true); + return 0; + } + } + } + // Don't send right mouse button up to the delegate when displaying system // command menu. This prevents left clicking in the upper left hand corner of // an app window and then right clicking from sending the right click to the
diff --git a/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html b/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html index b3a81f78..8159c43 100644 --- a/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html +++ b/ui/webui/resources/cr_elements/cr_tab_box/cr_tab_box.html
@@ -2,6 +2,7 @@ :host { display: flex; flex-direction: column; + width: fit-content; --tabs-background-color: #fbfbfb; --tabs-border-color: #c8c8c8; --tabs-hover-text-color: black; @@ -31,7 +32,6 @@ cursor: default; display: block; margin-inline-start: 0; - min-width: 0; padding: 4px 9px 4px 10px; text-align: center; transition: none;