diff --git a/DEPS b/DEPS index e0235356..826a91d 100644 --- a/DEPS +++ b/DEPS
@@ -179,7 +179,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '7f418fc2677a978c77f1a3aba4b163b7501ed960', + 'angle_revision': '72b2be2e56ffc63418db01b5858ade3fae92ff39', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -862,7 +862,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b582d244f3160b24d6b2edadc680fc0f03b7194d', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '68efdcdaefe26eae9bf3c14cf9cd59e06000e71b', 'condition': 'checkout_linux', }, @@ -887,7 +887,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'fcde3ba0a657dd3d5cac15ab8a1b6361e293c2fe', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'acf922ce48cfd1ecf88582d9dbecf14e8d1fe369', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1280,7 +1280,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '87ede8895026c93bf0336f61d8cbb5954d42c19e', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b78fa92a51140e60da2c3657c28efa26a7fbfda1', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1470,7 +1470,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '2701c130839edbeb226735b0775966b6423d9e83', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '55d19e590d9a6ed6d8b3ad97b6ea62158e56705b', + Var('webrtc_git') + '/src.git' + '@' + '0e3485c338ff50a6dbab1bd950690b177ff0f2df', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/browser/BUILD.gn b/android_webview/browser/BUILD.gn index c7773448..52863c7b 100644 --- a/android_webview/browser/BUILD.gn +++ b/android_webview/browser/BUILD.gn
@@ -239,6 +239,7 @@ "//third_party/crashpad/crashpad/client", "//ui/android", "//ui/gl", + "//ui/native_theme", "//ui/resources", "//ui/touch_selection", ]
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS index 1cb2ef7..2393e2c3 100644 --- a/android_webview/browser/DEPS +++ b/android_webview/browser/DEPS
@@ -76,6 +76,7 @@ "+ui/display", "+ui/gfx", "+ui/gl", + "+ui/native_theme", "+ui/touch_selection/touch_handle.h", # Temporary until we bundle our own favicon. See
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc index 7e612fb3..52d36c96 100644 --- a/android_webview/browser/aw_settings.cc +++ b/android_webview/browser/aw_settings.cc
@@ -26,6 +26,7 @@ #include "content/public/common/web_preferences.h" #include "net/http/http_util.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" +#include "ui/native_theme/native_theme.h" using base::android::ConvertJavaStringToUTF16; using base::android::ConvertUTF8ToJavaString; @@ -520,19 +521,19 @@ break; } } - web_prefs->preferred_color_scheme = - is_dark_mode ? blink::PreferredColorScheme::kDark - : blink::PreferredColorScheme::kNoPreference; + ui::NativeTheme::PreferredColorScheme preferred_color_scheme = + is_dark_mode ? ui::NativeTheme::PreferredColorScheme::kDark + : ui::NativeTheme::PreferredColorScheme::kNoPreference; if (is_dark_mode) { switch (Java_AwSettings_getForceDarkBehaviorLocked(env, obj)) { case ForceDarkBehavior::FORCE_DARK_ONLY: { - web_prefs->preferred_color_scheme = - blink::PreferredColorScheme::kNoPreference; + preferred_color_scheme = + ui::NativeTheme::PreferredColorScheme::kNoPreference; web_prefs->force_dark_mode_enabled = true; break; } case ForceDarkBehavior::MEDIA_QUERY_ONLY: { - web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; + preferred_color_scheme = ui::NativeTheme::PreferredColorScheme::kDark; web_prefs->force_dark_mode_enabled = false; break; } @@ -543,16 +544,19 @@ // dark so that dark themed content will be preferred over force // darkening. case ForceDarkBehavior::PREFER_MEDIA_QUERY_OVER_FORCE_DARK: { - web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; + preferred_color_scheme = ui::NativeTheme::PreferredColorScheme::kDark; web_prefs->force_dark_mode_enabled = true; break; } } } else { - web_prefs->preferred_color_scheme = - blink::PreferredColorScheme::kNoPreference; + preferred_color_scheme = + ui::NativeTheme::PreferredColorScheme::kNoPreference; web_prefs->force_dark_mode_enabled = false; } + // Notify NativeTheme of changes to dark mode. + ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( + preferred_color_scheme); } bool AwSettings::GetAllowFileAccess() {
diff --git a/ash/app_list/app_list_metrics.h b/ash/app_list/app_list_metrics.h index 86c12fa..1b10d9a 100644 --- a/ash/app_list/app_list_metrics.h +++ b/ash/app_list/app_list_metrics.h
@@ -113,6 +113,16 @@ constexpr char kSearchResultDistanceFromOrigin[] = "Apps.AppListSearchResultDistanceFromOrigin"; +// The different ways to create a new page in the apps grid. These values are +// written to logs. New enum values can be added, but existing enums must never +// be renumbered or deleted and reused. +enum class AppListPageCreationType { + kDraggingApp = 0, + kMovingAppWithKeyboard = 1, + kSyncOrInstall = 2, + kMaxValue = kSyncOrInstall, +}; + // These are used in histograms, do not remove/renumber entries. If you're // adding to this enum with the intention that it will be logged, update the // AppListZeroStateSearchResultUserActionType enum listing in
diff --git a/ash/app_list/app_list_presenter_impl.cc b/ash/app_list/app_list_presenter_impl.cc index f0492d0..99ca55e1 100644 --- a/ash/app_list/app_list_presenter_impl.cc +++ b/ash/app_list/app_list_presenter_impl.cc
@@ -440,7 +440,8 @@ //////////////////////////////////////////////////////////////////////////////// // AppListPresenterImpl, PaginationModelObserver implementation: -void AppListPresenterImpl::TotalPagesChanged() {} +void AppListPresenterImpl::TotalPagesChanged(int previous_page_count, + int new_page_count) {} void AppListPresenterImpl::SelectedPageChanged(int old_selected, int new_selected) {
diff --git a/ash/app_list/app_list_presenter_impl.h b/ash/app_list/app_list_presenter_impl.h index 2f735b9a..8cd05f5 100644 --- a/ash/app_list/app_list_presenter_impl.h +++ b/ash/app_list/app_list_presenter_impl.h
@@ -150,7 +150,7 @@ void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override; // PaginationModelObserver overrides: - void TotalPagesChanged() override; + void TotalPagesChanged(int previous_page_count, int new_page_count) override; void SelectedPageChanged(int old_selected, int new_selected) override; // Registers a callback that is run when the next frame successfully makes it
diff --git a/ash/app_list/views/app_list_drag_and_drop_host.h b/ash/app_list/views/app_list_drag_and_drop_host.h index ddfb6ca..9ff334d 100644 --- a/ash/app_list/views/app_list_drag_and_drop_host.h +++ b/ash/app_list/views/app_list_drag_and_drop_host.h
@@ -34,7 +34,7 @@ const gfx::ImageSkia& icon, views::View* replaced_view, const gfx::Vector2d& cursor_offset_from_center, - float scale_factor) = 0; + float scale_factor) {} // Creates an OS dependent drag proxy icon which can escape the given view. // The proxy should get created using the |icon| with a magnification of @@ -52,12 +52,12 @@ // Updates the screen location of the Drag icon proxy. virtual void UpdateDragIconProxy( - const gfx::Point& location_in_screen_coordinates) = 0; + const gfx::Point& location_in_screen_coordinates) {} // Updates the screen location of the Drag icon proxy with its origin at // |origin_in_screen_coordinates|. virtual void UpdateDragIconProxyByLocation( - const gfx::Point& origin_in_screen_coordinates) = 0; + const gfx::Point& origin_in_screen_coordinates) {} // Removes the OS dependent drag proxy from the screen. virtual void DestroyDragIconProxy() = 0; @@ -79,7 +79,7 @@ // Once |StartDrag| returned true, this function is guaranteed to be called // when the mouse / touch events stop. If |cancel| is set, the drag operation // was aborted, otherwise the change should be kept. - virtual void EndDrag(bool cancel) = 0; + virtual void EndDrag(bool cancel) {} }; } // namespace ash
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc index b801caf6..52211e9 100644 --- a/ash/app_list/views/apps_grid_view.cc +++ b/ash/app_list/views/apps_grid_view.cc
@@ -2674,7 +2674,26 @@ } } -void AppsGridView::TotalPagesChanged() {} +void AppsGridView::TotalPagesChanged(int previous_page_count, + int new_page_count) { + // Don't record from folder. + if (folder_delegate_) + return; + + // Initial setup for the AppList starts with -1 pages. Ignore the page count + // change resulting from the initialization of the view. + if (previous_page_count == -1) + return; + + if (previous_page_count < new_page_count) { + AppListPageCreationType type = AppListPageCreationType::kSyncOrInstall; + if (handling_keyboard_move_) + type = AppListPageCreationType::kMovingAppWithKeyboard; + else if (dragging()) + type = AppListPageCreationType::kDraggingApp; + UMA_HISTOGRAM_ENUMERATION("Apps.AppList.AppsGridAddPage", type); + } +} void AppsGridView::SelectedPageChanged(int old_selected, int new_selected) { items_container_->layer()->SetTransform(gfx::Transform());
diff --git a/ash/app_list/views/apps_grid_view.h b/ash/app_list/views/apps_grid_view.h index b786841..e7a91cd6 100644 --- a/ash/app_list/views/apps_grid_view.h +++ b/ash/app_list/views/apps_grid_view.h
@@ -480,7 +480,7 @@ void OnAppListItemHighlight(size_t index, bool highlight) override; // Overridden from PaginationModelObserver: - void TotalPagesChanged() override; + void TotalPagesChanged(int previous_page_count, int new_page_count) override; void SelectedPageChanged(int old_selected, int new_selected) override; void TransitionStarting() override; void TransitionStarted() override;
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc index 83cb1c4f..0be7518 100644 --- a/ash/app_list/views/apps_grid_view_unittest.cc +++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -149,7 +149,8 @@ private: // PaginationModelObserver overrides: - void TotalPagesChanged() override {} + void TotalPagesChanged(int previous_page_count, int new_page_count) override { + } void SelectedPageChanged(int old_selected, int new_selected) override { view_->UpdateDragFromItem(AppsGridView::MOUSE, drag_event_); } @@ -2177,5 +2178,62 @@ EXPECT_EQ(model_content, model_->GetModelContent()); } +TEST_F(AppsGridViewTest, CreateANewPageWithKeyboardLogsMetrics) { + base::HistogramTester histogram_tester; + model_->PopulateApps(2); + + // Select first app and move it with the keyboard down to create a new page. + AppListItemView* moving_item = GetItemViewAt(0); + apps_grid_view_->GetFocusManager()->SetFocusedView(moving_item); + SimulateKeyPress(ui::VKEY_DOWN, ui::EF_CONTROL_DOWN); + SimulateKeyReleased(ui::VKEY_DOWN, ui::EF_NONE); + + ASSERT_EQ(apps_grid_view_->pagination_model()->total_pages(), 2); + histogram_tester.ExpectBucketCount( + "Apps.AppList.AppsGridAddPage", + AppListPageCreationType::kMovingAppWithKeyboard, 1); +} + +TEST_F(AppsGridViewTest, CreateANewPageByDraggingLogsMetrics) { + base::HistogramTester histogram_tester; + model_->PopulateApps(2); + + PageFlipWaiter page_flip_waiter(GetPaginationModel()); + // Drag down the first item until a new page is created. + gfx::Point from = GetItemRectOnCurrentPageAt(0, 0).CenterPoint(); + const gfx::Rect apps_grid_bounds = apps_grid_view_->GetLocalBounds(); + gfx::Point to = + gfx::Point(apps_grid_bounds.width() / 2, apps_grid_bounds.bottom() + 1); + + // For fullscreen, drag to the bottom/right of bounds. + page_flip_waiter.Reset(); + SimulateDrag(AppsGridView::MOUSE, from, to); + + EXPECT_EQ(to, GetDragViewCenter()); + + while (test_api_->HasPendingPageFlip()) + page_flip_waiter.Wait(); + + apps_grid_view_->EndDrag(false /*cancel*/); + + ASSERT_EQ(apps_grid_view_->pagination_model()->total_pages(), 2); + histogram_tester.ExpectBucketCount("Apps.AppList.AppsGridAddPage", + AppListPageCreationType::kDraggingApp, 1); +} + +TEST_F(AppsGridViewTest, CreateANewPageByAddingAppLogsMetrics) { + base::HistogramTester histogram_tester; + model_->PopulateApps(GetTilesPerPage(0)); + + // Add an item to simulate installing or syncing, the metric should be + // recorded. + model_->CreateAndAddItem("Extra App"); + + ASSERT_EQ(apps_grid_view_->pagination_model()->total_pages(), 2); + histogram_tester.ExpectBucketCount("Apps.AppList.AppsGridAddPage", + AppListPageCreationType::kSyncOrInstall, + 1); +} + } // namespace test } // namespace ash
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc index ed7a4dc2..34489aa6 100644 --- a/ash/app_list/views/contents_view.cc +++ b/ash/app_list/views/contents_view.cc
@@ -699,7 +699,8 @@ return "ContentsView"; } -void ContentsView::TotalPagesChanged() {} +void ContentsView::TotalPagesChanged(int previous_page_count, + int new_page_count) {} void ContentsView::SelectedPageChanged(int old_selected, int new_selected) { if (old_selected >= 0)
diff --git a/ash/app_list/views/contents_view.h b/ash/app_list/views/contents_view.h index ca69c8f6..2024422 100644 --- a/ash/app_list/views/contents_view.h +++ b/ash/app_list/views/contents_view.h
@@ -203,7 +203,7 @@ const char* GetClassName() const override; // Overridden from PaginationModelObserver: - void TotalPagesChanged() override; + void TotalPagesChanged(int previous_page_count, int new_page_count) override; void SelectedPageChanged(int old_selected, int new_selected) override; void TransitionStarted() override; void TransitionChanged() override;
diff --git a/ash/app_list/views/horizontal_page_container.cc b/ash/app_list/views/horizontal_page_container.cc index 4e8845c..14d71358 100644 --- a/ash/app_list/views/horizontal_page_container.cc +++ b/ash/app_list/views/horizontal_page_container.cc
@@ -172,7 +172,8 @@ pagination_controller_->set_is_tablet_mode(started); } -void HorizontalPageContainer::TotalPagesChanged() {} +void HorizontalPageContainer::TotalPagesChanged(int previous_page_count, + int new_page_count) {} void HorizontalPageContainer::SelectedPageChanged(int old_selected, int new_selected) {
diff --git a/ash/app_list/views/horizontal_page_container.h b/ash/app_list/views/horizontal_page_container.h index 80d2e00..47aa369 100644 --- a/ash/app_list/views/horizontal_page_container.h +++ b/ash/app_list/views/horizontal_page_container.h
@@ -54,7 +54,7 @@ private: // PaginationModelObserver: - void TotalPagesChanged() override; + void TotalPagesChanged(int previous_page_count, int new_page_count) override; void SelectedPageChanged(int old_selected, int new_selected) override; void TransitionStarting() override; void TransitionChanged() override;
diff --git a/ash/app_list/views/page_switcher.cc b/ash/app_list/views/page_switcher.cc index 6c5d7252..79afe2f 100644 --- a/ash/app_list/views/page_switcher.cc +++ b/ash/app_list/views/page_switcher.cc
@@ -225,7 +225,7 @@ AddChildView(buttons_); - TotalPagesChanged(); + TotalPagesChanged(0, model->total_pages()); SelectedPageChanged(-1, model->selected_page()); model_->AddObserver(this); } @@ -279,7 +279,8 @@ model_->SelectPage(page, true /* animate */); } -void PageSwitcher::TotalPagesChanged() { +void PageSwitcher::TotalPagesChanged(int previous_page_count, + int new_page_count) { if (!model_) return;
diff --git a/ash/app_list/views/page_switcher.h b/ash/app_list/views/page_switcher.h index 3e6ea90..c6e941f 100644 --- a/ash/app_list/views/page_switcher.h +++ b/ash/app_list/views/page_switcher.h
@@ -40,7 +40,7 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; // Overridden from PaginationModelObserver: - void TotalPagesChanged() override; + void TotalPagesChanged(int previous_page_count, int new_page_count) override; void SelectedPageChanged(int old_selected, int new_selected) override; ash::PaginationModel* model_; // Owned by AppsGridView.
diff --git a/ash/login/ui/lock_screen_media_controls_view.cc b/ash/login/ui/lock_screen_media_controls_view.cc index e350055c..956d492 100644 --- a/ash/login/ui/lock_screen_media_controls_view.cc +++ b/ash/login/ui/lock_screen_media_controls_view.cc
@@ -15,6 +15,7 @@ #include "base/metrics/histogram_functions.h" #include "components/media_message_center/media_controls_progress_view.h" #include "components/media_message_center/media_notification_util.h" +#include "components/vector_icons/vector_icons.h" #include "services/media_session/public/cpp/util.h" #include "services/media_session/public/mojom/constants.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h" @@ -42,39 +43,36 @@ namespace { -constexpr SkColor kMediaButtonColor = SK_ColorWHITE; -constexpr SkColor kProgressBarForeground = - SkColorSetARGB(0xFF, 0x8A, 0xB4, 0xF8); +constexpr SkColor kProgressBarForeground = gfx::kGoogleBlue300; constexpr SkColor kProgressBarBackground = - SkColorSetARGB(0x4C, 0x8A, 0xB4, 0xF8); + SkColorSetA(gfx::kGoogleBlue300, 0x4C); // 30% // Maximum number of actions that should be displayed on |button_row_|. constexpr size_t kMaxActions = 5; // Dimensions. -constexpr gfx::Insets kMediaControlsInsets = gfx::Insets(15, 15, 15, 15); +constexpr gfx::Insets kMediaControlsInsets = gfx::Insets(16, 16, 16, 16); constexpr int kMediaControlsCornerRadius = 16; -constexpr int kMinimumIconSize = 16; -constexpr int kDesiredIconSize = 20; -constexpr int kIconSize = 20; -constexpr int kMinimumArtworkSize = 50; -constexpr int kDesiredArtworkSize = 80; -constexpr gfx::Size kArtworkSize = gfx::Size(80, 80); -constexpr int kArtworkRowSeparator = 10; -constexpr gfx::Size kArtworkRowPreferredSize = gfx::Size(300, 10); -constexpr gfx::Size kMediaButtonSize = gfx::Size(46, 46); -constexpr int kMediaButtonRowSeparator = 14; -constexpr gfx::Insets kButtonRowInsets = gfx::Insets(10, 0, 0, 0); -constexpr int kPlayPauseIconSize = 28; -constexpr int kChangeTrackIconSize = 14; -constexpr int kSeekingIconsSize = 26; +constexpr int kMinimumSourceIconSize = 16; +constexpr int kDesiredSourceIconSize = 20; +constexpr int kMinimumArtworkSize = 30; +constexpr int kDesiredArtworkSize = 48; +constexpr int kArtworkRowPadding = 16; +constexpr gfx::Insets kArtworkRowInsets = gfx::Insets(24, 0, 9, 0); +constexpr gfx::Size kArtworkRowPreferredSize = + gfx::Size(328, kDesiredArtworkSize); +constexpr int kMediaButtonRowPadding = 16; +constexpr gfx::Insets kButtonRowInsets = gfx::Insets(4, 0, 0, 0); +constexpr int kPlayPauseIconSize = 40; +constexpr int kMediaControlsIconSize = 24; +constexpr gfx::Size kPlayPauseButtonSize = gfx::Size(72, 72); +constexpr gfx::Size kMediaControlsButtonSize = gfx::Size(48, 48); constexpr gfx::Size kMediaControlsButtonRowSize = - gfx::Size(300, kMediaButtonSize.height()); + gfx::Size(328, kPlayPauseButtonSize.height()); constexpr gfx::Size kMediaButtonGroupSize = - gfx::Size(2 * kMediaButtonSize.width() + kMediaButtonRowSeparator, - kMediaButtonSize.height()); + gfx::Size(2 * kMediaControlsButtonSize.width() + kMediaButtonRowPadding, + kPlayPauseButtonSize.height()); constexpr int kArtworkCornerRadius = 4; -constexpr int kMediaActionButtonCornerRadius = kMediaButtonSize.width() / 2; constexpr int kDragVelocityThreshold = 6; constexpr int kDistanceDismissalThreshold = 20; @@ -109,17 +107,17 @@ const gfx::VectorIcon& GetVectorIconForMediaAction(MediaSessionAction action) { switch (action) { case MediaSessionAction::kPreviousTrack: - return kLockScreenPreviousTrackIcon; + return vector_icons::kMediaPreviousTrackIcon; case MediaSessionAction::kPause: - return kLockScreenPauseIcon; + return vector_icons::kPauseIcon; case MediaSessionAction::kNextTrack: - return kLockScreenNextTrackIcon; + return vector_icons::kMediaNextTrackIcon; case MediaSessionAction::kPlay: - return kLockScreenPlayIcon; + return vector_icons::kPlayArrowIcon; case MediaSessionAction::kSeekBackward: - return kLockScreenSeekBackwardIcon; + return vector_icons::kMediaSeekBackwardIcon; case MediaSessionAction::kSeekForward: - return kLockScreenSeekForwardIcon; + return vector_icons::kMediaSeekForwardIcon; // The following actions are not yet supported on the controls. case MediaSessionAction::kStop: @@ -141,7 +139,10 @@ int icon_size, MediaSessionAction action, const base::string16& accessible_name) - : views::ImageButton(listener), icon_size_(icon_size) { + : views::ImageButton(listener), + is_play_pause_(action == MediaSessionAction::kPause || + action == MediaSessionAction::kPlay), + icon_size_(icon_size) { SetInkDropMode(views::Button::InkDropMode::ON); set_has_ink_drop_action_on_click(true); SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER); @@ -149,7 +150,8 @@ SetBorder( views::CreateEmptyBorder(views::LayoutProvider::Get()->GetInsetsMetric( views::INSETS_VECTOR_IMAGE_BUTTON))); - SetPreferredSize(kMediaButtonSize); + SetPreferredSize(is_play_pause_ ? kPlayPauseButtonSize + : kMediaControlsButtonSize); SetFocusBehavior(views::View::FocusBehavior::ALWAYS); SetAction(action, accessible_name); } @@ -160,16 +162,22 @@ const base::string16& accessible_name) { set_tag(static_cast<int>(action)); SetTooltipText(accessible_name); - views::SetImageFromVectorIcon(this, GetVectorIconForMediaAction(action), - icon_size_, kMediaButtonColor); + views::SetImageFromVectorIcon( + this, GetVectorIconForMediaAction(action), icon_size_, + AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kIconPrimary, + AshColorProvider::AshColorMode::kDark)); } std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override { - return std::make_unique<views::RoundRectInkDropMask>( - size(), gfx::Insets(), kMediaActionButtonCornerRadius); + return std::make_unique<views::CircleInkDropMask>( + size(), GetLocalBounds().CenterPoint(), + is_play_pause_ ? kPlayPauseButtonSize.width() / 2 + : kMediaControlsButtonSize.width() / 2); } private: + const bool is_play_pause_; int const icon_size_; DISALLOW_COPY_AND_ASSIGN(MediaActionButton); @@ -196,6 +204,7 @@ const Callbacks& callbacks) : connector_(connector), hide_controls_timer_(new base::OneShotTimer()), + hide_artwork_timer_(new base::OneShotTimer()), media_controls_enabled_(callbacks.media_controls_enabled), hide_media_controls_(callbacks.hide_media_controls), show_media_controls_(callbacks.show_media_controls) { @@ -234,16 +243,18 @@ artwork_row->SetPreferredSize(kArtworkRowPreferredSize); auto* artwork_row_layout = artwork_row->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), - kArtworkRowSeparator)); + views::BoxLayout::Orientation::kHorizontal, kArtworkRowInsets, + kArtworkRowPadding)); artwork_row_layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); artwork_row_layout->set_main_axis_alignment( views::BoxLayout::MainAxisAlignment::kStart); auto session_artwork = std::make_unique<views::ImageView>(); - session_artwork->SetPreferredSize(kArtworkSize); + session_artwork->SetPreferredSize( + gfx::Size(kDesiredArtworkSize, kDesiredArtworkSize)); session_artwork_ = artwork_row->AddChildView(std::move(session_artwork)); + session_artwork_->SetVisible(false); // |track_column| contains the title and artist labels of the current media // session. @@ -259,7 +270,9 @@ auto title_label = std::make_unique<views::Label>(); title_label->SetFontList(base_font_list.Derive( 2, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::BOLD)); - title_label->SetEnabledColor(SK_ColorWHITE); + title_label->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kTextPrimary, + AshColorProvider::AshColorMode::kDark)); title_label->SetAutoColorReadabilityEnabled(false); title_label->SetElideBehavior(gfx::ELIDE_TAIL); title_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); @@ -268,7 +281,9 @@ auto artist_label = std::make_unique<views::Label>(); artist_label->SetFontList(base_font_list.Derive( 0, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::LIGHT)); - artist_label->SetEnabledColor(SK_ColorWHITE); + artist_label->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kTextSecondary, + AshColorProvider::AshColorMode::kDark)); artist_label->SetAutoColorReadabilityEnabled(false); artist_label->SetElideBehavior(gfx::ELIDE_TAIL); artist_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); @@ -298,7 +313,7 @@ auto* button_row_layout = button_row->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, kButtonRowInsets, - kMediaButtonRowSeparator)); + kMediaButtonRowPadding)); button_row_layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); button_row_layout->set_main_axis_alignment( @@ -307,7 +322,7 @@ auto* left_control_group_layout = left_control_group->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), - kMediaButtonRowSeparator)); + kMediaButtonRowPadding)); left_control_group_layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); left_control_group_layout->set_main_axis_alignment( @@ -316,7 +331,7 @@ auto* right_control_group_layout = right_control_group->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), - kMediaButtonRowSeparator)); + kMediaButtonRowPadding)); right_control_group_layout->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kCenter); right_control_group_layout->set_main_axis_alignment( @@ -330,13 +345,13 @@ media_action_buttons_.push_back( left_control_group->AddChildView(std::make_unique<MediaActionButton>( - this, kChangeTrackIconSize, MediaSessionAction::kPreviousTrack, + this, kMediaControlsIconSize, MediaSessionAction::kPreviousTrack, l10n_util::GetStringUTF16( IDS_ASH_LOCK_SCREEN_MEDIA_CONTROLS_ACTION_PREVIOUS_TRACK)))); media_action_buttons_.push_back( left_control_group->AddChildView(std::make_unique<MediaActionButton>( - this, kSeekingIconsSize, MediaSessionAction::kSeekBackward, + this, kMediaControlsIconSize, MediaSessionAction::kSeekBackward, l10n_util::GetStringUTF16( IDS_ASH_LOCK_SCREEN_MEDIA_CONTROLS_ACTION_SEEK_BACKWARD)))); @@ -354,13 +369,13 @@ media_action_buttons_.push_back( right_control_group->AddChildView(std::make_unique<MediaActionButton>( - this, kSeekingIconsSize, MediaSessionAction::kSeekForward, + this, kMediaControlsIconSize, MediaSessionAction::kSeekForward, l10n_util::GetStringUTF16( IDS_ASH_LOCK_SCREEN_MEDIA_CONTROLS_ACTION_SEEK_FORWARD)))); media_action_buttons_.push_back( right_control_group->AddChildView(std::make_unique<MediaActionButton>( - this, kChangeTrackIconSize, MediaSessionAction::kNextTrack, + this, kMediaControlsIconSize, MediaSessionAction::kNextTrack, l10n_util::GetStringUTF16( IDS_ASH_LOCK_SCREEN_MEDIA_CONTROLS_ACTION_NEXT_TRACK)))); @@ -398,7 +413,7 @@ media_controller_remote_->ObserveImages( media_session::mojom::MediaSessionImageType::kSourceIcon, - kMinimumIconSize, kDesiredIconSize, + kMinimumSourceIconSize, kDesiredSourceIconSize, icon_observer_receiver_.BindNewPipeAndPassRemote()); } @@ -590,8 +605,9 @@ switch (type) { case media_session::mojom::MediaSessionImageType::kArtwork: { - base::Optional<gfx::ImageSkia> session_artwork = - gfx::ImageSkia::CreateFrom1xBitmap(converted_bitmap); + base::Optional<gfx::ImageSkia> session_artwork; + if (!converted_bitmap.empty()) + session_artwork = gfx::ImageSkia::CreateFrom1xBitmap(converted_bitmap); SetArtwork(session_artwork); break; } @@ -599,8 +615,9 @@ gfx::ImageSkia session_icon = gfx::ImageSkia::CreateFrom1xBitmap(converted_bitmap); if (session_icon.isNull()) { - session_icon = gfx::CreateVectorIcon(message_center::kProductIcon, - kIconSize, gfx::kChromeIconGrey); + session_icon = + gfx::CreateVectorIcon(message_center::kProductIcon, + kDesiredSourceIconSize, gfx::kChromeIconGrey); } header_row_->SetAppIcon(session_icon); } @@ -719,6 +736,12 @@ hide_media_controls_.Run(); } +void LockScreenMediaControlsView::HideArtwork() { + session_artwork_->SetVisible(false); + session_artwork_->SetImage(nullptr); + session_artwork_->InvalidateLayout(); +} + void LockScreenMediaControlsView::SetShown(Shown shown) { DCHECK(!shown_); shown_ = shown; @@ -744,12 +767,25 @@ void LockScreenMediaControlsView::SetArtwork( base::Optional<gfx::ImageSkia> img) { if (!img.has_value()) { - session_artwork_->SetImage(nullptr); + if (!session_artwork_->GetVisible() || hide_artwork_timer_->IsRunning()) + return; + + hide_artwork_timer_->Start( + FROM_HERE, kNextMediaDelay, + base::BindOnce(&LockScreenMediaControlsView::HideArtwork, + base::Unretained(this))); return; } - session_artwork_->SetImageSize(ScaleSizeToFitView(img->size(), kArtworkSize)); + if (hide_artwork_timer_->IsRunning()) + hide_artwork_timer_->Stop(); + + session_artwork_->SetVisible(true); + session_artwork_->SetImageSize( + ScaleSizeToFitView(img->size(), session_artwork_->GetPreferredSize())); session_artwork_->SetImage(*img); + + Layout(); session_artwork_->set_clip_path(GetArtworkClipPath()); }
diff --git a/ash/login/ui/lock_screen_media_controls_view.h b/ash/login/ui/lock_screen_media_controls_view.h index be9c807..9846204 100644 --- a/ash/login/ui/lock_screen_media_controls_view.h +++ b/ash/login/ui/lock_screen_media_controls_view.h
@@ -153,6 +153,8 @@ // Hide the controls because of |reason|. void Hide(HideReason reason); + void HideArtwork(); + // Set whether the controls should be shown and record the reason why. void SetShown(Shown shown); @@ -226,6 +228,10 @@ // Automatically hides the controls a few seconds if no media playing. std::unique_ptr<base::OneShotTimer> hide_controls_timer_; + // Make artwork view invisible if there is no artwork update after receiving + // an empty artwork. + std::unique_ptr<base::OneShotTimer> hide_artwork_timer_; + // Caches the text to be read by screen readers describing the media controls // view. base::string16 accessible_name_;
diff --git a/ash/login/ui/lock_screen_media_controls_view_unittest.cc b/ash/login/ui/lock_screen_media_controls_view_unittest.cc index ba9a4ec..59a431fd 100644 --- a/ash/login/ui/lock_screen_media_controls_view_unittest.cc +++ b/ash/login/ui/lock_screen_media_controls_view_unittest.cc
@@ -36,7 +36,7 @@ namespace { const int kAppIconSize = 20; -constexpr int kArtworkViewHeight = 80; +constexpr int kArtworkViewHeight = 48; constexpr int kArtworkCornerRadius = 4; const base::string16 kTestAppName = base::ASCIIToUTF16("Test app"); @@ -746,7 +746,7 @@ { // Verify that the provided artwork is correctly scaled down. - gfx::Rect expected_artwork_bounds(0, 20, 80, 40); + gfx::Rect expected_artwork_bounds(0, 12, 48, 24); gfx::Rect artwork_bounds = artwork_view()->GetImageBounds(); EXPECT_EQ(expected_artwork_bounds, artwork_bounds); @@ -758,14 +758,14 @@ } // Create artwork that must be scaled up to fit the view. - artwork.allocN32Pixels(40, 70); + artwork.allocN32Pixels(20, 40); media_controls_view_->MediaControllerImageChanged( media_session::mojom::MediaSessionImageType::kArtwork, artwork); { // Verify that the provided artwork is correctly scaled up. - gfx::Rect expected_artwork_bounds(17, 0, 45, 80); + gfx::Rect expected_artwork_bounds(12, 0, 24, 48); gfx::Rect artwork_bounds = artwork_view()->GetImageBounds(); EXPECT_EQ(expected_artwork_bounds, artwork_bounds); @@ -777,14 +777,14 @@ } // Create artwork that already fits the view size. - artwork.allocN32Pixels(70, kArtworkViewHeight); + artwork.allocN32Pixels(30, kArtworkViewHeight); media_controls_view_->MediaControllerImageChanged( media_session::mojom::MediaSessionImageType::kArtwork, artwork); { // Verify that the provided artwork size doesn't change. - gfx::Rect expected_artwork_bounds(5, 0, 70, 80); + gfx::Rect expected_artwork_bounds(9, 0, 30, 48); gfx::Rect artwork_bounds = artwork_view()->GetImageBounds(); EXPECT_EQ(expected_artwork_bounds, artwork_bounds); @@ -796,6 +796,27 @@ } } +TEST_F(LockScreenMediaControlsViewTest, ArtworkVisibility) { + SimulateMediaSessionChanged( + media_session::mojom::MediaPlaybackState::kPlaying); + + EXPECT_FALSE(artwork_view()->GetVisible()); + + SkBitmap image; + image.allocN32Pixels(10, 10); + image.eraseColor(SK_ColorMAGENTA); + + media_controls_view_->MediaControllerImageChanged( + media_session::mojom::MediaSessionImageType::kArtwork, image); + EXPECT_TRUE(artwork_view()->GetVisible()); + + // Don't hide artwork immediately after getting null image. + image.reset(); + media_controls_view_->MediaControllerImageChanged( + media_session::mojom::MediaSessionImageType::kArtwork, image); + EXPECT_TRUE(artwork_view()->GetVisible()); +} + TEST_F(LockScreenMediaControlsViewTest, AccessibleNodeData) { SimulateMediaSessionChanged( media_session::mojom::MediaPlaybackState::kPlaying);
diff --git a/ash/login/ui/media_controls_header_view.cc b/ash/login/ui/media_controls_header_view.cc index 846d8f53..31b4574 100644 --- a/ash/login/ui/media_controls_header_view.cc +++ b/ash/login/ui/media_controls_header_view.cc
@@ -6,6 +6,7 @@ #include "ash/login/ui/non_accessible_view.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/style/ash_color_provider.h" #include "components/vector_icons/vector_icons.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" @@ -26,12 +27,10 @@ namespace { -constexpr gfx::Insets kHeaderViewInsets = gfx::Insets(0, 0, 15, 0); -constexpr int kIconViewSize = 18; -constexpr int kIconSize = 12; +constexpr int kIconViewSize = 20; +constexpr int kIconSize = 14; constexpr int kHeaderTextFontSize = 12; -constexpr gfx::Insets kIconPadding = gfx::Insets(1, 1, 1, 1); -constexpr gfx::Insets kAppNamePadding = gfx::Insets(0, 10, 0, 0); +constexpr gfx::Insets kAppNamePadding = gfx::Insets(0, 8, 0, 0); constexpr gfx::Size kAppNamePreferredSize = gfx::Size(200, 10); constexpr gfx::Size kCloseButtonSize = gfx::Size(20, 20); constexpr int kCloseButtonIconSize = 18; @@ -54,13 +53,11 @@ views::MaximumFlexSizeRule::kUnbounded) .WithOrder(2); - auto* layout = SetLayoutManager(std::make_unique<views::FlexLayout>()); - layout->SetInteriorMargin(kHeaderViewInsets); + SetLayoutManager(std::make_unique<views::FlexLayout>()); auto app_icon_view = std::make_unique<views::ImageView>(); app_icon_view->SetPreferredSize(gfx::Size(kIconViewSize, kIconViewSize)); app_icon_view->SetImageSize(gfx::Size(kIconSize, kIconSize)); - app_icon_view->SetBorder(views::CreateEmptyBorder(kIconPadding)); app_icon_view->SetBackground( views::CreateRoundedRectBackground(SK_ColorWHITE, kIconViewSize / 2)); @@ -76,7 +73,9 @@ auto app_name_view = std::make_unique<views::Label>(); app_name_view->SetFontList(font_list); app_name_view->SetHorizontalAlignment(gfx::ALIGN_LEFT); - app_name_view->SetEnabledColor(SK_ColorWHITE); + app_name_view->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( + AshColorProvider::ContentLayerType::kTextSecondary, + AshColorProvider::AshColorMode::kDark)); app_name_view->SetAutoColorReadabilityEnabled(false); app_name_view->SetBorder(views::CreateEmptyBorder(kAppNamePadding)); app_name_view->SetPreferredSize(kAppNamePreferredSize);
diff --git a/ash/public/cpp/pagination/pagination_model.cc b/ash/public/cpp/pagination/pagination_model.cc index b7c02aa..014f46e7 100644 --- a/ash/public/cpp/pagination/pagination_model.cc +++ b/ash/public/cpp/pagination/pagination_model.cc
@@ -30,13 +30,14 @@ if (total_pages == total_pages_) return; + int previous_pages = total_pages_; total_pages_ = total_pages; if (selected_page_ < 0) SelectPage(0, false /* animate */); if (selected_page_ >= total_pages_) SelectPage(std::max(total_pages_ - 1, 0), false /* animate */); for (auto& observer : observers_) - observer.TotalPagesChanged(); + observer.TotalPagesChanged(previous_pages, total_pages); } void PaginationModel::SelectPage(int page, bool animate) {
diff --git a/ash/public/cpp/pagination/pagination_model_observer.h b/ash/public/cpp/pagination/pagination_model_observer.h index 5add10b1..8f8e2683 100644 --- a/ash/public/cpp/pagination/pagination_model_observer.h +++ b/ash/public/cpp/pagination/pagination_model_observer.h
@@ -12,7 +12,7 @@ class ASH_PUBLIC_EXPORT PaginationModelObserver { public: // Invoked when the total number of page is changed. - virtual void TotalPagesChanged() {} + virtual void TotalPagesChanged(int previous_page_count, int new_page_count) {} // Invoked when the selected page index is changed. virtual void SelectedPageChanged(int old_selected, int new_selected) {}
diff --git a/ash/public/cpp/pagination/pagination_model_unittest.cc b/ash/public/cpp/pagination/pagination_model_unittest.cc index 5c8fc7e9..9c404170 100644 --- a/ash/public/cpp/pagination/pagination_model_unittest.cc +++ b/ash/public/cpp/pagination/pagination_model_unittest.cc
@@ -61,7 +61,8 @@ } // PaginationModelObserver overrides: - void TotalPagesChanged() override {} + void TotalPagesChanged(int previous_page_count, int new_page_count) override { + } void SelectedPageChanged(int old_selected, int new_selected) override { AppendSelectedPage(new_selected); ++selection_count_;
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index 5a4c216f..8a9f0d7 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -120,12 +120,6 @@ "palette_tray_icon_magnify.icon", "palette_tray_icon_metalayer.icon", "parent_access_lock.icon", - "lock_screen_pause.icon", - "lock_screen_play.icon", - "lock_screen_previous_track.icon", - "lock_screen_next_track.icon", - "lock_screen_seek_forward.icon", - "lock_screen_seek_backward.icon", "send.icon", "settings.icon", "shelf_add_person_button.icon",
diff --git a/ash/resources/vector_icons/lock_screen_next_track.icon b/ash/resources/vector_icons/lock_screen_next_track.icon deleted file mode 100644 index 600d971..0000000 --- a/ash/resources/vector_icons/lock_screen_next_track.icon +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 24, -MOVE_TO, 2, 25, -R_ARC_TO, 1.53f, 1.53f, 0, 0, 1, -0.69f, -0.17f, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 0.5f, 23.54f, -V_LINE_TO, 2, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 2.86f, 0.77f, -LINE_TO, 18.25f, 11.54f, -R_ARC_TO, 1.52f, 1.52f, 0, 0, 1, 0, 2.46f, -LINE_TO, 2.86f, 24.77f, -ARC_TO, 1.51f, 1.51f, 0, 0, 1, 2, 25, -CLOSE, -MOVE_TO, 3.5f, 4.88f, -V_LINE_TO, 20.66f, -R_LINE_TO, 11.27f, -7.89f, -CLOSE, -MOVE_TO, 23.23f, 25, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, -1.5f, -1.5f, -V_LINE_TO, 2, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, 3, 0, -V_LINE_TO, 23.54f, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 23.23f, 25, -CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_pause.icon b/ash/resources/vector_icons/lock_screen_pause.icon deleted file mode 100644 index dec26f0..0000000 --- a/ash/resources/vector_icons/lock_screen_pause.icon +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 40, -MOVE_TO, 7.5f, 39.5f, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 6, 38, -V_LINE_TO, 2, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 9, 2, -V_LINE_TO, 38, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 7.5f, 39.5f, -CLOSE, -MOVE_TO, 32.5f, 39.5f, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 31, 38, -V_LINE_TO, 2, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, 3, 0, -V_LINE_TO, 38, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 32.5f, 39.5f, -CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_play.icon b/ash/resources/vector_icons/lock_screen_play.icon deleted file mode 100644 index eedd910f..0000000 --- a/ash/resources/vector_icons/lock_screen_play.icon +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 40, -MOVE_TO, 7, 39.5f, -R_ARC_TO, 1.57f, 1.57f, 0, 0, 1, -0.7f, -0.17f, -ARC_TO, 1.51f, 1.51f, 0, 0, 1, 5.5f, 38, -V_LINE_TO, 2, -ARC_TO, 1.49f, 1.49f, 0, 0, 1, 7.85f, 0.77f, -R_LINE_TO, 26, 18, -R_ARC_TO, 1.49f, 1.49f, 0, 0, 1, 0, 2.46f, -R_LINE_TO, -26, 18, -ARC_TO, 1.46f, 1.46f, 0, 0, 1, 7, 39.5f, -CLOSE, -MOVE_TO, 8.5f, 4.86f, -V_LINE_TO, 35.14f, -LINE_TO, 30.37f, 20, -CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_previous_track.icon b/ash/resources/vector_icons/lock_screen_previous_track.icon deleted file mode 100644 index 2d3950f..0000000 --- a/ash/resources/vector_icons/lock_screen_previous_track.icon +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 24, -MOVE_TO, 22.73f, 24.54f, -R_ARC_TO, 1.51f, 1.51f, 0, 0, 1, -0.86f, -0.27f, -LINE_TO, 6.49f, 13.5f, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, 0, -2.46f, -LINE_TO, 21.87f, 0.27f, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 24.23f, 1.5f, -V_LINE_TO, 23, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, -1.5f, 1.5f, -CLOSE, -MOVE_TO, 10, 12.27f, -R_LINE_TO, 11.26f, 7.89f, -V_LINE_TO, 4.38f, -CLOSE, -MOVE_TO, 1.5f, 24.54f, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 0, 23, -V_LINE_TO, 1.5f, -R_ARC_TO, 1.5f, 1.5f, 0, 0, 1, 3, 0, -V_LINE_TO, 23, -ARC_TO, 1.5f, 1.5f, 0, 0, 1, 1.5f, 24.54f, -CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_seek_backward.icon b/ash/resources/vector_icons/lock_screen_seek_backward.icon deleted file mode 100644 index b563203..0000000 --- a/ash/resources/vector_icons/lock_screen_seek_backward.icon +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 24, -MOVE_TO, 9.44f, 18.88f, -ARC_TO, 0.89f, 0.89f, 0, 0, 1, 9, 18.72f, -R_LINE_TO, -8.58f, -6, -R_ARC_TO, 0.87f, 0.87f, 0, 0, 1, -0.22f, -1.2f, -R_ARC_TO, 0.88f, 0.88f, 0, 0, 1, 0.22f, -0.21f, -LINE_TO, 9, 5.3f, -R_ARC_TO, 0.86f, 0.86f, 0, 0, 1, 0.86f, -0.06f, -R_ARC_TO, 0.84f, 0.84f, 0, 0, 1, 0.45f, 0.76f, -V_LINE_TO, 18, -R_ARC_TO, 0.84f, 0.84f, 0, 0, 1, -0.45f, 0.76f, -ARC_TO, 1, 1, 0, 0, 1, 9.44f, 18.88f, -CLOSE, -MOVE_TO, 2.36f, 12, -R_LINE_TO, 6.22f, 4.36f, -V_LINE_TO, 7.65f, -CLOSE, -MOVE_TO, 23.18f, 18.88f, -R_ARC_TO, 0.84f, 0.84f, 0, 0, 1, -0.49f, -0.16f, -R_LINE_TO, -8.59f, -6, -R_ARC_TO, 0.86f, 0.86f, 0, 0, 1, -0.21f, -1.2f, -R_ARC_TO, 1, 1, 0, 0, 1, 0.21f, -0.21f, -R_LINE_TO, 8.59f, -6, -ARC_TO, 0.83f, 0.83f, 0, 0, 1, 24, 6, -V_LINE_TO, 18, -R_ARC_TO, 0.86f, 0.86f, 0, 0, 1, -0.45f, 0.76f, -ARC_TO, 1, 1, 0, 0, 1, 23.18f, 18.88f, -CLOSE, -MOVE_TO, 16.09f, 12, -R_LINE_TO, 6.23f, 4.36f, -V_LINE_TO, 7.65f, -CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_seek_forward.icon b/ash/resources/vector_icons/lock_screen_seek_forward.icon deleted file mode 100644 index 3b66fab..0000000 --- a/ash/resources/vector_icons/lock_screen_seek_forward.icon +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -CANVAS_DIMENSIONS, 24, -MOVE_TO, 0.86f, 18.87f, -R_ARC_TO, 0.93f, 0.93f, 0, 0, 1, -0.4f, -0.09f, -ARC_TO, 0.86f, 0.86f, 0, 0, 1, 0, 18, -V_LINE_TO, 6, -R_ARC_TO, 0.86f, 0.86f, 0, 0, 1, 0.46f, -0.76f, -R_ARC_TO, 0.85f, 0.85f, 0, 0, 1, 0.93f, 0.06f, -R_LINE_TO, 8.58f, 6, -R_ARC_TO, 0.86f, 0.86f, 0, 0, 1, 0.21f, 1.2f, -R_ARC_TO, 0.84f, 0.84f, 0, 0, 1, -0.21f, 0.21f, -R_LINE_TO, -8.58f, 6, -ARC_TO, 0.84f, 0.84f, 0, 0, 1, 0.86f, 18.87f, -CLOSE, -MOVE_TO, 1.72f, 7.65f, -R_V_LINE_TO, 8.72f, -LINE_TO, 8, 12, -CLOSE, -MOVE_TO, 14.59f, 18.87f, -R_ARC_TO, 0.93f, 0.93f, 0, 0, 1, -0.4f, -0.09f, -R_ARC_TO, 0.86f, 0.86f, 0, 0, 1, -0.46f, -0.76f, -V_LINE_TO, 6, -R_ARC_TO, 0.86f, 0.86f, 0, 0, 1, 0.46f, -0.76f, -R_ARC_TO, 0.85f, 0.85f, 0, 0, 1, 0.86f, 0.06f, -R_LINE_TO, 8.58f, 6, -R_ARC_TO, 0.87f, 0.87f, 0, 0, 1, 0.22f, 1.2f, -R_ARC_TO, 0.88f, 0.88f, 0, 0, 1, -0.22f, 0.21f, -R_LINE_TO, -8.58f, 6, -ARC_TO, 0.84f, 0.84f, 0, 0, 1, 14.59f, 18.87f, -CLOSE, -R_MOVE_TO, 0.86f, -11.22f, -R_V_LINE_TO, 8.72f, -LINE_TO, 21.68f, 12, -CLOSE
diff --git a/ash/shelf/hotseat_widget.cc b/ash/shelf/hotseat_widget.cc index 493e26d..5091a49e 100644 --- a/ash/shelf/hotseat_widget.cc +++ b/ash/shelf/hotseat_widget.cc
@@ -172,8 +172,8 @@ } else { // The shelf view observes the shelf model and creates icons as items are // added to the model. - shelf_view_ = GetContentsView()->AddChildView( - std::make_unique<ShelfView>(ShelfModel::Get(), shelf)); + shelf_view_ = GetContentsView()->AddChildView(std::make_unique<ShelfView>( + ShelfModel::Get(), shelf, /*drag_and_drop_host=*/nullptr)); shelf_view_->Init(); } delegate_view_->Init(scrollable_shelf_view(), GetLayer());
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc index fe087924..5ae3001b 100644 --- a/ash/shelf/scrollable_shelf_view.cc +++ b/ash/shelf/scrollable_shelf_view.cc
@@ -4,6 +4,7 @@ #include "ash/shelf/scrollable_shelf_view.h" +#include "ash/drag_drop/drag_image_view.h" #include "ash/public/cpp/shelf_config.h" #include "ash/screen_util.h" #include "ash/shelf/shelf_focus_cycler.h" @@ -56,6 +57,10 @@ // Length of the fade in/out zone. constexpr int kGradientZoneLength = 26; +// Delay to show a new page of shelf icons. +constexpr base::TimeDelta kShelfPageFlipDelay = + base::TimeDelta::FromMilliseconds(500); + // Sum of the shelf button size and the gap between shelf buttons. int GetUnit() { return ShelfConfig::Get()->button_size() + @@ -325,7 +330,8 @@ // ScrollableShelfView ScrollableShelfView::ScrollableShelfView(ShelfModel* model, Shelf* shelf) - : shelf_view_(new ShelfView(model, shelf)) { + : shelf_view_(new ShelfView(model, shelf, /*drag_and_drop_host=*/this)), + page_flip_time_threshold_(kShelfPageFlipDelay) { Shell::Get()->AddShellObserver(this); set_allow_deactivate_on_esc(true); } @@ -440,6 +446,12 @@ return CalculateAdjustedOffset(); } +void ScrollableShelfView::SetTestObserver(TestObserver* test_observer) { + DCHECK(!(test_observer && test_observer_)); + + test_observer_ = test_observer; +} + int ScrollableShelfView::CalculateScrollUpperBound() const { if (layout_strategy_ == kNotShowArrowButtons) return 0; @@ -820,9 +832,69 @@ return nullptr; } +void ScrollableShelfView::CreateDragIconProxyByLocationWithNoAnimation( + const gfx::Point& origin_in_screen_coordinates, + const gfx::ImageSkia& icon, + views::View* replaced_view, + float scale_factor, + int blur_radius) { + drag_icon_ = std::make_unique<DragImageView>( + GetWidget()->GetNativeWindow()->GetRootWindow(), + ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE); + drag_icon_->SetImage(icon); + const gfx::Rect replaced_view_screen_bounds = + replaced_view->GetBoundsInScreen(); + drag_icon_->SetBoundsInScreen(replaced_view_screen_bounds); + drag_icon_->GetWidget()->SetVisibilityAnimationTransition( + views::Widget::ANIMATE_NONE); + drag_icon_->SetWidgetVisible(true); +} + +void ScrollableShelfView::UpdateDragIconProxy( + const gfx::Point& location_in_screen_coordinates) { + drag_icon_->SetScreenPosition(location_in_screen_coordinates); + + if (IsDragIconWithinVisibleSpace()) { + page_flip_timer_.AbandonAndStop(); + return; + } + + if (!page_flip_timer_.IsRunning()) { + page_flip_timer_.Start(FROM_HERE, page_flip_time_threshold_, this, + &ScrollableShelfView::OnPageFlipTimer); + } +} + +void ScrollableShelfView::DestroyDragIconProxy() { + drag_icon_.reset(); + + if (page_flip_timer_.IsRunning()) + page_flip_timer_.AbandonAndStop(); +} + +bool ScrollableShelfView::StartDrag( + const std::string& app_id, + const gfx::Point& location_in_screen_coordinates) { + return false; +} + +bool ScrollableShelfView::Drag( + const gfx::Point& location_in_screen_coordinates) { + return false; +} + void ScrollableShelfView::OnImplicitAnimationsCompleted() { during_scrolling_animation_ = false; Layout(); + + if (!drag_icon_.get()) + return; + + if (IsDragIconWithinVisibleSpace()) + return; + + page_flip_timer_.Start(FROM_HERE, page_flip_time_threshold_, this, + &ScrollableShelfView::OnPageFlipTimer); } gfx::Insets ScrollableShelfView::CalculateEdgePadding() const { @@ -1373,4 +1445,39 @@ return gfx::RoundedCornersF(upper_left, upper_right, lower_right, lower_left); } +void ScrollableShelfView::OnPageFlipTimer() { + gfx::Rect visible_space_in_screen = visible_space_; + views::View::ConvertRectToScreen(this, &visible_space_in_screen); + + const gfx::Rect drag_icon_screen_bounds = drag_icon_->GetBoundsInScreen(); + + DCHECK(!visible_space_in_screen.Contains(drag_icon_screen_bounds)); + + // Calculates the page scrolling direction based on the |drag_icon_|'s + // location and the bounds of the visible space. + bool should_scroll_to_next; + if (ShouldAdaptToRTL()) { + should_scroll_to_next = + drag_icon_screen_bounds.x() < visible_space_in_screen.x(); + } else { + should_scroll_to_next = + GetShelf()->IsHorizontalAlignment() + ? drag_icon_screen_bounds.right() > visible_space_in_screen.right() + : drag_icon_screen_bounds.bottom() > + visible_space_in_screen.bottom(); + } + + ScrollToNewPage(/*forward=*/should_scroll_to_next); + + if (test_observer_) + test_observer_->OnPageFlipTimerFired(); +} + +bool ScrollableShelfView::IsDragIconWithinVisibleSpace() const { + gfx::Rect visible_space_in_screen = visible_space_; + views::View::ConvertRectToScreen(this, &visible_space_in_screen); + + return visible_space_in_screen.Contains(drag_icon_->GetBoundsInScreen()); +} + } // namespace ash
diff --git a/ash/shelf/scrollable_shelf_view.h b/ash/shelf/scrollable_shelf_view.h index 3fb7d33..8c6998c3 100644 --- a/ash/shelf/scrollable_shelf_view.h +++ b/ash/shelf/scrollable_shelf_view.h
@@ -5,6 +5,7 @@ #ifndef ASH_SHELF_SCROLLABLE_SHELF_VIEW_H_ #define ASH_SHELF_SCROLLABLE_SHELF_VIEW_H_ +#include "ash/app_list/views/app_list_drag_and_drop_host.h" #include "ash/ash_export.h" #include "ash/public/cpp/shelf_model.h" #include "ash/shelf/scroll_arrow_view.h" @@ -29,8 +30,15 @@ public ShelfButtonDelegate, public ShelfTooltipDelegate, public views::ContextMenuController, + public ApplicationDragAndDropHost, public ui::ImplicitAnimationObserver { public: + class TestObserver { + public: + virtual ~TestObserver() = default; + virtual void OnPageFlipTimerFired() = 0; + }; + enum LayoutStrategy { // The arrow buttons are not shown. It means that there is enough space to // accommodate all of shelf icons. @@ -71,6 +79,8 @@ views::View* GetShelfContainerViewForTest(); bool ShouldAdjustForTest() const; + void SetTestObserver(TestObserver* test_observer); + ShelfView* shelf_view() { return shelf_view_; } ShelfContainerView* shelf_container_view() { return shelf_container_view_; } ScrollArrowView* left_arrow() { return left_arrow_; } @@ -86,6 +96,10 @@ default_last_focusable_child_ = default_last_focusable_child; } + void set_page_flip_time_threshold(base::TimeDelta page_flip_time_threshold) { + page_flip_time_threshold_ = page_flip_time_threshold; + } + const gfx::Rect& visible_space() const { return visible_space_; } // Size of the arrow button. @@ -177,6 +191,20 @@ base::string16 GetTitleForView(const views::View* view) const override; views::View* GetViewForEvent(const ui::Event& event) override; + // ApplicationDragAndDropHost: + void CreateDragIconProxyByLocationWithNoAnimation( + const gfx::Point& origin_in_screen_coordinates, + const gfx::ImageSkia& icon, + views::View* replaced_view, + float scale_factor, + int blur_radius) override; + void UpdateDragIconProxy( + const gfx::Point& location_in_screen_coordinates) override; + void DestroyDragIconProxy() override; + bool StartDrag(const std::string& app_id, + const gfx::Point& location_in_screen_coordinates) override; + bool Drag(const gfx::Point& location_in_screen_coordinates) override; + // ui::ImplicitAnimationObserver: void OnImplicitAnimationsCompleted() override; @@ -270,6 +298,12 @@ // ripple ring. gfx::RoundedCornersF CalculateShelfContainerRoundedCorners() const; + // Scrolls to a new page if |drag_icon_| is dragged out of |visible_space_| + // for enough time. The function is called when |page_flip_timer_| is fired. + void OnPageFlipTimer(); + + bool IsDragIconWithinVisibleSpace() const; + LayoutStrategy layout_strategy_ = kNotShowArrowButtons; // Child views Owned by views hierarchy. @@ -323,6 +357,17 @@ bool should_show_start_gradient_zone_ = false; bool should_show_end_gradient_zone_ = false; + // Waiting time before flipping the page. + base::TimeDelta page_flip_time_threshold_; + + TestObserver* test_observer_ = nullptr; + + // Replaces the dragged app icon during drag procedure. It ensures that the + // app icon can be dragged out of the shelf view. + std::unique_ptr<DragImageView> drag_icon_; + + base::OneShotTimer page_flip_timer_; + DISALLOW_COPY_AND_ASSIGN(ScrollableShelfView); };
diff --git a/ash/shelf/scrollable_shelf_view_unittest.cc b/ash/shelf/scrollable_shelf_view_unittest.cc index 2121cc4..8c7816b 100644 --- a/ash/shelf/scrollable_shelf_view_unittest.cc +++ b/ash/shelf/scrollable_shelf_view_unittest.cc
@@ -16,6 +16,31 @@ namespace ash { +class PageFlipWaiter : public ScrollableShelfView::TestObserver { + public: + explicit PageFlipWaiter(ScrollableShelfView* scrollable_shelf_view) + : scrollable_shelf_view_(scrollable_shelf_view) { + scrollable_shelf_view->SetTestObserver(this); + } + ~PageFlipWaiter() override { + scrollable_shelf_view_->SetTestObserver(nullptr); + } + + void Wait() { + run_loop_ = std::make_unique<base::RunLoop>(); + run_loop_->Run(); + } + + private: + void OnPageFlipTimerFired() override { + DCHECK(run_loop_.get()); + run_loop_->Quit(); + } + + ScrollableShelfView* scrollable_shelf_view_ = nullptr; + std::unique_ptr<base::RunLoop> run_loop_; +}; + class TestShelfItemDelegate : public ShelfItemDelegate { public: explicit TestShelfItemDelegate(const ShelfID& shelf_id) @@ -345,4 +370,45 @@ EXPECT_TRUE(tooltip_manager->IsVisible()); } +// Verifies that dragging an app icon to a new shelf page works well. +TEST_F(ScrollableShelfViewTest, DragIconToNewPage) { + scrollable_shelf_view_->set_page_flip_time_threshold( + base::TimeDelta::FromMilliseconds(10)); + + AddAppShortcutsUntilOverflow(); + GetEventGenerator()->GestureTapAt( + scrollable_shelf_view_->right_arrow()->GetBoundsInScreen().CenterPoint()); + AddAppShortcutsUntilRightArrowIsShown(); + ASSERT_EQ(ScrollableShelfView::kShowButtons, + scrollable_shelf_view_->layout_strategy_for_test()); + + views::ViewModel* view_model = shelf_view_->view_model(); + views::View* dragged_view = + view_model->view_at(scrollable_shelf_view_->last_tappable_app_index()); + const gfx::Point drag_start_point = + dragged_view->GetBoundsInScreen().CenterPoint(); + const gfx::Point drag_end_point = + scrollable_shelf_view_->left_arrow()->GetBoundsInScreen().CenterPoint(); + + ASSERT_NE(0, view_model->GetIndexOfView(dragged_view)); + + // Drag |dragged_view| from |drag_start_point| to |drag_end_point|. Wait + // for enough time before releasing the mouse button. + GetEventGenerator()->MoveMouseTo(drag_start_point); + GetEventGenerator()->PressLeftButton(); + GetEventGenerator()->MoveMouseTo(drag_end_point); + { + PageFlipWaiter waiter(scrollable_shelf_view_); + waiter.Wait(); + } + GetEventGenerator()->ReleaseLeftButton(); + + // Verifies that: + // (1) Scrollable shelf view has the expected layout strategy. + // (2) The dragged view has the correct view index. + EXPECT_EQ(ScrollableShelfView::kShowRightArrowButton, + scrollable_shelf_view_->layout_strategy_for_test()); + EXPECT_EQ(0, view_model->GetIndexOfView(dragged_view)); +} + } // namespace ash
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 12a06b9..48011aa 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -299,12 +299,15 @@ // static const int ShelfView::kMinimumDragDistance = 8; -ShelfView::ShelfView(ShelfModel* model, Shelf* shelf) +ShelfView::ShelfView(ShelfModel* model, + Shelf* shelf, + ApplicationDragAndDropHost* drag_and_drop_host) : model_(model), shelf_(shelf), view_model_(std::make_unique<views::ViewModel>()), bounds_animator_(std::make_unique<views::BoundsAnimator>(this)), - focus_search_(std::make_unique<ShelfFocusSearch>(this)) { + focus_search_(std::make_unique<ShelfFocusSearch>(this)), + drag_and_drop_host_(drag_and_drop_host) { DCHECK(model_); DCHECK(shelf_); Shell::Get()->tablet_mode_controller()->AddObserver(this); @@ -521,7 +524,8 @@ if (!overflow_bubble_) overflow_bubble_.reset(new OverflowBubble(shelf_)); - ShelfView* overflow_view = new ShelfView(model_, shelf_); + ShelfView* overflow_view = + new ShelfView(model_, shelf_, /*drag_and_drop_host=*/nullptr); overflow_view->overflow_mode_ = true; overflow_view->Init(); overflow_view->set_owner_overflow_bubble(overflow_bubble_.get()); @@ -1462,10 +1466,21 @@ drag_pointer_ = NONE; AnimateToIdealBounds(); } + + if (drag_pointer_ != NONE) + return; + + if (chromeos::switches::ShouldShowScrollableShelf()) { + drag_and_drop_host_->DestroyDragIconProxy(); + + // |drag_view_| is reset already when being removed from the shelf view. + if (drag_view_) + drag_view_->layer()->SetOpacity(1.0f); + } + // If the drag pointer is NONE, no drag operation is going on and the // drag_view can be released. - if (drag_pointer_ == NONE) - drag_view_ = nullptr; + drag_view_ = nullptr; } void ShelfView::LayoutToIdealBounds() { @@ -1521,8 +1536,6 @@ for (int i = 0; i < view_model_->view_size(); ++i) { View* view = view_model_->view_at(i); - if (view->size() == gfx::Size()) - continue; // Do not animate a hidden item (see StartDrag) bounds_animator_->AnimateViewTo(view, view_model_->ideal_bounds(i)); // Now that the item animation starts, we have to make sure that the // padding of the first gets properly transferred to the new first item. @@ -1559,6 +1572,13 @@ bounds_animator_->StopAnimatingView(drag_view_); drag_view_->OnDragStarted(&event); + + if (chromeos::switches::ShouldShowScrollableShelf()) { + drag_view_->layer()->SetOpacity(0.0f); + drag_and_drop_host_->CreateDragIconProxyByLocationWithNoAnimation( + event.root_location(), drag_view_->GetImage(), drag_view_, + /*scale_factor=*/1.0f, /*blur_radius=*/0); + } } void ShelfView::ContinueDrag(const ui::LocatedEvent& event) { @@ -1622,6 +1642,10 @@ ConvertPointToTarget(drag_view_, this, &drag_point); MoveDragViewTo(shelf_->PrimaryAxisValue(drag_point.x() - drag_origin_.x(), drag_point.y() - drag_origin_.y())); + if (chromeos::switches::ShouldShowScrollableShelf()) { + drag_and_drop_host_->UpdateDragIconProxy( + drag_view_->GetBoundsInScreen().origin()); + } } void ShelfView::ScrollForUserDrag(int offset) { @@ -1736,7 +1760,25 @@ // Re-insert the item and return simply false since the caller will handle // the move as in any normal case. dragged_off_shelf_ = false; - drag_view_->layer()->SetOpacity(1.0f); + + if (chromeos::switches::ShouldShowScrollableShelf()) { + // |drag_view_| is moved to the end of the view model when the app icon + // is dragged off the shelf. So updates the location of |drag_view_| + // before creating a proxy icon to ensure that the proxy icon has the + // correct bounds. + gfx::Point drag_point(event.location()); + ConvertPointToTarget(drag_view_, this, &drag_point); + MoveDragViewTo( + shelf_->PrimaryAxisValue(drag_point.x() - drag_origin_.x(), + drag_point.y() - drag_origin_.y())); + + drag_and_drop_host_->CreateDragIconProxyByLocationWithNoAnimation( + event.root_location(), drag_view_->GetImage(), drag_view_, + /*scale_factor=*/1.0f, /*blur_radius=*/0); + } else { + drag_view_->layer()->SetOpacity(1.0f); + } + // The size of Overflow bubble should be updated immediately when an item // is re-inserted. if (is_overflow_mode()) @@ -1810,7 +1852,12 @@ CreateDragIconProxy(event.root_location(), drag_view_->GetImage(), drag_view_, gfx::Vector2d(0, 0), kDragAndDropProxyScale); - drag_view_->layer()->SetOpacity(0.0f); + + if (chromeos::switches::ShouldShowScrollableShelf()) + drag_and_drop_host_->DestroyDragIconProxy(); + else + drag_view_->layer()->SetOpacity(0.0f); + dragged_off_shelf_ = true; if (RemovableByRipOff(current_index) == REMOVABLE) { // Move the item to the back and hide it. ShelfItemMoved() callback will
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index e1c2efd..4271f2b 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -118,7 +118,9 @@ public VirtualKeyboardModel::Observer, public ShelfConfig::Observer { public: - ShelfView(ShelfModel* model, Shelf* shelf); + ShelfView(ShelfModel* model, + Shelf* shelf, + ApplicationDragAndDropHost* drag_and_drop_host); ~ShelfView() override; Shelf* shelf() const { return shelf_; } @@ -727,6 +729,10 @@ // becomes y-axis) int app_icons_layout_offset_ = 0; + // When the scrollable shelf is enabled, |drag_and_drop_host_| should be + // ScrollableShelfView. + ApplicationDragAndDropHost* drag_and_drop_host_ = nullptr; + base::WeakPtrFactory<ShelfView> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ShelfView);
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index e6db5922..7da4489 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -1905,7 +1905,7 @@ // Checks various drag and drop operations from OverflowBubble to Shelf, and // vice versa. -TEST_F(ShelfViewTest, DISABLED_CheckDragAndDropFromShelfToOtherShelf) { +TEST_F(ShelfViewTest, CheckDragAndDropFromShelfToOtherShelf) { // No overflow bubble when scrollable shelf enabled. // TODO(https://crbug.com/1002576): revisit when scrollable shelf is launched. if (chromeos::switches::ShouldShowScrollableShelf())
diff --git a/ash/system/unified/page_indicator_view.cc b/ash/system/unified/page_indicator_view.cc index f57b402..65b9a49c 100644 --- a/ash/system/unified/page_indicator_view.cc +++ b/ash/system/unified/page_indicator_view.cc
@@ -177,7 +177,7 @@ AddChildView(buttons_container_); - TotalPagesChanged(); + TotalPagesChanged(0, model_->total_pages()); DCHECK(model_); model_->AddObserver(this); @@ -214,7 +214,8 @@ layer()->SetOpacity(std::max(0., 6 * expanded_amount_ - 5.)); } -void PageIndicatorView::TotalPagesChanged() { +void PageIndicatorView::TotalPagesChanged(int previous_page_count, + int new_page_count) { DCHECK(model_); buttons_container_->RemoveAllChildViews(true);
diff --git a/ash/system/unified/page_indicator_view.h b/ash/system/unified/page_indicator_view.h index ec405ecb..3677493 100644 --- a/ash/system/unified/page_indicator_view.h +++ b/ash/system/unified/page_indicator_view.h
@@ -40,7 +40,7 @@ class PageIndicatorButton; // PaginationModelObserver: - void TotalPagesChanged() override; + void TotalPagesChanged(int previous_page_count, int new_page_count) override; void SelectedPageChanged(int old_selected, int new_selected) override; bool IsPageSelectedForTesting(int index);
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 085c0f0..a36a45e 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -36,6 +36,7 @@ #include "ash/wm/overview/overview_item.h" #include "ash/wm/overview/overview_session.h" #include "ash/wm/overview/overview_utils.h" +#include "ash/wm/overview/overview_window_drag_controller.h" #include "ash/wm/overview/scoped_overview_animation_settings.h" #include "ash/wm/resize_shadow_controller.h" #include "ash/wm/splitview/split_view_constants.h" @@ -304,36 +305,6 @@ return bounds; } -// Get the grid bounds if a window is snapped in splitview, or what they will be -// when snapped based on |indicator_state|. -gfx::Rect GetGridBoundsInScreenForSplitview( - aura::Window* window, - base::Optional<IndicatorState> indicator_state = base::nullopt) { - SplitViewController* split_view_controller = SplitViewController::Get(window); - auto state = split_view_controller->state(); - - // If we are in splitview mode already just use the given state, otherwise - // convert |indicator_state| to a splitview state. - if (!split_view_controller->InSplitViewMode() && indicator_state) { - if (*indicator_state == IndicatorState::kPreviewAreaLeft) - state = SplitViewController::State::kLeftSnapped; - else if (*indicator_state == IndicatorState::kPreviewAreaRight) - state = SplitViewController::State::kRightSnapped; - } - - switch (state) { - case SplitViewController::State::kLeftSnapped: - return split_view_controller->GetSnappedWindowBoundsInScreen( - SplitViewController::RIGHT); - case SplitViewController::State::kRightSnapped: - return split_view_controller->GetSnappedWindowBoundsInScreen( - SplitViewController::LEFT); - default: - return screen_util:: - GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(window); - } -} - gfx::Insets GetGridInsets(const gfx::Rect& grid_bounds) { const int horizontal_inset = gfx::ToFlooredInt(std::min(kOverviewInsetRatio * grid_bounds.width(), @@ -811,6 +782,7 @@ bool animate) { DCHECK_EQ(dragged_window->GetRootWindow(), root_window_); DCHECK(!drop_target_widget_); + dragged_window_ = dragged_window; drop_target_widget_ = CreateDropTargetWidget(dragged_window, animate); overview_session_->AddItem(drop_target_widget_->GetNativeWindow(), /*reposition=*/true, animate); @@ -825,6 +797,7 @@ void OverviewGrid::OnWindowDragContinued(aura::Window* dragged_window, const gfx::PointF& location_in_screen, IndicatorState indicator_state) { + DCHECK_EQ(dragged_window_, dragged_window); DCHECK_EQ(dragged_window->GetRootWindow(), root_window_); RearrangeDuringDrag(dragged_window, indicator_state); @@ -869,8 +842,10 @@ const gfx::PointF& location_in_screen, bool should_drop_window_into_overview, bool snap) { + DCHECK_EQ(dragged_window_, dragged_window); DCHECK_EQ(dragged_window->GetRootWindow(), root_window_); DCHECK(drop_target_widget_.get()); + dragged_window_ = nullptr; // Add the dragged window into drop target in overview if // |should_drop_window_into_overview| is true. Only consider add the dragged @@ -1511,7 +1486,8 @@ items_scrolling_bounds_.clear(); presentation_time_recorder_.reset(); - PositionWindows(/*animate=*/false); + if (!overview_session_->is_shutting_down()) + PositionWindows(/*animate=*/false); } void OverviewGrid::MaybeInitDesksWidget() { @@ -1684,13 +1660,9 @@ continue; } - // Maintains the aspect ratio from the original window. The window's - // original height will be shrunk to fit into |height|, minus the margin and - // overview header. - const float ratio = float{height - kHeaderHeightDp - kOverviewMargin} / - item->GetWindow()->bounds().height(); + // Calculate the width and y position of the item. const int width = - item->GetWindow()->bounds().width() * ratio + kOverviewMargin; + CalculateWidthAndMaybeSetUnclippedBounds(window_list_[i].get(), height); const int y = height * (window_position % kTabletLayoutRow) + total_bounds.y(); @@ -1735,30 +1707,14 @@ // All elements are of same height and only the height is necessary to // determine each item's scale. - const gfx::Size item_size(0, height); for (size_t i = 0u; i < window_count; ++i) { if (window_list_[i]->animating_to_close() || ignored_items.contains(window_list_[i].get())) { continue; } - const gfx::RectF target_bounds = window_list_[i]->GetTargetBoundsInScreen(); - int width = std::max( - 1, gfx::ToFlooredInt(target_bounds.width() * - window_list_[i]->GetItemScale(item_size)) + - 2 * kWindowMargin); - switch (window_list_[i]->GetWindowDimensionsType()) { - case ScopedOverviewTransformWindow::GridWindowFillMode::kLetterBoxed: - width = ScopedOverviewTransformWindow::kExtremeWindowRatioThreshold * - height; - break; - case ScopedOverviewTransformWindow::GridWindowFillMode::kPillarBoxed: - width = height / - ScopedOverviewTransformWindow::kExtremeWindowRatioThreshold; - break; - default: - break; - } + int width = + CalculateWidthAndMaybeSetUnclippedBounds(window_list_[i].get(), height); if (left + width > bounds.right()) { // Move to the next row if possible. @@ -1778,10 +1734,10 @@ } // Position the current rect. - (*out_rects)[i] = gfx::RectF(gfx::Rect(left, top, width, height)); + (*out_rects)[i] = gfx::RectF(left, top, width, height); - // Increment horizontal position using sanitized positive |width()|. - left += gfx::ToRoundedInt((*out_rects)[i].width()); + // Increment horizontal position using sanitized positive |width|. + left += width; *out_max_bottom = top + height; } @@ -1842,4 +1798,82 @@ /*animate=*/false); } +int OverviewGrid::CalculateWidthAndMaybeSetUnclippedBounds(OverviewItem* item, + int height) { + const gfx::Size item_size(0, height); + gfx::RectF target_bounds = item->GetTargetBoundsInScreen(); + float scale = item->GetItemScale(item_size); + + // The drop target, unlike the other windows has its bounds set directly, so + // |GetTargetBoundsInScreen()| won't return the value we want. Instead, get + // the scale from the window it was meant to be a placeholder for. + if (IsDropTargetWindow(item->GetWindow())) { + aura::Window* dragged_window = nullptr; + OverviewItem* item = + overview_session_->window_drag_controller() + ? overview_session_->window_drag_controller()->item() + : nullptr; + if (item) + dragged_window = item->GetWindow(); + else if (dragged_window_) + dragged_window = dragged_window_; + + if (dragged_window && dragged_window->parent()) { + target_bounds = ::ash::GetTargetBoundsInScreen(dragged_window); + const gfx::SizeF inset_size(0, height - 2 * kWindowMargin); + scale = ScopedOverviewTransformWindow::GetItemScale( + target_bounds.size(), inset_size, + dragged_window->GetProperty(aura::client::kTopViewInset), + kHeaderHeightDp); + } + } + + int width = std::max( + 1, gfx::ToFlooredInt(target_bounds.width() * scale) + 2 * kWindowMargin); + switch (item->GetWindowDimensionsType()) { + case ScopedOverviewTransformWindow::GridWindowFillMode::kLetterBoxed: + width = + ScopedOverviewTransformWindow::kExtremeWindowRatioThreshold * height; + break; + case ScopedOverviewTransformWindow::GridWindowFillMode::kPillarBoxed: + width = + height / ScopedOverviewTransformWindow::kExtremeWindowRatioThreshold; + break; + default: + break; + } + + // Get the bounds of the window if there is a snapped window or a window + // about to be snapped. + base::Optional<gfx::RectF> split_view_bounds = + GetSplitviewBoundsMaintainingAspectRatio(item->GetWindow()); + if (!split_view_bounds) { + item->set_unclipped_size(base::nullopt); + return width; + } + + const bool is_landscape = IsCurrentScreenOrientationLandscape(); + gfx::Size unclipped_size; + if (is_landscape) { + unclipped_size.set_width(width - 2 * kWindowMargin); + unclipped_size.set_height(height - 2 * kWindowMargin); + // For landscape mode, shrink |width| so that the aspect ratio matches + // that of |split_view_bounds|. + width = std::max(1, gfx::ToFlooredInt(split_view_bounds->width() * scale) + + 2 * kWindowMargin); + } else { + // For portrait mode, we want |height| to stay the same, so calculate + // what the unclipped height would be based on |split_view_bounds|. + width = split_view_bounds->width() * height / split_view_bounds->height(); + int unclipped_height = + (target_bounds.height() * width) / target_bounds.width(); + unclipped_size.set_width(width); + unclipped_size.set_height(unclipped_height); + } + + DCHECK(!unclipped_size.IsEmpty()); + item->set_unclipped_size(base::make_optional(unclipped_size)); + return width; +} + } // namespace ash
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index e1092445..ef7456a 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -396,6 +396,12 @@ // the window's bounds if it has been resized. void AddDraggedWindowIntoOverviewOnDragEnd(aura::Window* dragged_window); + // Calculate the width of an item based on |height|. The width tries to keep + // the same aspect ratio as the original window, but may be modified if the + // bounds of the window are considered extreme, or if the window is in + // splitview or entering splitview. + int CalculateWidthAndMaybeSetUnclippedBounds(OverviewItem* item, int height); + // Root window the grid is in. aura::Window* root_window_; @@ -465,6 +471,10 @@ // Records the presentation time of scrolling the grid in overview mode. std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_; + // Weak pointer to the window that is being dragged from the top, if there is + // one. + aura::Window* dragged_window_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(OverviewGrid); };
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc index 906b280..5772780 100644 --- a/ash/wm/overview/overview_item.cc +++ b/ash/wm/overview/overview_item.cc
@@ -1173,9 +1173,15 @@ screen_rect.set_size(screen_size); const int top_view_inset = transform_window_.GetTopInset(); + gfx::RectF transformed_bounds = target_bounds; + // Update |transformed_bounds| to match the unclipped size of the window, so + // we transform the window to the correct size. + if (unclipped_size_) + transformed_bounds.set_size(gfx::SizeF(*unclipped_size_)); + gfx::RectF overview_item_bounds = transform_window_.ShrinkRectToFitPreservingAspectRatio( - screen_rect, target_bounds, top_view_inset, kHeaderHeightDp); + screen_rect, transformed_bounds, top_view_inset, kHeaderHeightDp); const gfx::Transform transform = gfx::TransformBetweenRects(screen_rect, overview_item_bounds); @@ -1186,17 +1192,24 @@ return; } - ScopedOverviewTransformWindow::ScopedAnimationSettings animation_settings; - transform_window_.BeginScopedAnimation(animation_type, &animation_settings); - if (animation_type == OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW && - !animation_settings.empty()) { - animation_settings.front()->AddObserver(new AnimationObserver{ - base::BindOnce(&OverviewItem::OnItemBoundsAnimationStarted, - weak_ptr_factory_.GetWeakPtr()), - base::BindOnce(&OverviewItem::OnItemBoundsAnimationEnded, - weak_ptr_factory_.GetWeakPtr())}); + { + ScopedOverviewTransformWindow::ScopedAnimationSettings animation_settings; + transform_window_.BeginScopedAnimation(animation_type, &animation_settings); + if (animation_type == + OVERVIEW_ANIMATION_LAYOUT_OVERVIEW_ITEMS_IN_OVERVIEW && + !animation_settings.empty()) { + animation_settings.front()->AddObserver(new AnimationObserver{ + base::BindOnce(&OverviewItem::OnItemBoundsAnimationStarted, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&OverviewItem::OnItemBoundsAnimationEnded, + weak_ptr_factory_.GetWeakPtr())}); + } + SetTransform(window, transform); } - SetTransform(window, transform); + + transform_window_.SetClipping(unclipped_size_ + ? GetWindowTargetBoundsWithInsets().size() + : gfx::SizeF()); } void OverviewItem::CreateWindowLabel() {
diff --git a/ash/wm/overview/overview_item.h b/ash/wm/overview/overview_item.h index e8855c1e..b3bc86e 100644 --- a/ash/wm/overview/overview_item.h +++ b/ash/wm/overview/overview_item.h
@@ -259,6 +259,10 @@ void set_disable_mask(bool disable) { disable_mask_ = disable; } + void set_unclipped_size(base::Optional<gfx::Size> unclipped_size) { + unclipped_size_ = unclipped_size; + } + views::ImageButton* GetCloseButtonForTesting(); float GetCloseButtonVisibilityForTesting() const; float GetTitlebarOpacityForTesting() const; @@ -347,7 +351,9 @@ // The contained Window's wrapper. ScopedOverviewTransformWindow transform_window_; - // The target bounds this overview item is fit within. + // The target bounds this overview item is fit within. When in splitview, + // |item_widget_| is fit within these bounds, but the window itself is + // transformed to |unclipped_size_|, and then clipped. gfx::RectF target_bounds_; // True if running SetItemBounds. This prevents recursive calls resulting from @@ -411,9 +417,18 @@ bool prepared_for_overview_ = false; - // Stores the last translations of the windows affected by SetBounds. Used for - // ease of calculations when swiping away overview mode using home launcher - // gesture. + // This has a value when there is a snapped window, or a window about to be + // snapped (triggering a splitview preview area). This will be set when items + // are positioned in OverviewGrid. The bounds delivered in |SetBounds| are the + // true bounds of this item, but we want to maintain the aspect ratio of the + // window, who's bounds are not set to split view size. So in |SetItemBounds|, + // we transform the window not to |target_bounds_| but to this value, and then + // apply clipping on the window to |target_bounds_|. + base::Optional<gfx::Size> unclipped_size_ = base::nullopt; + + // Stores the last translations of the windows affected by |SetBounds|. Used + // for ease of calculations when swiping away overview mode using home + // launcher gesture. base::flat_map<aura::Window*, int> translation_y_map_; // The shadow around the overview window. Shadows the original window, not
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc index fdad20b1..0a5e1650 100644 --- a/ash/wm/overview/overview_session_unittest.cc +++ b/ash/wm/overview/overview_session_unittest.cc
@@ -3820,6 +3820,92 @@ EXPECT_EQ(expected_grid_bounds, GetGridBounds()); } +TEST_P(SplitViewOverviewSessionTest, Clipping) { + // Helper to check if two rectangles have roughly the same aspect ratio. They + // may be off by a bit due to insets and overview headers, but should have + // roughly the same shape. + auto aspect_ratio_near = [](const gfx::Rect& rect1, const gfx::Rect& rect2) { + DCHECK_GT(rect1.height(), 0); + DCHECK_GT(rect2.height(), 0); + constexpr float kEpsilon = 0.1f; + const float rect1_aspect_ratio = + float{rect1.width()} / float{rect1.height()}; + const float rect2_aspect_ratio = + float{rect2.width()} / float{rect2.height()}; + return std::abs(rect2_aspect_ratio - rect1_aspect_ratio) < kEpsilon; + }; + + std::unique_ptr<aura::Window> window1 = CreateTestWindow(); + std::unique_ptr<aura::Window> window2 = CreateTestWindow(); + + for (bool portrait : {false, true}) { + SCOPED_TRACE(portrait ? "Portrait" : "Landscape"); + if (portrait) { + ScreenOrientationControllerTestApi test_api( + Shell::Get()->screen_orientation_controller()); + test_api.SetDisplayRotation(display::Display::ROTATE_90, + display::Display::RotationSource::ACTIVE); + } + + const gfx::Rect clipping1 = window1->layer()->clip_rect(); + const gfx::Rect clipping2 = window2->layer()->clip_rect(); + const gfx::Rect maximized_bounds = + screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer( + window1.get()); + const gfx::Rect split_view_bounds_right = + split_view_controller()->GetSnappedWindowBoundsInScreen( + SplitViewController::SnapPosition::RIGHT); + + ToggleOverview(); + // Tests that in regular overview, the clipping is unchanged. + ASSERT_TRUE(overview_controller()->InOverviewSession()); + EXPECT_EQ(clipping1, window1->layer()->clip_rect()); + EXPECT_EQ(clipping2, window2->layer()->clip_rect()); + + OverviewItem* item1 = GetOverviewItemForWindow(window1.get()); + OverviewItem* item2 = GetOverviewItemForWindow(window2.get()); + overview_session()->InitiateDrag(item1, + item1->target_bounds().CenterPoint(), + /*is_touch_dragging=*/false); + + // Tests that after we drag to a preview area, the items target bounds have + // a matching aspect ratio to what the window would have if it were to be + // snapped in splitview. The window clipping should match this, but the + // windows regular bounds remain unchanged (maximized). + overview_session()->Drag(item1, gfx::PointF()); + EXPECT_EQ(IndicatorState::kPreviewAreaLeft, + overview_session() + ->split_view_drag_indicators() + ->current_indicator_state()); + EXPECT_FALSE(window2->layer()->clip_rect().IsEmpty()); + EXPECT_TRUE(aspect_ratio_near(window2->layer()->clip_rect(), + split_view_bounds_right)); + EXPECT_TRUE(aspect_ratio_near(gfx::ToEnclosedRect(item2->target_bounds()), + split_view_bounds_right)); + EXPECT_TRUE( + aspect_ratio_near(window2->GetBoundsInScreen(), maximized_bounds)); + + // Tests that after snapping, the aspect ratios should be the same as being + // in the preview area. + overview_session()->CompleteDrag(item1, gfx::PointF()); + ASSERT_EQ(SplitViewController::State::kLeftSnapped, + split_view_controller()->state()); + EXPECT_FALSE(window2->layer()->clip_rect().IsEmpty()); + EXPECT_TRUE(aspect_ratio_near(window2->layer()->clip_rect(), + split_view_bounds_right)); + EXPECT_TRUE(aspect_ratio_near(gfx::ToEnclosedRect(item2->target_bounds()), + split_view_bounds_right)); + EXPECT_TRUE( + aspect_ratio_near(window2->GetBoundsInScreen(), maximized_bounds)); + + // Tests that the clipping is reset after exiting overview. + EndSplitView(); + ToggleOverview(); + EXPECT_EQ(clipping1, window1->layer()->clip_rect()); + EXPECT_EQ(clipping2, window1->layer()->clip_rect()); + } +} + // Tests that if there is only one window in the MRU window list in the overview // mode, snapping the window to one side of the screen will not end the overview // mode even if there is no more window left in the overview window grid.
diff --git a/ash/wm/overview/overview_utils.cc b/ash/wm/overview/overview_utils.cc index 1adc7e2..5c4f7718 100644 --- a/ash/wm/overview/overview_utils.cc +++ b/ash/wm/overview/overview_utils.cc
@@ -12,6 +12,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_properties.h" #include "ash/scoped_animation_disabler.h" +#include "ash/screen_util.h" #include "ash/shell.h" #include "ash/wm/overview/cleanup_animation_observer.h" #include "ash/wm/overview/delayed_animation_observer_impl.h" @@ -218,6 +219,58 @@ } } +// Get the grid bounds if a window is snapped in splitview, or what they will be +// when snapped based on |indicator_state|. +gfx::Rect GetGridBoundsInScreenForSplitview( + aura::Window* window, + base::Optional<IndicatorState> indicator_state) { + auto* split_view_controller = + SplitViewController::Get(Shell::GetPrimaryRootWindow()); + auto state = split_view_controller->state(); + + // If we are in splitview mode already just use the given state, otherwise + // convert |indicator_state| to a splitview state. + if (!split_view_controller->InSplitViewMode() && indicator_state) { + if (*indicator_state == IndicatorState::kPreviewAreaLeft) + state = SplitViewController::State::kLeftSnapped; + else if (*indicator_state == IndicatorState::kPreviewAreaRight) + state = SplitViewController::State::kRightSnapped; + } + + switch (state) { + case SplitViewController::State::kLeftSnapped: + return split_view_controller->GetSnappedWindowBoundsInScreen( + SplitViewController::RIGHT); + case SplitViewController::State::kRightSnapped: + return split_view_controller->GetSnappedWindowBoundsInScreen( + SplitViewController::LEFT); + default: + return screen_util:: + GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(window); + } +} + +base::Optional<gfx::RectF> GetSplitviewBoundsMaintainingAspectRatio( + aura::Window* window) { + if (!Shell::Get()->tablet_mode_controller()->InTabletMode()) + return base::nullopt; + auto* overview_session = + Shell::Get()->overview_controller()->overview_session(); + DCHECK(overview_session); + // TODO(sammiequon): This does not work for drag from top as they have + // different drag indicators object as regular overview. + auto indicator_state = + overview_session->split_view_drag_indicators()->current_indicator_state(); + if (!SplitViewController::Get(Shell::GetPrimaryRootWindow()) + ->InSplitViewMode() && + !SplitViewDragIndicators::IsPreviewAreaState(indicator_state)) { + return base::nullopt; + } + + return base::make_optional(gfx::RectF(GetGridBoundsInScreenForSplitview( + window, base::make_optional(indicator_state)))); +} + bool ShouldUseTabletModeGridLayout() { return base::FeatureList::IsEnabled(features::kNewOverviewLayout) && Shell::Get()->tablet_mode_controller()->InTabletMode();
diff --git a/ash/wm/overview/overview_utils.h b/ash/wm/overview/overview_utils.h index 01906309..9947bdd 100644 --- a/ash/wm/overview/overview_utils.h +++ b/ash/wm/overview/overview_utils.h
@@ -9,7 +9,9 @@ #include "ash/ash_export.h" #include "ash/wm/overview/overview_animation_type.h" +#include "ash/wm/splitview/split_view_drag_indicators.h" #include "ash/wm/window_transient_descendant_iterator.h" +#include "base/optional.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/compositor/layer_type.h" #include "ui/gfx/geometry/rect.h" @@ -76,6 +78,18 @@ // Maximize the window if it is snapped without animation. void MaximizeIfSnapped(aura::Window* window); +// Get the grid bounds if a window is snapped in splitview, or what they will be +// when snapped based on |indicator_state|. +gfx::Rect GetGridBoundsInScreenForSplitview( + aura::Window* window, + base::Optional<IndicatorState> indicator_state = base::nullopt); + +// Gets the bounds of a window if it were to be snapped or about to be snapped +// in splitview. Returns nothing if we are not in tablet mode, or if we aren't +// in splitview, or if we aren't showing a splitview preview. +base::Optional<gfx::RectF> GetSplitviewBoundsMaintainingAspectRatio( + aura::Window* window); + // Check if kNewOverviewLayout is enabled for tablet mode. bool ShouldUseTabletModeGridLayout();
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc index 866f8ad..529eb85 100644 --- a/ash/wm/overview/overview_window_drag_controller.cc +++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -580,10 +580,10 @@ snap_position_ = GetSnapPosition(location_in_screen); IndicatorState indicator_state = GetIndicatorState(item_->GetWindow(), snap_position_); - item_->overview_grid()->RearrangeDuringDrag(item_->GetWindow(), - indicator_state); overview_session_->SetSplitViewDragIndicatorsIndicatorState( indicator_state, gfx::ToRoundedPoint(location_in_screen)); + item_->overview_grid()->RearrangeDuringDrag(item_->GetWindow(), + indicator_state); } gfx::Rect OverviewWindowDragController::GetWorkAreaOfDisplayBeingDraggedIn()
diff --git a/ash/wm/overview/scoped_overview_transform_window.cc b/ash/wm/overview/scoped_overview_transform_window.cc index 05858ec..ce3061d4 100644 --- a/ash/wm/overview/scoped_overview_transform_window.cc +++ b/ash/wm/overview/scoped_overview_transform_window.cc
@@ -285,6 +285,22 @@ window->layer()->SetOpacity(opacity); } +void ScopedOverviewTransformWindow::SetClipping(const gfx::SizeF& size) { + // If width or height are 0, restore the overview clipping. + if (size.IsEmpty()) { + window_->layer()->SetClipRect(overview_clip_rect_); + return; + } + + // Compute the clip rect. Transform affects the clip rect, so take that into + // account. + gfx::Rect clip_rect; + const gfx::Vector2dF scale = window_->layer()->GetTargetTransform().Scale2d(); + clip_rect.set_width(size.width() / scale.x()); + clip_rect.set_height(size.height() / scale.y()); + window_->layer()->SetClipRect(clip_rect); +} + gfx::RectF ScopedOverviewTransformWindow::ShrinkRectToFitPreservingAspectRatio( const gfx::RectF& rect, const gfx::RectF& bounds, @@ -417,6 +433,7 @@ ScopedOverviewAnimationSettings settings( OVERVIEW_ANIMATION_FRAME_HEADER_CLIP, window_); layer->SetClipRect(clip_rect); + overview_clip_rect_ = clip_rect; } }
diff --git a/ash/wm/overview/scoped_overview_transform_window.h b/ash/wm/overview/scoped_overview_transform_window.h index 7f5827ec..5d9521ce 100644 --- a/ash/wm/overview/scoped_overview_transform_window.h +++ b/ash/wm/overview/scoped_overview_transform_window.h
@@ -112,6 +112,10 @@ // Sets the opacity of the managed windows. void SetOpacity(float opacity); + // Apply clipping on the managed windows. If |size| is empty, then restore + // |overview_clip_rect_|. + void SetClipping(const gfx::SizeF& size); + // Returns |rect| having been shrunk to fit within |bounds| (preserving the // aspect ratio). Takes into account a window header that is |top_view_inset| // tall in the original window getting replaced by a window caption that is @@ -211,6 +215,11 @@ // mode. gfx::Rect original_clip_rect_; + // The clippng on the layer of |window_| after entering overview mode. + // Additional clipping may be added, and when that additional clipping is + // removed, we should go back to this clipping. + gfx::Rect overview_clip_rect_; + std::unique_ptr<ScopedOverviewHideWindows> hidden_transient_children_; base::WeakPtrFactory<ScopedOverviewTransformWindow> weak_ptr_factory_{this};
diff --git a/base/task/post_task.cc b/base/task/post_task.cc index 244e5f6..dce2f96 100644 --- a/base/task/post_task.cc +++ b/base/task/post_task.cc
@@ -146,4 +146,17 @@ } #endif // defined(OS_WIN) +const scoped_refptr<SequencedTaskRunner>& GetContinuationTaskRunner() { + TaskExecutor* executor = GetTaskExecutorForCurrentThread(); + DCHECK(executor) << "Couldn't find a TaskExecutor for this thread. Note " + "you can't use base::GetContinuationTaskRunner in " + "a one-off base::ThreadPool task."; + const auto& task_runner = executor->GetContinuationTaskRunner(); + DCHECK(task_runner) + << "The current execution context lacks a continuation task runner. " + "Note: you can't use base::GetContinuationTaskRunner() from a native " + "system event or any other context outside of a Chrome task."; + return task_runner; +} + } // namespace base
diff --git a/base/task/post_task.h b/base/task/post_task.h index 9f9b5a2..f1536ad7 100644 --- a/base/task/post_task.h +++ b/base/task/post_task.h
@@ -51,6 +51,13 @@ // task_runner->PostTask(FROM_HERE, BindOnce(...)); // task_runner->PostTask(FROM_HERE, BindOnce(...)); // +// To post a task on the current thread or sequence but with an explicit +// priority: +// PostTask(FROM_HERE, +// {CurrentThread(), TaskPriority::BEST_EFFORT}, +// BindOnce(...)); +// +// // The default traits apply to tasks that: // (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()), // (2) prefer inheriting the current priority to specifying their own, and @@ -232,6 +239,12 @@ SingleThreadTaskRunnerThreadMode::SHARED); #endif // defined(OS_WIN) +// Returns: The SequencedTaskRunner for the currently executing task, if any. +// Otherwise it returns a null scoped_refptr. On threads where there's no +// TaskExecutor registered this will DCHECK e.g. in a one-off ThreadPool task. +BASE_EXPORT const scoped_refptr<SequencedTaskRunner>& +GetContinuationTaskRunner(); + } // namespace base #endif // BASE_TASK_POST_TASK_H_
diff --git a/base/task/post_task_unittest.cc b/base/task/post_task_unittest.cc index 798eba8..f4dcfd87 100644 --- a/base/task/post_task_unittest.cc +++ b/base/task/post_task_unittest.cc
@@ -73,6 +73,9 @@ SingleThreadTaskRunnerThreadMode thread_mode)); #endif // defined(OS_WIN) + MOCK_METHOD0(GetContinuationTaskRunner, + const scoped_refptr<SequencedTaskRunner>&()); + TestSimpleTaskRunner* runner() const { return runner_.get(); } private: @@ -279,6 +282,49 @@ run_loop.Run(); } +TEST_F(PostTaskTestWithExecutor, TaskRunnerTaskGetContinuationTaskRunner) { + auto task_runner = CreateTaskRunner({ThreadPool()}); + RunLoop run_loop; + + EXPECT_TRUE(task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() { + // GetContinuationTaskRunner is + // meaningless in this context. + EXPECT_DCHECK_DEATH( + GetContinuationTaskRunner()); + run_loop.Quit(); + }))); + + run_loop.Run(); +} + +TEST_F(PostTaskTestWithExecutor, + SequencedTaskRunnerTaskGetContinuationTaskRunner) { + auto sequenced_task_runner = CreateSequencedTaskRunner({ThreadPool()}); + RunLoop run_loop; + + EXPECT_TRUE(sequenced_task_runner->PostTask( + FROM_HERE, BindLambdaForTesting([&]() { + EXPECT_EQ(GetContinuationTaskRunner(), sequenced_task_runner); + run_loop.Quit(); + }))); + + run_loop.Run(); +} + +TEST_F(PostTaskTestWithExecutor, + SingleThreadTaskRunnerTaskGetContinuationTaskRunner) { + auto single_thread_task_runner = CreateSingleThreadTaskRunner({ThreadPool()}); + RunLoop run_loop; + + EXPECT_TRUE(single_thread_task_runner->PostTask( + FROM_HERE, BindLambdaForTesting([&]() { + EXPECT_EQ(GetContinuationTaskRunner(), single_thread_task_runner); + run_loop.Quit(); + }))); + + run_loop.Run(); +} + TEST_F(PostTaskTestWithExecutor, ThreadPoolCurrentThreadChangePriority) { auto single_thread_task_runner = CreateSingleThreadTaskRunner({ThreadPool(), TaskPriority::USER_BLOCKING});
diff --git a/base/task/sequence_manager/sequence_manager.h b/base/task/sequence_manager/sequence_manager.h index 6e1cb0b..809de08 100644 --- a/base/task/sequence_manager/sequence_manager.h +++ b/base/task/sequence_manager/sequence_manager.h
@@ -150,7 +150,8 @@ // Returns the task runner the current task was posted on. Returns null if no // task is currently running. Must be called on the bound thread. - virtual scoped_refptr<SequencedTaskRunner> GetTaskRunnerForCurrentTask() = 0; + virtual const scoped_refptr<SequencedTaskRunner>& + GetTaskRunnerForCurrentTask() = 0; // Finishes the initialization for a SequenceManager created via // CreateUnboundSequenceManagerWithPump(). Must not be called in any other
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc index 7eea742a..cc59af2 100644 --- a/base/task/sequence_manager/sequence_manager_impl.cc +++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -42,6 +42,12 @@ return lazy_tls_ptr.get(); } +const scoped_refptr<SequencedTaskRunner>& GetNullTaskRunner() { + static const base::NoDestructor<scoped_refptr<SequencedTaskRunner>> + null_task_runner; + return *null_task_runner; +} + } // namespace // This controls how big the the initial for @@ -320,11 +326,11 @@ BindToMessagePump(std::move(pump)); } -scoped_refptr<SequencedTaskRunner> +const scoped_refptr<SequencedTaskRunner>& SequenceManagerImpl::GetTaskRunnerForCurrentTask() { DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); if (main_thread_only().task_execution_stack.empty()) - return nullptr; + return GetNullTaskRunner(); return main_thread_only() .task_execution_stack.back() .pending_task.task_runner;
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h index 1ee7944..ddd0a580 100644 --- a/base/task/sequence_manager/sequence_manager_impl.h +++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -102,7 +102,8 @@ // SequenceManager implementation: void BindToCurrentThread() override; - scoped_refptr<SequencedTaskRunner> GetTaskRunnerForCurrentTask() override; + const scoped_refptr<SequencedTaskRunner>& GetTaskRunnerForCurrentTask() + override; void BindToMessagePump(std::unique_ptr<MessagePump> message_pump) override; void SetObserver(Observer* observer) override; void AddTaskTimeObserver(TaskTimeObserver* task_time_observer) override;
diff --git a/base/task/simple_task_executor.cc b/base/task/simple_task_executor.cc index ffccf52..c4d7d2f 100644 --- a/base/task/simple_task_executor.cc +++ b/base/task/simple_task_executor.cc
@@ -4,11 +4,16 @@ #include "base/task/simple_task_executor.h" +#include "base/task/sequence_manager/sequence_manager.h" + namespace base { SimpleTaskExecutor::SimpleTaskExecutor( + sequence_manager::SequenceManager* sequence_manager, scoped_refptr<SingleThreadTaskRunner> task_queue) - : task_queue_(std::move(task_queue)), + : sequence_manager_(sequence_manager), + sequenced_task_queue_(task_queue), + task_queue_(std::move(task_queue)), previous_task_executor_(GetTaskExecutorForCurrentThread()) { DCHECK(task_queue_); // The TaskExecutor API does not expect nesting, but this can happen in tests @@ -38,7 +43,7 @@ scoped_refptr<SequencedTaskRunner> SimpleTaskExecutor::CreateSequencedTaskRunner(const TaskTraits& traits) { - return task_queue_; + return sequenced_task_queue_; } scoped_refptr<SingleThreadTaskRunner> @@ -59,4 +64,11 @@ } #endif // defined(OS_WIN) +const scoped_refptr<SequencedTaskRunner>& +SimpleTaskExecutor::GetContinuationTaskRunner() { + if (sequence_manager_) + return sequence_manager_->GetTaskRunnerForCurrentTask(); + return sequenced_task_queue_; +} + } // namespace base
diff --git a/base/task/simple_task_executor.h b/base/task/simple_task_executor.h index 7d9a74dc..be6531f 100644 --- a/base/task/simple_task_executor.h +++ b/base/task/simple_task_executor.h
@@ -9,13 +9,19 @@ #include "build/build_config.h" namespace base { +namespace sequence_manager { +class SequenceManager; +} // namespace sequence_manager // A simple TaskExecutor with exactly one SingleThreadTaskRunner. // Must be instantiated and destroyed on the thread that runs tasks for the // SingleThreadTaskRunner. class BASE_EXPORT SimpleTaskExecutor : public TaskExecutor { public: - explicit SimpleTaskExecutor(scoped_refptr<SingleThreadTaskRunner> task_queue); + // If |sequence_manager| is null, GetContinuationTaskRunner will always return + // |task_queue| even if no task is running. + SimpleTaskExecutor(sequence_manager::SequenceManager* sequence_manager, + scoped_refptr<SingleThreadTaskRunner> task_queue); ~SimpleTaskExecutor() override; @@ -39,7 +45,12 @@ SingleThreadTaskRunnerThreadMode thread_mode) override; #endif // defined(OS_WIN) - private: + const scoped_refptr<SequencedTaskRunner>& GetContinuationTaskRunner() + override; + + protected: + sequence_manager::SequenceManager* const sequence_manager_; + const scoped_refptr<SequencedTaskRunner> sequenced_task_queue_; const scoped_refptr<SingleThreadTaskRunner> task_queue_; // In tests there may already be a TaskExecutor registered for the thread, we
diff --git a/base/task/single_thread_task_executor.cc b/base/task/single_thread_task_executor.cc index 01d993b..2228cd4 100644 --- a/base/task/single_thread_task_executor.cc +++ b/base/task/single_thread_task_executor.cc
@@ -18,7 +18,7 @@ default_task_queue_(sequence_manager_->CreateTaskQueue( sequence_manager::TaskQueue::Spec("default_tq"))), type_(type), - simple_task_executor_(task_runner()) { + simple_task_executor_(sequence_manager_.get(), task_runner()) { sequence_manager_->SetDefaultTaskRunner(default_task_queue_->task_runner()); sequence_manager_->BindToMessagePump(MessagePump::Create(type));
diff --git a/base/task/single_thread_task_executor_unittest.cc b/base/task/single_thread_task_executor_unittest.cc index b64294f..b69bbf3cb 100644 --- a/base/task/single_thread_task_executor_unittest.cc +++ b/base/task/single_thread_task_executor_unittest.cc
@@ -7,6 +7,7 @@ #include "base/run_loop.h" #include "base/task/post_task.h" #include "base/test/bind_test_util.h" +#include "base/test/gtest_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -55,4 +56,24 @@ {base::CurrentThread(), base::TaskPriority::BEST_EFFORT})); } +TEST(SingleThreadTaskExecutorTest, GetContinuationTaskRunner) { + SingleThreadTaskExecutor single_thread_task_executor; + RunLoop run_loop; + + auto task_runner = CreateSingleThreadTaskRunner({CurrentThread()}); + + task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() { + EXPECT_EQ(task_runner, GetContinuationTaskRunner()); + run_loop.Quit(); + })); + + run_loop.Run(); +} + +TEST(SingleThreadTaskExecutorTest, GetCurrentTaskWithNoTaskRunning) { + SingleThreadTaskExecutor single_thread_task_executor; + + EXPECT_DCHECK_DEATH(GetContinuationTaskRunner()); +} + } // namespace base
diff --git a/base/task/task_executor.h b/base/task/task_executor.h index a062fdc..77debc9 100644 --- a/base/task/task_executor.h +++ b/base/task/task_executor.h
@@ -63,6 +63,11 @@ const TaskTraits& traits, SingleThreadTaskRunnerThreadMode thread_mode) = 0; #endif // defined(OS_WIN) + + // Returns the sequence the current task was posted on, if any, or null + // otherwise (e.g. for parallel tasks). + virtual const scoped_refptr<SequencedTaskRunner>& + GetContinuationTaskRunner() = 0; }; // Register a TaskExecutor with the //base/task/post_task.h API in the current
diff --git a/base/task/thread_pool/task_tracker.cc b/base/task/thread_pool/task_tracker.cc index a74f140..e42bad69 100644 --- a/base/task/thread_pool/task_tracker.cc +++ b/base/task/thread_pool/task_tracker.cc
@@ -113,18 +113,20 @@ switches::kLogBestEffortTasks); } -// Needed for PostTaskHere and CurrentThread. This executor lives for the -// duration of a threadpool task invocation. +// Needed for GetContinuationTaskRunner and CurrentThread. This executor lives +// for the duration of a threadpool task invocation. class EphemeralTaskExecutor : public TaskExecutor { public: // |sequenced_task_runner| and |single_thread_task_runner| must outlive this - // EphemeralTaskExecutor. - EphemeralTaskExecutor(SequencedTaskRunner* sequenced_task_runner, - SingleThreadTaskRunner* single_thread_task_runner, - const TaskTraits* sequence_traits) - : sequenced_task_runner_(sequenced_task_runner), + // EphemeralTaskExecutor. Note |single_thread_task_runner| may be null. + EphemeralTaskExecutor( + scoped_refptr<SequencedTaskRunner> sequenced_task_runner, + SingleThreadTaskRunner* single_thread_task_runner, + const TaskTraits* sequence_traits) + : sequenced_task_runner_(std::move(sequenced_task_runner)), single_thread_task_runner_(single_thread_task_runner), sequence_traits_(sequence_traits) { + DCHECK(sequenced_task_runner_); SetTaskExecutorForCurrentThread(this); } @@ -170,6 +172,11 @@ } #endif // defined(OS_WIN) + const scoped_refptr<SequencedTaskRunner>& GetContinuationTaskRunner() + override { + return sequenced_task_runner_; + } + private: // Currently ignores |traits.priority()|. void CheckTraitsCompatibleWithSequenceTraits(const TaskTraits& traits) { @@ -186,7 +193,7 @@ sequence_traits_->with_base_sync_primitives()); } - SequencedTaskRunner* const sequenced_task_runner_; + const scoped_refptr<SequencedTaskRunner> sequenced_task_runner_; SingleThreadTaskRunner* const single_thread_task_runner_; const TaskTraits* const sequence_traits_; };
diff --git a/base/task/thread_pool/thread_pool_impl.cc b/base/task/thread_pool/thread_pool_impl.cc index ff1bfa7..ed3d5de 100644 --- a/base/task/thread_pool/thread_pool_impl.cc +++ b/base/task/thread_pool/thread_pool_impl.cc
@@ -60,6 +60,12 @@ switches::kDisableBestEffortTasks); } +const scoped_refptr<SequencedTaskRunner>& GetNullTaskRunner() { + static const NoDestructor<scoped_refptr<SequencedTaskRunner>> + null_task_runner; + return *null_task_runner; +} + } // namespace ThreadPoolImpl::ThreadPoolImpl(StringPiece histogram_label) @@ -267,6 +273,14 @@ return MakeRefCounted<PooledSequencedTaskRunner>(new_traits, this); } +const scoped_refptr<SequencedTaskRunner>& +ThreadPoolImpl::GetContinuationTaskRunner() { + // Default to null for parallel tasks; see task_tracker.cc's + // EphemeralTaskExecutor for how sequenced contexts handle this. + NOTREACHED(); + return GetNullTaskRunner(); +} + Optional<TimeTicks> ThreadPoolImpl::NextScheduledRunTimeForTesting() const { if (task_tracker_->HasIncompleteTaskSourcesForTesting()) return TimeTicks::Now();
diff --git a/base/task/thread_pool/thread_pool_impl.h b/base/task/thread_pool/thread_pool_impl.h index 8b3a6760..43fe7661 100644 --- a/base/task/thread_pool/thread_pool_impl.h +++ b/base/task/thread_pool/thread_pool_impl.h
@@ -98,6 +98,8 @@ const TaskTraits& traits, SingleThreadTaskRunnerThreadMode thread_mode) override; #endif // defined(OS_WIN) + const scoped_refptr<SequencedTaskRunner>& GetContinuationTaskRunner() + override; scoped_refptr<UpdateableSequencedTaskRunner> CreateUpdateableSequencedTaskRunner(const TaskTraits& traits);
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index 9691186..348297d 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -238,8 +238,6 @@ // Handled by the launcher process. switches.erase(kGTestRepeatFlag); switches.erase(kIsolatedScriptTestRepeatFlag); - switches.erase(kGTestShuffleFlag); - switches.erase(kGTestRandomSeedFlag); // Don't try to write the final XML report in child processes. switches.erase(kGTestOutputFlag);
diff --git a/base/test/task_environment.cc b/base/test/task_environment.cc index 3f9d6af..393ecb6 100644 --- a/base/test/task_environment.cc +++ b/base/test/task_environment.cc
@@ -396,7 +396,8 @@ .SetTimeDomain(mock_time_domain_.get())); task_runner_ = task_queue_->task_runner(); sequence_manager_->SetDefaultTaskRunner(task_runner_); - simple_task_executor_ = std::make_unique<SimpleTaskExecutor>(task_runner_); + simple_task_executor_ = std::make_unique<SimpleTaskExecutor>( + sequence_manager_.get(), task_runner_); CHECK(base::ThreadTaskRunnerHandle::IsSet()) << "ThreadTaskRunnerHandle should've been set now."; CompleteInitialization();
diff --git a/base/test/task_environment.h b/base/test/task_environment.h index 945ae64..4ba48525 100644 --- a/base/test/task_environment.h +++ b/base/test/task_environment.h
@@ -35,7 +35,7 @@ // This header exposes SingleThreadTaskEnvironment and TaskEnvironment. // // SingleThreadTaskEnvironment enables the following APIs within its scope: -// - (Thread|Sequenced)TaskRunnerHandle on the main thread +// - ThreadTaskRunnerHandle & GetContinuationTaskRunner on the main thread // - RunLoop on the main thread // // TaskEnvironment additionally enables: @@ -46,7 +46,7 @@ // Tests should prefer SingleThreadTaskEnvironment over TaskEnvironment when the // former is sufficient. // -// Tasks posted to the (Thread|Sequenced)TaskRunnerHandle run synchronously when +// Tasks posted to the APIs listed above run synchronously when // RunLoop::Run(UntilIdle) or TaskEnvironment::RunUntilIdle is called on the // main thread. // @@ -180,7 +180,7 @@ trait_helpers::NotATraitTag()) {} // Waits until no undelayed ThreadPool tasks remain. Then, unregisters the - // ThreadPoolInstance and the (Thread|Sequenced)TaskRunnerHandle. + // ThreadPoolInstance and the APIs listed in the top level comment. virtual ~TaskEnvironment(); // Returns a TaskRunner that schedules tasks on the main thread. @@ -190,11 +190,11 @@ // always return true if called right after RunUntilIdle. bool MainThreadIsIdle() const; - // Runs tasks until both the (Thread|Sequenced)TaskRunnerHandle and the - // ThreadPool's non-delayed queues are empty. - // While RunUntilIdle() is quite practical and sometimes even necessary -- for - // example, to flush all tasks bound to Unretained() state before destroying - // test members -- it should be used with caution per the following warnings: + // Runs tasks until both the APIs listed in the top level comment and the + // ThreadPool's non-delayed queues are empty. While RunUntilIdle() is quite + // practical and sometimes even necessary -- for example, to flush all tasks + // bound to Unretained() state before destroying test members -- it should be + // used with caution per the following warnings: // // WARNING #1: This may run long (flakily timeout) and even never return! Do // not use this when repeating tasks such as animated web pages
diff --git a/base/test/task_environment_unittest.cc b/base/test/task_environment_unittest.cc index e6a929e..03b35465 100644 --- a/base/test/task_environment_unittest.cc +++ b/base/test/task_environment_unittest.cc
@@ -1199,5 +1199,23 @@ run_loop.Run(); } +TEST_F(TaskEnvironmentTest, GetContinuationTaskRunner) { + SingleThreadTaskEnvironment task_environment; + RunLoop run_loop; + auto task_runner = CreateSingleThreadTaskRunner({CurrentThread()}); + + task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() { + EXPECT_EQ(task_runner, GetContinuationTaskRunner()); + run_loop.Quit(); + })); + + run_loop.Run(); +} + +TEST_F(TaskEnvironmentTest, GetContinuationTaskRunnerWithNoTaskRunning) { + SingleThreadTaskEnvironment task_environment; + EXPECT_DCHECK_DEATH(GetContinuationTaskRunner()); +} + } // namespace test } // namespace base
diff --git a/base/threading/sequenced_task_runner_handle.h b/base/threading/sequenced_task_runner_handle.h index 4822495..dddbb33 100644 --- a/base/threading/sequenced_task_runner_handle.h +++ b/base/threading/sequenced_task_runner_handle.h
@@ -21,6 +21,11 @@ // run after the current task is finished and will satisfy a SequenceChecker. // It should only be called if IsSet() returns true (see the comment there for // the requirements). + // + // DEPRECATED: Prefer base::CurrentThread() instead or + // base::GetContinuationTaskRunner() if you need to post a continuation of the + // current task. See threading_and_tasks.md for details. + // TODO(scheduler-dev): Migrate all instances. static const scoped_refptr<SequencedTaskRunner>& Get() WARN_UNUSED_RESULT; // Returns true if one of the following conditions is fulfilled:
diff --git a/base/threading/thread.cc b/base/threading/thread.cc index eecd3491..093d8842 100644 --- a/base/threading/thread.cc +++ b/base/threading/thread.cc
@@ -87,7 +87,8 @@ sequence_manager_->BindToMessagePump( std::move(message_pump_factory_).Run()); sequence_manager_->SetTimerSlack(timer_slack); - simple_task_executor_.emplace(GetDefaultTaskRunner()); + simple_task_executor_.emplace(sequence_manager_.get(), + GetDefaultTaskRunner()); } private:
diff --git a/base/threading/thread_task_runner_handle.h b/base/threading/thread_task_runner_handle.h index 892affc..44092cb 100644 --- a/base/threading/thread_task_runner_handle.h +++ b/base/threading/thread_task_runner_handle.h
@@ -23,6 +23,10 @@ class BASE_EXPORT ThreadTaskRunnerHandle { public: // Gets the SingleThreadTaskRunner for the current thread. + // DEPRECATED: Prefer base::CurrentThread() instead or + // base::GetContinuationTaskRunner() if you need to post a continuation of the + // current task. See threading_and_tasks.md for details. + // TODO(scheduler-dev): Migrate all instances. static const scoped_refptr<SingleThreadTaskRunner>& Get() WARN_UNUSED_RESULT; // Returns true if the SingleThreadTaskRunner is already created for
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 0dd3041..11b0fd4d 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2241,6 +2241,7 @@ frame_trackers_.NotifyImplFrameCausedNoDamage(frame->begin_frame_ack); TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoDamage", TRACE_EVENT_SCOPE_THREAD); active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS); + active_tree()->ResetAllChangeTracking(); return false; }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 03d02988..2c60b61 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1139,7 +1139,6 @@ case 3: EXPECT_FALSE(GetRenderSurface(root_impl)->AncestorPropertyChanged()); EXPECT_TRUE(GetRenderSurface(child_impl)->AncestorPropertyChanged()); - EndTest(); PostSetNeedsCommitToMainThread(); break; case 4: @@ -1158,8 +1157,7 @@ scoped_refptr<Layer> grand_child_; }; -// TODO(crbug.com/1014263): Disable because this test is flaky. -// SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSurfaceDamage); +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSurfaceDamage); class LayerTreeHostTestLayerListSurfaceDamage : public LayerTreeHostTest { protected:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 4bde768..9d8c5ff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -40,7 +40,6 @@ import org.chromium.base.ActivityState; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApplicationStatus; -import org.chromium.base.BaseSwitches; import org.chromium.base.Callback; import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; @@ -120,7 +119,6 @@ import org.chromium.chrome.browser.omaha.UpdateNotificationController; import org.chromium.chrome.browser.page_info.PageInfoController; import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations; -import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.PreferencesLauncher; import org.chromium.chrome.browser.printing.TabPrinter; @@ -227,8 +225,6 @@ */ static final int NO_TOOLBAR_LAYOUT = -1; - private static final int RECORD_MULTI_WINDOW_SCREEN_WIDTH_DELAY_MS = 5000; - /** * Timeout in ms for reading PartnerBrowserCustomizations provider. */ @@ -447,33 +443,14 @@ mAssistStatusHandler.updateAssistState(); } - // This check is only applicable for JB since in KK svelte was supported from the start. - // See https://crbug.com/826460 for context. - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2) { - // If a user had ALLOW_LOW_END_DEVICE_UI explicitly set to false then we manually - // override SysUtils.isLowEndDevice() with a switch so that they continue to see the - // normal UI. This is only the case for grandfathered-in svelte users. We no longer - // do - - // so for newer users. - if (!ChromePreferenceManager.getInstance().readBoolean( - ChromePreferenceManager.ALLOW_LOW_END_DEVICE_UI, true)) { - CommandLine.getInstance().appendSwitch( - BaseSwitches.DISABLE_LOW_END_DEVICE_MODE); - } - } - AccessibilityManager manager = (AccessibilityManager) getBaseContext().getSystemService( Context.ACCESSIBILITY_SERVICE); manager.addAccessibilityStateChangeListener(this); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - mTouchExplorationStateChangeListener = enabled -> { - AccessibilityUtil.resetAccessibilityEnabled(); - checkAccessibility(); - }; - manager.addTouchExplorationStateChangeListener( - mTouchExplorationStateChangeListener); - } + mTouchExplorationStateChangeListener = enabled -> { + AccessibilityUtil.resetAccessibilityEnabled(); + checkAccessibility(); + }; + manager.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); // Make the activity listen to policy change events CombinedPolicyProvider.get().addPolicyChangeListener(this); @@ -1329,9 +1306,7 @@ AccessibilityManager manager = (AccessibilityManager) getBaseContext().getSystemService(Context.ACCESSIBILITY_SERVICE); manager.removeAccessibilityStateChangeListener(this); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - manager.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); - } + manager.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener); if (mTabThemeColorProvider != null) { mTabThemeColorProvider.destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java index 42d15b0..34676e2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -115,11 +115,14 @@ "signin_promo_last_shown_account_names"; /** - * This value may have been explicitly set to false when we used to keep existing low-end - * devices on the normal UI rather than the simplified UI. We want to keep the existing device - * settings. For all new low-end devices they should get the simplified UI by default. + * This value was used prior to KitKat to keep existing low-end devices on the normal UI rather + * than the simplified UI. + * + * This value may still exist in shared preferences file. Do not reuse. */ + @Deprecated public static final String ALLOW_LOW_END_DEVICE_UI = "allow_low_end_device_ui"; + private static final String PREF_WEBSITE_SETTINGS_FILTER = "website_settings_filter"; private static final String CONTEXTUAL_SEARCH_TAP_TRIGGERED_PROMO_COUNT = "contextual_search_tap_triggered_promo_count";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMetrics.java index dedb5f8..d0836ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMetrics.java
@@ -11,6 +11,11 @@ * Helper Class for Shared Clipboard metrics. */ public class SharedClipboardMetrics { + public static void recordDeviceCount(int count) { + RecordHistogram.recordLinearCountHistogram("Sharing.SharedClipboardDevicesToShow", count, + /*min=*/1, /*max=*/20, /*num buckets=*/21); + } + public static void recordDeviceClick(int index) { RecordHistogram.recordLinearCountHistogram("Sharing.SharedClipboardSelectedDeviceIndex", index, /*min=*/1, /*max=*/20, /*num buckets=*/21);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java index 83abbd5..0249b4b7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
@@ -103,6 +103,8 @@ SharedClipboardMetrics.recordShowEducationalDialog(); } + SharedClipboardMetrics.recordDeviceCount(mAdapter.getCount()); + ListView listView = findViewById(R.id.device_picker_list); listView.setAdapter(mAdapter); listView.setOnItemClickListener(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 6467225..98dda43 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -689,7 +689,9 @@ @Override public int getBaseStatusBarColor() { - return isStatusBarDefaultThemeColor() ? Color.BLACK : mBrandColor; + // White default color is used to match CCTs and WebAPK shell. The returned color is ignored + // pre Android M when isStatusBarDefaultThemeColor() == true. + return isStatusBarDefaultThemeColor() ? Color.WHITE : mBrandColor; } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java index 16fc9bef..09bdf4633 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
@@ -85,8 +85,13 @@ mActivityTestRule.startWebappActivityAndWaitForSplashScreen(); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; + // Status bar color should be white on M+ to match CCTs and WebAPK shell. + int expectedColor = Color.WHITE; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + expectedColor = Color.BLACK; + } Assert.assertEquals( - Color.BLACK, mActivityTestRule.getActivity().getWindow().getStatusBarColor()); + expectedColor, mActivityTestRule.getActivity().getWindow().getStatusBarColor()); } @Test
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni index 181af5ce..226e396 100644 --- a/chrome/android/webapk/shell_apk/current_version/current_version.gni +++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@ # //chrome/android/webapk/shell_apk:webapk is changed. This includes # Java files, Android resource files and AndroidManifest.xml. Does not affect # Chrome.apk -current_shell_apk_version = 110 +current_shell_apk_version = 111
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java index 35e79f0..bce6ea0 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java
@@ -29,7 +29,7 @@ private static final int MINIMUM_REQUIRED_INTENT_HELPER_VERSION = 2; // Lowest version of Chromium which supports ShellAPK showing the splash screen. - public static final int MINIMUM_REQUIRED_CHROMIUM_VERSION_NEW_SPLASH = 77; + public static final int MINIMUM_REQUIRED_CHROMIUM_VERSION_NEW_SPLASH = 78; private static final String VERSION_NAME_DEVELOPER_BUILD = "Developer Build";
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java index 4f2244c..bcc1996 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
@@ -44,9 +44,6 @@ public class WebApkUtils { private static final String TAG = "cr_WebApkUtils"; - /** Percentage to darken a color by when setting the status bar color. */ - private static final float DARKEN_COLOR_FRACTION = 0.6f; - private static final float CONTRAST_LIGHT_ITEM_THRESHOLD = 3f; /** Returns whether the application is installed and enabled. */ @@ -205,28 +202,6 @@ } /** - * Darkens the given color to use on the status bar. - * @param color Color which should be darkened. - * @return Color that should be used for Android status bar. - */ - public static int getDarkenedColorForStatusBar(int color) { - return getDarkenedColor(color, DARKEN_COLOR_FRACTION); - } - - /** - * Darken a color to a fraction of its current brightness. - * @param color The input color. - * @param darkenFraction The fraction of the current brightness the color should be. - * @return The new darkened color. - */ - public static int getDarkenedColor(int color, float darkenFraction) { - float[] hsv = new float[3]; - Color.colorToHSV(color, hsv); - hsv[2] *= darkenFraction; - return Color.HSVToColor(hsv); - } - - /** * Check whether lighter or darker foreground elements (i.e. text, drawables etc.) * should be used depending on the given background color. * @param backgroundColor The background color value which is being queried. @@ -258,6 +233,25 @@ } /** + * Sets the status bar icons to dark or light. Note that this is only valid for + * Android M+. + * + * @param rootView The root view used to request updates to the system UI theming. + * @param useDarkIcons Whether the status bar icons should be dark. + */ + public static void setStatusBarIconColor(View rootView, boolean useDarkIcons) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return; + + int systemUiVisibility = rootView.getSystemUiVisibility(); + if (useDarkIcons) { + systemUiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } else { + systemUiVisibility &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } + rootView.setSystemUiVisibility(systemUiVisibility); + } + + /** * @see android.view.Window#setStatusBarColor(int color). */ public static void setStatusBarColor(Window window, int statusBarColor) {
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashActivity.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashActivity.java index 701e4f1..72c447f 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashActivity.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashActivity.java
@@ -150,10 +150,7 @@ private void showSplashScreen() { Bundle metadata = WebApkUtils.readMetaData(this); - int themeColor = (int) WebApkMetaDataUtils.getLongFromMetaData( - metadata, WebApkMetaDataKeys.THEME_COLOR, Color.BLACK); - WebApkUtils.setStatusBarColor( - getWindow(), WebApkUtils.getDarkenedColorForStatusBar(themeColor)); + updateStatusBar(metadata); int orientation = WebApkUtils.computeScreenLockOrientationFromMetaData(this, metadata); if (orientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { @@ -175,6 +172,19 @@ setContentView(mSplashView); } + /** + * Sets the the color of the status bar and status bar icons. + */ + private void updateStatusBar(Bundle metadata) { + int statusBarColor = (int) WebApkMetaDataUtils.getLongFromMetaData( + metadata, WebApkMetaDataKeys.THEME_COLOR, Color.WHITE); + WebApkUtils.setStatusBarColor(getWindow(), statusBarColor); + boolean needsDarkStatusBarIcons = + !WebApkUtils.shouldUseLightForegroundOnBackground(statusBarColor); + WebApkUtils.setStatusBarIconColor( + getWindow().getDecorView().getRootView(), needsDarkStatusBarIcons); + } + /** Called once the host browser has been selected. */ private void onHostBrowserSelected(HostBrowserLauncherParams params) { if (params == null) {
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index ac55f6a..c005907 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5838,6 +5838,9 @@ <message name="IDS_FEEDBACK_SCREENSHOT_LABEL" desc="Label for the screenshot field if current screenshots are being shown"> Include this screenshot </message> + <message name="IDS_FEEDBACK_SCREENSHOT_A11Y_TEXT" desc="Accessibility label text for screenshot of system, which shows contents of screen apart from feedback dialog"> + Screenshot of programs that are currently on the screen + </message> <message name="IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX" desc="Checkbox for including system performance data on the bug report dialog box"> Send performance trace data </message>
diff --git a/chrome/app/generated_resources_grd/IDS_FEEDBACK_SCREENSHOT_ALT_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_FEEDBACK_SCREENSHOT_ALT_TEXT.png.sha1 new file mode 100644 index 0000000..a4fab6bb --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_FEEDBACK_SCREENSHOT_ALT_TEXT.png.sha1
@@ -0,0 +1 @@ +ce7547b911affc1addcd31a63680bfee1fd57bcd \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 104128c..dbb4418f 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1348,8 +1348,8 @@ // TODO(crbug.com/991082,1015377): Remove after proper support for back-forward // cache is implemented. const FeatureEntry::FeatureParam kBackForwardCache_ExtendedSupport[] = { - {"experimental extended supported feature set", "true"}, -}; + {"service_worker_supported", "true"}, + {"geolocation_supported", "true"}}; const FeatureEntry::FeatureVariation kBackForwardCacheVariations[] = { {"experimental extended supported feature set",
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc index 802df38..b035756 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc +++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -104,7 +104,7 @@ base::WeakPtr<ContextualSearchContext> contextual_search_context, content::WebContents* web_contents) { DCHECK(web_contents); - blink::mojom::Frame::GetTextSurroundingSelectionCallback callback = + blink::mojom::LocalFrame::GetTextSurroundingSelectionCallback callback = base::BindOnce( &ContextualSearchDelegate::OnTextSurroundingSelectionAvailable, AsWeakPtr());
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 3621fd6..de70f9d9 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3071,6 +3071,7 @@ base::GetFieldTrialParamByFeatureAsBool(features::kDataSaverHoldback, "holdback_web", false); + auto* native_theme = GetWebTheme(); auto* contents = content::WebContents::FromRenderViewHost(rvh); if (contents) { #if defined(OS_ANDROID) @@ -3085,9 +3086,11 @@ web_prefs->picture_in_picture_enabled = delegate->IsPictureInPictureEnabled(); - web_prefs->preferred_color_scheme = - delegate->IsNightModeEnabled() ? blink::PreferredColorScheme::kDark - : blink::PreferredColorScheme::kLight; + // Notify NativeTheme of changes to night mode. + native_theme->set_preferred_color_scheme( + delegate->IsNightModeEnabled() + ? ui::NativeTheme::PreferredColorScheme::kDark + : ui::NativeTheme::PreferredColorScheme::kLight); } #endif // defined(OS_ANDROID) @@ -3241,7 +3244,6 @@ } } - auto* native_theme = GetWebTheme(); #if !defined(OS_ANDROID) if (IsAutoplayAllowedByPolicy(contents, prefs)) { // If autoplay is allowed by policy then force the no user gesture required @@ -3259,39 +3261,10 @@ ? content::AutoplayPolicy::kDocumentUserActivationRequired : content::AutoplayPolicy::kNoUserGestureRequired; } - - switch (native_theme->GetPreferredColorScheme()) { - case ui::NativeTheme::PreferredColorScheme::kDark: - web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; - break; - case ui::NativeTheme::PreferredColorScheme::kLight: - web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; - break; - case ui::NativeTheme::PreferredColorScheme::kNoPreference: - web_prefs->preferred_color_scheme = - blink::PreferredColorScheme::kNoPreference; - } #endif // !defined(OS_ANDROID) web_prefs->translate_service_available = TranslateService::IsAvailable(prefs); - // Force a light preferred color scheme on certain URLs if kWebUIDarkMode is - // disabled; some of the UI is not yet correctly themed. Note: the WebUI CSS - // explicitly uses light (instead of not dark), which is why we don't reset - // back to no-preference. https://crbug.com/965811 - if (!base::FeatureList::IsEnabled(features::kWebUIDarkMode)) { - const GURL url = rvh->GetSiteInstance()->GetSiteURL(); - bool force_light = url.SchemeIs(content::kChromeUIScheme); -#if BUILDFLAG(ENABLE_EXTENSIONS) - if (!force_light) { - force_light = url.SchemeIs(extensions::kExtensionScheme) && - url.host_piece() == extension_misc::kPdfExtensionId; - } -#endif - if (force_light) - web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; - } - // Apply native CaptionStyle parameters. base::Optional<ui::CaptionStyle> style; @@ -4892,7 +4865,7 @@ url->host() == chrome::kChromeUISettingsHost; } -const ui::NativeTheme* ChromeContentBrowserClient::GetWebTheme() const { +ui::NativeTheme* ChromeContentBrowserClient::GetWebTheme() const { return ui::NativeTheme::GetInstanceForWeb(); }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index af0c061b..f443b13 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -649,7 +649,7 @@ static bool HandleWebUI(GURL* url, content::BrowserContext* browser_context); static bool HandleWebUIReverse(GURL* url, content::BrowserContext* browser_context); - virtual const ui::NativeTheme* GetWebTheme() const; // For testing. + virtual ui::NativeTheme* GetWebTheme() const; // For testing. private: friend class DisableWebRtcEncryptionFlagTest;
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc index 8a22d3b..27506b53 100644 --- a/chrome/browser/chrome_content_browser_client_browsertest.cc +++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -881,111 +881,6 @@ opened_tab->GetMainFrame()->GetProcess()->GetID())); } -class PrefersColorSchemeTest : public testing::WithParamInterface<bool>, - public InProcessBrowserTest { - protected: - PrefersColorSchemeTest() : theme_client_(&test_theme_) { - feature_list_.InitWithFeatureState(features::kWebUIDarkMode, GetParam()); - } - - ~PrefersColorSchemeTest() { - CHECK_EQ(&theme_client_, SetBrowserClientForTesting(original_client_)); - } - - const char* ExpectedColorScheme() const { - return GetParam() ? "dark" : "light"; - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - InProcessBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, - "MediaQueryPrefersColorScheme"); - } - - void SetUpOnMainThread() override { - InProcessBrowserTest::SetUpOnMainThread(); - original_client_ = SetBrowserClientForTesting(&theme_client_); - } - - protected: - ui::TestNativeTheme test_theme_; - - private: - content::ContentBrowserClient* original_client_ = nullptr; - - class ChromeContentBrowserClientWithWebTheme - : public ChromeContentBrowserClient { - public: - explicit ChromeContentBrowserClientWithWebTheme( - const ui::NativeTheme* theme) - : theme_(theme) {} - - protected: - const ui::NativeTheme* GetWebTheme() const override { return theme_; } - - private: - const ui::NativeTheme* const theme_; - }; - - base::test::ScopedFeatureList feature_list_; - ChromeContentBrowserClientWithWebTheme theme_client_; -}; - -IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, PrefersColorScheme) { - test_theme_.SetDarkMode(GetParam()); - browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetRenderViewHost() - ->OnWebkitPreferencesChanged(); - ui_test_utils::NavigateToURL( - browser(), - ui_test_utils::GetTestUrl( - base::FilePath(base::FilePath::kCurrentDirectory), - base::FilePath(FILE_PATH_LITERAL("prefers-color-scheme.html")))); - base::string16 tab_title; - ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); - EXPECT_EQ(base::ASCIIToUTF16(ExpectedColorScheme()), tab_title); -} - -IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, FeatureOverridesChromeSchemes) { - test_theme_.SetDarkMode(true); - - ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); - - bool matches; - ASSERT_TRUE(ExecuteScriptAndExtractBool( - browser()->tab_strip_model()->GetActiveWebContents(), - base::StringPrintf("window.domAutomationController.send(window." - "matchMedia('(prefers-color-scheme: %s)').matches)", - ExpectedColorScheme()), - &matches)); - EXPECT_TRUE(matches); -} - -#if BUILDFLAG(ENABLE_EXTENSIONS) -IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, FeatureOverridesPdfUI) { - test_theme_.SetDarkMode(true); - - std::string pdf_extension_url(extensions::kExtensionScheme); - pdf_extension_url.append(url::kStandardSchemeSeparator); - pdf_extension_url.append(extension_misc::kPdfExtensionId); - GURL pdf_index = GURL(pdf_extension_url).Resolve("/index.html"); - ui_test_utils::NavigateToURL(browser(), pdf_index); - - bool matches; - ASSERT_TRUE(ExecuteScriptAndExtractBool( - browser()->tab_strip_model()->GetActiveWebContents(), - base::StringPrintf("window.domAutomationController.send(window." - "matchMedia('(prefers-color-scheme: %s)').matches)", - ExpectedColorScheme()), - &matches)); - EXPECT_TRUE(matches); -} -#endif - -INSTANTIATE_TEST_SUITE_P(All, PrefersColorSchemeTest, testing::Bool()); - class ProtocolHandlerTest : public InProcessBrowserTest { public: ProtocolHandlerTest() = default;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 339ac92..36487b7 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -438,13 +438,14 @@ "apps/intent_helper/chromeos_apps_navigation_throttle.h", "apps/intent_helper/common_apps_navigation_throttle.cc", "apps/intent_helper/common_apps_navigation_throttle.h", + "arc/accessibility/accessibility_info_data_wrapper.cc", + "arc/accessibility/accessibility_info_data_wrapper.h", "arc/accessibility/accessibility_node_info_data_wrapper.cc", "arc/accessibility/accessibility_node_info_data_wrapper.h", "arc/accessibility/accessibility_window_info_data_wrapper.cc", "arc/accessibility/accessibility_window_info_data_wrapper.h", "arc/accessibility/arc_accessibility_helper_bridge.cc", "arc/accessibility/arc_accessibility_helper_bridge.h", - "arc/accessibility/arc_accessibility_info_data.h", "arc/accessibility/arc_accessibility_util.cc", "arc/accessibility/arc_accessibility_util.h", "arc/accessibility/ax_tree_source_arc.cc",
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.cc b/chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.cc new file mode 100644 index 0000000..d2d3a3c --- /dev/null +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.cc
@@ -0,0 +1,48 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h" + +#include "chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h" +#include "components/exo/wm_helper.h" + +namespace arc { + +AccessibilityInfoDataWrapper::AccessibilityInfoDataWrapper( + AXTreeSourceArc* tree_source) + : tree_source_(tree_source) {} + +void AccessibilityInfoDataWrapper::Serialize(ui::AXNodeData* out_data) const { + out_data->id = GetId(); + PopulateAXRole(out_data); + + exo::WMHelper* wm_helper = + exo::WMHelper::HasInstance() ? exo::WMHelper::GetInstance() : nullptr; + + if (tree_source_->GetRoot() && wm_helper) { + // This is the computed bounds which relies upon the existence of an + // associated focused window and a root node. + aura::Window* active_window = (tree_source_->is_notification() || + tree_source_->is_input_method_window()) + ? nullptr + : wm_helper->GetActiveWindow(); + const gfx::Rect& local_bounds = tree_source_->GetBounds( + tree_source_->GetFromId(GetId()), active_window); + out_data->relative_bounds.bounds.SetRect(local_bounds.x(), local_bounds.y(), + local_bounds.width(), + local_bounds.height()); + } else { + // We cannot compute global bounds, so use the raw bounds. + const auto& bounds = GetBounds(); + out_data->relative_bounds.bounds.SetRect(bounds.x(), bounds.y(), + bounds.width(), bounds.height()); + } + + // TODO(katie): Try using offset_container_id to make bounds calculations + // more efficient. If this is the child of the root, set the + // offset_container_id to be the root. Otherwise, set it to the first node + // child of the root. +} + +} // namespace arc
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h b/chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h new file mode 100644 index 0000000..96c505a --- /dev/null +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h
@@ -0,0 +1,51 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ACCESSIBILITY_INFO_DATA_WRAPPER_H_ +#define CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ACCESSIBILITY_INFO_DATA_WRAPPER_H_ + +#include "components/arc/mojom/accessibility_helper.mojom.h" + +namespace ui { +struct AXNodeData; +} // namespace ui + +namespace arc { +class AXTreeSourceArc; + +// AccessibilityInfoDataWrapper represents a single ARC++ node or window. This +// class can be used by AXTreeSourceArc to encapsulate ARC-side information +// which maps to a single AXNodeData. +class AccessibilityInfoDataWrapper { + public: + explicit AccessibilityInfoDataWrapper(AXTreeSourceArc* tree_source); + virtual ~AccessibilityInfoDataWrapper() = default; + + // True if this AccessibilityInfoDataWrapper represents an Android node, false + // if it represents an Android window. + virtual bool IsNode() const = 0; + + // These getters return nullptr if the class doesn't hold the specified type + // of data. + virtual mojom::AccessibilityNodeInfoData* GetNode() const = 0; + virtual mojom::AccessibilityWindowInfoData* GetWindow() const = 0; + + virtual int32_t GetId() const = 0; + virtual const gfx::Rect GetBounds() const = 0; + virtual bool IsVisibleToUser() const = 0; + virtual bool IsFocused() const = 0; + virtual bool CanBeAccessibilityFocused() const = 0; + virtual void PopulateAXRole(ui::AXNodeData* out_data) const = 0; + virtual void PopulateAXState(ui::AXNodeData* out_data) const = 0; + virtual void Serialize(ui::AXNodeData* out_data) const = 0; + virtual void GetChildren( + std::vector<AccessibilityInfoDataWrapper*>* children) const = 0; + + protected: + AXTreeSourceArc* tree_source_; +}; + +} // namespace arc + +#endif // CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ACCESSIBILITY_INFO_DATA_WRAPPER_H_
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc index 1bc2c41..1ec66bb 100644 --- a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc
@@ -7,7 +7,6 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h" -#include "components/exo/wm_helper.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node.h" #include "ui/accessibility/platform/ax_android_constants.h" @@ -30,7 +29,7 @@ AccessibilityNodeInfoDataWrapper::AccessibilityNodeInfoDataWrapper( AXTreeSourceArc* tree_source, AXNodeInfoData* node) - : tree_source_(tree_source), node_ptr_(node) {} + : AccessibilityInfoDataWrapper(tree_source), node_ptr_(node) {} bool AccessibilityNodeInfoDataWrapper::IsNode() const { return true; @@ -143,8 +142,8 @@ // need additional information contained only in the CollectionInfo. The // CollectionInfo should be an ancestor of this node. AXCollectionInfoData* collection_info = nullptr; - for (const ArcAccessibilityInfoData* container = - static_cast<const ArcAccessibilityInfoData*>(this); + for (const AccessibilityInfoDataWrapper* container = + static_cast<const AccessibilityInfoDataWrapper*>(this); container;) { if (!container || !container->IsNode()) break; @@ -272,7 +271,7 @@ void AccessibilityNodeInfoDataWrapper::Serialize( ui::AXNodeData* out_data) const { - PopulateAXRole(out_data); + AccessibilityInfoDataWrapper::Serialize(out_data); // String properties. int labelled_by = -1; @@ -287,7 +286,7 @@ GetProperty(AXStringProperty::TEXT, &text); if (GetProperty(AXIntProperty::LABELED_BY, &labelled_by)) { - ArcAccessibilityInfoData* labelled_by_node = + AccessibilityInfoDataWrapper* labelled_by_node = tree_source_->GetFromId(labelled_by); if (labelled_by_node && labelled_by_node->IsNode()) { ui::AXNodeData labelled_by_data; @@ -401,29 +400,6 @@ range_info->max); } - exo::WMHelper* wm_helper = - exo::WMHelper::HasInstance() ? exo::WMHelper::GetInstance() : nullptr; - - // To get bounds of a node which can be passed to AXNodeData.location, - // - Root node must exist. - // - Window where this tree is attached to need to be focused. - if (tree_source_->GetRoot()->GetId() != ui::AXNode::kInvalidAXID && - wm_helper) { - aura::Window* active_window = (tree_source_->is_notification() || - tree_source_->is_input_method_window()) - ? nullptr - : wm_helper->GetActiveWindow(); - const gfx::Rect& local_bounds = tree_source_->GetBounds( - tree_source_->GetFromId(GetId()), active_window); - out_data->relative_bounds.bounds.SetRect(local_bounds.x(), local_bounds.y(), - local_bounds.width(), - local_bounds.height()); - } - // TODO(katie): Try using offset_container_id to make bounds calculations - // more efficient. If this is the child of the root, set the - // offset_container_id to be the root. Otherwise, set it to the first node - // child of the root. - // Integer properties. int32_t val; if (GetProperty(AXIntProperty::TEXT_SELECTION_START, &val) && val >= 0) @@ -470,7 +446,7 @@ } void AccessibilityNodeInfoDataWrapper::GetChildren( - std::vector<ArcAccessibilityInfoData*>* children) const { + std::vector<AccessibilityInfoDataWrapper*>* children) const { if (!node_ptr_->int_list_properties) return; auto it = @@ -598,9 +574,9 @@ } // Otherwise, continue looking for a name in this subtree. - std::vector<ArcAccessibilityInfoData*> children; + std::vector<AccessibilityInfoDataWrapper*> children; data->GetChildren(&children); - for (ArcAccessibilityInfoData* child : children) { + for (AccessibilityInfoDataWrapper* child : children) { ComputeNameFromContents( static_cast<AccessibilityNodeInfoDataWrapper*>(child), names); }
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h index 381cd23..7690295 100644 --- a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ACCESSIBILITY_NODE_INFO_DATA_WRAPPER_H_ #define CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ACCESSIBILITY_NODE_INFO_DATA_WRAPPER_H_ -#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_info_data.h" +#include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h" #include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_node_data.h" @@ -14,13 +14,12 @@ class AXTreeSourceArc; // Wrapper class for an AccessibilityWindowInfoData. -class AccessibilityNodeInfoDataWrapper : public ArcAccessibilityInfoData { +class AccessibilityNodeInfoDataWrapper : public AccessibilityInfoDataWrapper { public: - explicit AccessibilityNodeInfoDataWrapper( - AXTreeSourceArc* tree_source, - mojom::AccessibilityNodeInfoData* node); + AccessibilityNodeInfoDataWrapper(AXTreeSourceArc* tree_source, + mojom::AccessibilityNodeInfoData* node); - // ArcAccessibilityInfoData overrides. + // AccessibilityInfoDataWrapper overrides. bool IsNode() const override; mojom::AccessibilityNodeInfoData* GetNode() const override; mojom::AccessibilityWindowInfoData* GetWindow() const override; @@ -33,7 +32,7 @@ void PopulateAXState(ui::AXNodeData* out_data) const override; void Serialize(ui::AXNodeData* out_data) const override; void GetChildren( - std::vector<ArcAccessibilityInfoData*>* children) const override; + std::vector<AccessibilityInfoDataWrapper*>* children) const override; mojom::AccessibilityNodeInfoData* node() { return node_ptr_; } @@ -55,7 +54,6 @@ void ComputeNameFromContents(const AccessibilityNodeInfoDataWrapper* data, std::vector<std::string>* names) const; - AXTreeSourceArc* tree_source_ = nullptr; mojom::AccessibilityNodeInfoData* node_ptr_ = nullptr; DISALLOW_COPY_AND_ASSIGN(AccessibilityNodeInfoDataWrapper);
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.cc b/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.cc index 49196b4c..901648b 100644 --- a/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.cc +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.cc
@@ -15,7 +15,7 @@ AccessibilityWindowInfoDataWrapper::AccessibilityWindowInfoDataWrapper( AXTreeSourceArc* tree_source, mojom::AccessibilityWindowInfoData* window) - : tree_source_(tree_source), window_ptr_(window) {} + : AccessibilityInfoDataWrapper(tree_source), window_ptr_(window) {} bool AccessibilityWindowInfoDataWrapper::IsNode() const { return false; @@ -93,7 +93,7 @@ if (!tree_source_->GetRoot()) return; - PopulateAXRole(out_data); + AccessibilityInfoDataWrapper::Serialize(out_data); // String properties. std::string title; @@ -102,22 +102,6 @@ out_data->SetNameFrom(ax::mojom::NameFrom::kTitle); } - // Bounds. - exo::WMHelper* wm_helper = - exo::WMHelper::HasInstance() ? exo::WMHelper::GetInstance() : nullptr; - if (tree_source_->GetRoot()->GetId() != ui::AXNode::kInvalidAXID && - wm_helper) { - aura::Window* active_window = (tree_source_->is_notification() || - tree_source_->is_input_method_window()) - ? nullptr - : wm_helper->GetActiveWindow(); - const gfx::Rect& local_bounds = tree_source_->GetBounds( - tree_source_->GetFromId(GetId()), active_window); - out_data->relative_bounds.bounds.SetRect(local_bounds.x(), local_bounds.y(), - local_bounds.width(), - local_bounds.height()); - } - // Not all properties are currently used in Chrome Accessibility. // Boolean properties: @@ -132,7 +116,7 @@ } void AccessibilityWindowInfoDataWrapper::GetChildren( - std::vector<ArcAccessibilityInfoData*>* children) const { + std::vector<AccessibilityInfoDataWrapper*>* children) const { // Populate the children vector by combining the child window IDs with the // root node ID. if (window_ptr_->int_list_properties) {
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h b/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h index 2e4df47..d1bb872 100644 --- a/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h +++ b/chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h
@@ -7,7 +7,7 @@ #include <vector> -#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_info_data.h" +#include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h" #include "ui/accessibility/ax_node_data.h" namespace arc { @@ -15,13 +15,13 @@ class AXTreeSourceArc; // Wrapper class for an AccessibilityWindowInfoData. -class AccessibilityWindowInfoDataWrapper : public ArcAccessibilityInfoData { +class AccessibilityWindowInfoDataWrapper : public AccessibilityInfoDataWrapper { public: - explicit AccessibilityWindowInfoDataWrapper( + AccessibilityWindowInfoDataWrapper( AXTreeSourceArc* tree_source, mojom::AccessibilityWindowInfoData* window); - // ArcAccessibilityInfoData overrides. + // AccessibilityInfoDataWrapper overrides. bool IsNode() const override; mojom::AccessibilityNodeInfoData* GetNode() const override; mojom::AccessibilityWindowInfoData* GetWindow() const override; @@ -34,7 +34,7 @@ void PopulateAXState(ui::AXNodeData* out_data) const override; void Serialize(ui::AXNodeData* out_data) const override; void GetChildren( - std::vector<ArcAccessibilityInfoData*>* children) const override; + std::vector<AccessibilityInfoDataWrapper*>* children) const override; private: bool GetProperty(mojom::AccessibilityWindowBooleanProperty prop) const; @@ -46,7 +46,6 @@ bool GetProperty(mojom::AccessibilityWindowIntListProperty prop, std::vector<int32_t>* out_value) const; - AXTreeSourceArc* tree_source_ = nullptr; mojom::AccessibilityWindowInfoData* window_ptr_ = nullptr; DISALLOW_COPY_AND_ASSIGN(AccessibilityWindowInfoDataWrapper);
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc index a465f1b..311dcfc 100644 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc +++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -578,7 +578,7 @@ AXTreeSourceArc* tree_source = GetFromTreeId(data.target_tree_id); if (!tree_source) return; - action_data->window_id = tree_source->window_id(); + action_data->window_id = tree_source->GetWindowId(); switch (data.action) { case ax::mojom::Action::kDoDefault:
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_info_data.h b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_info_data.h deleted file mode 100644 index 46e3f16..0000000 --- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_info_data.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ARC_ACCESSIBILITY_INFO_DATA_H_ -#define CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ARC_ACCESSIBILITY_INFO_DATA_H_ - -#include "components/arc/mojom/accessibility_helper.mojom.h" - -namespace ui { -struct AXNodeData; -} // namespace ui - -namespace arc { - -// ArcAccessibilityInfoData represents a single ARC++ node or window. This class -// can be used by AXTreeSourceArc to encapsulate ARC-side information which maps -// to a single AXNodeData. -class ArcAccessibilityInfoData { - public: - virtual ~ArcAccessibilityInfoData() = default; - - // True if this ArcAccessibilityInfoData represents an Android node, false - // if it represents an Android window. - virtual bool IsNode() const = 0; - - // These getters return nullptr if the class doesn't hold the specified type - // of data. - virtual mojom::AccessibilityNodeInfoData* GetNode() const = 0; - virtual mojom::AccessibilityWindowInfoData* GetWindow() const = 0; - - virtual int32_t GetId() const = 0; - virtual const gfx::Rect GetBounds() const = 0; - virtual bool IsVisibleToUser() const = 0; - virtual bool IsFocused() const = 0; - virtual bool CanBeAccessibilityFocused() const = 0; - virtual void PopulateAXRole(ui::AXNodeData* out_data) const = 0; - virtual void PopulateAXState(ui::AXNodeData* out_data) const = 0; - virtual void Serialize(ui::AXNodeData* out_data) const = 0; - virtual void GetChildren( - std::vector<ArcAccessibilityInfoData*>* children) const = 0; -}; - -} // namespace arc - -#endif // CHROME_BROWSER_CHROMEOS_ARC_ACCESSIBILITY_ARC_ACCESSIBILITY_INFO_DATA_H_
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc index cc3886f..840dfd0 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -29,9 +29,6 @@ AXTreeSourceArc::AXTreeSourceArc(Delegate* delegate) : current_tree_serializer_(new AXTreeArcSerializer(this)), - root_id_(ui::AXNode::kInvalidAXID), - window_id_(ui::AXNode::kInvalidAXID), - focused_id_(ui::AXNode::kInvalidAXID), is_notification_(false), is_input_method_window_(false), delegate_(delegate) {} @@ -44,7 +41,7 @@ tree_map_.clear(); parent_map_.clear(); cached_computed_bounds_.clear(); - root_id_ = ui::AXNode::kInvalidAXID; + root_id_.reset(); window_id_ = event_data->window_id; is_notification_ = event_data->notification_key.has_value(); @@ -104,7 +101,7 @@ root_id_ = source_root; // Walk back down through children map to populate parent_map_. std::stack<int32_t> stack; - stack.push(root_id_); + stack.push(*root_id_); while (!stack.empty()) { int32_t parent = stack.top(); stack.pop(); @@ -160,16 +157,16 @@ } // Calculate the focused ID. - if (focused_id_ == ui::AXNode::kInvalidAXID) { - if (root_id_ != ui::AXNode::kInvalidAXID) { - ArcAccessibilityInfoData* root = GetRoot(); + if (!focused_id_.has_value()) { + if (root_id_.has_value()) { + AccessibilityInfoDataWrapper* root = GetRoot(); // TODO (sarakato): Add proper fix once cause of invalid node is known. if (!IsValid(root)) { return; } else if (root->IsNode()) { focused_id_ = root_id_; } else { - std::vector<ArcAccessibilityInfoData*> children; + std::vector<AccessibilityInfoDataWrapper*> children; root->GetChildren(&children); if (!children.empty()) { for (size_t i = 0; i < children.size(); ++i) { @@ -191,8 +188,9 @@ // When the focused node exists, give it as a hint to decide a Chrome // automation event type. AXNodeInfoData* opt_focused_node = nullptr; - if (tree_map_.find(focused_id_) != tree_map_.end()) - opt_focused_node = tree_map_[focused_id_]->GetNode(); + if (focused_id_.has_value() && + tree_map_.find(*focused_id_) != tree_map_.end()) + opt_focused_node = tree_map_[*focused_id_]->GetNode(); event.event_type = ToAXEvent(event_data->event_type, opt_focused_node); event.id = event_data->source_id; @@ -220,129 +218,10 @@ GetAutomationEventRouter()->DispatchGetTextLocationDataResult(data, rect); } -bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { - data->tree_id = ax_tree_id(); - if (focused_id_ != ui::AXNode::kInvalidAXID) { - data->focus_id = focused_id_; - } - return true; -} - -ArcAccessibilityInfoData* AXTreeSourceArc::GetRoot() const { - ArcAccessibilityInfoData* root = GetFromId(root_id_); - return root; -} - -ArcAccessibilityInfoData* AXTreeSourceArc::GetFromId(int32_t id) const { - auto it = tree_map_.find(id); - if (it == tree_map_.end()) - return nullptr; - return it->second.get(); -} - -int32_t AXTreeSourceArc::GetId(ArcAccessibilityInfoData* info_data) const { - if (!info_data) - return ui::AXNode::kInvalidAXID; - return info_data->GetId(); -} - -void AXTreeSourceArc::GetChildren( - ArcAccessibilityInfoData* info_data, - std::vector<ArcAccessibilityInfoData*>* out_children) const { - if (!info_data) - return; - - info_data->GetChildren(out_children); - if (out_children->empty()) - return; - - std::map<int32_t, size_t> id_to_index; - for (size_t i = 0; i < out_children->size(); i++) - id_to_index[out_children->at(i)->GetId()] = i; - - // Sort children based on their enclosing bounding rectangles, based on their - // descendants. - std::sort( - out_children->begin(), out_children->end(), - [this, &id_to_index](auto left, auto right) { - auto left_bounds = ComputeEnclosingBounds(left); - auto right_bounds = ComputeEnclosingBounds(right); - - if (left_bounds.IsEmpty() || right_bounds.IsEmpty()) { - return id_to_index.at(left->GetId()) < id_to_index.at(right->GetId()); - } - - // Top to bottom sort (non-overlapping). - if (!left_bounds.Intersects(right_bounds)) - return left_bounds.y() < right_bounds.y(); - - // Overlapping - // Left to right. - int left_difference = left_bounds.x() - right_bounds.x(); - if (left_difference != 0) - return left_difference < 0; - - // Top to bottom. - int top_difference = left_bounds.y() - right_bounds.y(); - if (top_difference != 0) - return top_difference < 0; - - // Larger to smaller. - int height_difference = left_bounds.height() - right_bounds.height(); - if (height_difference != 0) - return height_difference > 0; - - int width_difference = left_bounds.width() - right_bounds.width(); - if (width_difference != 0) - return width_difference > 0; - - // The rects are equal. - return id_to_index.at(left->GetId()) < id_to_index.at(right->GetId()); - }); -} - -ArcAccessibilityInfoData* AXTreeSourceArc::GetParent( - ArcAccessibilityInfoData* info_data) const { - if (!info_data) - return nullptr; - auto it = parent_map_.find(info_data->GetId()); - if (it != parent_map_.end()) - return GetFromId(it->second); - return nullptr; -} - -bool AXTreeSourceArc::IsIgnored(ArcAccessibilityInfoData* info_data) const { - return false; -} - -bool AXTreeSourceArc::IsValid(ArcAccessibilityInfoData* info_data) const { - return info_data; -} - -bool AXTreeSourceArc::IsEqual(ArcAccessibilityInfoData* info_data1, - ArcAccessibilityInfoData* info_data2) const { - if (!info_data1 || !info_data2) - return false; - return info_data1->GetId() == info_data2->GetId(); -} - -ArcAccessibilityInfoData* AXTreeSourceArc::GetNull() const { - return nullptr; -} - -void AXTreeSourceArc::SerializeNode(ArcAccessibilityInfoData* info_data, - ui::AXNodeData* out_data) const { - if (!info_data) - return; - - int32_t id = info_data->GetId(); - out_data->id = id; - info_data->Serialize(out_data); -} - -const gfx::Rect AXTreeSourceArc::GetBounds(ArcAccessibilityInfoData* info_data, - aura::Window* active_window) const { - DCHECK_NE(root_id_, ui::AXNode::kInvalidAXID); +const gfx::Rect AXTreeSourceArc::GetBounds( + AccessibilityInfoDataWrapper* info_data, + aura::Window* active_window) const { + DCHECK(root_id_.has_value()); gfx::Rect info_data_bounds = info_data->GetBounds(); @@ -405,8 +284,54 @@ return !parent_tree_it->second->IsNode(); } +int32_t AXTreeSourceArc::GetWindowId() const { + CHECK(window_id_.has_value()); + return *window_id_; +} + +bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { + data->tree_id = ax_tree_id(); + if (focused_id_.has_value()) + data->focus_id = *focused_id_; + return true; +} + +AccessibilityInfoDataWrapper* AXTreeSourceArc::GetRoot() const { + return root_id_.has_value() ? GetFromId(*root_id_) : nullptr; +} + +AccessibilityInfoDataWrapper* AXTreeSourceArc::GetFromId(int32_t id) const { + auto it = tree_map_.find(id); + if (it == tree_map_.end()) + return nullptr; + return it->second.get(); +} + +AccessibilityInfoDataWrapper* AXTreeSourceArc::GetParent( + AccessibilityInfoDataWrapper* info_data) const { + if (!info_data) + return nullptr; + auto it = parent_map_.find(info_data->GetId()); + if (it != parent_map_.end()) + return GetFromId(it->second); + return nullptr; +} + +void AXTreeSourceArc::SerializeNode(AccessibilityInfoDataWrapper* info_data, + ui::AXNodeData* out_data) const { + if (!info_data) + return; + + info_data->Serialize(out_data); +} + +extensions::AutomationEventRouterInterface* +AXTreeSourceArc::GetAutomationEventRouter() const { + return extensions::AutomationEventRouter::GetInstance(); +} + gfx::Rect AXTreeSourceArc::ComputeEnclosingBounds( - ArcAccessibilityInfoData* info_data) const { + AccessibilityInfoDataWrapper* info_data) const { gfx::Rect computed_bounds; // Exit early if the node or window is invisible. if (!info_data->IsVisibleToUser()) @@ -417,7 +342,7 @@ } void AXTreeSourceArc::ComputeEnclosingBoundsInternal( - ArcAccessibilityInfoData* info_data, + AccessibilityInfoDataWrapper* info_data, gfx::Rect& computed_bounds) const { auto cached_bounds = cached_computed_bounds_.find(info_data->GetId()); if (cached_bounds != cached_computed_bounds_.end()) { @@ -432,26 +357,22 @@ computed_bounds.Union(info_data->GetBounds()); return; } - std::vector<ArcAccessibilityInfoData*> children; + std::vector<AccessibilityInfoDataWrapper*> children; info_data->GetChildren(&children); if (children.empty()) return; - for (ArcAccessibilityInfoData* child : children) + for (AccessibilityInfoDataWrapper* child : children) ComputeEnclosingBoundsInternal(child, computed_bounds); return; } -void AXTreeSourceArc::PerformAction(const ui::AXActionData& data) { - delegate_->OnAction(data); -} - void AXTreeSourceArc::Reset() { tree_map_.clear(); parent_map_.clear(); cached_computed_bounds_.clear(); current_tree_serializer_.reset(new AXTreeArcSerializer(this)); - root_id_ = -1; - focused_id_ = -1; + root_id_.reset(); + focused_id_.reset(); extensions::AutomationEventRouterInterface* router = GetAutomationEventRouter(); if (!router) @@ -460,9 +381,88 @@ router->DispatchTreeDestroyedEvent(ax_tree_id(), nullptr); } -extensions::AutomationEventRouterInterface* -AXTreeSourceArc::GetAutomationEventRouter() const { - return extensions::AutomationEventRouter::GetInstance(); +int32_t AXTreeSourceArc::GetId(AccessibilityInfoDataWrapper* info_data) const { + if (!info_data) + return ui::AXNode::kInvalidAXID; + return info_data->GetId(); +} + +void AXTreeSourceArc::GetChildren( + AccessibilityInfoDataWrapper* info_data, + std::vector<AccessibilityInfoDataWrapper*>* out_children) const { + if (!info_data) + return; + + info_data->GetChildren(out_children); + if (out_children->empty()) + return; + + std::map<int32_t, size_t> id_to_index; + for (size_t i = 0; i < out_children->size(); i++) + id_to_index[out_children->at(i)->GetId()] = i; + + // Sort children based on their enclosing bounding rectangles, based on their + // descendants. + std::sort( + out_children->begin(), out_children->end(), + [this, &id_to_index](auto left, auto right) { + auto left_bounds = ComputeEnclosingBounds(left); + auto right_bounds = ComputeEnclosingBounds(right); + + if (left_bounds.IsEmpty() || right_bounds.IsEmpty()) { + return id_to_index.at(left->GetId()) < id_to_index.at(right->GetId()); + } + + // Top to bottom sort (non-overlapping). + if (!left_bounds.Intersects(right_bounds)) + return left_bounds.y() < right_bounds.y(); + + // Overlapping + // Left to right. + int left_difference = left_bounds.x() - right_bounds.x(); + if (left_difference != 0) + return left_difference < 0; + + // Top to bottom. + int top_difference = left_bounds.y() - right_bounds.y(); + if (top_difference != 0) + return top_difference < 0; + + // Larger to smaller. + int height_difference = left_bounds.height() - right_bounds.height(); + if (height_difference != 0) + return height_difference > 0; + + int width_difference = left_bounds.width() - right_bounds.width(); + if (width_difference != 0) + return width_difference > 0; + + // The rects are equal. + return id_to_index.at(left->GetId()) < id_to_index.at(right->GetId()); + }); +} + +bool AXTreeSourceArc::IsIgnored(AccessibilityInfoDataWrapper* info_data) const { + return false; +} + +bool AXTreeSourceArc::IsValid(AccessibilityInfoDataWrapper* info_data) const { + return info_data; +} + +bool AXTreeSourceArc::IsEqual(AccessibilityInfoDataWrapper* info_data1, + AccessibilityInfoDataWrapper* info_data2) const { + if (!info_data1 || !info_data2) + return false; + return info_data1->GetId() == info_data2->GetId(); +} + +AccessibilityInfoDataWrapper* AXTreeSourceArc::GetNull() const { + return nullptr; +} + +void AXTreeSourceArc::PerformAction(const ui::AXActionData& data) { + delegate_->OnAction(data); } } // namespace arc
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h index a64d7c0..f0794e24 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
@@ -9,7 +9,7 @@ #include <memory> #include <vector> -#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_info_data.h" +#include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h" #include "components/arc/mojom/accessibility_helper.mojom.h" #include "extensions/browser/api/automation_internal/automation_event_router.h" #include "ui/accessibility/ax_action_handler.h" @@ -27,11 +27,12 @@ namespace arc { class AXTreeSourceArcTest; -using AXTreeArcSerializer = ui:: - AXTreeSerializer<ArcAccessibilityInfoData*, ui::AXNodeData, ui::AXTreeData>; +using AXTreeArcSerializer = ui::AXTreeSerializer<AccessibilityInfoDataWrapper*, + ui::AXNodeData, + ui::AXTreeData>; // This class represents the accessibility tree from the focused ARC window. -class AXTreeSourceArc : public ui::AXTreeSource<ArcAccessibilityInfoData*, +class AXTreeSourceArc : public ui::AXTreeSource<AccessibilityInfoDataWrapper*, ui::AXNodeData, ui::AXTreeData>, public ui::AXActionHandler { @@ -44,9 +45,6 @@ explicit AXTreeSourceArc(Delegate* delegate); ~AXTreeSourceArc() override; - // AXTreeSource overrides. - bool GetTreeData(ui::AXTreeData* data) const override; - // Notify automation of an accessibility event. void NotifyAccessibilityEvent(mojom::AccessibilityEventData* event_data); @@ -57,21 +55,6 @@ void NotifyGetTextLocationDataResult(const ui::AXActionData& data, const base::Optional<gfx::Rect>& rect); - // Attaches tree to an aura window and gives it system focus. - void Focus(aura::Window* window); - - // Gets the window id of this tree. - int32_t window_id() const { return window_id_; } - - // AXTreeSource overrides used by ArcAccessibilityInfoData subclasses. - // TODO(katie): should these be "friended" or "protected" instead? - ArcAccessibilityInfoData* GetRoot() const override; - ArcAccessibilityInfoData* GetFromId(int32_t id) const override; - void SerializeNode(ArcAccessibilityInfoData* info_data, - ui::AXNodeData* out_data) const override; - ArcAccessibilityInfoData* GetParent( - ArcAccessibilityInfoData* info_data) const override; - // Returns bounds of a node which can be passed to AXNodeData.location. Bounds // are returned in the following coordinates depending on whether it's root or // not. @@ -79,7 +62,7 @@ // - Non-root node is relative to the root node of this tree. // // focused_window is nullptr for notification. - const gfx::Rect GetBounds(ArcAccessibilityInfoData* info_data, + const gfx::Rect GetBounds(AccessibilityInfoDataWrapper* info_data, aura::Window* focused_window) const; // Invalidates the tree serializer. @@ -89,53 +72,65 @@ // parent window). bool IsRootOfNodeTree(int32_t id) const; + // Gets the window id of this tree. + int32_t GetWindowId() const; + + // AXTreeSource: + bool GetTreeData(ui::AXTreeData* data) const override; + AccessibilityInfoDataWrapper* GetRoot() const override; + AccessibilityInfoDataWrapper* GetFromId(int32_t id) const override; + AccessibilityInfoDataWrapper* GetParent( + AccessibilityInfoDataWrapper* info_data) const override; + void SerializeNode(AccessibilityInfoDataWrapper* info_data, + ui::AXNodeData* out_data) const override; + bool is_notification() { return is_notification_; } bool is_input_method_window() { return is_input_method_window_; } private: + friend class arc::AXTreeSourceArcTest; + // virtual for testing. virtual extensions::AutomationEventRouterInterface* GetAutomationEventRouter() const; - friend class arc::AXTreeSourceArcTest; - class FocusStealer; - - // AXTreeSource overrides. - int32_t GetId(ArcAccessibilityInfoData* info_data) const override; - void GetChildren( - ArcAccessibilityInfoData* info_data, - std::vector<ArcAccessibilityInfoData*>* out_children) const override; - bool IsIgnored(ArcAccessibilityInfoData* info_data) const override; - bool IsValid(ArcAccessibilityInfoData* info_data) const override; - bool IsEqual(ArcAccessibilityInfoData* info_data1, - ArcAccessibilityInfoData* info_data2) const override; - ArcAccessibilityInfoData* GetNull() const override; - // Computes the smallest rect that encloses all of the descendants of // |info_data|. - gfx::Rect ComputeEnclosingBounds(ArcAccessibilityInfoData* info_data) const; + gfx::Rect ComputeEnclosingBounds( + AccessibilityInfoDataWrapper* info_data) const; // Helper to recursively compute bounds for |info_data|. Returns true if // non-empty bounds were encountered. - void ComputeEnclosingBoundsInternal(ArcAccessibilityInfoData* info_data, + void ComputeEnclosingBoundsInternal(AccessibilityInfoDataWrapper* info_data, gfx::Rect& computed_bounds) const; - // AXActionHandler overrides. - void PerformAction(const ui::AXActionData& data) override; - // Resets tree state. void Reset(); - // Maps an ArcAccessibilityInfoData ID to its tree data. - std::map<int32_t, std::unique_ptr<ArcAccessibilityInfoData>> tree_map_; + // AXTreeSource: + int32_t GetId(AccessibilityInfoDataWrapper* info_data) const override; + void GetChildren( + AccessibilityInfoDataWrapper* info_data, + std::vector<AccessibilityInfoDataWrapper*>* out_children) const override; + bool IsIgnored(AccessibilityInfoDataWrapper* info_data) const override; + bool IsValid(AccessibilityInfoDataWrapper* info_data) const override; + bool IsEqual(AccessibilityInfoDataWrapper* info_data1, + AccessibilityInfoDataWrapper* info_data2) const override; + AccessibilityInfoDataWrapper* GetNull() const override; - // Maps an ArcAccessibilityInfoData ID to its parent. + // AXActionHandler: + void PerformAction(const ui::AXActionData& data) override; + + // Maps an AccessibilityInfoDataWrapper ID to its tree data. + std::map<int32_t, std::unique_ptr<AccessibilityInfoDataWrapper>> tree_map_; + + // Maps an AccessibilityInfoDataWrapper ID to its parent. std::map<int32_t, int32_t> parent_map_; std::unique_ptr<AXTreeArcSerializer> current_tree_serializer_; - int32_t root_id_; - int32_t window_id_; - int32_t focused_id_; + base::Optional<int32_t> root_id_; + base::Optional<int32_t> window_id_; + base::Optional<int32_t> focused_id_; bool is_notification_; bool is_input_method_window_; @@ -144,7 +139,7 @@ const Delegate* const delegate_; std::string package_name_; - // Mapping from ArcAccessibilityInfoData ID to its cached computed bounds. + // Mapping from AccessibilityInfoDataWrapper ID to its cached computed bounds. // This simplifies bounds calculations. std::map<int32_t, gfx::Rect> cached_computed_bounds_;
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc index bda31ec..871e7721 100644 --- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc +++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc_unittest.cc
@@ -163,7 +163,7 @@ void CallGetChildren( AXNodeInfoData* node, - std::vector<ArcAccessibilityInfoData*>* out_children) const { + std::vector<AccessibilityInfoDataWrapper*>* out_children) const { AccessibilityNodeInfoDataWrapper node_data(tree_source_.get(), node); tree_source_->GetChildren(&node_data, out_children); } @@ -184,7 +184,7 @@ tree_source_->SerializeNode(&window_data, out_data->get()); } - ArcAccessibilityInfoData* CallGetFromId(int32_t id) const { + AccessibilityInfoDataWrapper* CallGetFromId(int32_t id) const { return tree_source_->GetFromId(id); } @@ -244,6 +244,7 @@ SetProperty(button1, AXStringProperty::CLASS_NAME, ui::kAXButtonClassname); SetProperty(button1, AXBooleanProperty::VISIBLE_TO_USER, true); SetProperty(button1, AXBooleanProperty::FOCUSABLE, true); + SetProperty(button1, AXBooleanProperty::IMPORTANCE, true); // Add another child button. event->node_data.push_back(AXNodeInfoData::New()); @@ -252,6 +253,7 @@ SetProperty(button2, AXStringProperty::CLASS_NAME, ui::kAXButtonClassname); SetProperty(button2, AXBooleanProperty::VISIBLE_TO_USER, true); SetProperty(button2, AXBooleanProperty::FOCUSABLE, true); + SetProperty(button2, AXBooleanProperty::IMPORTANCE, true); // Non-overlapping, bottom to top. button1->bounds_in_screen = gfx::Rect(100, 100, 100, 100); @@ -259,7 +261,7 @@ // Trigger an update which refreshes the computed bounds used for reordering. CallNotifyAccessibilityEvent(event.get()); - std::vector<ArcAccessibilityInfoData*> top_to_bottom; + std::vector<AccessibilityInfoDataWrapper*> top_to_bottom; CallGetChildren(root, &top_to_bottom); ASSERT_EQ(2U, top_to_bottom.size()); EXPECT_EQ(2, top_to_bottom[0]->GetId()); @@ -279,7 +281,7 @@ button1->bounds_in_screen = gfx::Rect(101, 100, 99, 100); button2->bounds_in_screen = gfx::Rect(100, 100, 100, 100); CallNotifyAccessibilityEvent(event.get()); - std::vector<ArcAccessibilityInfoData*> left_to_right; + std::vector<AccessibilityInfoDataWrapper*> left_to_right; CallGetChildren(root, &left_to_right); ASSERT_EQ(2U, left_to_right.size()); EXPECT_EQ(2, left_to_right[0]->GetId()); @@ -319,7 +321,7 @@ button1->bounds_in_screen = gfx::Rect(100, 100, 100, 10); button2->bounds_in_screen = gfx::Rect(100, 100, 100, 100); CallNotifyAccessibilityEvent(event.get()); - std::vector<ArcAccessibilityInfoData*> dimension; + std::vector<AccessibilityInfoDataWrapper*> dimension; CallGetChildren(event->node_data[0].get(), &dimension); ASSERT_EQ(2U, dimension.size()); EXPECT_EQ(2, dimension[0]->GetId()); @@ -354,6 +356,15 @@ EXPECT_EQ(2, dimension[1]->GetId()); EXPECT_EQ(10, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + + // Sanity check tree output. + ExpectTree( + "id=0 genericContainer INVISIBLE (0, 0)-(0, 0) restriction=disabled " + "modal=true child_ids=1,2\n" + " id=1 button FOCUSABLE (100, 100)-(100, 100) restriction=disabled " + "class_name=android.widget.Button\n" + " id=2 button FOCUSABLE (100, 100)-(10, 100) restriction=disabled " + "class_name=android.widget.Button\n"); } TEST_F(AXTreeSourceArcTest, AccessibleNameComputationTextField) { @@ -692,7 +703,7 @@ CallNotifyAccessibilityEvent(event.get()); // Check that only the middle tree was added, and that it is correct. - std::vector<ArcAccessibilityInfoData*> children; + std::vector<AccessibilityInfoDataWrapper*> children; CallGetChildren(event->node_data.at(tree_size).get(), &children); ASSERT_EQ(1U, children.size()); EXPECT_EQ(5, children[0]->GetId()); @@ -766,7 +777,7 @@ CallNotifyAccessibilityEvent(event.get()); // Check that each node subtree tree was added, and that it is correct. - std::vector<ArcAccessibilityInfoData*> children; + std::vector<AccessibilityInfoDataWrapper*> children; for (int i = 0; i < num_trees; i++) { CallGetChildren(event->node_data.at(i * tree_size).get(), &children); ASSERT_EQ(1U, children.size());
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc index 1742e58..9c2a4f4 100644 --- a/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/welcome_screen_browsertest.cc
@@ -196,7 +196,8 @@ {"connect", "welcomeScreen", "enableDebuggingLink"}); } -IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest, WelcomeScreenNext) { +// Flaky: crbug.com/1014952 +IN_PROC_BROWSER_TEST_F(WelcomeScreenBrowserTest, DISABLED_WelcomeScreenNext) { welcome_screen_->Show(); OobeScreenWaiter(WelcomeView::kScreenId).Wait(); test::OobeJS().TapOnPath({"connect", "welcomeScreen", "welcomeNextButton"});
diff --git a/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc b/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc index 9fed9da7..ed35f6b 100644 --- a/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc +++ b/chrome/browser/chromeos/policy/login_screen_accessibility_policy_browsertest.cc
@@ -919,8 +919,9 @@ EXPECT_FALSE(accessibility_manager->IsFocusHighlightEnabled()); } +// TODO(crbug.com/1015763): Flaky on ChromeOS. IN_PROC_BROWSER_TEST_F(LoginScreenAccessibilityPolicyBrowsertest, - DeviceLoginScreenFullScreenMagnifier) { + DISABLED_DeviceLoginScreenFullScreenMagnifier) { // Verifies that the state of the full-screen magnifier accessibility // feature on the login screen can be controlled through device policy. chromeos::MagnificationManager* magnification_manager =
diff --git a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc index 33f9d427..3e46c8c 100644 --- a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc +++ b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
@@ -77,6 +77,7 @@ SET_STRING("close-btn-label", IDS_FEEDBACK_CLOSE_BUTTON_LABEL); SET_STRING("page-url", IDS_FEEDBACK_REPORT_URL_LABEL); SET_STRING("screenshot", IDS_FEEDBACK_SCREENSHOT_LABEL); + SET_STRING("screenshotA11y", IDS_FEEDBACK_SCREENSHOT_A11Y_TEXT); SET_STRING("user-email", IDS_FEEDBACK_USER_EMAIL_LABEL); SET_STRING("anonymous-user", IDS_FEEDBACK_ANONYMOUS_EMAIL_OPTION); SET_STRING("sys-info", GetSysInfoCheckboxStringId(browser_context));
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc index 0bac26b5..f0ccf81 100644 --- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc +++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
@@ -120,7 +120,7 @@ event_router_->BroadcastEvent(std::move(extension_event)); } - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Convert |params| to a real-time event dictionary and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUrl, params.url); @@ -145,7 +145,7 @@ event_router_->BroadcastEvent(std::move(extension_event)); } - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Convert |params| to a real-time event dictionary and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUserName, user_name); @@ -178,7 +178,7 @@ event_router_->BroadcastEvent(std::move(extension_event)); } - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Convert |params| to a real-time event dictionary and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUrl, params.url); @@ -220,7 +220,7 @@ event_router_->BroadcastEvent(std::move(extension_event)); } - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Convert |params| to a real-time event dictionary and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUrl, params.url); @@ -257,7 +257,7 @@ event_router_->BroadcastEvent(std::move(extension_event)); } - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Convert |params| to a real-time event dictionary and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUrl, params.url); @@ -277,7 +277,7 @@ const std::string& mime_type, const std::string& trigger, const int64_t content_size) { - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Create a real-time event dictionary from the arguments and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUrl, url.spec()); @@ -303,7 +303,7 @@ const std::string& mime_type, const std::string& trigger, const int64_t content_size) { - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Create a real-time event dictionary from the arguments and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUrl, url.spec()); @@ -333,7 +333,7 @@ const std::string& mime_type, const std::string& trigger, const int64_t content_size) { - if (IsRealtimeReportingEnabled()) { + if (IsRealtimeReportingEnabled() && client_) { // Create a real-time event dictionary from the arguments and report it. base::Value event(base::Value::Type::DICTIONARY); event.SetStringKey(kKeyUrl, url.spec()); @@ -357,7 +357,7 @@ const std::string& threat_type, const std::string& mime_type, const int64_t content_size) { - if (!IsRealtimeReportingEnabled()) + if (!IsRealtimeReportingEnabled() || !client_) return; // Create a real-time event dictionary and report it. @@ -384,7 +384,7 @@ const std::string& threat_type, const std::string& mime_type, const int64_t content_size) { - if (!IsRealtimeReportingEnabled()) + if (!IsRealtimeReportingEnabled() || !client_) return; // Create a real-time event dictionary and report it.
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc index f47ed3f4..b0ebb21 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -324,17 +324,18 @@ // Mock frame remote. Processes calls to SendInterventionReport and waits // for all pending messages to be sent. -class FrameRemoteTester : public blink::mojom::Frame { +class FrameRemoteTester : public blink::mojom::LocalFrame { public: FrameRemoteTester() = default; ~FrameRemoteTester() override = default; void BindPendingReceiver(mojo::ScopedInterfaceEndpointHandle handle) { - receivers_.Add(this, mojo::PendingAssociatedReceiver<blink::mojom::Frame>( - std::move(handle))); + receivers_.Add(this, + mojo::PendingAssociatedReceiver<blink::mojom::LocalFrame>( + std::move(handle))); } - // blink::mojom::Frame + // blink::mojom::LocalFrame void SendInterventionReport(const std::string& id, const std::string& message) override { if (!on_empty_report_callback_) @@ -378,7 +379,7 @@ // The message string for the last received non-empty intervention report. std::string last_message_; base::OnceClosure on_empty_report_callback_; - mojo::AssociatedReceiverSet<blink::mojom::Frame> receivers_; + mojo::AssociatedReceiverSet<blink::mojom::LocalFrame> receivers_; }; } // namespace @@ -479,7 +480,7 @@ navigation_simulator->GetFinalRenderFrameHost() ->GetRemoteAssociatedInterfaces(); remote_interfaces->OverrideBinderForTesting( - blink::mojom::Frame::Name_, + blink::mojom::LocalFrame::Name_, base::BindRepeating(&FrameRemoteTester::BindPendingReceiver, base::Unretained(&frame_remote_tester_)));
diff --git a/chrome/browser/previews/defer_all_script_priority_browsertest.cc b/chrome/browser/previews/defer_all_script_priority_browsertest.cc index 72b7fc47..e8ef334 100644 --- a/chrome/browser/previews/defer_all_script_priority_browsertest.cc +++ b/chrome/browser/previews/defer_all_script_priority_browsertest.cc
@@ -36,6 +36,7 @@ #include "content/public/test/browser_test_utils.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "third_party/blink/public/common/features.h" namespace { @@ -80,6 +81,7 @@ scoped_feature_list_.InitWithFeatures( {previews::features::kPreviews, previews::features::kDeferAllScriptPreviews, + blink::features::kLowerJavaScriptPriorityWhenForceDeferred, optimization_guide::features::kOptimizationHints, data_reduction_proxy::features:: kDataReductionProxyEnabledWithNetworkService}, @@ -87,6 +89,7 @@ } else { scoped_feature_list_.InitWithFeatures( {previews::features::kPreviews, + blink::features::kLowerJavaScriptPriorityWhenForceDeferred, optimization_guide::features::kOptimizationHints, data_reduction_proxy::features:: kDataReductionProxyEnabledWithNetworkService},
diff --git a/chrome/browser/profiles/avatar_menu_desktop.cc b/chrome/browser/profiles/avatar_menu_desktop.cc index edaeef0..9541231 100644 --- a/chrome/browser/profiles/avatar_menu_desktop.cc +++ b/chrome/browser/profiles/avatar_menu_desktop.cc
@@ -44,12 +44,8 @@ status = ImageLoadStatus::LOADING; } - // Otherwise, use the default resource, not the downloaded high-res one. - const size_t icon_index = entry->GetAvatarIconIndex(); - const int resource_id = - profiles::GetDefaultAvatarIconResourceIDAtIndex(icon_index); - *image = - ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id); + // Otherwise, use the high resolution icon from local storage. + *image = entry->GetAvatarIcon(); return status; }
diff --git a/chrome/browser/resources/chromeos/emulator/BUILD.gn b/chrome/browser/resources/chromeos/emulator/BUILD.gn index a48f3e5..2e92fc5 100644 --- a/chrome/browser/resources/chromeos/emulator/BUILD.gn +++ b/chrome/browser/resources/chromeos/emulator/BUILD.gn
@@ -19,6 +19,9 @@ } js_library("bluetooth_settings") { + deps = [ + "//ui/webui/resources/js:web_ui_listener_behavior", + ] externs_list = [ "$externs_path/chrome_send.js" ] }
diff --git a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html index 00e1c009..a1eb364ee 100644 --- a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html +++ b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.html
@@ -8,6 +8,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="icons.html"> <link rel="import" href="shared_styles.html">
diff --git a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js index bd7a2c4..1e4c0f04 100644 --- a/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js +++ b/chrome/browser/resources/chromeos/emulator/bluetooth_settings.js
@@ -54,6 +54,8 @@ Polymer({ is: 'bluetooth-settings', + behaviors: [WebUIListenerBehavior], + properties: { /** * A set of bluetooth devices. @@ -148,6 +150,16 @@ devicePaths: {}, ready: function() { + this.addWebUIListener( + 'bluetooth-device-added', this.addBluetoothDevice_.bind(this)); + this.addWebUIListener( + 'device-paired-from-tray', this.devicePairedFromTray_.bind(this)); + this.addWebUIListener( + 'device-removed-from-main-adapter', + this.deviceRemovedFromMainAdapter_.bind(this)); + this.addWebUIListener('pair-failed', this.pairFailed_.bind(this)); + this.addWebUIListener( + 'bluetooth-info-updated', this.updateBluetoothInfo_.bind(this)); chrome.send('requestBluetoothInfo'); }, @@ -274,19 +286,20 @@ /** * Called by the WebUI which provides a list of devices which are connected * to the main adapter. - * @param {!Array<!BluetoothDevice>} predefinedDevices A list of bluetooth - * devices. - * @param {!Array<!BluetoothDevice>} loadedCustomDevices - * @param {!Array<string>} pairingMethodOptions - * @param {!Array<string>} pairingActionOptions + * @param {{ + * predefined_devices: !Array<!BluetoothDevice>, + * devices: !Array<!BluetoothDevice>, + * pairing_method_options: !Array<string>, + * pairing_action_options: !Array<string>, + * }} info + * @private */ - updateBluetoothInfo: function( - predefinedDevices, loadedCustomDevices, pairingMethodOptions, - pairingActionOptions) { - this.predefinedDevices = this.loadDevicesFromList(predefinedDevices, true); - this.devices = this.loadDevicesFromList(loadedCustomDevices, false); - this.deviceAuthenticationMethods = pairingMethodOptions; - this.deviceAuthenticationActions = pairingActionOptions; + updateBluetoothInfo_: function(info) { + this.predefinedDevices = + this.loadDevicesFromList(info.predefined_devices, true); + this.devices = this.loadDevicesFromList(info.devices, false); + this.deviceAuthenticationMethods = info.pairing_method_options; + this.deviceAuthenticationActions = info.pairing_action_options; }, /** @@ -318,8 +331,9 @@ /** * Called when a device is paired from the Tray. Checks the paired box for * the device with path |path|. + * @private */ - devicePairedFromTray: function(path) { + devicePairedFromTray_: function(path) { var obj = this.devicePaths[path]; if (obj == undefined) @@ -368,8 +382,9 @@ /** * Called from Chrome OS back-end when a pair request fails. * @param {string} path The path of the device which failed to pair. + * @private */ - pairFailed: function(path) { + pairFailed_: function(path) { var obj = this.devicePaths[path]; if (obj == undefined) @@ -420,8 +435,9 @@ * The device is only added to the view's list if it is not already in * the list (i.e. its path has not yet been recorded in |devicePaths|). * @param {BluetoothDevice} device A bluetooth device. + * @private */ - addBluetoothDevice: function(device) { + addBluetoothDevice_: function(device) { if (this.devicePaths[device.path] != undefined) { var obj = this.devicePaths[device.path]; var devicePath = (obj.predefined ? 'predefinedDevices.' : 'devices.'); @@ -501,8 +517,9 @@ * adapter's device list. It sets that device's |.discoverable| and |.paired| * attributes to false. * @param {string} path A bluetooth device's path. + * @private */ - deviceRemovedFromMainAdapter: function(path) { + deviceRemovedFromMainAdapter_: function(path) { if (this.devicePaths[path] == undefined) return;
diff --git a/chrome/browser/resources/feedback/css/feedback.css b/chrome/browser/resources/feedback/css/feedback.css index 57bfe51..b8c20b9 100644 --- a/chrome/browser/resources/feedback/css/feedback.css +++ b/chrome/browser/resources/feedback/css/feedback.css
@@ -140,7 +140,7 @@ width: 200px; } -.content #screenshot-label { +.content #screenshot-chk-label { flex: auto; }
diff --git a/chrome/browser/resources/feedback/html/default.html b/chrome/browser/resources/feedback/html/default.html index c2e2f27..fde8795 100644 --- a/chrome/browser/resources/feedback/html/default.html +++ b/chrome/browser/resources/feedback/html/default.html
@@ -59,9 +59,10 @@ <div id="attach-file-note" i18n-content="attach-file-note"></div> <!-- Screenshot --> <div id="screenshot-container" class="checkbox-field-container"> - <input id="screenshot-checkbox" type="checkbox" aria-labelledby="screenshot-label"> - <label id="screenshot-label" i18n-content="screenshot"></label> - <img id="screenshot-image"> + <input id="screenshot-checkbox" type="checkbox" + aria-labelledby="screenshot-chk-label"> + <label id="screenshot-chk-label" i18n-content="screenshot"></label> + <img id="screenshot-image" i18n-values="aria-label:screenshotA11y"> </div> <!-- System Information --> <div id="sys-info-container" class="checkbox-field-container">
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index 29ffca7..97364ef 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -1076,6 +1076,8 @@ /** @param {!DeleteAutocompleteMatchResult} result */ function onDeleteAutocompleteMatch(result) { + assert(matchElBeingDeleted); + if (!result.success) { matchElBeingDeleted = null; return; @@ -1305,6 +1307,7 @@ if (key === 'Delete') { if (e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey && autocompleteMatches[selected].supportsDeletion) { + matchElBeingDeleted = matchEls[selected]; window.chrome.embeddedSearch.searchBox.deleteAutocompleteMatch(selected); e.preventDefault(); }
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.js b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.js index a4ca333..583b4c39 100644 --- a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.js +++ b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.js
@@ -129,25 +129,22 @@ return; } - // If the card is expired, reflect the error to the user. - // Otherwise, update the card, save and close the dialog. - if (!this.checkIfCardExpired_( - this.expirationMonth_, this.expirationYear_)) { - this.creditCard.expirationYear = this.expirationYear_; - this.creditCard.expirationMonth = this.expirationMonth_; - this.fire('save-credit-card', this.creditCard); - this.close(); - } + this.creditCard.expirationYear = this.expirationYear_; + this.creditCard.expirationMonth = this.expirationMonth_; + this.fire('save-credit-card', this.creditCard); + this.close(); }, /** @private */ onMonthChange_: function() { this.expirationMonth_ = this.monthList_[this.$.month.selectedIndex]; + this.$.saveButton.disabled = !this.saveEnabled_(); }, /** @private */ onYearChange_: function() { this.expirationYear_ = this.yearList_[this.$.year.selectedIndex]; + this.$.saveButton.disabled = !this.saveEnabled_(); }, /** @private */ @@ -157,8 +154,13 @@ /** @private */ saveEnabled_: function() { - return (this.creditCard.name && this.creditCard.name.trim()) || - (this.creditCard.cardNumber && this.creditCard.cardNumber.trim()); + // The save button is enabled if: + // There is and name or number for the card + // and the expiration date is valid. + return ((this.creditCard.name && this.creditCard.name.trim()) || + (this.creditCard.cardNumber && + this.creditCard.cardNumber.trim())) && + !this.checkIfCardExpired_(this.expirationMonth_, this.expirationYear_); }, }); })();
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc index 3f24d23e..c8d5613 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -806,13 +806,14 @@ } // For non sync password changes, we have to loop through all the password - // hashes and find the hash associated with the username. Right now this - // double counts when a password is first saved which is inaccurate. + // hashes and find the hash associated with the username. password_manager::HashPasswordManager hash_password_manager; hash_password_manager.set_prefs(profile_->GetPrefs()); for (const auto& hash_data : hash_password_manager.RetrieveAllPasswordHashes()) { - if (hash_data.username == username) { + if (password_manager::AreUsernamesSame( + hash_data.username, /*is_username1_gaia_account=*/true, username, + /*is_username2_gaia_account=*/true)) { OnGaiaPasswordChanged(username, /*is_other_gaia_password=*/true); break; }
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h index 84520fa..e3d7f240 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.h +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -149,7 +149,8 @@ // Check if Gaia password hash has changed. If it is changed, it will call // |OnGaiaPasswordChanged|. |username| is used to get the appropriate account // to check if the account is a Gmail account as no reporting is done for - // those accounts. + // those accounts. This method is only called if there was already an existing + // password hash in the hash password manager reused password. void CheckGaiaPasswordChangeForAllSignedInUsers(const std::string& username); // Called when user's GAIA password changed. |username| is used to get
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc index ba1610e..7eab77a 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_utils_unittest.cc
@@ -40,7 +40,7 @@ class MockSharingDeviceRegistration : public SharingDeviceRegistration { public: - explicit MockSharingDeviceRegistration() + MockSharingDeviceRegistration() : SharingDeviceRegistration(/* pref_service_= */ nullptr, /* sharing_sync_preference_= */ nullptr, /* instance_id_driver_= */ nullptr, @@ -54,28 +54,6 @@ DISALLOW_COPY_AND_ASSIGN(MockSharingDeviceRegistration); }; -class MockSharingService : public SharingService { - public: - explicit MockSharingService(std::unique_ptr<SharingFCMHandler> fcm_handler) - : SharingService(/* sync_prefs= */ nullptr, - /* vapid_key_manager= */ nullptr, - std::make_unique<MockSharingDeviceRegistration>(), - /* fcm_sender= */ nullptr, - std::move(fcm_handler), - /* gcm_driver= */ nullptr, - /* device_info_tracker= */ nullptr, - /* local_device_info_provider= */ nullptr, - /* sync_service */ nullptr, - /* notification_display_service= */ nullptr) {} - - ~MockSharingService() override = default; - - MOCK_CONST_METHOD0(GetState, State()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockSharingService); -}; - class ClickToCallUtilsTest : public testing::Test { public: ClickToCallUtilsTest() = default; @@ -106,8 +84,17 @@ if (!create_service_) return nullptr; - return std::make_unique<NiceMock<MockSharingService>>( - std::make_unique<SharingFCMHandler>(nullptr, nullptr, nullptr)); + return std::make_unique<SharingService>( + /* sync_prefs= */ nullptr, + /* vapid_key_manager= */ nullptr, + std::make_unique<MockSharingDeviceRegistration>(), + /* fcm_sender= */ nullptr, + std::make_unique<SharingFCMHandler>(nullptr, nullptr, nullptr), + /* gcm_driver= */ nullptr, + /* device_info_tracker= */ nullptr, + /* local_device_info_provider= */ nullptr, + /* sync_service */ nullptr, + /* notification_display_service= */ nullptr); } base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc index f9f53e20..0b77a6c 100644 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc +++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc
@@ -36,7 +36,7 @@ class MockSharingDeviceRegistration : public SharingDeviceRegistration { public: - explicit MockSharingDeviceRegistration() + MockSharingDeviceRegistration() : SharingDeviceRegistration(/* pref_service_= */ nullptr, /* sharing_sync_preference_= */ nullptr, /* instance_id_driver_= */ nullptr, @@ -50,28 +50,6 @@ DISALLOW_COPY_AND_ASSIGN(MockSharingDeviceRegistration); }; -class MockSharingService : public SharingService { - public: - explicit MockSharingService(std::unique_ptr<SharingFCMHandler> fcm_handler) - : SharingService(/* sync_prefs= */ nullptr, - /* vapid_key_manager= */ nullptr, - std::make_unique<MockSharingDeviceRegistration>(), - /* fcm_sender= */ nullptr, - std::move(fcm_handler), - /* gcm_driver= */ nullptr, - /* device_info_tracker= */ nullptr, - /* local_device_info_provider= */ nullptr, - /* sync_service */ nullptr, - /* notification_display_service= */ nullptr) {} - - ~MockSharingService() override = default; - - MOCK_CONST_METHOD0(GetState, State()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockSharingService); -}; - class SharedClipboardUtilsTest : public testing::Test { public: SharedClipboardUtilsTest() = default; @@ -90,8 +68,17 @@ if (!create_service_) return nullptr; - return std::make_unique<NiceMock<MockSharingService>>( - std::make_unique<SharingFCMHandler>(nullptr, nullptr, nullptr)); + return std::make_unique<SharingService>( + /* sync_prefs= */ nullptr, + /* vapid_key_manager= */ nullptr, + std::make_unique<MockSharingDeviceRegistration>(), + /* fcm_sender= */ nullptr, + std::make_unique<SharingFCMHandler>(nullptr, nullptr, nullptr), + /* gcm_driver= */ nullptr, + /* device_info_tracker= */ nullptr, + /* local_device_info_provider= */ nullptr, + /* sync_service */ nullptr, + /* notification_display_service= */ nullptr); } base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/sharing/sharing_browsertest.cc b/chrome/browser/sharing/sharing_browsertest.cc index 4e05aee..d209bc32c 100644 --- a/chrome/browser/sharing/sharing_browsertest.cc +++ b/chrome/browser/sharing/sharing_browsertest.cc
@@ -147,7 +147,8 @@ void SharingBrowserTest::CheckLastReceiver( const std::string& device_guid) const { auto sharing_info = - sharing_service_->GetSyncPreferences()->GetSharingInfo(device_guid); + sharing_service_->GetSyncPreferencesForTesting()->GetSharingInfo( + device_guid); ASSERT_TRUE(sharing_info); EXPECT_EQ(sharing_info->fcm_token, gcm_service_->last_receiver_id()); }
diff --git a/chrome/browser/sharing/sharing_service.cc b/chrome/browser/sharing/sharing_service.cc index 008becb..4dde1914 100644 --- a/chrome/browser/sharing/sharing_service.cc +++ b/chrome/browser/sharing/sharing_service.cc
@@ -37,6 +37,13 @@ #include "content/public/browser/browser_task_traits.h" #include "ui/base/l10n/l10n_util.h" +#if defined(OS_ANDROID) +#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_android.h" +#include "chrome/browser/sharing/sharing_service_proxy_android.h" +#else +#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.h" +#endif // defined(OS_ANDROID) + namespace { // Util function to return a string denoting the type of device. std::string GetDeviceType(sync_pb::SyncEnums::DeviceType type) { @@ -161,28 +168,32 @@ // Initialize sharing handlers. fcm_handler_->AddSharingHandler( + chrome_browser_sharing::SharingMessage::kPingMessage, + &ping_message_handler_); + + fcm_handler_->AddSharingHandler( chrome_browser_sharing::SharingMessage::kAckMessage, &ack_message_handler_); ack_message_handler_.AddObserver(this); - fcm_handler_->AddSharingHandler( - chrome_browser_sharing::SharingMessage::kPingMessage, - &ping_message_handler_); + #if defined(OS_ANDROID) + // Note: IsClickToCallSupported() is not used as it requires JNI call. if (base::FeatureList::IsEnabled(kClickToCallReceiver)) { fcm_handler_->AddSharingHandler( chrome_browser_sharing::SharingMessage::kClickToCallMessage, - sharing_service_proxy_android_.click_to_call_message_handler()); + &click_to_call_message_handler_); } - - shared_clipboard_message_handler_ = - std::make_unique<SharedClipboardMessageHandlerAndroid>(this); -#else - shared_clipboard_message_handler_ = - std::make_unique<SharedClipboardMessageHandlerDesktop>( - this, notification_display_service); #endif // defined(OS_ANDROID) if (sharing_device_registration_->IsSharedClipboardSupported()) { +#if defined(OS_ANDROID) + shared_clipboard_message_handler_ = + std::make_unique<SharedClipboardMessageHandlerAndroid>(this); +#else + shared_clipboard_message_handler_ = + std::make_unique<SharedClipboardMessageHandlerDesktop>( + this, notification_display_service); +#endif // defined(OS_ANDROID) fcm_handler_->AddSharingHandler( chrome_browser_sharing::SharingMessage::kSharedClipboardMessage, shared_clipboard_message_handler_.get()); @@ -325,6 +336,14 @@ device_info_tracker_ = tracker; } +SharingService::State SharingService::GetStateForTesting() const { + return state_; +} + +SharingSyncPreference* SharingService::GetSyncPreferencesForTesting() const { + return sync_prefs_.get(); +} + void SharingService::OnMessageSent( base::TimeTicks start_time, const std::string& message_guid, @@ -390,14 +409,6 @@ device_candidates_initialized_callbacks_.clear(); } -void SharingService::RegisterHandler( - chrome_browser_sharing::SharingMessage::PayloadCase payload_type, - SharingMessageHandler* handler) {} - -SharingService::State SharingService::GetState() const { - return state_; -} - void SharingService::OnSyncShutdown(syncer::SyncService* sync) { if (sync_service_ && sync_service_->HasObserver(this)) sync_service_->RemoveObserver(this); @@ -549,10 +560,6 @@ sync_service_->GetActiveDataTypes().HasAll(GetRequiredSyncDataTypes()); } -SharingSyncPreference* SharingService::GetSyncPreferences() const { - return sync_prefs_.get(); -} - bool SharingService::IsSyncDisabled() const { return sync_service_ && (sync_service_->GetTransportState() == syncer::SyncService::TransportState::DISABLED ||
diff --git a/chrome/browser/sharing/sharing_service.h b/chrome/browser/sharing/sharing_service.h index a7323035..89b183b8 100644 --- a/chrome/browser/sharing/sharing_service.h +++ b/chrome/browser/sharing/sharing_service.h
@@ -29,10 +29,8 @@ #include "net/base/backoff_entry.h" #if defined(OS_ANDROID) -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_android.h" +#include "chrome/browser/sharing/click_to_call/click_to_call_message_handler_android.h" #include "chrome/browser/sharing/sharing_service_proxy_android.h" -#else -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop.h" #endif // defined(OS_ANDROID) namespace gcm { @@ -45,9 +43,9 @@ } // namespace syncer class NotificationDisplayService; +class SharedClipboardMessageHandler; class SharingFCMHandler; class SharingFCMSender; -class SharingMessageHandler; class SharingSyncPreference; class VapidKeyManager; enum class SharingDeviceRegistrationResult; @@ -109,24 +107,20 @@ chrome_browser_sharing::SharingMessage message, SendMessageCallback callback); - // Registers a handler of a given SharingMessage payload type. - void RegisterHandler( - chrome_browser_sharing::SharingMessage::PayloadCase payload_type, - SharingMessageHandler* handler); - - // Returns the current state of SharingService. - virtual State GetState() const; - // Used to register devices with required capabilities in tests. void RegisterDeviceInTesting( std::set<sync_pb::SharingSpecificFields_EnabledFeatures> enabled_features, SharingDeviceRegistration::RegistrationCallback callback); - SharingSyncPreference* GetSyncPreferences() const; - // Used to fake client names in integration tests. void SetDeviceInfoTrackerForTesting(syncer::DeviceInfoTracker* tracker); + // Returns the current state of SharingService for testing. + State GetStateForTesting() const; + + // Returns SharingSyncPreference for integration tests. + SharingSyncPreference* GetSyncPreferencesForTesting() const; + private: // Overrides for syncer::SyncServiceObserver. void OnSyncShutdown(syncer::SyncService* sync) override; @@ -141,7 +135,6 @@ void OnDeviceInfoChange() override; void RefreshVapidKey(); - void RegisterDevice(); void UnregisterDevice(); @@ -188,24 +181,23 @@ std::unique_ptr<SharingDeviceRegistration> sharing_device_registration_; std::unique_ptr<SharingFCMSender> fcm_sender_; std::unique_ptr<SharingFCMHandler> fcm_handler_; + syncer::DeviceInfoTracker* device_info_tracker_; syncer::LocalDeviceInfoProvider* local_device_info_provider_; syncer::SyncService* sync_service_; - AckMessageHandler ack_message_handler_; - PingMessageHandler ping_message_handler_; + net::BackoffEntry backoff_entry_; State state_; - std::vector<base::OnceClosure> device_candidates_initialized_callbacks_; bool is_observing_device_info_tracker_; std::unique_ptr<syncer::LocalDeviceInfoProvider::Subscription> local_device_info_ready_subscription_; + // List of callbacks for AddDeviceCandidatesInitializedObserver. + std::vector<base::OnceClosure> device_candidates_initialized_callbacks_; // Map of random GUID to SendMessageCallback. std::map<std::string, SendMessageCallback> send_message_callbacks_; - // Map of FCM message_id to time at start of send message request to FCM. std::map<std::string, base::TimeTicks> send_message_times_; - // Map of FCM message_id to random GUID. std::map<std::string, std::string> message_guids_; @@ -213,6 +205,11 @@ SharingServiceProxyAndroid sharing_service_proxy_android_{this}; #endif // defined(OS_ANDROID) + PingMessageHandler ping_message_handler_; + AckMessageHandler ack_message_handler_; +#if defined(OS_ANDROID) + ClickToCallMessageHandler click_to_call_message_handler_; +#endif // defined(OS_ANDROID) std::unique_ptr<SharedClipboardMessageHandler> shared_clipboard_message_handler_;
diff --git a/chrome/browser/sharing/sharing_service_proxy_android.h b/chrome/browser/sharing/sharing_service_proxy_android.h index 421f9a8..81af31b 100644 --- a/chrome/browser/sharing/sharing_service_proxy_android.h +++ b/chrome/browser/sharing/sharing_service_proxy_android.h
@@ -7,8 +7,6 @@ #include "base/android/jni_android.h" #include "base/macros.h" -#include "chrome/browser/sharing/click_to_call/click_to_call_message_handler_android.h" -#include "chrome/browser/sharing/sharing_message_handler.h" class SharingService; @@ -18,10 +16,6 @@ explicit SharingServiceProxyAndroid(SharingService* sharing_service); ~SharingServiceProxyAndroid(); - ClickToCallMessageHandler* click_to_call_message_handler() { - return &click_to_call_message_handler_; - } - void SendSharedClipboardMessage( JNIEnv* env, const base::android::JavaParamRef<jstring>& j_guid, @@ -39,7 +33,6 @@ private: SharingService* sharing_service_ = nullptr; - ClickToCallMessageHandler click_to_call_message_handler_; DISALLOW_COPY_AND_ASSIGN(SharingServiceProxyAndroid); };
diff --git a/chrome/browser/sharing/sharing_service_unittest.cc b/chrome/browser/sharing/sharing_service_unittest.cc index 2d729f16..4eff67c 100644 --- a/chrome/browser/sharing/sharing_service_unittest.cc +++ b/chrome/browser/sharing/sharing_service_unittest.cc
@@ -412,7 +412,7 @@ ASSERT_TRUE( sharing_message.ParseFromString(fake_gcm_driver_.message().payload)); EXPECT_EQ("id", sharing_message.sender_guid()); - EXPECT_EQ("model Computer manufacturer", + EXPECT_EQ("manufacturer Computer model", sharing_message.sender_device_name()); // Simulate ack message received by AckMessageHandler. @@ -512,7 +512,8 @@ test_sync_service_.SetActiveDataTypes( {syncer::DEVICE_INFO, syncer::PREFERENCES}); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // Expect registration to be successful on sync state changed. sharing_device_registration_->SetResult( @@ -520,13 +521,15 @@ EXPECT_CALL(*fcm_handler_, StartListening()).Times(1); test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); // As device is already registered, won't attempt registration anymore. EXPECT_CALL(*fcm_handler_, StartListening()).Times(0); test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); auto vapid_key = crypto::ECPrivateKey::Create(); ASSERT_TRUE(vapid_key); @@ -537,7 +540,8 @@ EXPECT_CALL(*fcm_handler_, StartListening()).Times(0); sync_prefs_->SetVapidKey(vapid_key_info); EXPECT_EQ(2, sharing_device_registration_->registration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); } TEST_F(SharingServiceTest, DeviceRegistrationPreferenceNotAvailable) { @@ -547,13 +551,15 @@ syncer::SyncService::TransportState::ACTIVE); test_sync_service_.SetActiveDataTypes(syncer::DEVICE_INFO); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // As sync preferences is not available, registration shouldn't start. EXPECT_CALL(*fcm_handler_, StartListening()).Times(0); test_sync_service_.FireStateChanged(); EXPECT_EQ(0, sharing_device_registration_->registration_attempts()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); } TEST_F(SharingServiceTest, DeviceRegistrationTransportMode) { @@ -568,7 +574,8 @@ test_sync_service_.SetExperimentalAuthenticationKey( crypto::ECPrivateKey::Create()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // Expect registration to be successful on sync state changed. sharing_device_registration_->SetResult( @@ -576,7 +583,8 @@ EXPECT_CALL(*fcm_handler_, StartListening()).Times(1); test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); // Registration will be attempeted as sync auth id has changed. EXPECT_CALL(*fcm_handler_, StartListening()).Times(0); @@ -584,7 +592,8 @@ crypto::ECPrivateKey::Create()); test_sync_service_.FireSyncCycleCompleted(); EXPECT_EQ(2, sharing_device_registration_->registration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); } TEST_F(SharingServiceTest, DeviceRegistrationTransientError) { @@ -595,7 +604,8 @@ test_sync_service_.SetActiveDataTypes( {syncer::DEVICE_INFO, syncer::PREFERENCES}); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // Retry will be scheduled on transient error received. sharing_device_registration_->SetResult( @@ -603,7 +613,7 @@ test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); EXPECT_EQ(SharingService::State::REGISTERING, - GetSharingService()->GetState()); + GetSharingService()->GetStateForTesting()); // Retry should be scheduled by now. Next retry after 5 minutes will be // successful. @@ -613,7 +623,8 @@ task_environment_.FastForwardBy( base::TimeDelta::FromMilliseconds(kRetryBackoffPolicy.initial_delay_ms)); EXPECT_EQ(2, sharing_device_registration_->registration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); } TEST_F(SharingServiceTest, DeviceUnregistrationFeatureDisabled) { @@ -623,16 +634,19 @@ sharing_device_registration_->SetResult( SharingDeviceRegistrationResult::kSuccess); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // Further state changes are ignored. test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); } TEST_F(SharingServiceTest, DeviceUnregistrationSyncDisabled) { @@ -643,7 +657,8 @@ // Create new SharingService instance with sync disabled at constructor. GetSharingService(); EXPECT_EQ(1, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); } TEST_F(SharingServiceTest, DeviceRegisterAndUnregister) { @@ -656,7 +671,8 @@ // Create new SharingService instance with feature enabled at constructor. GetSharingService(); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // Expect registration to be successful on sync state changed. sharing_device_registration_->SetResult( @@ -665,14 +681,16 @@ test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); EXPECT_EQ(0, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); // Further state changes do nothing. EXPECT_CALL(*fcm_handler_, StartListening()).Times(0); test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); EXPECT_EQ(0, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); // Change sync to configuring, which will be ignored. test_sync_service_.SetTransportState( @@ -680,7 +698,8 @@ test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); EXPECT_EQ(0, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); // Disable sync and un-registration should happen. test_sync_service_.SetTransportState( @@ -689,14 +708,16 @@ test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); EXPECT_EQ(1, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // Further state changes do nothing. EXPECT_CALL(*fcm_handler_, StopListening()).Times(0); test_sync_service_.FireStateChanged(); EXPECT_EQ(1, sharing_device_registration_->registration_attempts()); EXPECT_EQ(1, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); // Should be able to register once again when sync is back on. test_sync_service_.SetTransportState( @@ -705,7 +726,8 @@ test_sync_service_.FireStateChanged(); EXPECT_EQ(2, sharing_device_registration_->registration_attempts()); EXPECT_EQ(1, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::ACTIVE, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::ACTIVE, + GetSharingService()->GetStateForTesting()); // Disable syncing of preference and un-registration should happen. test_sync_service_.SetActiveDataTypes(syncer::DEVICE_INFO); @@ -713,7 +735,8 @@ test_sync_service_.FireStateChanged(); EXPECT_EQ(2, sharing_device_registration_->registration_attempts()); EXPECT_EQ(2, sharing_device_registration_->unregistration_attempts()); - EXPECT_EQ(SharingService::State::DISABLED, GetSharingService()->GetState()); + EXPECT_EQ(SharingService::State::DISABLED, + GetSharingService()->GetStateForTesting()); } TEST_F(SharingServiceTest, StartListeningToFCMAtConstructor) {
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn b/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn index f6a564d9..997f2b5 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn +++ b/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn
@@ -16,7 +16,9 @@ "//base", "//chrome/app:generated_resources", "//chrome/browser:resources_grit", + "//components/signin/public/base", "//ui/base", + "//url", ] }
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.cc b/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.cc index 0f6860ea..7d2273c 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.cc +++ b/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.cc
@@ -11,10 +11,12 @@ #include "base/values.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" +#include "components/signin/public/base/avatar_icon_util.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" #include "ui/base/webui/web_ui_util.h" +#include "url/gurl.h" namespace supervised_user_error_page { @@ -28,15 +30,13 @@ } std::string BuildAvatarImageUrl(const std::string& url, int size) { - std::string result = url; - size_t slash = result.rfind('/'); - if (slash != std::string::npos) { - // Check if the URL already contains the monogram (-mo) option. - // In that case, we must use the '-' separator, instead of '/'. - std::string separator = result.substr(slash - 3, 3) == "/mo" ? "-" : "/"; - result.insert(slash, separator + "s" + base::NumberToString(size) + "-c"); - } - return result; + GURL gurl(url); + if (!gurl.is_valid()) + return url; + + GURL to_return = signin::GetAvatarImageURLWithOptions( + gurl, size, false /* no_silhouette */); + return to_return.spec(); } } // namespace
diff --git a/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm index 1acbec1..58f39f8 100644 --- a/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm +++ b/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm
@@ -163,14 +163,12 @@ // Always use the low-res, small default avatars in the menu. AvatarMenu::GetImageForMenuButton(itemData.profile_path, &itemIcon); - // The image might be too large and need to be resized, e.g. if this is - // a signed-in user using the GAIA profile photo. - if (itemIcon.Width() > kMenuAvatarIconSize || - itemIcon.Height() > kMenuAvatarIconSize) { - itemIcon = profiles::GetSizedAvatarIcon(itemIcon, /*is_rectangle=*/true, - kMenuAvatarIconSize, - kMenuAvatarIconSize); - } + // Shapes the avatar icon into a circle for consistency with other avatar + // UI elements. + itemIcon = profiles::GetSizedAvatarIcon( + itemIcon, /*is_rectangle=*/true, kMenuAvatarIconSize, + kMenuAvatarIconSize, profiles::SHAPE_CIRCLE); + [item setImage:itemIcon.ToNSImage()]; [item setState:itemData.active ? NSOnState : NSOffState]; }
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc index f5b068b6..9bbf210 100644 --- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc +++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
@@ -85,20 +85,21 @@ void CheckShouldPromptForNewProfile( Profile* profile, - const base::Callback<void(bool)>& return_result) { + base::OnceCallback<void(bool)> return_result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (HasBeenShutdown(profile) || HasBookmarks(profile) || HasSyncedExtensions(profile)) { - return_result.Run(true); + std::move(return_result).Run(true); return; } history::HistoryService* service = HistoryServiceFactory::GetForProfileWithoutCreating(profile); // Fire asynchronous queries for profile data. browser_sync::SigninConfirmationHelper* helper = - new browser_sync::SigninConfirmationHelper(service, return_result); + new browser_sync::SigninConfirmationHelper(service, + std::move(return_result)); helper->CheckHasHistory(kHistoryEntriesBeforeNewProfilePrompt); helper->CheckHasTypedURLs(); }
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h index 65b6bc44..051cfc4 100644 --- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h +++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
@@ -29,9 +29,8 @@ // Determines whether the user should be prompted to create a new // profile before signin. -void CheckShouldPromptForNewProfile( - Profile* profile, - const base::Callback<void(bool)>& cb); +void CheckShouldPromptForNewProfile(Profile* profile, + base::OnceCallback<void(bool)> cb); // Handles user input from confirmation dialog. class ProfileSigninConfirmationDelegate {
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc index 199f1fe..f9cf382 100644 --- a/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc +++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
@@ -62,12 +62,13 @@ quit.Run(); } -template<typename T> +template <typename T> T GetCallbackResult( - const base::Callback<void(const base::Callback<void(T)>&)>& callback) { + const base::Callback<void(base::OnceCallback<void(T)>)>& callback) { T result = false; base::RunLoop loop; - callback.Run(base::Bind(&GetValueAndQuit<T>, &result, loop.QuitClosure())); + callback.Run( + base::BindOnce(&GetValueAndQuit<T>, &result, loop.QuitClosure())); loop.Run(); return result; }
diff --git a/chrome/browser/ui/views/frame/top_container_background.cc b/chrome/browser/ui/views/frame/top_container_background.cc index 2151cb8..655efbc 100644 --- a/chrome/browser/ui/views/frame/top_container_background.cc +++ b/chrome/browser/ui/views/frame/top_container_background.cc
@@ -16,23 +16,19 @@ views::View* view) const { const ui::ThemeProvider* const theme_provider = view->GetThemeProvider(); if (theme_provider->HasCustomImage(IDR_THEME_TOOLBAR)) { - // Calculate the offset of the upper-left corner of the owner view in the - // browser view. Not all views are directly parented to the browser, so we - // have to walk up the view hierarchy. This will tell us the offset into the - // tiled image that will correspond to the upper-left corner of the view. - int x = 0; - int y = 0; - views::View* current = view; - for (; current != browser_view_; current = current->parent()) { - x += current->x(); - y += current->y(); - } - x += browser_view_->frame()->GetThemeBackgroundXInset(); + // This is a recapitulation of the logic originally used to place the + // background image in the bookmarks bar. It is used to ensure backwards- + // compatibility with existing themes, even though it is not technically + // correct in all cases. + gfx::Point pos = view->GetMirroredPosition() + + browser_view_->GetMirroredPosition().OffsetFromOrigin(); + pos.Offset(browser_view_->frame()->GetThemeBackgroundXInset(), + -browser_view_->frame()->GetTopInset()); + const gfx::Rect bounds = view->GetLocalBounds(); - // Start tiling from coordinates (x, y) in the image into local space, - // filling the entire local bounds of the owner view. canvas->TileImageInt(*theme_provider->GetImageSkiaNamed(IDR_THEME_TOOLBAR), - x, y, 0, 0, view->width(), view->height()); + pos.x(), pos.y(), bounds.x(), bounds.y(), + bounds.width(), bounds.height()); } else { canvas->DrawColor(theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR)); }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 4b1c1ab..bbd4555 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -431,7 +431,10 @@ ->GetRevealedLock(ImmersiveModeController::ANIMATE_REVEAL_YES)); } + suppress_on_focus_suggestions_ = !is_user_initiated; RequestFocus(); + suppress_on_focus_suggestions_ = false; + // Restore caret visibility if focus is explicitly requested. This is // necessary because if we already have invisible focus, the RequestFocus() // call above will short-circuit, preventing us from reaching @@ -1306,7 +1309,7 @@ // Investigate why it's needed and see if we can remove it. model()->ResetDisplayTexts(); // TODO(oshima): Get control key state. - model()->OnSetFocus(false); + model()->OnSetFocus(false, suppress_on_focus_suggestions_); // Don't call controller()->OnSetFocus, this view has already acquired focus. // Restore the selection we saved in OnBlur() if it's still valid.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h index e83f4ea..f844c4a 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -341,6 +341,10 @@ // and gets a tap. So we use this variable to remember focus state before tap. bool select_all_on_gesture_tap_ = false; + // True if we should suppress on-focus suggestions, because we are currently + // processing a focus ovent that we know the user didn't explicitly initiate. + bool suppress_on_focus_suggestions_ = false; + // The time of the first character insert operation that has not yet been // painted. Used to measure omnibox responsiveness with a histogram. base::TimeTicks insert_char_time_;
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc index b32bf5d8..e4b92943b 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -427,10 +427,12 @@ ProfileAttributesEntry* profile_attributes = GetProfileAttributesEntry(profile); - base::string16 heading; + SetHeading(profile_attributes->GetLocalProfileName(), + l10n_util::GetStringUTF16(IDS_SETTINGS_EDIT_PERSON), + base::BindRepeating(&ProfileMenuView::OnEditProfileButtonClicked, + base::Unretained(this))); if (account_info.has_value()) { - heading = profile_attributes->GetLocalProfileName(); SetIdentityInfo(account_info.value().account_image.AsImageSkia(), GetSyncIcon(), base::UTF8ToUTF16(account_info.value().full_name), @@ -438,15 +440,9 @@ } else { SetIdentityInfo( profile_attributes->GetAvatarIcon().AsImageSkia(), GetSyncIcon(), - profile_attributes->GetName(), + /*title=*/base::string16(), l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE)); } - - SetHeading(heading, - ImageForMenu(vector_icons::kEditIcon, kShortcutIconToImageRatio), - l10n_util::GetStringUTF16(IDS_SETTINGS_EDIT_PERSON), - base::BindRepeating(&ProfileMenuView::OnEditProfileButtonClicked, - base::Unretained(this))); } void ProfileMenuView::BuildGuestIdentity() {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc index 7624d78..735aacc 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -250,7 +250,6 @@ } void ProfileMenuViewBase::SetHeading(const base::string16& heading, - const gfx::ImageSkia& clickable_icon, const base::string16& tooltip_text, base::RepeatingClosure action) { constexpr int kInsidePadding = 4; @@ -259,46 +258,29 @@ ui::NativeTheme::kColorId_HighlightedMenuItemBackgroundColor); heading_container_->RemoveAllChildViews(/*delete_children=*/true); - views::BoxLayout* heading_layout = heading_container_->SetLayoutManager( - CreateBoxLayout(views::BoxLayout::Orientation::kHorizontal, - views::BoxLayout::CrossAxisAlignment::kCenter, - gfx::Insets(kInsidePadding))); - if (!heading.empty()) { - heading_container_->SetBackground( - views::CreateSolidBackground(kBackgroundColor)); - } + heading_container_->SetLayoutManager(std::make_unique<views::FillLayout>()); + heading_container_->SetBackground( + views::CreateSolidBackground(kBackgroundColor)); + heading_container_->SetBorder( + views::CreateEmptyBorder(gfx::Insets(kInsidePadding))); - // Add the label even if |heading| is empty. This needs to be done so the icon - // button gets pushed to the right. - views::Label* label = - heading_container_->AddChildView(std::make_unique<views::Label>( - heading, views::style::CONTEXT_LABEL, STYLE_HINT)); - label->SetHandlesTooltips(false); - // Stretch the label. - heading_layout->SetFlexForView(label, 1); - - // Add icon button. - views::Button* button = - heading_container_->AddChildView(CreateCircularImageButton( - this, clickable_icon, tooltip_text, /*show_border=*/false)); - // Don't stretch the button, so it only takes the space it needs. - heading_layout->SetFlexForView(button, 0); - RegisterClickAction(button, std::move(action)); - - // Center the label by adding a left padding. - button->SizeToPreferredSize(); - int left_label_padding = button->GetContentsBounds().width(); - label->SetBorder( - views::CreateEmptyBorder(gfx::Insets(0, left_label_padding, 0, 0))); + views::Link* link = + heading_container_->AddChildView(std::make_unique<views::Link>(heading)); + link->SetEnabledColor(views::style::GetColor( + *this, views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY)); + link->SetTooltipText(tooltip_text); + link->set_listener(this); + RegisterClickAction(link, std::move(action)); } void ProfileMenuViewBase::SetIdentityInfo(const gfx::ImageSkia& image, const gfx::ImageSkia& badge, const base::string16& title, const base::string16& subtitle) { - constexpr int kTopMargin = 16; - constexpr int kBottomMargin = 8; - constexpr int kImageToLabelSpacing = 4; + constexpr int kTopMargin = kMenuEdgeMargin; + constexpr int kBottomMargin = kDefaultVerticalMargin; + constexpr int kHorizontalMargin = kMenuEdgeMargin; + constexpr int kImageBottomMargin = 8; constexpr int kBadgeSize = 16; constexpr int kBadgePadding = 1; @@ -306,7 +288,8 @@ identity_info_container_->SetLayoutManager( CreateBoxLayout(views::BoxLayout::Orientation::kVertical, views::BoxLayout::CrossAxisAlignment::kCenter, - gfx::Insets(kTopMargin, 0, kBottomMargin, 0))); + gfx::Insets(kTopMargin, kHorizontalMargin, kBottomMargin, + kHorizontalMargin))); views::ImageView* image_view = identity_info_container_->AddChildView( std::make_unique<views::ImageView>()); @@ -323,12 +306,12 @@ gfx::ImageSkia badged_image = gfx::ImageSkiaOperations::CreateIconWithBadge(sized_image, sized_badge); image_view->SetImage(badged_image); + image_view->SetBorder(views::CreateEmptyBorder(0, 0, kImageBottomMargin, 0)); - views::View* title_label = - identity_info_container_->AddChildView(std::make_unique<views::Label>( - title, views::style::CONTEXT_DIALOG_TITLE)); - title_label->SetBorder( - views::CreateEmptyBorder(kImageToLabelSpacing, 0, 0, 0)); + if (!title.empty()) { + identity_info_container_->AddChildView(std::make_unique<views::Label>( + title, views::style::CONTEXT_DIALOG_TITLE)); + } if (!subtitle.empty()) { identity_info_container_->AddChildView(std::make_unique<views::Label>(
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h index d61ba709..97a37677 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -121,7 +121,6 @@ // API to build the profile menu. void SetHeading(const base::string16& heading, - const gfx::ImageSkia& clickable_icon, const base::string16& tooltip_text, base::RepeatingClosure action); void SetIdentityInfo(const gfx::ImageSkia& image,
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc index dfc86462..08a863e4 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -47,12 +47,27 @@ ProfileSigninConfirmationDialogViews::ProfileSigninConfirmationDialogViews( Browser* browser, const std::string& username, - std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) + std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate, + bool prompt_for_new_profile) : browser_(browser), username_(username), delegate_(std::move(delegate)), - prompt_for_new_profile_(true) { + prompt_for_new_profile_(prompt_for_new_profile) { DialogDelegate::set_default_button(ui::DIALOG_BUTTON_NONE); + DialogDelegate::set_button_label( + ui::DIALOG_BUTTON_OK, + l10n_util::GetStringUTF16(prompt_for_new_profile_ + ? IDS_ENTERPRISE_SIGNIN_CREATE_NEW_PROFILE + : IDS_ENTERPRISE_SIGNIN_CONTINUE)); + DialogDelegate::set_button_label( + ui::DIALOG_BUTTON_CANCEL, + l10n_util::GetStringUTF16(IDS_ENTERPRISE_SIGNIN_CANCEL)); + + if (prompt_for_new_profile) { + DialogDelegate::SetExtraView(views::MdTextButton::CreateSecondaryUiButton( + this, l10n_util::GetStringUTF16(IDS_ENTERPRISE_SIGNIN_CONTINUE))); + } + chrome::RecordDialogCreation( chrome::DialogIdentifier::PROFILE_SIGNIN_CONFIRMATION); } @@ -60,6 +75,19 @@ ProfileSigninConfirmationDialogViews::~ProfileSigninConfirmationDialogViews() {} // static +void ProfileSigninConfirmationDialogViews::Show( + Browser* browser, + const std::string& username, + std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate, + bool prompt) { + auto dialog = std::make_unique<ProfileSigninConfirmationDialogViews>( + browser, username, std::move(delegate), prompt); + constrained_window::CreateBrowserModalDialogViews( + dialog.release(), browser->window()->GetNativeWindow()) + ->Show(); +} + +// static void ProfileSigninConfirmationDialogViews::ShowDialog( Browser* browser, Profile* profile, @@ -74,25 +102,12 @@ // is fixed. ProfileMenuView::Hide(); - ProfileSigninConfirmationDialogViews* dialog = - new ProfileSigninConfirmationDialogViews(browser, username, - std::move(delegate)); + // Checking whether to show the prompt is sometimes asynchronous. Defer + // constructing the dialog (in ::Show) until that check completes. ui::CheckShouldPromptForNewProfile( profile, - // This callback is guaranteed to be invoked, and once it is, the dialog - // owns itself. - base::Bind(&ProfileSigninConfirmationDialogViews::Show, - base::Unretained(dialog))); -} - -void ProfileSigninConfirmationDialogViews::Show(bool prompt_for_new_profile) { - prompt_for_new_profile_ = prompt_for_new_profile; - if (prompt_for_new_profile) { - DialogDelegate::SetExtraView(views::MdTextButton::CreateSecondaryUiButton( - this, l10n_util::GetStringUTF16(IDS_ENTERPRISE_SIGNIN_CONTINUE))); - } - constrained_window::CreateBrowserModalDialogViews( - this, browser_->window()->GetNativeWindow())->Show(); + base::BindOnce(&ProfileSigninConfirmationDialogViews::Show, + base::Unretained(browser), username, std::move(delegate))); } base::string16 ProfileSigninConfirmationDialogViews::GetWindowTitle() const { @@ -100,19 +115,6 @@ IDS_ENTERPRISE_SIGNIN_TITLE); } -base::string16 ProfileSigninConfirmationDialogViews::GetDialogButtonLabel( - ui::DialogButton button) const { - if (button == ui::DIALOG_BUTTON_OK) { - // If we're giving the option to create a new profile, then OK is - // "Create new profile". Otherwise it is "Continue signin". - return l10n_util::GetStringUTF16( - prompt_for_new_profile_ ? - IDS_ENTERPRISE_SIGNIN_CREATE_NEW_PROFILE : - IDS_ENTERPRISE_SIGNIN_CONTINUE); - } - return l10n_util::GetStringUTF16(IDS_ENTERPRISE_SIGNIN_CANCEL); -} - bool ProfileSigninConfirmationDialogViews::Accept() { if (delegate_) { if (prompt_for_new_profile_)
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h index 9f75356..d6a2343 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h
@@ -31,16 +31,22 @@ const std::string& username, std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate); - private: ProfileSigninConfirmationDialogViews( Browser* browser, const std::string& username, - std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate); + std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate, + bool prompt_for_new_profile); ~ProfileSigninConfirmationDialogViews() override; + private: + static void Show( + Browser* browser, + const std::string& username, + std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate, + bool prompt_for_new_profile); + // views::DialogDelegateView: base::string16 GetWindowTitle() const override; - base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; bool Accept() override; bool Cancel() override; ui::ModalType GetModalType() const override; @@ -58,11 +64,6 @@ // views::ButtonListener: void ButtonPressed(views::Button*, const ui::Event& event) override; - // Shows the dialog and releases ownership of this object. It will - // delete itself when the dialog is closed. If |prompt_for_new_profile| - // is true, the dialog will offer to create a new profile before signin. - void Show(bool prompt_for_new_profile); - // Weak ptr to parent view. Browser* const browser_; @@ -73,7 +74,7 @@ std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate_; // Whether the user should be prompted to create a new profile. - bool prompt_for_new_profile_; + const bool prompt_for_new_profile_; DISALLOW_COPY_AND_ASSIGN(ProfileSigninConfirmationDialogViews); };
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc deleted file mode 100644 index d00f28c..0000000 --- a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc +++ /dev/null
@@ -1,453 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.h" - -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/infobars/infobar_service.h" -#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/tabs/tab_strip.h" -#include "chrome/common/webui_url_constants.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/infobars/core/infobar.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/common/result_codes.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "ui/views/widget/widget.h" - -namespace { - -content::WebContents* GetWebContents(Browser* browser, int tab) { - return browser->tab_strip_model()->GetWebContentsAt(tab); -} - -InfoBarService* GetInfobarService(Browser* browser, int tab) { - return InfoBarService::FromWebContents(GetWebContents(browser, tab)); -} - -base::string16 GetInfobarMessageText(Browser* browser, int tab) { - return static_cast<ConfirmInfoBarDelegate*>( - GetInfobarService(browser, tab)->infobar_at(0)->delegate()) - ->GetMessageText(); -} - -content::DesktopMediaID GetDesktopMediaID(Browser* browser, int tab) { - content::RenderFrameHost* main_frame = - GetWebContents(browser, tab)->GetMainFrame(); - return content::DesktopMediaID( - content::DesktopMediaID::TYPE_WEB_CONTENTS, - content::DesktopMediaID::kNullId, - content::WebContentsMediaCaptureId(main_frame->GetProcess()->GetID(), - main_frame->GetRoutingID())); -} - -views::Widget* GetContentsBorder(Browser* browser) { - return BrowserView::GetBrowserViewForBrowser(browser) - ->contents_border_widget(); -} - -scoped_refptr<MediaStreamCaptureIndicator> GetCaptureIndicator() { - return MediaCaptureDevicesDispatcher::GetInstance() - ->GetMediaStreamCaptureIndicator(); -} - -void ActivateTab(Browser* browser, int tab) { - browser->tab_strip_model()->ActivateTabAt( - tab, {TabStripModel::GestureType::kMouse}); -} - -constexpr int kNoSharedTabIndex = -1; -} // namespace - -class TabSharingUIViewsBrowserTest : public InProcessBrowserTest { - public: - TabSharingUIViewsBrowserTest() {} - - void CreateUiAndStartSharing(Browser* browser, int tab) { - // Explicitly activate the shared tab in testing. - ActivateTab(browser, tab); - - tab_sharing_ui_ = - TabSharingUI::Create(GetDesktopMediaID(browser, tab), - base::UTF8ToUTF16("example-sharing.com")); - tab_sharing_ui_->OnStarted( - base::OnceClosure(), - base::BindRepeating(&TabSharingUIViewsBrowserTest::OnStartSharing, - base::Unretained(this))); - } - - // Verify that tab sharing infobars are displayed on all tabs, and content - // border and tab capture indicator are only visible on the shared tab. Pass - // |kNoSharedTabIndex| for |shared_tab_index| to indicate the shared tab is - // not in |browser|. - void VerifyUi(Browser* browser, - int shared_tab_index, - size_t infobar_count = 1, - bool has_border = true) { - views::Widget* contents_border = GetContentsBorder(browser); - EXPECT_EQ(has_border, contents_border != nullptr); - auto capture_indicator = GetCaptureIndicator(); - for (int i = 0; i < browser->tab_strip_model()->count(); ++i) { - // All tabs have |infobar_count| tab sharing infobars. - InfoBarService* infobar_service = GetInfobarService(browser, i); - EXPECT_EQ(infobar_count, infobar_service->infobar_count()); - for (size_t j = 0; j < infobar_count; ++j) { - EXPECT_EQ(infobars::InfoBarDelegate::TAB_SHARING_INFOBAR_DELEGATE, - infobar_service->infobar_at(j)->delegate()->GetIdentifier()); - } - - // Content border is only visible on the shared tab. - if (has_border) { - ActivateTab(browser, i); - EXPECT_EQ(i == shared_tab_index, contents_border->IsVisible()); - } - - // Tab capture indicator is only displayed on the shared tab. - EXPECT_EQ(i == shared_tab_index, - capture_indicator->IsBeingMirrored(GetWebContents(browser, i))); - } - } - - void AddTabs(Browser* browser, int tab_count = 1) { - for (int i = 0; i < tab_count; ++i) { - AddTabAtIndexToBrowser(browser, 0, GURL(chrome::kChromeUINewTabURL), - ui::PAGE_TRANSITION_LINK, true); - } - } - - TabSharingUIViews* tab_sharing_ui_views() { - return static_cast<TabSharingUIViews*>(tab_sharing_ui_.get()); - } - - private: - void OnStartSharing(const content::DesktopMediaID& media_id) { - tab_sharing_ui_->OnStarted( - base::OnceClosure(), - base::BindRepeating(&TabSharingUIViewsBrowserTest::OnStartSharing, - base::Unretained(this))); - } - - std::unique_ptr<TabSharingUI> tab_sharing_ui_; -}; - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, StartSharing) { - AddTabs(browser(), 2); - - // Test that before sharing there are no infobars, content border or tab - // capture indicator. - VerifyUi(browser(), kNoSharedTabIndex, 0 /*infobar_count*/, - false /*has_border*/); - - // Create UI and start sharing the tab at index 1. - CreateUiAndStartSharing(browser(), 1); - - // Test that infobars were created, and contents border and tab capture - // indicator are displayed on the shared tab. - VerifyUi(browser(), 1); -} - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, SwitchSharedTab) { - AddTabs(browser(), 2); - CreateUiAndStartSharing(browser(), 1); - - // Share a different tab. - ActivateTab(browser(), 2); - tab_sharing_ui_views()->StartSharing( - GetInfobarService(browser(), 2)->infobar_at(0)); - - // Test that the UI has been updated. - VerifyUi(browser(), 2); -} - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, StopSharing) { - AddTabs(browser()); - CreateUiAndStartSharing(browser(), 1); - - tab_sharing_ui_views()->StopSharing(); - - // Test that the infobars have been removed, and the contents border and tab - // capture indicator are no longer visible. - VerifyUi(browser(), kNoSharedTabIndex, 0 /*infobar_count*/); -} - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, CloseTab) { - AddTabs(browser(), 2); - CreateUiAndStartSharing(browser(), 1); - - // Close a tab different than the shared one and test that the UI has not - // changed. - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - tab_strip_model->CloseWebContentsAt(2, TabStripModel::CLOSE_NONE); - VerifyUi(browser(), 1); - - // Close the shared tab and verify that sharing is stopped, i.e. the UI is - // removed. - tab_strip_model->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); - VerifyUi(browser(), kNoSharedTabIndex, 0 /*infobar_count*/); -} - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, - CloseTabInIncognitoBrowser) { - AddTabs(browser(), 2); - - // Start sharing a tab in an incognito browser. - Browser* incognito_browser = CreateIncognitoBrowser(); - AddTabs(incognito_browser, 2); - CreateUiAndStartSharing(incognito_browser, 1); - VerifyUi(incognito_browser, 1); - VerifyUi(browser(), kNoSharedTabIndex, 1 /*infobar_count*/, - false /*has_border*/); - - // Close a tab different than the shared one and test that the UI has not - // changed. - TabStripModel* tab_strip_model = incognito_browser->tab_strip_model(); - tab_strip_model->CloseWebContentsAt(2, TabStripModel::CLOSE_NONE); - VerifyUi(incognito_browser, 1); - VerifyUi(browser(), kNoSharedTabIndex, 1, false); - - // Close the shared tab in the incognito browser and test that the UI is - // removed. - incognito_browser->tab_strip_model()->CloseWebContentsAt( - 1, TabStripModel::CLOSE_NONE); - VerifyUi(incognito_browser, kNoSharedTabIndex, 0 /*infobar_count*/); - VerifyUi(browser(), kNoSharedTabIndex, 0, false); -} - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, KillTab) { - AddTabs(browser(), 2); - CreateUiAndStartSharing(browser(), 1); - - // Kill a tab different than the shared one. - content::WebContents* web_contents = GetWebContents(browser(), 0); - content::RenderProcessHost* process = - web_contents->GetMainFrame()->GetProcess(); - content::RenderProcessHostWatcher crash_observer( - process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); - process->Shutdown(content::RESULT_CODE_KILLED); - crash_observer.Wait(); - - // Verify that the sad tab does not have an infobar. - InfoBarService* infobar_service = GetInfobarService(browser(), 0); - EXPECT_EQ(0u, infobar_service->infobar_count()); - - // Stop sharing should not result in a crash. - tab_sharing_ui_views()->StopSharing(); -} - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, KillSharedTab) { - AddTabs(browser(), 2); - CreateUiAndStartSharing(browser(), 1); - - // Kill the shared tab. - content::WebContents* shared_tab_web_contents = GetWebContents(browser(), 1); - content::RenderProcessHost* shared_tab_process = - shared_tab_web_contents->GetMainFrame()->GetProcess(); - content::RenderProcessHostWatcher shared_tab_crash_observer( - shared_tab_process, - content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); - shared_tab_process->Shutdown(content::RESULT_CODE_KILLED); - shared_tab_crash_observer.Wait(); - - // Verify that killing the shared tab stopped sharing. - VerifyUi(browser(), kNoSharedTabIndex, 0); -} - -IN_PROC_BROWSER_TEST_F(TabSharingUIViewsBrowserTest, - InfobarLabelUpdatedOnNavigation) { - AddTabs(browser()); - CreateUiAndStartSharing(browser(), 0); - ASSERT_THAT(base::UTF16ToUTF8(GetInfobarMessageText(browser(), 1)), - ::testing::HasSubstr(chrome::kChromeUINewTabHost)); - - ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); - EXPECT_THAT(base::UTF16ToUTF8(GetInfobarMessageText(browser(), 1)), - ::testing::HasSubstr(chrome::kChromeUIVersionHost)); - - ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); - EXPECT_THAT(base::UTF16ToUTF8(GetInfobarMessageText(browser(), 1)), - ::testing::HasSubstr("about:blank")); -} - -namespace { - -class DragObserver : public content::NotificationObserver { - public: - DragObserver() { - registrar_.Add(this, chrome::NOTIFICATION_TAB_DRAG_LOOP_DONE, - content::NotificationService::AllSources()); - } - - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { - run_loop_.QuitWhenIdle(); - } - void Wait() & { run_loop_.Run(); } - - private: - content::NotificationRegistrar registrar_; - base::RunLoop run_loop_; -}; -} // namespace - -class TabDragTabSharingUIViewsBrowserTest - : public TabSharingUIViewsBrowserTest { - public: - TabDragTabSharingUIViewsBrowserTest() {} - - void DragTab(Browser* browser, int tab) { - TabStrip* tab_strip = - BrowserView::GetBrowserViewForBrowser(browser)->tabstrip(); - DragObserver observer; - size_t browser_count = BrowserList::GetInstance()->size(); - const gfx::Point tab_center = - ui_test_utils::GetCenterInScreenCoordinates(tab_strip->tab_at(tab)); - ASSERT_TRUE(ui_test_utils::SendMouseMoveSync(tab_center) && - ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, - ui_controls::DOWN)); - // Drag the tab enough so that it detaches. - const gfx::Point drag_location = - tab_center + gfx::Vector2d(0, tab_strip->height() * 2); - ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone( - drag_location.x(), drag_location.y(), - base::BindOnce( - &TabDragTabSharingUIViewsBrowserTest::ReleaseInputAfterDrag, - base::Unretained(this), browser_count + 1))); - observer.Wait(); - } - - void ReleaseInputAfterDrag(size_t browser_count) { - if (BrowserList::GetInstance()->size() != browser_count) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce( - &TabDragTabSharingUIViewsBrowserTest::ReleaseInputAfterDrag, - base::Unretained(this), browser_count), - base::TimeDelta::FromMilliseconds(1)); - return; - } - - ASSERT_TRUE( - ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP)); - } -}; - -IN_PROC_BROWSER_TEST_F(TabDragTabSharingUIViewsBrowserTest, DragTab) { - AddTabs(browser()); - CreateUiAndStartSharing(browser(), 1); - - DragTab(browser(), 0); - - BrowserList* browser_list = BrowserList::GetInstance(); - ASSERT_EQ(browser_list->size(), 2u); - ASSERT_EQ(browser_list->get(0), browser()); - VerifyUi(browser(), 0); - VerifyUi(browser_list->get(1), kNoSharedTabIndex, 1 /*infobar_count*/, - false /*has_border*/); -} - -IN_PROC_BROWSER_TEST_F(TabDragTabSharingUIViewsBrowserTest, DragSharedTab) { - AddTabs(browser()); - CreateUiAndStartSharing(browser(), 1); - - DragTab(browser(), 1); - - BrowserList* browser_list = BrowserList::GetInstance(); - ASSERT_EQ(browser_list->size(), 2u); - ASSERT_EQ(browser_list->get(0), browser()); - VerifyUi(browser(), kNoSharedTabIndex); - VerifyUi(browser_list->get(1), 0); -} - -class MultipleTabSharingUIViewsBrowserTest : public InProcessBrowserTest { - public: - MultipleTabSharingUIViewsBrowserTest() {} - - void CreateUIsAndStartSharing(Browser* browser, - int tab_index, - int tab_count) { - for (int i = 0; i < tab_count; ++i) { - int tab = tab_index + i; - ActivateTab(browser, tab); - tab_sharing_ui_views_.push_back( - TabSharingUI::Create(GetDesktopMediaID(browser, tab), - base::UTF8ToUTF16("example-sharing.com"))); - tab_sharing_ui_views_[tab_sharing_ui_views_.size() - 1]->OnStarted( - base::OnceClosure(), content::MediaStreamUI::SourceCallback()); - } - } - - TabSharingUIViews* tab_sharing_ui_views(int i) { - return static_cast<TabSharingUIViews*>(tab_sharing_ui_views_[i].get()); - } - - void AddTabs(Browser* browser, int tab_count) { - for (int i = 0; i < tab_count; ++i) - AddBlankTabAndShow(browser); - } - - private: - std::vector<std::unique_ptr<TabSharingUI>> tab_sharing_ui_views_; -}; - -IN_PROC_BROWSER_TEST_F(MultipleTabSharingUIViewsBrowserTest, VerifyUi) { - AddTabs(browser(), 3); - CreateUIsAndStartSharing(browser(), 1, 3); - - // Check that all tabs have 3 infobars corresponding to the 3 sharing - // sessions. - int tab_count = browser()->tab_strip_model()->count(); - for (int i = 0; i < tab_count; ++i) - EXPECT_EQ(3u, GetInfobarService(browser(), i)->infobar_count()); - - // Check that all shared tabs display a tab capture indicator. - auto capture_indicator = GetCaptureIndicator(); - for (int i = 1; i < tab_count; ++i) - EXPECT_TRUE( - capture_indicator->IsBeingMirrored(GetWebContents(browser(), i))); - - // Check that the border is only displayed on the last shared tab (known - // limitation https://crbug.com/996631). - views::Widget* contents_border = GetContentsBorder(browser()); - for (int i = 0; i < tab_count; ++i) { - ActivateTab(browser(), i); - EXPECT_EQ(i == 3, contents_border->IsVisible()); - } -} - -IN_PROC_BROWSER_TEST_F(MultipleTabSharingUIViewsBrowserTest, StopSharing) { - AddTabs(browser(), 3); - CreateUIsAndStartSharing(browser(), 1, 3); - - // Stop sharing tabs one by one and check that infobars are removed as well. - size_t shared_tab_count = 3; - while (shared_tab_count) { - tab_sharing_ui_views(--shared_tab_count)->StopSharing(); - for (int j = 0; j < browser()->tab_strip_model()->count(); ++j) - EXPECT_EQ(shared_tab_count, - GetInfobarService(browser(), j)->infobar_count()); - } -} - -IN_PROC_BROWSER_TEST_F(MultipleTabSharingUIViewsBrowserTest, CloseTabs) { - AddTabs(browser(), 3); - CreateUIsAndStartSharing(browser(), 1, 3); - - // Close shared tabs one by one and check that infobars are removed as well. - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - while (tab_strip_model->count() > 1) { - tab_strip_model->CloseWebContentsAt(1, TabStripModel::CLOSE_NONE); - for (int i = 0; i < tab_strip_model->count(); ++i) - EXPECT_EQ(tab_strip_model->count() - 1u, - GetInfobarService(browser(), i)->infobar_count()); - } -}
diff --git a/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc b/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc index 23a10695..bb780d6 100644 --- a/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc +++ b/chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.cc
@@ -28,10 +28,8 @@ // Fixed height of the illustration shown in the top half of the sheet. constexpr int kIllustrationHeight = 148; -// Foreground/background color, and the height of the progress bar style -// activity indicator shown at the top of some sheets. -constexpr SkColor kActivityIndicateFgColor = SkColorSetRGB(0xf2, 0x99, 0x00); -constexpr SkColor kActivityIndicateBkColor = SkColorSetRGB(0xf6, 0xe6, 0xc8); +// Height of the progress bar style activity indicator shown at the top of some +// sheets. constexpr int kActivityIndicatorHeight = 4; using ImageColorScheme = AuthenticatorRequestSheetModel::ImageColorScheme; @@ -100,8 +98,7 @@ auto activity_indicator = std::make_unique<views::ProgressBar>( kActivityIndicatorHeight, false /* allow_round_corner */); activity_indicator->SetValue(-1 /* inifinite animation */); - activity_indicator->SetForegroundColor(kActivityIndicateFgColor); - activity_indicator->SetBackgroundColor(kActivityIndicateBkColor); + activity_indicator->SetBackgroundColor(SK_ColorTRANSPARENT); activity_indicator->SetPreferredSize( gfx::Size(illustration_width, kActivityIndicatorHeight)); activity_indicator->SizeToPreferredSize();
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc index 1c6ecadb..485ac505 100644 --- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc +++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
@@ -55,16 +55,6 @@ // and the web UI. const char kUpdateAudioNodes[] = "device_emulator.audioSettings.updateAudioNodes"; -const char kAddBluetoothDeviceJSCallback[] = - "device_emulator.bluetoothSettings.addBluetoothDevice"; -const char kDevicePairedFromTrayJSCallback[] = - "device_emulator.bluetoothSettings.devicePairedFromTray"; -const char kDeviceRemovedFromMainAdapterJSCallback[] = - "device_emulator.bluetoothSettings.deviceRemovedFromMainAdapter"; -const char kPairFailedJSCallback[] = - "device_emulator.bluetoothSettings.pairFailed"; -const char kUpdateBluetoothInfoJSCallback[] = - "device_emulator.bluetoothSettings.updateBluetoothInfo"; const char kUpdatePowerPropertiesJSCallback[] = "device_emulator.batterySettings.updatePowerProperties"; const char kTouchpadExistsCallback[] = @@ -116,24 +106,22 @@ owner_->GetDeviceInfo(object_path); // Request to add the device to the view's list of devices. - owner_->web_ui()->CallJavascriptFunctionUnsafe(kAddBluetoothDeviceJSCallback, - *device); + owner_->FireWebUIListener("bluetooth-device-added", *device); } void DeviceEmulatorMessageHandler::BluetoothObserver::DevicePropertyChanged( const dbus::ObjectPath& object_path, const std::string& property_name) { if (property_name == kPairedPropertyName) { - owner_->web_ui()->CallJavascriptFunctionUnsafe( - kDevicePairedFromTrayJSCallback, base::Value(object_path.value())); + owner_->FireWebUIListener("device-paired-from-tray", + base::Value(object_path.value())); } } void DeviceEmulatorMessageHandler::BluetoothObserver::DeviceRemoved( const dbus::ObjectPath& object_path) { - owner_->web_ui()->CallJavascriptFunctionUnsafe( - kDeviceRemovedFromMainAdapterJSCallback, - base::Value(object_path.value())); + owner_->FireWebUIListener("device-removed-from-main-adapter", + base::Value(object_path.value())); } class DeviceEmulatorMessageHandler::CrasAudioObserver @@ -240,44 +228,49 @@ void DeviceEmulatorMessageHandler::HandleRequestBluetoothInfo( const base::ListValue* args) { + AllowJavascript(); // Get a list containing paths of the devices which are connected to // the main adapter. std::vector<dbus::ObjectPath> paths = fake_bluetooth_device_client_->GetDevicesForAdapter( dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); - base::ListValue devices; + auto devices = std::make_unique<base::ListValue>(); // Get each device's properties. for (const dbus::ObjectPath& path : paths) { std::unique_ptr<base::DictionaryValue> device = GetDeviceInfo(path); - devices.Append(std::move(device)); + devices->Append(std::move(device)); } std::unique_ptr<base::ListValue> predefined_devices = fake_bluetooth_device_client_->GetBluetoothDevicesAsDictionaries(); - base::ListValue pairing_method_options; - pairing_method_options.AppendString( + auto pairing_method_options = std::make_unique<base::ListValue>(); + pairing_method_options->AppendString( bluez::FakeBluetoothDeviceClient::kPairingMethodNone); - pairing_method_options.AppendString( + pairing_method_options->AppendString( bluez::FakeBluetoothDeviceClient::kPairingMethodPinCode); - pairing_method_options.AppendString( + pairing_method_options->AppendString( bluez::FakeBluetoothDeviceClient::kPairingMethodPassKey); - base::ListValue pairing_action_options; - pairing_action_options.AppendString( + auto pairing_action_options = std::make_unique<base::ListValue>(); + pairing_action_options->AppendString( bluez::FakeBluetoothDeviceClient::kPairingActionDisplay); - pairing_action_options.AppendString( + pairing_action_options->AppendString( bluez::FakeBluetoothDeviceClient::kPairingActionRequest); - pairing_action_options.AppendString( + pairing_action_options->AppendString( bluez::FakeBluetoothDeviceClient::kPairingActionConfirmation); - pairing_action_options.AppendString( + pairing_action_options->AppendString( bluez::FakeBluetoothDeviceClient::kPairingActionFail); + auto info = std::make_unique<base::DictionaryValue>(); + info->Set("predefined_devices", std::move(predefined_devices)); + info->Set("devices", std::move(devices)); + info->Set("pairing_method_options", std::move(pairing_method_options)); + info->Set("pairing_action_options", std::move(pairing_action_options)); + // Send the list of devices to the view. - web_ui()->CallJavascriptFunctionUnsafe( - kUpdateBluetoothInfoJSCallback, *predefined_devices, devices, - pairing_method_options, pairing_action_options); + FireWebUIListener("bluetooth-info-updated", *info); } void DeviceEmulatorMessageHandler::HandleRequestBluetoothPair( @@ -291,8 +284,7 @@ // by its device ID, which, in this case is the same as its address. ConnectToBluetoothDevice(props->address.value()); if (!props->paired.value()) { - web_ui()->CallJavascriptFunctionUnsafe(kPairFailedJSCallback, - base::Value(path)); + FireWebUIListener("pair-failed", base::Value(path)); } }
diff --git a/chrome/chrome_cleaner/mojom/typemaps/pup_typemap_unittest.cc b/chrome/chrome_cleaner/mojom/typemaps/pup_typemap_unittest.cc index b630ca965..a850d49 100644 --- a/chrome/chrome_cleaner/mojom/typemaps/pup_typemap_unittest.cc +++ b/chrome/chrome_cleaner/mojom/typemaps/pup_typemap_unittest.cc
@@ -4,16 +4,19 @@ #include "base/bind.h" #include "base/synchronization/waitable_event.h" -#include "chrome/chrome_cleaner/mojom/pup.mojom.h" -#include "chrome/chrome_cleaner/mojom/test_pup_typemap.mojom.h" #include "chrome/chrome_cleaner/ipc/ipc_test_util.h" #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" +#include "chrome/chrome_cleaner/mojom/pup.mojom.h" +#include "chrome/chrome_cleaner/mojom/test_pup_typemap.mojom.h" #include "chrome/chrome_cleaner/pup_data/pup_data.h" #include "chrome/chrome_cleaner/test/test_extensions.h" #include "chrome/chrome_cleaner/test/test_util.h" #include "components/chrome_cleaner/test/test_name_helper.h" #include "mojo/core/embedder/embedder.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" @@ -32,15 +35,16 @@ class TestPUPTypemapImpl : public mojom::TestPUPTypemap { public: - explicit TestPUPTypemapImpl(mojom::TestPUPTypemapRequest request) - : binding_(this, std::move(request)) {} + explicit TestPUPTypemapImpl( + mojo::PendingReceiver<mojom::TestPUPTypemap> receiver) + : receiver_(this, std::move(receiver)) {} void EchoPUP(const PUPData::PUP& pup, EchoPUPCallback callback) override { std::move(callback).Run(pup); } private: - mojo::Binding<mojom::TestPUPTypemap> binding_; + mojo::Receiver<mojom::TestPUPTypemap> receiver_; }; class EchoingParentProcess : public chrome_cleaner::ParentProcess { @@ -50,8 +54,8 @@ protected: void CreateImpl(mojo::ScopedMessagePipeHandle mojo_pipe) override { - mojom::TestPUPTypemapRequest request(std::move(mojo_pipe)); - impl_ = std::make_unique<TestPUPTypemapImpl>(std::move(request)); + mojo::PendingReceiver<mojom::TestPUPTypemap> receiver(std::move(mojo_pipe)); + impl_ = std::make_unique<TestPUPTypemapImpl>(std::move(receiver)); } void DestroyImpl() override { impl_.reset(); } @@ -66,16 +70,17 @@ public: explicit EchoingChildProcess(scoped_refptr<MojoTaskRunner> mojo_task_runner) : ChildProcess(mojo_task_runner), - ptr_(std::make_unique<mojom::TestPUPTypemapPtr>()) {} + remote_(new mojo::Remote<mojom::TestPUPTypemap>(), + base::OnTaskRunnerDeleter(mojo_task_runner)) {} void BindToPipe(mojo::ScopedMessagePipeHandle mojo_pipe, WaitableEvent* event) { - ptr_->Bind( - chrome_cleaner::mojom::TestPUPTypemapPtrInfo(std::move(mojo_pipe), 0)); + remote_->Bind(mojo::PendingRemote<chrome_cleaner::mojom::TestPUPTypemap>( + std::move(mojo_pipe), 0)); // If the connection is lost while this object is processing a request or // waiting for a response, then it will terminate with a special result code // that will be expected by the parent process. - ptr_->set_connection_error_handler(base::BindOnce( + remote_->set_disconnect_handler(base::BindOnce( [](bool* processing_request) { if (*processing_request) exit(kConnectionBrokenResultCode); @@ -90,17 +95,11 @@ } private: - ~EchoingChildProcess() override { - mojo_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - [](std::unique_ptr<mojom::TestPUPTypemapPtr> ptr) { ptr.reset(); }, - base::Passed(&ptr_))); - } + ~EchoingChildProcess() override = default; void RunEchoPUP(const PUPData::PUP& input, mojom::TestPUPTypemap::EchoPUPCallback callback) { - (*ptr_)->EchoPUP(input, std::move(callback)); + (*remote_)->EchoPUP(input, std::move(callback)); } template <typename EchoedValue> @@ -131,7 +130,10 @@ return output; } - std::unique_ptr<mojom::TestPUPTypemapPtr> ptr_; + std::unique_ptr<mojo::Remote<mojom::TestPUPTypemap>, + base::OnTaskRunnerDeleter> + remote_; + // All requests are synchronous and happen on the same sequence, so no // synchronization is needed. bool processing_request_ = false;
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 4d3cfef..1ef8d05 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -170,9 +170,9 @@ #include "extensions/renderer/dispatcher.h" #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h" #include "extensions/renderer/renderer_extension_registry.h" -#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/public/web/web_view.h" +#include "ui/native_theme/native_theme.h" #endif #if BUILDFLAG(ENABLE_PLUGINS) @@ -881,12 +881,8 @@ if (GURL(frame->GetDocument().Url()).host_piece() == extension_misc::kPdfExtensionId) { if (!base::FeatureList::IsEnabled(features::kWebUIDarkMode)) { - auto* render_view = render_frame->GetRenderView(); - auto* web_view = render_view ? render_view->GetWebView() : nullptr; - if (web_view) { - web_view->GetSettings()->SetPreferredColorScheme( - blink::PreferredColorScheme::kLight); - } + ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( + ui::NativeTheme::PreferredColorScheme::kLight); } } else if (info.name == ASCIIToUTF16(ChromeContentClient::kPDFExtensionPluginName)) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 382ed88..286577d 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -5642,7 +5642,6 @@ "../browser/ui/views/passwords/password_bubble_interactive_uitest.cc", "../browser/ui/views/sad_tab_view_interactive_uitest.cc", "../browser/ui/views/status_icons/status_tray_state_changer_interactive_uitest_win.cc", - "../browser/ui/views/tab_sharing/tab_sharing_ui_views_browsertest.cc", "../browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc", "../browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h", "../browser/ui/views/tabs/tab_hover_card_bubble_view_interactive_uitest.cc",
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc index cc78d77..24cca152 100644 --- a/chrome/test/base/ui_test_utils.cc +++ b/chrome/test/base/ui_test_utils.cc
@@ -481,7 +481,8 @@ base::TimeTicks match_selection_timestamp) { LocationBar* location_bar = browser->window()->GetLocationBar(); OmniboxView* omnibox = location_bar->GetOmniboxView(); - omnibox->model()->OnSetFocus(false); + omnibox->model()->OnSetFocus(/*control_down=*/false, + /*suppress_on_focus_suggestions=*/false); omnibox->SetUserText(base::ASCIIToUTF16(input)); location_bar->AcceptInput(match_selection_timestamp);
diff --git a/chrome/test/data/extensions/api_test/printing_metrics/update_manifest.xml b/chrome/test/data/extensions/api_test/printing_metrics/update_manifest.xml index f06a638..8ab0e89 100644 --- a/chrome/test/data/extensions/api_test/printing_metrics/update_manifest.xml +++ b/chrome/test/data/extensions/api_test/printing_metrics/update_manifest.xml
@@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <!-- - This update manifest points to the enterprise_device_attributes.crx file. + This update manifest points to the printing_metrics.crx file. "mock.http" is a placeholder that gets substituted with the test server address in runtime. -->
diff --git a/chrome/test/data/local_ntp/realbox_browsertest.js b/chrome/test/data/local_ntp/realbox_browsertest.js index bdb6586..5af7e09d 100644 --- a/chrome/test/data/local_ntp/realbox_browsertest.js +++ b/chrome/test/data/local_ntp/realbox_browsertest.js
@@ -518,17 +518,10 @@ }); test.realbox.realboxEl.dispatchEvent(keyEvent); assertFalse(keyEvent.defaultPrevented); + assertEquals(0, test.realbox.deletedLines.length); const matchesEl = $(test.realbox.IDS.REALBOX_MATCHES); assertFalse(matchesEl.classList.contains(test.realbox.CLASSES.REMOVABLE)); - - // The below 2 statements shouldn't really happen in updated code but isn't - // terrible idea to keep testing for now. This is because SupportsDeletion() - // is now propagated to the client, so we shouldn't allow users (via the UI) - // to attempt to delete non-deletable things. - chrome.embeddedSearch.searchBox.ondeleteautocompletematch( - {success: false, matches: []}); - assertEquals(1, $(test.realbox.IDS.REALBOX_MATCHES).children.length); }; test.realbox.testSupportedDeletion = function() { @@ -566,6 +559,14 @@ test.realbox.realboxEl.dispatchEvent(shiftDelete); assertTrue(shiftDelete.defaultPrevented); + // Pretend like the focused match gets removed from DOM when deleted. + matchesEl.children[1].dispatchEvent(new Event('focusout', {bubbles: true})); + + // stopAutocomplete() should not be called if the focused match gets removed + // from the DOM (and focus gets dropped). There's explicit code in the + // focusout handler to deal with this case. + assertEquals(0, test.realbox.stops.length); + assertEquals(1, test.realbox.deletedLines.length); assertEquals(1, test.realbox.deletedLines[0]);
diff --git a/chrome/test/data/prefers-color-scheme.html b/chrome/test/data/prefers-color-scheme.html deleted file mode 100644 index f8913c10..0000000 --- a/chrome/test/data/prefers-color-scheme.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!DOCTYPE html> -<title>FAIL</title> -<script> - if (window.matchMedia("(prefers-color-scheme: light)").matches) { - document.title = "light"; - } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { - document.title = "dark"; - } else if (window.matchMedia("(prefers-color-scheme: no-preference)").matches) { - document.title = "no-preference"; - } -</script>
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index bf06a5b92..f50421d 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -382,6 +382,8 @@ "exo/cast_wm_helper.h", "exo/wayland_server_controller.cc", "exo/wayland_server_controller.h", + "webview/web_content_controller.cc", + "webview/web_content_controller.h", "webview/webview_controller.cc", "webview/webview_controller.h", "webview/webview_grpc_service.cc",
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc new file mode 100644 index 0000000..43fbdaf --- /dev/null +++ b/chromecast/browser/webview/web_content_controller.cc
@@ -0,0 +1,365 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/browser/webview/web_content_controller.h" + +#include "base/json/json_writer.h" +#include "base/strings/utf_string_conversions.h" +#include "chromecast/base/version.h" +#include "chromecast/browser/webview/proto/webview.pb.h" +#include "chromecast/browser/webview/webview_layout_manager.h" +#include "chromecast/browser/webview/webview_navigation_throttle.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browsing_data_remover.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/web_preferences.h" +#include "ui/aura/window.h" +#include "ui/aura/window_delegate.h" +#include "ui/events/event.h" + +namespace chromecast { + +WebContentController::WebContentController(Client* client) : client_(client) {} + +WebContentController::~WebContentController() { + if (surface_) { + surface_->RemoveSurfaceObserver(this); + surface_->SetEmbeddedSurfaceId(base::RepeatingCallback<viz::SurfaceId()>()); + } +} + +void WebContentController::ProcessRequest( + const webview::WebviewRequest& request) { + content::WebContents* contents = GetWebContents(); + switch (request.type_case()) { + case webview::WebviewRequest::kInput: + ProcessInputEvent(request.input()); + break; + + case webview::WebviewRequest::kEvaluateJavascript: + if (request.has_evaluate_javascript()) { + HandleEvaluateJavascript(request.id(), request.evaluate_javascript()); + } else { + client_->OnError("evaluate_javascript() not supplied"); + } + break; + + case webview::WebviewRequest::kAddJavascriptChannels: + if (request.has_add_javascript_channels()) { + HandleAddJavascriptChannels(request.add_javascript_channels()); + } else { + client_->OnError("add_javascript_channels() not supplied"); + } + break; + + case webview::WebviewRequest::kRemoveJavascriptChannels: + if (request.has_remove_javascript_channels()) { + HandleRemoveJavascriptChannels(request.remove_javascript_channels()); + } else { + client_->OnError("remove_javascript_channels() not supplied"); + } + break; + + case webview::WebviewRequest::kGetCurrentUrl: + HandleGetCurrentUrl(request.id()); + break; + + case webview::WebviewRequest::kCanGoBack: + HandleCanGoBack(request.id()); + break; + + case webview::WebviewRequest::kCanGoForward: + HandleCanGoForward(request.id()); + break; + + case webview::WebviewRequest::kGoBack: + contents->GetController().GoBack(); + break; + + case webview::WebviewRequest::kGoForward: + contents->GetController().GoForward(); + break; + + case webview::WebviewRequest::kReload: + // TODO(dnicoara): Are the default parameters correct? + contents->GetController().Reload(content::ReloadType::NORMAL, + /*check_for_repost=*/true); + break; + + case webview::WebviewRequest::kClearCache: + HandleClearCache(); + break; + + case webview::WebviewRequest::kUpdateSettings: + if (request.has_update_settings()) { + HandleUpdateSettings(request.update_settings()); + } else { + client_->OnError("update_settings() not supplied"); + } + break; + + case webview::WebviewRequest::kGetTitle: + HandleGetTitle(request.id()); + break; + + case webview::WebviewRequest::kSetAutoMediaPlaybackPolicy: + if (request.has_set_auto_media_playback_policy()) { + HandleSetAutoMediaPlaybackPolicy( + request.set_auto_media_playback_policy()); + } else { + client_->OnError("set_auto_media_playback_policy() not supplied"); + } + break; + + default: + client_->OnError("Unknown request code"); + break; + } +} + +void WebContentController::AttachTo(aura::Window* window, int window_id) { + content::WebContents* contents = GetWebContents(); + auto* contents_window = contents->GetNativeView(); + window->SetLayoutManager(new WebviewLayoutManager(window, contents_window)); + contents_window->set_id(window_id); + contents_window->SetBounds(gfx::Rect(window->bounds().size())); + // The aura window is hidden to avoid being shown via the usual layer method, + // instead it is shows via a SurfaceDrawQuad by exo. + contents_window->Hide(); + window->AddChild(contents_window); + + exo::Surface* surface = exo::Surface::AsSurface(window); + CHECK(surface) << "Attaching Webview to non-EXO surface window"; + CHECK(!surface_) << "Attaching already attached WebView"; + + surface_ = surface; + surface_->AddSurfaceObserver(this); + + // Unretained is safe because we unset this in the destructor. + surface_->SetEmbeddedSurfaceId( + base::Bind(&WebContentController::GetSurfaceId, base::Unretained(this))); +} + +void WebContentController::ProcessInputEvent(const webview::InputEvent& ev) { + content::WebContents* contents = GetWebContents(); + // Ensure this web contents has focus before sending it input. + if (!contents->GetNativeView()->HasFocus()) + contents->GetNativeView()->Focus(); + + ui::EventHandler* handler = + contents->GetRenderWidgetHostView()->GetNativeView()->delegate(); + ui::EventType type = static_cast<ui::EventType>(ev.event_type()); + switch (type) { + case ui::ET_TOUCH_RELEASED: + case ui::ET_TOUCH_PRESSED: + case ui::ET_TOUCH_MOVED: + case ui::ET_TOUCH_CANCELLED: + if (ev.has_touch()) { + auto& touch = ev.touch(); + ui::TouchEvent evt( + type, gfx::PointF(touch.x(), touch.y()), + gfx::PointF(touch.root_x(), touch.root_y()), + base::TimeTicks() + + base::TimeDelta::FromMicroseconds(ev.timestamp()), + ui::PointerDetails( + static_cast<ui::EventPointerType>(touch.pointer_type()), + static_cast<ui::PointerId>(touch.pointer_id()), + touch.radius_x(), touch.radius_y(), touch.force(), + touch.twist(), touch.tilt_x(), touch.tilt_y(), + touch.tangential_pressure()), + ev.flags()); + + ui::TouchEvent root_relative_event(evt); + root_relative_event.set_location_f(evt.root_location_f()); + + // GestureRecognizerImpl makes several APIs private so cast it to the + // interface. + ui::GestureRecognizer* recognizer = &gesture_recognizer_; + + // Run touches through the gesture recognition pipeline, web content + // typically wants to process gesture events, not touch events. + if (!recognizer->ProcessTouchEventPreDispatch( + &root_relative_event, contents->GetNativeView())) { + return; + } + + handler->OnTouchEvent(&evt); + + // Normally this would be done when the renderer acknowledges the touch + // event and using flags from the renderer, inside + // RenderWidgetHostViewAura, but we don't have those so... fake it. + auto list = + recognizer->AckTouchEvent(evt.unique_event_id(), ui::ER_UNHANDLED, + false, contents->GetNativeView()); + for (auto& e : list) { + // Forward all gestures. + handler->OnGestureEvent(e.get()); + } + } else { + client_->OnError("touch() not supplied for touch event"); + } + break; + case ui::ET_MOUSE_PRESSED: + case ui::ET_MOUSE_DRAGGED: + case ui::ET_MOUSE_RELEASED: + case ui::ET_MOUSE_MOVED: + case ui::ET_MOUSE_ENTERED: + case ui::ET_MOUSE_EXITED: + case ui::ET_MOUSEWHEEL: + case ui::ET_MOUSE_CAPTURE_CHANGED: + if (ev.has_mouse()) { + auto& mouse = ev.mouse(); + ui::MouseEvent evt( + type, gfx::PointF(mouse.x(), mouse.y()), + gfx::PointF(mouse.root_x(), mouse.root_y()), + base::TimeTicks() + + base::TimeDelta::FromMicroseconds(ev.timestamp()), + ev.flags(), mouse.changed_button_flags()); + handler->OnMouseEvent(&evt); + } else { + client_->OnError("mouse() not supplied for mouse event"); + } + break; + default: + break; + } +} + +void WebContentController::JavascriptCallback(int64_t id, base::Value result) { + std::string json; + base::JSONWriter::Write(result, &json); + std::unique_ptr<webview::WebviewResponse> response = + std::make_unique<webview::WebviewResponse>(); + response->set_id(id); + response->mutable_evaluate_javascript()->set_json(json); + client_->EnqueueSend(std::move(response)); +} + +void WebContentController::HandleEvaluateJavascript( + int64_t id, + const webview::EvaluateJavascriptRequest& request) { + GetWebContents()->GetMainFrame()->ExecuteJavaScript( + base::UTF8ToUTF16(request.javascript_blob()), + base::BindOnce(&WebContentController::JavascriptCallback, + weak_ptr_factory_.GetWeakPtr(), id)); +} + +void WebContentController::HandleAddJavascriptChannels( + const webview::AddJavascriptChannelsRequest& request) { + // TODO(dnicoara): Handle this. +} + +void WebContentController::HandleRemoveJavascriptChannels( + const webview::RemoveJavascriptChannelsRequest& request) { + // TODO(dnicoara): Handle this. +} + +void WebContentController::HandleGetCurrentUrl(int64_t id) { + std::unique_ptr<webview::WebviewResponse> response = + std::make_unique<webview::WebviewResponse>(); + + response->set_id(id); + response->mutable_get_current_url()->set_url( + GetWebContents()->GetURL().spec()); + client_->EnqueueSend(std::move(response)); +} + +void WebContentController::HandleCanGoBack(int64_t id) { + std::unique_ptr<webview::WebviewResponse> response = + std::make_unique<webview::WebviewResponse>(); + + response->set_id(id); + response->mutable_can_go_back()->set_can_go_back( + GetWebContents()->GetController().CanGoBack()); + client_->EnqueueSend(std::move(response)); +} + +void WebContentController::HandleCanGoForward(int64_t id) { + std::unique_ptr<webview::WebviewResponse> response = + std::make_unique<webview::WebviewResponse>(); + + response->set_id(id); + response->mutable_can_go_forward()->set_can_go_forward( + GetWebContents()->GetController().CanGoForward()); + client_->EnqueueSend(std::move(response)); +} + +void WebContentController::HandleClearCache() { + // TODO(dnicoara): See if there is a generic way to inform the renderer to + // clear cache. + // Android has a specific renderer message for this: + // https://cs.chromium.org/chromium/src/android_webview/common/render_view_messages.h?rcl=65107121555167a3db39de5633c3297f7e861315&l=44 + + // Remove disk cache. + content::BrowsingDataRemover* remover = + content::BrowserContext::GetBrowsingDataRemover( + GetWebContents()->GetBrowserContext()); + remover->Remove(base::Time(), base::Time::Max(), + content::BrowsingDataRemover::DATA_TYPE_CACHE, + content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | + content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); +} + +void WebContentController::HandleGetTitle(int64_t id) { + std::unique_ptr<webview::WebviewResponse> response = + std::make_unique<webview::WebviewResponse>(); + + response->set_id(id); + response->mutable_get_title()->set_title( + base::UTF16ToUTF8(GetWebContents()->GetTitle())); + client_->EnqueueSend(std::move(response)); +} + +void WebContentController::HandleUpdateSettings( + const webview::UpdateSettingsRequest& request) { + content::WebContents* contents = GetWebContents(); + content::WebPreferences prefs = + contents->GetRenderViewHost()->GetWebkitPreferences(); + prefs.javascript_enabled = request.javascript_enabled(); + contents->GetRenderViewHost()->UpdateWebkitPreferences(prefs); + + has_navigation_delegate_ = request.has_navigation_delegate(); + + // Given that cast_shell enables devtools unconditionally there isn't + // anything that needs to be done for |request.debugging_enabled()|. Though, + // as a note, remote debugging is always on. + + if (request.has_user_agent() && + request.user_agent().type_case() == webview::UserAgent::kValue) { + contents->SetUserAgentOverride(request.user_agent().value(), true); + } +} + +void WebContentController::HandleSetAutoMediaPlaybackPolicy( + const webview::SetAutoMediaPlaybackPolicyRequest& request) { + content::WebContents* contents = GetWebContents(); + content::WebPreferences prefs = + contents->GetRenderViewHost()->GetWebkitPreferences(); + prefs.autoplay_policy = request.require_user_gesture() + ? content::AutoplayPolicy::kUserGestureRequired + : content::AutoplayPolicy::kNoUserGestureRequired; + contents->GetRenderViewHost()->UpdateWebkitPreferences(prefs); +} + +viz::SurfaceId WebContentController::GetSurfaceId() { + auto* rwhv = GetWebContents()->GetRenderWidgetHostView(); + if (!rwhv) + return viz::SurfaceId(); + auto frame_sink_id = rwhv->GetRenderWidgetHost()->GetFrameSinkId(); + auto local_surface_id = + rwhv->GetNativeView()->GetLocalSurfaceIdAllocation().local_surface_id(); + return viz::SurfaceId(frame_sink_id, local_surface_id); +} + +void WebContentController::OnSurfaceDestroying(exo::Surface* surface) { + DCHECK_EQ(surface, surface_); + surface->RemoveSurfaceObserver(this); + surface_ = nullptr; +} + +} // namespace chromecast
diff --git a/chromecast/browser/webview/web_content_controller.h b/chromecast/browser/webview/web_content_controller.h new file mode 100644 index 0000000..fcd0678 --- /dev/null +++ b/chromecast/browser/webview/web_content_controller.h
@@ -0,0 +1,85 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_BROWSER_WEBVIEW_WEB_CONTENT_CONTROLLER_H_ +#define CHROMECAST_BROWSER_WEBVIEW_WEB_CONTENT_CONTROLLER_H_ + +#include <memory> +#include <string> + +#include "chromecast/browser/webview/proto/webview.pb.h" +#include "components/exo/surface.h" +#include "components/exo/surface_observer.h" +#include "ui/events/gestures/gesture_recognizer_impl.h" + +namespace aura { +class Window; +} // namespace aura + +namespace content { +class WebContents; +} // namespace content + +namespace chromecast { + +// Processes proto commands to control WebContents +class WebContentController : public exo::SurfaceObserver { + public: + class Client { + public: + virtual ~Client() {} + virtual void EnqueueSend( + std::unique_ptr<webview::WebviewResponse> response) = 0; + virtual void OnError(const std::string& error_message) = 0; + }; + WebContentController(Client* client); + ~WebContentController() override; + + virtual void Destroy() = 0; + + virtual void ProcessRequest(const webview::WebviewRequest& request); + + // Attach this web contents to an aura window as a child. + void AttachTo(aura::Window* window, int window_id); + + protected: + virtual content::WebContents* GetWebContents() = 0; + Client* client_; // Not owned. + bool has_navigation_delegate_ = false; + + private: + void ProcessInputEvent(const webview::InputEvent& ev); + void JavascriptCallback(int64_t id, base::Value result); + void HandleEvaluateJavascript( + int64_t id, + const webview::EvaluateJavascriptRequest& request); + void HandleAddJavascriptChannels( + const webview::AddJavascriptChannelsRequest& request); + void HandleRemoveJavascriptChannels( + const webview::RemoveJavascriptChannelsRequest& request); + void HandleGetCurrentUrl(int64_t id); + void HandleCanGoBack(int64_t id); + void HandleCanGoForward(int64_t id); + void HandleClearCache(); + void HandleGetTitle(int64_t id); + void HandleUpdateSettings(const webview::UpdateSettingsRequest& request); + void HandleSetAutoMediaPlaybackPolicy( + const webview::SetAutoMediaPlaybackPolicyRequest& request); + viz::SurfaceId GetSurfaceId(); + + // exo::SurfaceObserver + void OnSurfaceDestroying(exo::Surface* surface) override; + + ui::GestureRecognizerImpl gesture_recognizer_; + + exo::Surface* surface_ = nullptr; + + base::WeakPtrFactory<WebContentController> weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(WebContentController); +}; + +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_WEBVIEW_WEB_CONTENT_CONTROLLER_H_
diff --git a/chromecast/browser/webview/webview_controller.cc b/chromecast/browser/webview/webview_controller.cc index 5c074fb..1d96ab1b 100644 --- a/chromecast/browser/webview/webview_controller.cc +++ b/chromecast/browser/webview/webview_controller.cc
@@ -19,9 +19,6 @@ #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "content/public/common/web_preferences.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/events/event.h" namespace chromecast { @@ -46,7 +43,7 @@ WebviewController::WebviewController(content::BrowserContext* browser_context, Client* client) - : client_(client) { + : WebContentController(client) { content::WebContents::CreateParams create_params(browser_context, nullptr); contents_ = content::WebContents::Create(create_params); contents_->SetUserData(kWebviewResponseUserDataKey, @@ -70,11 +67,6 @@ WebviewController::~WebviewController() { cast_web_contents_->RemoveObserver(this); - - if (surface_) { - surface_->RemoveSurfaceObserver(this); - surface_->SetEmbeddedSurfaceId(base::RepeatingCallback<viz::SurfaceId()>()); - } } std::unique_ptr<content::NavigationThrottle> @@ -93,10 +85,6 @@ void WebviewController::ProcessRequest(const webview::WebviewRequest& request) { switch (request.type_case()) { - case webview::WebviewRequest::kInput: - ProcessInputEvent(request.input()); - break; - case webview::WebviewRequest::kNavigate: if (request.has_navigate()) { LOG(INFO) << "Navigate webview to " << request.navigate().url(); @@ -115,80 +103,6 @@ } break; - case webview::WebviewRequest::kEvaluateJavascript: - if (request.has_evaluate_javascript()) { - HandleEvaluateJavascript(request.id(), request.evaluate_javascript()); - } else { - client_->OnError("evaluate_javascript() not supplied"); - } - break; - - case webview::WebviewRequest::kAddJavascriptChannels: - if (request.has_add_javascript_channels()) { - HandleAddJavascriptChannels(request.add_javascript_channels()); - } else { - client_->OnError("add_javascript_channels() not supplied"); - } - break; - - case webview::WebviewRequest::kRemoveJavascriptChannels: - if (request.has_remove_javascript_channels()) { - HandleRemoveJavascriptChannels(request.remove_javascript_channels()); - } else { - client_->OnError("remove_javascript_channels() not supplied"); - } - break; - - case webview::WebviewRequest::kGetCurrentUrl: - HandleGetCurrentUrl(request.id()); - break; - - case webview::WebviewRequest::kCanGoBack: - HandleCanGoBack(request.id()); - break; - - case webview::WebviewRequest::kCanGoForward: - HandleCanGoForward(request.id()); - break; - - case webview::WebviewRequest::kGoBack: - contents_->GetController().GoBack(); - break; - - case webview::WebviewRequest::kGoForward: - contents_->GetController().GoForward(); - break; - - case webview::WebviewRequest::kReload: - // TODO(dnicoara): Are the default parameters correct? - contents_->GetController().Reload(content::ReloadType::NORMAL, - /*check_for_repost=*/true); - break; - - case webview::WebviewRequest::kClearCache: - HandleClearCache(); - break; - - case webview::WebviewRequest::kUpdateSettings: - if (request.has_update_settings()) { - HandleUpdateSettings(request.update_settings()); - } else { - client_->OnError("update_settings() not supplied"); - } - break; - - case webview::WebviewRequest::kGetTitle: - HandleGetTitle(request.id()); - break; - - case webview::WebviewRequest::kSetAutoMediaPlaybackPolicy: - if (request.has_set_auto_media_playback_policy()) { - HandleSetAutoMediaPlaybackPolicy( - request.set_auto_media_playback_policy()); - } else { - client_->OnError("set_auto_media_playback_policy() not supplied"); - } - break; case webview::WebviewRequest::kNavigationDecision: if (current_navigation_throttle_) { current_navigation_throttle_->ProcessNavigationDecision( @@ -196,8 +110,9 @@ current_navigation_throttle_ = nullptr; } break; + default: - client_->OnError("Unknown request code"); + WebContentController::ProcessRequest(request); break; } } @@ -218,239 +133,8 @@ cast_web_contents_->ClosePage(); } -viz::SurfaceId WebviewController::GetSurfaceId() { - auto* rwhv = contents_->GetRenderWidgetHostView(); - if (!rwhv) - return viz::SurfaceId(); - auto frame_sink_id = rwhv->GetRenderWidgetHost()->GetFrameSinkId(); - auto local_surface_id = - rwhv->GetNativeView()->GetLocalSurfaceIdAllocation().local_surface_id(); - return viz::SurfaceId(frame_sink_id, local_surface_id); -} - -void WebviewController::AttachTo(aura::Window* window, int window_id) { - auto* contents_window = contents_->GetNativeView(); - window->SetLayoutManager(new WebviewLayoutManager(window, contents_window)); - contents_window->set_id(window_id); - contents_window->SetBounds(gfx::Rect(window->bounds().size())); - // The aura window is hidden to avoid being shown via the usual layer method, - // instead it is shows via a SurfaceDrawQuad by exo. - contents_window->Hide(); - window->AddChild(contents_window); - - exo::Surface* surface = exo::Surface::AsSurface(window); - CHECK(surface) << "Attaching Webview to non-EXO surface window"; - CHECK(!surface_) << "Attaching already attached WebView"; - - surface_ = surface; - surface_->AddSurfaceObserver(this); - - // Unretained is safe because we unset this in the destructor. - surface_->SetEmbeddedSurfaceId( - base::Bind(&WebviewController::GetSurfaceId, base::Unretained(this))); -} - -void WebviewController::OnSurfaceDestroying(exo::Surface* surface) { - DCHECK_EQ(surface, surface_); - surface->RemoveSurfaceObserver(this); - surface_ = nullptr; -} - -void WebviewController::ProcessInputEvent(const webview::InputEvent& ev) { - // Ensure this web contents has focus before sending it input. - if (!contents_->GetNativeView()->HasFocus()) - contents_->GetNativeView()->Focus(); - - ui::EventHandler* handler = - contents_->GetRenderWidgetHostView()->GetNativeView()->delegate(); - ui::EventType type = static_cast<ui::EventType>(ev.event_type()); - switch (type) { - case ui::ET_TOUCH_RELEASED: - case ui::ET_TOUCH_PRESSED: - case ui::ET_TOUCH_MOVED: - case ui::ET_TOUCH_CANCELLED: - if (ev.has_touch()) { - auto& touch = ev.touch(); - ui::TouchEvent evt( - type, gfx::PointF(touch.x(), touch.y()), - gfx::PointF(touch.root_x(), touch.root_y()), - base::TimeTicks() + - base::TimeDelta::FromMicroseconds(ev.timestamp()), - ui::PointerDetails( - static_cast<ui::EventPointerType>(touch.pointer_type()), - static_cast<ui::PointerId>(touch.pointer_id()), - touch.radius_x(), touch.radius_y(), touch.force(), - touch.twist(), touch.tilt_x(), touch.tilt_y(), - touch.tangential_pressure()), - ev.flags()); - - ui::TouchEvent root_relative_event(evt); - root_relative_event.set_location_f(evt.root_location_f()); - - // GestureRecognizerImpl makes several APIs private so cast it to the - // interface. - ui::GestureRecognizer* recognizer = &gesture_recognizer_; - - // Run touches through the gesture recognition pipeline, web content - // typically wants to process gesture events, not touch events. - if (!recognizer->ProcessTouchEventPreDispatch( - &root_relative_event, contents_->GetNativeView())) { - return; - } - - handler->OnTouchEvent(&evt); - - // Normally this would be done when the renderer acknowledges the touch - // event and using flags from the renderer, inside - // RenderWidgetHostViewAura, but we don't have those so... fake it. - auto list = - recognizer->AckTouchEvent(evt.unique_event_id(), ui::ER_UNHANDLED, - false, contents_->GetNativeView()); - for (auto& e : list) { - // Forward all gestures. - handler->OnGestureEvent(e.get()); - } - } else { - client_->OnError("touch() not supplied for touch event"); - } - break; - case ui::ET_MOUSE_PRESSED: - case ui::ET_MOUSE_DRAGGED: - case ui::ET_MOUSE_RELEASED: - case ui::ET_MOUSE_MOVED: - case ui::ET_MOUSE_ENTERED: - case ui::ET_MOUSE_EXITED: - case ui::ET_MOUSEWHEEL: - case ui::ET_MOUSE_CAPTURE_CHANGED: - if (ev.has_mouse()) { - auto& mouse = ev.mouse(); - ui::MouseEvent evt( - type, gfx::PointF(mouse.x(), mouse.y()), - gfx::PointF(mouse.root_x(), mouse.root_y()), - base::TimeTicks() + - base::TimeDelta::FromMicroseconds(ev.timestamp()), - ev.flags(), mouse.changed_button_flags()); - handler->OnMouseEvent(&evt); - } else { - client_->OnError("mouse() not supplied for mouse event"); - } - break; - default: - break; - } -} - -void WebviewController::JavascriptCallback(int64_t id, base::Value result) { - std::string json; - base::JSONWriter::Write(result, &json); - std::unique_ptr<webview::WebviewResponse> response = - std::make_unique<webview::WebviewResponse>(); - response->set_id(id); - response->mutable_evaluate_javascript()->set_json(json); - client_->EnqueueSend(std::move(response)); -} - -void WebviewController::HandleEvaluateJavascript( - int64_t id, - const webview::EvaluateJavascriptRequest& request) { - contents_->GetMainFrame()->ExecuteJavaScript( - base::UTF8ToUTF16(request.javascript_blob()), - base::BindOnce(&WebviewController::JavascriptCallback, - weak_ptr_factory_.GetWeakPtr(), id)); -} - -void WebviewController::HandleAddJavascriptChannels( - const webview::AddJavascriptChannelsRequest& request) { - // TODO(dnicoara): Handle this. -} - -void WebviewController::HandleRemoveJavascriptChannels( - const webview::RemoveJavascriptChannelsRequest& request) { - // TODO(dnicoara): Handle this. -} - -void WebviewController::HandleGetCurrentUrl(int64_t id) { - std::unique_ptr<webview::WebviewResponse> response = - std::make_unique<webview::WebviewResponse>(); - - response->set_id(id); - response->mutable_get_current_url()->set_url(contents_->GetURL().spec()); - client_->EnqueueSend(std::move(response)); -} - -void WebviewController::HandleCanGoBack(int64_t id) { - std::unique_ptr<webview::WebviewResponse> response = - std::make_unique<webview::WebviewResponse>(); - - response->set_id(id); - response->mutable_can_go_back()->set_can_go_back( - contents_->GetController().CanGoBack()); - client_->EnqueueSend(std::move(response)); -} - -void WebviewController::HandleCanGoForward(int64_t id) { - std::unique_ptr<webview::WebviewResponse> response = - std::make_unique<webview::WebviewResponse>(); - - response->set_id(id); - response->mutable_can_go_forward()->set_can_go_forward( - contents_->GetController().CanGoForward()); - client_->EnqueueSend(std::move(response)); -} - -void WebviewController::HandleClearCache() { - // TODO(dnicoara): See if there is a generic way to inform the renderer to - // clear cache. - // Android has a specific renderer message for this: - // https://cs.chromium.org/chromium/src/android_webview/common/render_view_messages.h?rcl=65107121555167a3db39de5633c3297f7e861315&l=44 - - // Remove disk cache. - content::BrowsingDataRemover* remover = - content::BrowserContext::GetBrowsingDataRemover( - contents_->GetBrowserContext()); - remover->Remove(base::Time(), base::Time::Max(), - content::BrowsingDataRemover::DATA_TYPE_CACHE, - content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | - content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB); -} - -void WebviewController::HandleGetTitle(int64_t id) { - std::unique_ptr<webview::WebviewResponse> response = - std::make_unique<webview::WebviewResponse>(); - - response->set_id(id); - response->mutable_get_title()->set_title( - base::UTF16ToUTF8(contents_->GetTitle())); - client_->EnqueueSend(std::move(response)); -} - -void WebviewController::HandleUpdateSettings( - const webview::UpdateSettingsRequest& request) { - content::WebPreferences prefs = - contents_->GetRenderViewHost()->GetWebkitPreferences(); - prefs.javascript_enabled = request.javascript_enabled(); - contents_->GetRenderViewHost()->UpdateWebkitPreferences(prefs); - - has_navigation_delegate_ = request.has_navigation_delegate(); - - // Given that cast_shell enables devtools unconditionally there isn't - // anything that needs to be done for |request.debugging_enabled()|. Though, - // as a note, remote debugging is always on. - - if (request.has_user_agent() && - request.user_agent().type_case() == webview::UserAgent::kValue) { - contents_->SetUserAgentOverride(request.user_agent().value(), true); - } -} - -void WebviewController::HandleSetAutoMediaPlaybackPolicy( - const webview::SetAutoMediaPlaybackPolicyRequest& request) { - content::WebPreferences prefs = - contents_->GetRenderViewHost()->GetWebkitPreferences(); - prefs.autoplay_policy = request.require_user_gesture() - ? content::AutoplayPolicy::kUserGestureRequired - : content::AutoplayPolicy::kNoUserGestureRequired; - contents_->GetRenderViewHost()->UpdateWebkitPreferences(prefs); +content::WebContents* WebviewController::GetWebContents() { + return contents_.get(); } webview::AsyncPageEvent_State WebviewController::current_state() {
diff --git a/chromecast/browser/webview/webview_controller.h b/chromecast/browser/webview/webview_controller.h index cddd688..daa2eda1 100644 --- a/chromecast/browser/webview/webview_controller.h +++ b/chromecast/browser/webview/webview_controller.h
@@ -11,15 +11,9 @@ #include "base/supports_user_data.h" #include "chromecast/browser/cast_web_contents.h" #include "chromecast/browser/webview/proto/webview.pb.h" -#include "components/exo/surface.h" -#include "components/exo/surface_observer.h" -#include "ui/events/gestures/gesture_recognizer_impl.h" +#include "chromecast/browser/webview/web_content_controller.h" #include "url/gurl.h" -namespace aura { -class Window; -} // namespace aura - namespace chromecast { class CastWebContents; } // namespace chromecast @@ -39,15 +33,8 @@ // to allow the web contents to be controlled and embedded. class WebviewController : public CastWebContents::Delegate, public CastWebContents::Observer, - public exo::SurfaceObserver { + public WebContentController { public: - class Client { - public: - virtual ~Client() {} - virtual void EnqueueSend( - std::unique_ptr<webview::WebviewResponse> response) = 0; - virtual void OnError(const std::string& error_message) = 0; - }; WebviewController(content::BrowserContext* browser_context, Client* client); ~WebviewController() override; @@ -59,44 +46,23 @@ // Cause the controller to be destroyed after giving the webpage a chance to // run unload events. This unsets the client so no more messages will be // sent. - void Destroy(); + void Destroy() override; + + void ProcessRequest(const webview::WebviewRequest& request) override; // Close the page. This will cause a stopped response to eventually be sent. void ClosePage(); - void ProcessRequest(const webview::WebviewRequest& request); - - // Attach this web contents to an aura window as a child. - void AttachTo(aura::Window* window, int window_id); - void SendNavigationEvent(WebviewNavigationThrottle* throttle, const GURL& url, bool is_in_main_frame); + protected: + content::WebContents* GetWebContents() override; + private: webview::AsyncPageEvent_State current_state(); - void ProcessInputEvent(const webview::InputEvent& ev); - void JavascriptCallback(int64_t id, base::Value result); - void HandleEvaluateJavascript( - int64_t id, - const webview::EvaluateJavascriptRequest& request); - void HandleAddJavascriptChannels( - const webview::AddJavascriptChannelsRequest& request); - void HandleRemoveJavascriptChannels( - const webview::RemoveJavascriptChannelsRequest& request); - void HandleGetCurrentUrl(int64_t id); - void HandleCanGoBack(int64_t id); - void HandleCanGoForward(int64_t id); - void HandleClearCache(); - void HandleGetTitle(int64_t id); - void HandleUpdateSettings(const webview::UpdateSettingsRequest& request); - void HandleSetAutoMediaPlaybackPolicy( - const webview::SetAutoMediaPlaybackPolicyRequest& request); - viz::SurfaceId GetSurfaceId(); - - bool Check(bool condition, const char* error); - // CastWebContents::Delegate void OnPageStateChanged(CastWebContents* cast_web_contents) override; void OnPageStopped(CastWebContents* cast_web_contents, @@ -105,20 +71,10 @@ // CastWebContents::Observer void ResourceLoadFailed(CastWebContents* cast_web_contents) override; - // exo::SurfaceObserver - void OnSurfaceDestroying(exo::Surface* surface) override; - - Client* client_; // Not owned. std::unique_ptr<content::WebContents> contents_; std::unique_ptr<CastWebContents> cast_web_contents_; bool stopped_ = false; - bool has_navigation_delegate_ = false; - - ui::GestureRecognizerImpl gesture_recognizer_; - - exo::Surface* surface_ = nullptr; - // The navigation throttle for the current navigation event, if any. // Is set only: // When has_navigation_delegate is true, and
diff --git a/chromecast/browser/webview/webview_grpc_service.cc b/chromecast/browser/webview/webview_grpc_service.cc index cb81f03..867a26d6 100644 --- a/chromecast/browser/webview/webview_grpc_service.cc +++ b/chromecast/browser/webview/webview_grpc_service.cc
@@ -138,6 +138,12 @@ } void WebviewRpcInstance::InitComplete(bool ok) { + if (!ok) { + destroying_ = true; + delete this; + return; + } + request_ = std::make_unique<webview::WebviewRequest>(); io_.Read(request_.get(), &read_callback_); @@ -263,6 +269,7 @@ } WebviewAsyncService::~WebviewAsyncService() { + cq_->Shutdown(); base::PlatformThread::Join(rpc_thread_); }
diff --git a/components/arc/session/arc_client_adapter.cc b/components/arc/session/arc_client_adapter.cc index 41577b6..9ec7d6f 100644 --- a/components/arc/session/arc_client_adapter.cc +++ b/components/arc/session/arc_client_adapter.cc
@@ -22,8 +22,9 @@ } // static -std::unique_ptr<ArcClientAdapter> ArcClientAdapter::Create() { - return IsArcVmEnabled() ? CreateArcVmClientAdapter() +std::unique_ptr<ArcClientAdapter> ArcClientAdapter::Create( + version_info::Channel channel) { + return IsArcVmEnabled() ? CreateArcVmClientAdapter(channel) : CreateArcContainerClientAdapter(); }
diff --git a/components/arc/session/arc_client_adapter.h b/components/arc/session/arc_client_adapter.h index 264b79d..d32b62f 100644 --- a/components/arc/session/arc_client_adapter.h +++ b/components/arc/session/arc_client_adapter.h
@@ -13,6 +13,7 @@ #include "chromeos/dbus/dbus_method_call_status.h" #include "components/arc/session/arc_start_params.h" #include "components/arc/session/arc_upgrade_params.h" +#include "components/version_info/channel.h" namespace arc { @@ -26,7 +27,8 @@ }; // Creates a default instance of ArcClientAdapter. - static std::unique_ptr<ArcClientAdapter> Create(); + static std::unique_ptr<ArcClientAdapter> Create( + version_info::Channel channel); virtual ~ArcClientAdapter(); // StartMiniArc starts ARC with only a handful of ARC processes for Chrome OS
diff --git a/components/arc/session/arc_session_impl.cc b/components/arc/session/arc_session_impl.cc index 46d8bb8..3c38c4e 100644 --- a/components/arc/session/arc_session_impl.cc +++ b/components/arc/session/arc_session_impl.cc
@@ -316,7 +316,7 @@ chromeos::SchedulerConfigurationManagerBase* scheduler_configuration_manager) : delegate_(std::move(delegate)), - client_(ArcClientAdapter::Create()), + client_(ArcClientAdapter::Create(delegate_->GetChannel())), scheduler_configuration_manager_(scheduler_configuration_manager) { DCHECK(client_); client_->AddObserver(this);
diff --git a/components/arc/session/arc_vm_client_adapter.cc b/components/arc/session/arc_vm_client_adapter.cc index b14d050..528679b4 100644 --- a/components/arc/session/arc_vm_client_adapter.cc +++ b/components/arc/session/arc_vm_client_adapter.cc
@@ -40,6 +40,7 @@ #include "components/arc/arc_features.h" #include "components/arc/arc_util.h" #include "components/arc/session/arc_session.h" +#include "components/version_info/version_info.h" namespace arc { namespace { @@ -179,34 +180,6 @@ return request; } -// TODO(yusukes): ArcSessionImpl already has this info through the delegate. -// Use it and remove this function. -std::string GetReleaseChannel() { - constexpr const char kUnknown[] = "unknown"; - const std::set<std::string> channels = {"beta", "canary", "dev", - "dogfood", "stable", "testimage"}; - - std::string value; - if (!base::SysInfo::GetLsbReleaseValue("CHROMEOS_RELEASE_TRACK", &value)) { - LOG(ERROR) << "Could not load lsb-release"; - return kUnknown; - } - - auto pieces = base::SplitString(value, "-", base::KEEP_WHITESPACE, - base::SPLIT_WANT_ALL); - - if (pieces.size() != 2 || pieces[1] != "channel") { - LOG(ERROR) << "Misformatted CHROMEOS_RELEASE_TRACK value in lsb-release"; - return kUnknown; - } - if (channels.find(pieces[0]) == channels.end()) { - LOG(WARNING) << "Unknown ChromeOS channel: \"" << pieces[0] << "\""; - return kUnknown; - } - - return pieces[0]; -} - std::string MonotonicTimestamp() { struct timespec ts; const int ret = clock_gettime(CLOCK_BOOTTIME, &ts); @@ -220,7 +193,8 @@ const StartParams& start_params, const FileSystemStatus& file_system_status, bool is_dev_mode, - bool is_host_on_vm) { + bool is_host_on_vm, + const std::string& channel) { std::vector<std::string> result = { "androidboot.hardware=bertha", "androidboot.container=1", @@ -240,7 +214,7 @@ start_params.arc_custom_tabs_experiment), base::StringPrintf("androidboot.arc_print_spooler=%d", start_params.arc_print_spooler_experiment), - "androidboot.chromeos_channel=" + GetReleaseChannel(), + "androidboot.chromeos_channel=" + channel, "androidboot.boottime_offset=" + MonotonicTimestamp(), // TODO(yusukes): remove this once arcvm supports SELinux. "androidboot.selinux=permissive", @@ -327,8 +301,9 @@ // Initializing |is_host_on_vm_| and |is_dev_mode_| is not always very fast. // Try to initialize them in the constructor and in StartMiniArc respectively. // They usually run when the system is not busy. - ArcVmClientAdapter() - : is_host_on_vm_(chromeos::system::StatisticsProvider::GetInstance() + explicit ArcVmClientAdapter(version_info::Channel channel) + : channel_(channel), + is_host_on_vm_(chromeos::system::StatisticsProvider::GetInstance() ->IsRunningOnVm()) { auto* client = GetConciergeClient(); client->AddVmObserver(this); @@ -507,7 +482,8 @@ // TODO(yusukes): Use |params| for generating kernel command line too. DCHECK(is_dev_mode_); std::vector<std::string> kernel_cmdline = GenerateKernelCmdline( - start_params_, file_system_status, *is_dev_mode_, is_host_on_vm_); + start_params_, file_system_status, *is_dev_mode_, is_host_on_vm_, + version_info::GetChannelString(channel_)); auto start_request = CreateStartArcVmRequest(user_id_hash_, cpus, data_disk_path, file_system_status, std::move(kernel_cmdline)); @@ -592,6 +568,8 @@ VLOG(1) << "OnArcVmServerProxyJobStopped result=" << result; } + const version_info::Channel channel_; + base::Optional<bool> is_dev_mode_; // True when the *host* is running on a VM. const bool is_host_on_vm_; @@ -608,8 +586,9 @@ DISALLOW_COPY_AND_ASSIGN(ArcVmClientAdapter); }; -std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter() { - return std::make_unique<ArcVmClientAdapter>(); +std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter( + version_info::Channel channel) { + return std::make_unique<ArcVmClientAdapter>(channel); } bool IsAndroidDebuggableForTesting(const base::FilePath& json_path) {
diff --git a/components/arc/session/arc_vm_client_adapter.h b/components/arc/session/arc_vm_client_adapter.h index 6e521bf6..01365514 100644 --- a/components/arc/session/arc_vm_client_adapter.h +++ b/components/arc/session/arc_vm_client_adapter.h
@@ -8,6 +8,7 @@ #include <memory> #include "components/arc/session/arc_client_adapter.h" +#include "components/version_info/channel.h" namespace base { class FilePath; @@ -16,7 +17,8 @@ namespace arc { // Returns an adapter for arcvm. -std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter(); +std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter( + version_info::Channel channel); // Function(s) below are for testing. bool IsAndroidDebuggableForTesting(const base::FilePath& json_path);
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/components/arc/session/arc_vm_client_adapter_unittest.cc index 7468a03..8712b27 100644 --- a/components/arc/session/arc_vm_client_adapter_unittest.cc +++ b/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -5,6 +5,7 @@ #include "components/arc/session/arc_vm_client_adapter.h" #include <memory> +#include <string> #include <utility> #include "base/bind.h" @@ -97,7 +98,7 @@ void SetUp() override { run_loop_ = std::make_unique<base::RunLoop>(); - adapter_ = CreateArcVmClientAdapter(); + adapter_ = CreateArcVmClientAdapter(version_info::Channel::STABLE); arc_instance_stopped_called_ = false; adapter_->AddObserver(this); ASSERT_TRUE(dir_.CreateUniqueTempDir());
diff --git a/components/discardable_memory/service/discardable_shared_memory_manager.h b/components/discardable_memory/service/discardable_shared_memory_manager.h index 515d74e7..90f3370 100644 --- a/components/discardable_memory/service/discardable_shared_memory_manager.h +++ b/components/discardable_memory/service/discardable_shared_memory_manager.h
@@ -25,6 +25,7 @@ #include "base/process/process_handle.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" +#include "base/thread_annotations.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_provider.h" #include "components/discardable_memory/common/discardable_memory_export.h" @@ -128,14 +129,17 @@ void DeletedDiscardableSharedMemory(int32_t id, int client_id); void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); - void ReduceMemoryUsageUntilWithinMemoryLimit(); - void ReduceMemoryUsageUntilWithinLimit(size_t limit); - void ReleaseMemory(base::DiscardableSharedMemory* memory); + void ReduceMemoryUsageUntilWithinMemoryLimit() + EXCLUSIVE_LOCKS_REQUIRED(lock_); + void ReduceMemoryUsageUntilWithinLimit(size_t limit) + EXCLUSIVE_LOCKS_REQUIRED(lock_); + void ReleaseMemory(base::DiscardableSharedMemory* memory) + EXCLUSIVE_LOCKS_REQUIRED(lock_); void BytesAllocatedChanged(size_t new_bytes_allocated) const; // Virtual for tests. virtual base::Time Now() const; - virtual void ScheduleEnforceMemoryPolicy(); + virtual void ScheduleEnforceMemoryPolicy() EXCLUSIVE_LOCKS_REQUIRED(lock_); // Invalidate weak pointers for the mojo thread. void InvalidateMojoThreadWeakPtrs(base::WaitableEvent* event); @@ -146,19 +150,20 @@ using MemorySegmentMap = std::unordered_map<int32_t, scoped_refptr<MemorySegment>>; using ClientMap = std::unordered_map<int, MemorySegmentMap>; - ClientMap clients_; + ClientMap clients_ GUARDED_BY(lock_); // Note: The elements in |segments_| are arranged in such a way that they form // a heap. The LRU memory segment always first. using MemorySegmentVector = std::vector<scoped_refptr<MemorySegment>>; - MemorySegmentVector segments_; - size_t default_memory_limit_; - size_t memory_limit_; - size_t bytes_allocated_; - std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - scoped_refptr<base::SingleThreadTaskRunner> - enforce_memory_policy_task_runner_; - base::Closure enforce_memory_policy_callback_; - bool enforce_memory_policy_pending_; + MemorySegmentVector segments_ GUARDED_BY(lock_); + size_t default_memory_limit_ GUARDED_BY(lock_); + size_t memory_limit_ GUARDED_BY(lock_); + size_t bytes_allocated_ GUARDED_BY(lock_); + std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_ + GUARDED_BY(lock_); + scoped_refptr<base::SingleThreadTaskRunner> enforce_memory_policy_task_runner_ + GUARDED_BY(lock_); + base::Closure enforce_memory_policy_callback_ GUARDED_BY(lock_); + bool enforce_memory_policy_pending_ GUARDED_BY(lock_); // The message loop for running mojom::DiscardableSharedMemoryManager // implementations.
diff --git a/components/dom_distiller/DEPS b/components/dom_distiller/DEPS index 9e2dcd6..4371aab 100644 --- a/components/dom_distiller/DEPS +++ b/components/dom_distiller/DEPS
@@ -4,8 +4,6 @@ "+components/pref_registry", "+components/prefs", "+components/strings/grit/components_strings.h", - "+components/sync/model", - "+components/sync/protocol", "+components/sync_preferences", "+components/variations", "+crypto", # For sha256
diff --git a/components/dom_distiller/content/browser/BUILD.gn b/components/dom_distiller/content/browser/BUILD.gn index d7113a8e..cc183878 100644 --- a/components/dom_distiller/content/browser/BUILD.gn +++ b/components/dom_distiller/content/browser/BUILD.gn
@@ -32,7 +32,6 @@ "//components/dom_distiller/content/common/mojom", "//components/resources", "//components/strings", - "//components/sync", "//content/public/browser", "//content/public/common", "//mojo/public/cpp/bindings",
diff --git a/components/dom_distiller/core/BUILD.gn b/components/dom_distiller/core/BUILD.gn index e29b253..4a681d84 100644 --- a/components/dom_distiller/core/BUILD.gn +++ b/components/dom_distiller/core/BUILD.gn
@@ -63,7 +63,6 @@ "//components/prefs", "//components/resources", "//components/strings", - "//components/sync", "//components/variations", "//services/network/public/cpp:cpp", "//skia", @@ -95,7 +94,6 @@ ":core", "//base", "//components/leveldb_proto:test_support", - "//components/sync", "//testing/gmock", "//testing/gtest", "//url", @@ -140,7 +138,6 @@ "//components/leveldb_proto:test_support", "//components/resources", "//components/strings", - "//components/sync", "//components/sync_preferences:test_support", "//net:test_support", "//services/network:test_support",
diff --git a/components/dom_distiller/core/article_entry.cc b/components/dom_distiller/core/article_entry.cc index ff872d7..1c3eb4c1 100644 --- a/components/dom_distiller/core/article_entry.cc +++ b/components/dom_distiller/core/article_entry.cc
@@ -8,24 +8,18 @@ namespace dom_distiller { -bool IsEntryPageValid(const ArticleEntryPage& page) { - return page.has_url(); -} +ArticleEntry::ArticleEntry() = default; +ArticleEntry::ArticleEntry(const ArticleEntry&) = default; +ArticleEntry::~ArticleEntry() = default; bool IsEntryValid(const ArticleEntry& entry) { - if (!entry.has_entry_id()) + if (entry.entry_id.empty()) return false; - for (int i = 0; i < entry.pages_size(); ++i) { - if (!IsEntryPageValid(entry.pages(i))) + for (const GURL& page : entry.pages) { + if (!page.is_valid()) return false; } return true; } -bool AreEntriesEqual(const ArticleEntry& left, const ArticleEntry& right) { - DCHECK(IsEntryValid(left)); - DCHECK(IsEntryValid(right)); - return left.SerializeAsString() == right.SerializeAsString(); -} - } // namespace dom_distiller
diff --git a/components/dom_distiller/core/article_entry.h b/components/dom_distiller/core/article_entry.h index e23f9ff..8a5cf27 100644 --- a/components/dom_distiller/core/article_entry.h +++ b/components/dom_distiller/core/article_entry.h
@@ -5,18 +5,26 @@ #ifndef COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ENTRY_H_ #define COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ENTRY_H_ -#include "components/sync/protocol/article_specifics.pb.h" +#include <string> +#include <vector> + +#include "url/gurl.h" namespace dom_distiller { -typedef sync_pb::ArticleSpecifics ArticleEntry; -typedef sync_pb::ArticlePage ArticleEntryPage; +struct ArticleEntry { + ArticleEntry(); + ArticleEntry(const ArticleEntry&); + ~ArticleEntry(); -// A valid entry has an entry_id and all its pages have a URL. + std::string entry_id; + std::string title; + std::vector<GURL> pages; +}; + +// A valid entry has a non-empty entry_id and all its pages have a valid URL. bool IsEntryValid(const ArticleEntry& entry); -bool AreEntriesEqual(const ArticleEntry& left, const ArticleEntry& right); - } // namespace dom_distiller #endif // COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ENTRY_H_
diff --git a/components/dom_distiller/core/article_entry_unittest.cc b/components/dom_distiller/core/article_entry_unittest.cc index 62919a1..ce4b81b 100644 --- a/components/dom_distiller/core/article_entry_unittest.cc +++ b/components/dom_distiller/core/article_entry_unittest.cc
@@ -11,46 +11,12 @@ TEST(DomDistillerArticleEntryTest, TestIsEntryValid) { ArticleEntry entry; EXPECT_FALSE(IsEntryValid(entry)); - entry.set_entry_id("entry0"); + entry.entry_id = "entry0"; EXPECT_TRUE(IsEntryValid(entry)); - ArticleEntryPage* page0 = entry.add_pages(); + entry.pages.push_back(GURL()); EXPECT_FALSE(IsEntryValid(entry)); - page0->set_url("example.com/1"); + entry.pages.back() = GURL("https://example.com/1"); EXPECT_TRUE(IsEntryValid(entry)); } -TEST(DomDistillerArticleEntryTest, TestAreEntriesEqual) { - ArticleEntry left; - ArticleEntry right; - left.set_entry_id("entry0"); - right.set_entry_id("entry1"); - EXPECT_FALSE(AreEntriesEqual(left, right)); - right = left; - EXPECT_TRUE(AreEntriesEqual(left, right)); - - left.set_title("a title"); - EXPECT_FALSE(AreEntriesEqual(left, right)); - right.set_title("a different title"); - EXPECT_FALSE(AreEntriesEqual(left, right)); - right.set_title("a title"); - EXPECT_TRUE(AreEntriesEqual(left, right)); - - ArticleEntryPage left_page; - left_page.set_url("example.com/1"); - *left.add_pages() = left_page; - - EXPECT_FALSE(AreEntriesEqual(left, right)); - - ArticleEntryPage right_page; - right_page.set_url("foo.example.com/1"); - *right.add_pages() = right_page; - EXPECT_FALSE(AreEntriesEqual(left, right)); - - right = left; - EXPECT_TRUE(AreEntriesEqual(left, right)); - - *right.add_pages() = right_page; - EXPECT_FALSE(AreEntriesEqual(left, right)); -} - } // namespace dom_distiller
diff --git a/components/dom_distiller/core/distilled_content_store.cc b/components/dom_distiller/core/distilled_content_store.cc index 0a734c0..0fbbd88b 100644 --- a/components/dom_distiller/core/distilled_content_store.cc +++ b/components/dom_distiller/core/distilled_content_store.cc
@@ -36,12 +36,12 @@ if (callback.is_null()) return; - ContentMap::const_iterator it = cache_.Get(entry.entry_id()); + ContentMap::const_iterator it = cache_.Get(entry.entry_id); bool success = it != cache_.end(); if (!success) { // Could not find article by entry ID, so try looking it up by URL. - for (int i = 0; i < entry.pages_size(); ++i) { - UrlMap::const_iterator url_it = url_to_id_.find(entry.pages(i).url()); + for (const GURL& page : entry.pages) { + UrlMap::const_iterator url_it = url_to_id_.find(page.spec()); if (url_it != url_to_id_.end()) { it = cache_.Get(url_it->second); success = it != cache_.end(); @@ -64,7 +64,7 @@ void InMemoryContentStore::InjectContent(const ArticleEntry& entry, const DistilledArticleProto& proto) { - cache_.Put(entry.entry_id(), + cache_.Put(entry.entry_id, std::unique_ptr<DistilledArticleProto, CacheDeletor>( new DistilledArticleProto(proto), CacheDeletor(this))); AddUrlToIdMapping(entry, proto); @@ -76,7 +76,7 @@ for (int i = 0; i < proto.pages_size(); i++) { const DistilledPageProto& page = proto.pages(i); if (page.has_url()) { - url_to_id_[page.url()] = entry.entry_id(); + url_to_id_[page.url()] = entry.entry_id; } } }
diff --git a/components/dom_distiller/core/distilled_content_store.h b/components/dom_distiller/core/distilled_content_store.h index cf7c1fa..a1a8680 100644 --- a/components/dom_distiller/core/distilled_content_store.h +++ b/components/dom_distiller/core/distilled_content_store.h
@@ -79,7 +79,6 @@ typedef base::MRUCache<std::string, std::unique_ptr<DistilledArticleProto, CacheDeletor>> - ContentMap; typedef std::unordered_map<std::string, std::string> UrlMap;
diff --git a/components/dom_distiller/core/distilled_content_store_unittest.cc b/components/dom_distiller/core/distilled_content_store_unittest.cc index 62ff73d..7c47d09 100644 --- a/components/dom_distiller/core/distilled_content_store_unittest.cc +++ b/components/dom_distiller/core/distilled_content_store_unittest.cc
@@ -18,22 +18,19 @@ namespace { ArticleEntry CreateEntry(std::string entry_id, - std::string page_url1, - std::string page_url2, - std::string page_url3) { + GURL page_url1 = GURL(), + GURL page_url2 = GURL(), + GURL page_url3 = GURL()) { ArticleEntry entry; - entry.set_entry_id(entry_id); - if (!page_url1.empty()) { - ArticleEntryPage* page = entry.add_pages(); - page->set_url(page_url1); + entry.entry_id = entry_id; + if (!page_url1.is_empty()) { + entry.pages.push_back(page_url1); } - if (!page_url2.empty()) { - ArticleEntryPage* page = entry.add_pages(); - page->set_url(page_url2); + if (!page_url2.is_empty()) { + entry.pages.push_back(page_url2); } - if (!page_url3.empty()) { - ArticleEntryPage* page = entry.add_pages(); - page->set_url(page_url3); + if (!page_url3.is_empty()) { + entry.pages.push_back(page_url3); } return entry; } @@ -41,10 +38,10 @@ DistilledArticleProto CreateDistilledArticleForEntry( const ArticleEntry& entry) { DistilledArticleProto article; - for (int i = 0; i < entry.pages_size(); ++i) { + for (const GURL& url : entry.pages) { DistilledPageProto* page = article.add_pages(); - page->set_url(entry.pages(i).url()); - page->set_html("<div>" + entry.pages(i).url() + "</div>"); + page->set_url(url.spec()); + page->set_html("<div>" + url.spec() + "</div>"); } return article; } @@ -79,7 +76,9 @@ // Tests whether saving and then loading a single article works as expected. TEST_F(InMemoryContentStoreTest, SaveAndLoadSingleArticle) { base::test::SingleThreadTaskEnvironment task_environment; - const ArticleEntry entry = CreateEntry("test-id", "url1", "url2", "url3"); + const ArticleEntry entry = + CreateEntry("test-id", GURL("https://url1"), GURL("https://url2"), + GURL("https://url3")); const DistilledArticleProto stored_proto = CreateDistilledArticleForEntry(entry); store_->SaveContent(entry, stored_proto, @@ -102,7 +101,9 @@ // where success is false. TEST_F(InMemoryContentStoreTest, LoadNonExistentArticle) { base::test::SingleThreadTaskEnvironment task_environment; - const ArticleEntry entry = CreateEntry("bogus-id", "url1", "url2", "url3"); + const ArticleEntry entry = + CreateEntry("bogus-id", GURL("https://url1"), GURL("https://url2"), + GURL("https://url3")); store_->LoadContent(entry, base::Bind(&InMemoryContentStoreTest::OnLoadCallback, base::Unretained(this))); @@ -116,7 +117,9 @@ TEST_F(InMemoryContentStoreTest, SaveAndLoadMultipleArticles) { base::test::SingleThreadTaskEnvironment task_environment; // Store first article. - const ArticleEntry first_entry = CreateEntry("first", "url1", "url2", "url3"); + const ArticleEntry first_entry = + CreateEntry("first", GURL("https://url1"), GURL("https://url2"), + GURL("https://url3")); const DistilledArticleProto first_stored_proto = CreateDistilledArticleForEntry(first_entry); store_->SaveContent(first_entry, first_stored_proto, @@ -128,7 +131,8 @@ // Store second article. const ArticleEntry second_entry = - CreateEntry("second", "url4", "url5", "url6"); + CreateEntry("second", GURL("https://url4"), GURL("https://url5"), + GURL("https://url6")); const DistilledArticleProto second_stored_proto = CreateDistilledArticleForEntry(second_entry); store_->SaveContent(second_entry, second_stored_proto, @@ -169,7 +173,9 @@ store_.reset(new InMemoryContentStore(kMaxNumArticles)); // Store first article. - const ArticleEntry first_entry = CreateEntry("first", "url1", "url2", "url3"); + const ArticleEntry first_entry = + CreateEntry("first", GURL("https://url1"), GURL("https://url2"), + GURL("https://url3")); const DistilledArticleProto first_stored_proto = CreateDistilledArticleForEntry(first_entry); store_->SaveContent(first_entry, first_stored_proto, @@ -181,7 +187,8 @@ // Store second article. const ArticleEntry second_entry = - CreateEntry("second", "url4", "url5", "url6"); + CreateEntry("second", GURL("https://url4"), GURL("https://url5"), + GURL("https://url6")); const DistilledArticleProto second_stored_proto = CreateDistilledArticleForEntry(second_entry); store_->SaveContent(second_entry, second_stored_proto, @@ -192,7 +199,9 @@ save_success_ = false; // Store third article. - const ArticleEntry third_entry = CreateEntry("third", "url7", "url8", "url9"); + const ArticleEntry third_entry = + CreateEntry("third", GURL("https://url7"), GURL("https://url8"), + GURL("https://url9")); const DistilledArticleProto third_stored_proto = CreateDistilledArticleForEntry(third_entry); store_->SaveContent(third_entry, third_stored_proto, @@ -216,7 +225,8 @@ // Store fourth article. const ArticleEntry fourth_entry = - CreateEntry("fourth", "url10", "url11", "url12"); + CreateEntry("fourth", GURL("https://url10"), GURL("https://url11"), + GURL("https://url12")); const DistilledArticleProto fourth_stored_proto = CreateDistilledArticleForEntry(fourth_entry); store_->SaveContent(fourth_entry, fourth_stored_proto, @@ -240,7 +250,9 @@ // Tests whether saving and then loading a single article works as expected. TEST_F(InMemoryContentStoreTest, LookupArticleByURL) { base::test::SingleThreadTaskEnvironment task_environment; - const ArticleEntry entry = CreateEntry("test-id", "url1", "url2", "url3"); + const ArticleEntry entry = + CreateEntry("test-id", GURL("https://url1"), GURL("https://url2"), + GURL("https://url3")); const DistilledArticleProto stored_proto = CreateDistilledArticleForEntry(entry); store_->SaveContent(entry, stored_proto, @@ -251,7 +263,8 @@ save_success_ = false; // Create an entry where the entry ID does not match, but the first URL does. - const ArticleEntry lookup_entry1 = CreateEntry("lookup-id", "url1", "", ""); + const ArticleEntry lookup_entry1 = + CreateEntry("lookup-id", GURL("https://url1")); store_->LoadContent(lookup_entry1, base::Bind(&InMemoryContentStoreTest::OnLoadCallback, base::Unretained(this))); @@ -262,7 +275,7 @@ // Create an entry where the entry ID does not match, but the second URL does. const ArticleEntry lookup_entry2 = - CreateEntry("lookup-id", "bogus", "url2", ""); + CreateEntry("lookup-id", GURL("bogus"), GURL("https://url2")); store_->LoadContent(lookup_entry2, base::Bind(&InMemoryContentStoreTest::OnLoadCallback, base::Unretained(this))); @@ -282,7 +295,9 @@ store_.reset(new InMemoryContentStore(kMaxNumArticles)); // Store an article. - const ArticleEntry first_entry = CreateEntry("first", "url1", "url2", "url3"); + const ArticleEntry first_entry = + CreateEntry("first", GURL("https://url1"), GURL("https://url2"), + GURL("https://url3")); const DistilledArticleProto first_stored_proto = CreateDistilledArticleForEntry(first_entry); store_->SaveContent(first_entry, first_stored_proto, @@ -295,7 +310,7 @@ // Looking up the first entry by URL should succeed when it is still in the // cache. const ArticleEntry first_entry_lookup = - CreateEntry("lookup-id", "url1", "", ""); + CreateEntry("lookup-id", GURL("https://url1")); store_->LoadContent(first_entry_lookup, base::Bind(&InMemoryContentStoreTest::OnLoadCallback, base::Unretained(this))); @@ -306,7 +321,8 @@ // Store second article. This will remove the first article from the cache. const ArticleEntry second_entry = - CreateEntry("second", "url4", "url5", "url6"); + CreateEntry("second", GURL("https://url4"), GURL("https://url5"), + GURL("https://url6")); const DistilledArticleProto second_stored_proto = CreateDistilledArticleForEntry(second_entry); store_->SaveContent(second_entry, second_stored_proto,
diff --git a/components/dom_distiller/core/dom_distiller_service.cc b/components/dom_distiller/core/dom_distiller_service.cc index 309595ba..34abda8 100644 --- a/components/dom_distiller/core/dom_distiller_service.cc +++ b/components/dom_distiller/core/dom_distiller_service.cc
@@ -23,9 +23,8 @@ ArticleEntry CreateSkeletonEntryForUrl(const GURL& url) { ArticleEntry skeleton; - skeleton.set_entry_id(base::GenerateGUID()); - ArticleEntryPage* page = skeleton.add_pages(); - page->set_url(url.spec()); + skeleton.entry_id = base::GenerateGUID(); + skeleton.pages.push_back(url); DCHECK(IsEntryValid(skeleton)); return skeleton;
diff --git a/components/dom_distiller/core/task_tracker.cc b/components/dom_distiller/core/task_tracker.cc index 24b8ab5..a8f74cdd 100644 --- a/components/dom_distiller/core/task_tracker.cc +++ b/components/dom_distiller/core/task_tracker.cc
@@ -49,10 +49,10 @@ if (distiller_) { return; } - if (entry_.pages_size() == 0) { + if (entry_.pages.empty()) { return; } - GURL url(entry_.pages(0).url()); + GURL url(entry_.pages[0]); DCHECK(url.is_valid()); distiller_ = factory->CreateDistillerForUrl(url); @@ -97,16 +97,16 @@ } const std::string& TaskTracker::GetEntryId() const { - return entry_.entry_id(); + return entry_.entry_id; } bool TaskTracker::HasEntryId(const std::string& entry_id) const { - return entry_.entry_id() == entry_id; + return entry_.entry_id == entry_id; } bool TaskTracker::HasUrl(const GURL& url) const { - for (int i = 0; i < entry_.pages_size(); ++i) { - if (entry_.pages(i).url() == url.spec()) { + for (const GURL& page : entry_.pages) { + if (page == url) { return true; } } @@ -208,11 +208,10 @@ content_ready_ = true; distilled_article_ = std::move(distilled_article); - entry_.set_title(distilled_article_->title()); - entry_.clear_pages(); + entry_.title = distilled_article_->title(); + entry_.pages.clear(); for (int i = 0; i < distilled_article_->pages_size(); ++i) { - sync_pb::ArticlePage* page = entry_.add_pages(); - page->set_url(distilled_article_->pages(i).url()); + entry_.pages.push_back(GURL(distilled_article_->pages(i).url())); } NotifyViewersAndCallbacks();
diff --git a/components/dom_distiller/core/task_tracker_unittest.cc b/components/dom_distiller/core/task_tracker_unittest.cc index 087a769..5e8f459 100644 --- a/components/dom_distiller/core/task_tracker_unittest.cc +++ b/components/dom_distiller/core/task_tracker_unittest.cc
@@ -69,11 +69,9 @@ ArticleEntry GetDefaultEntry() { ArticleEntry entry; - entry.set_entry_id(entry_id_); - ArticleEntryPage* page0 = entry.add_pages(); - ArticleEntryPage* page1 = entry.add_pages(); - page0->set_url(page_0_url_.spec()); - page1->set_url(page_1_url_.spec()); + entry.entry_id = entry_id_; + entry.pages.push_back(page_0_url_); + entry.pages.push_back(page_1_url_); return entry; } @@ -219,10 +217,10 @@ DistilledArticleProto CreateDistilledArticleForEntry( const ArticleEntry& entry) { DistilledArticleProto article; - for (int i = 0; i < entry.pages_size(); ++i) { + for (const GURL& url : entry.pages) { DistilledPageProto* page = article.add_pages(); - page->set_url(entry.pages(i).url()); - page->set_html("<div>" + entry.pages(i).url() + "</div>"); + page->set_url(url.spec()); + page->set_html("<div>" + url.spec() + "</div>"); } return article; }
diff --git a/components/media_message_center/media_controls_progress_view.cc b/components/media_message_center/media_controls_progress_view.cc index ba07285..44cda87 100644 --- a/components/media_message_center/media_controls_progress_view.cc +++ b/components/media_message_center/media_controls_progress_view.cc
@@ -6,6 +6,7 @@ #include "base/i18n/time_formatting.h" #include "services/media_session/public/mojom/media_session.mojom.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/font_list.h" #include "ui/views/border.h" #include "ui/views/controls/label.h" @@ -19,7 +20,8 @@ namespace { -constexpr int kProgressBarAndTimeSpacing = 3; +constexpr SkColor kTimeColor = gfx::kGoogleGrey200; +constexpr int kProgressBarAndTimeSpacing = 8; constexpr int kProgressTimeFontSize = 11; constexpr int kProgressBarHeight = 4; constexpr int kMinClickHeight = 14; @@ -56,7 +58,7 @@ auto progress_time = std::make_unique<views::Label>(); progress_time->SetFontList(font_list); - progress_time->SetEnabledColor(SK_ColorWHITE); + progress_time->SetEnabledColor(kTimeColor); progress_time->SetAutoColorReadabilityEnabled(false); progress_time_ = time_view->AddChildView(std::move(progress_time));
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index 0fcae52..45e5574 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -1055,7 +1055,8 @@ } } -void OmniboxEditModel::OnSetFocus(bool control_down) { +void OmniboxEditModel::OnSetFocus(bool control_down, + bool suppress_on_focus_suggestions) { last_omnibox_focus_ = base::TimeTicks::Now(); user_input_since_focus_ = false; @@ -1069,7 +1070,8 @@ // example, if the user presses ctrl-l to focus the omnibox. control_key_state_ = control_down ? DOWN_AND_CONSUMED : UP; - ShowOnFocusSuggestionsIfAutocompleteIdle(); + if (!suppress_on_focus_suggestions) + ShowOnFocusSuggestionsIfAutocompleteIdle(); if (user_input_in_progress_ || !in_revert_) client_->OnInputStateChanged();
diff --git a/components/omnibox/browser/omnibox_edit_model.h b/components/omnibox/browser/omnibox_edit_model.h index b607d73..b54dc4e6 100644 --- a/components/omnibox/browser/omnibox_edit_model.h +++ b/components/omnibox/browser/omnibox_edit_model.h
@@ -291,7 +291,10 @@ // Called when the view is gaining focus. |control_down| is whether the // control key is down (at the time we're gaining focus). - void OnSetFocus(bool control_down); + // |suppress_on_focus_suggestions| is set to true when on-focus suggestions + // should not appear for this focus event. For instance, for + // renderer-initiated focus events, it should be set to true. + void OnSetFocus(bool control_down, bool suppress_on_focus_suggestions); // Shows On-Focus Suggestions (ZeroSuggest) if no query is currently running // and the popup is closed. This can be called multiple times without harm,
diff --git a/components/omnibox/browser/omnibox_edit_model_unittest.cc b/components/omnibox/browser/omnibox_edit_model_unittest.cc index 177305b..3de66fe 100644 --- a/components/omnibox/browser/omnibox_edit_model_unittest.cc +++ b/components/omnibox/browser/omnibox_edit_model_unittest.cc
@@ -323,7 +323,7 @@ AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED); const GURL alternate_nav_url("http://abcd/"); - model()->OnSetFocus(false); // Avoids DCHECK in OpenMatch(). + model()->OnSetFocus(false, false); // Avoids DCHECK in OpenMatch(). model()->SetUserText(base::ASCIIToUTF16("http://abcd")); model()->OpenMatch(match, WindowOpenDisposition::CURRENT_TAB, alternate_nav_url, base::string16(), 0); @@ -457,7 +457,7 @@ ASSERT_EQ(OMNIBOX_FOCUS_NONE, state.focus_state); // Simulate the tab-switching system focusing the Omnibox. - model()->OnSetFocus(false); + model()->OnSetFocus(false, true); // Restoring the old saved state should not clobber the model's focus state. model()->RestoreState(&state); @@ -483,9 +483,9 @@ // Tests ctrl_key_state_ is set consumed if the ctrl key is down on focus. TEST_F(OmniboxEditModelTest, ConsumeCtrlKeyOnRequestFocus) { model()->control_key_state_ = TestOmniboxEditModel::DOWN; - model()->OnSetFocus(false); + model()->OnSetFocus(false, false); EXPECT_EQ(model()->control_key_state_, TestOmniboxEditModel::UP); - model()->OnSetFocus(true); + model()->OnSetFocus(true, false); EXPECT_EQ(model()->control_key_state_, TestOmniboxEditModel::DOWN_AND_CONSUMED); }
diff --git a/components/password_manager/core/browser/hash_password_manager.cc b/components/password_manager/core/browser/hash_password_manager.cc index 6a32fdc..7720576 100644 --- a/components/password_manager/core/browser/hash_password_manager.cc +++ b/components/password_manager/core/browser/hash_password_manager.cc
@@ -170,9 +170,18 @@ } } } + // A password hash does not exist when it is first sign-in. + bool is_first_sign_in = !HasPasswordHash(username, is_gaia_password); bool is_saved = SavePasswordHash( PasswordHashData(username, password, true, is_gaia_password)); - state_callback_list_.Notify(username); + // Currently, the only callback in this list is + // CheckGaiaPasswordChangeForAllSignedInUsers which is in + // ChromePasswordProtectionService. We only want to notify ChromePPS only when + // a user has changed their password. This means that an existing password + // hash has to already exist in the password store and the SavePasswordHash + // has to succeed. + if (!is_first_sign_in && is_saved) + state_callback_list_.Notify(username); return is_saved; }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 0b35865..c2ab204c8 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -9053,7 +9053,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9063,7 +9063,9 @@ 'id': 172, 'caption': '''Screen dim delay when running on AC power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the screen is dimmed when running on AC power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which the screen is dimmed when running on AC power. When this policy is set to a value greater than zero, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> dims the screen. @@ -9081,7 +9083,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9091,7 +9093,9 @@ 'id': 173, 'caption': '''Screen off delay when running on AC power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the screen is turned off when running on AC power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which the screen is turned off when running on AC power. When this policy is set to a value greater than zero, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> turns off the screen. @@ -9109,7 +9113,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9119,7 +9123,9 @@ 'id': 174, 'caption': '''Screen lock delay when running on AC power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the screen is locked when running on AC power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="SCREEN_LOCK_DELAYS_POLICY_NAME">ScreenLockDelays</ph> instead. + + Specifies the length of time without user input after which the screen is locked when running on AC power. When this policy is set to a value greater than zero, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> locks the screen. @@ -9139,7 +9145,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:27-'], + 'supported_on': ['chrome_os:27-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9149,7 +9155,9 @@ 'id': 197, 'caption': '''Idle warning delay when running on AC power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which a warning dialog is shown when running on AC power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which a warning dialog is shown when running on AC power. When this policy is set, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> shows a warning dialog telling the user that the idle action is about to be taken. @@ -9167,7 +9175,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9177,7 +9185,9 @@ 'id': 175, 'caption': '''Idle delay when running on AC power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the idle action is taken when running on AC power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which the idle action is taken when running on AC power. When this policy is set, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes the idle action, which can be configured separately. @@ -9193,7 +9203,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9203,7 +9213,9 @@ 'id': 176, 'caption': '''Screen dim delay when running on battery power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the screen is dimmed when running on battery power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which the screen is dimmed when running on battery power. When this policy is set to a value greater than zero, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> dims the screen. @@ -9221,7 +9233,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9231,7 +9243,9 @@ 'id': 177, 'caption': '''Screen off delay when running on battery power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the screen is turned off when running on battery power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which the screen is turned off when running on battery power. When this policy is set to a value greater than zero, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> turns off the screen. @@ -9249,7 +9263,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9259,7 +9273,9 @@ 'id': 178, 'caption': '''Screen lock delay when running on battery power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the screen is locked when running on battery power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="SCREEN_LOCK_DELAYS_POLICY_NAME">ScreenLockDelays</ph> instead. + + Specifies the length of time without user input after which the screen is locked when running on battery power. When this policy is set to a value greater than zero, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> locks the screen. @@ -9279,7 +9295,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:27-'], + 'supported_on': ['chrome_os:27-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9289,7 +9305,9 @@ 'id': 198, 'caption': '''Idle warning delay when running on battery power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which a warning dialog is shown when running on battery power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which a warning dialog is shown when running on battery power. When this policy is set, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> shows a warning dialog telling the user that the idle action is about to be taken. @@ -9307,7 +9325,7 @@ 'type': 'integer', 'minimum': 0 }, - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9317,7 +9335,9 @@ 'id': 179, 'caption': '''Idle delay when running on battery power''', 'tags': [], - 'desc': '''Specifies the length of time without user input after which the idle action is taken when running on battery power. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + Specifies the length of time without user input after which the idle action is taken when running on battery power. When this policy is set, it specifies the length of time that the user must remain idle before <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes the idle action, which can be configured separately. @@ -9355,7 +9375,7 @@ 'caption': '''Do nothing''', }, ], - 'supported_on': ['chrome_os:26-'], + 'supported_on': ['chrome_os:26-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9365,7 +9385,7 @@ 'id': 180, 'caption': '''Action to take when the idle delay is reached''', 'tags': [], - 'desc': '''Note that this policy is deprecated and will be removed in the future. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. This policy provides a fallback value for the more-specific <ph name="IDLE_ACTION_AC_POLICY_NAME">IdleActionAC</ph> and <ph name="IDLE_ACTION_BATTERY_POLICY_NAME">IdleActionBattery</ph> policies. If this policy is set, its value gets used if the respective more-specific policy is not set. @@ -9401,7 +9421,7 @@ 'caption': '''Do nothing''', }, ], - 'supported_on': ['chrome_os:30-'], + 'supported_on': ['chrome_os:30-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9411,7 +9431,9 @@ 'id': 226, 'caption': '''Action to take when the idle delay is reached while running on AC power''', 'tags': [], - 'desc': '''When this policy is set, it specifies the action that <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes when the user remains idle for the length of time given by the idle delay, which can be configured separately. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + When this policy is set, it specifies the action that <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes when the user remains idle for the length of time given by the idle delay, which can be configured separately. When this policy is unset, the default action is taken, which is suspend. @@ -9447,7 +9469,7 @@ 'caption': '''Do nothing''', }, ], - 'supported_on': ['chrome_os:30-'], + 'supported_on': ['chrome_os:30-81'], 'features': { 'dynamic_refresh': True, 'per_profile': False, @@ -9457,7 +9479,9 @@ 'id': 222, 'caption': '''Action to take when the idle delay is reached while running on battery power''', 'tags': [], - 'desc': '''When this policy is set, it specifies the action that <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes when the user remains idle for the length of time given by the idle delay, which can be configured separately. + 'desc': '''Note that this policy is deprecated and will be removed in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> version 82. Please use <ph name="POWER_MANAGEMENT_IDLE_SETTINGS_POLICY_NAME">PowerManagementIdleSettings</ph> instead. + + When this policy is set, it specifies the action that <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> takes when the user remains idle for the length of time given by the idle delay, which can be configured separately. When this policy is unset, the default action is taken, which is suspend.
diff --git a/components/sync_device_info/fake_local_device_info_provider.cc b/components/sync_device_info/fake_local_device_info_provider.cc index 3c753206..a54afa2 100644 --- a/components/sync_device_info/fake_local_device_info_provider.cc +++ b/components/sync_device_info/fake_local_device_info_provider.cc
@@ -17,7 +17,7 @@ "user_agent", sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id", - base::SysInfo::HardwareInfo{"model", "manufacturer", "serial"}, + base::SysInfo::HardwareInfo{"manufacturer", "model", "serial"}, /*last_updated_timestamp=*/base::Time::Now(), /*send_tab_to_self_receiving_enabled=*/false, /*sharing_info=*/base::nullopt) {}
diff --git a/components/url_formatter/spoof_checks/top_domains/make_top_domain_list_variables.cc b/components/url_formatter/spoof_checks/top_domains/make_top_domain_list_variables.cc index 1207cee..6e6c393 100644 --- a/components/url_formatter/spoof_checks/top_domains/make_top_domain_list_variables.cc +++ b/components/url_formatter/spoof_checks/top_domains/make_top_domain_list_variables.cc
@@ -130,13 +130,22 @@ } if (keywords.size() < kTopN) { - std::string keyword; + std::string keywords_for_current_line; base::TrimString( url_formatter::top_domains::HostnameWithoutRegistry(line), ".", - &keyword); - CHECK(keyword.find('.') == std::string::npos); - if (keywords.find(keyword) == keywords.end()) { - keywords.insert(keyword); + &keywords_for_current_line); + CHECK(keywords_for_current_line.find('.') == std::string::npos); + + for (const std::string& keyword : base::SplitString( + keywords_for_current_line, "-", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + if (keywords.find(keyword) == keywords.end()) { + keywords.insert(keyword); + } + + if (keywords.size() >= kTopN) { + break; + } } } }
diff --git a/components/viz/service/display_embedder/skia_output_device.h b/components/viz/service/display_embedder/skia_output_device.h index 9d95eea2..bec5cc0 100644 --- a/components/viz/service/display_embedder/skia_output_device.h +++ b/components/viz/service/display_embedder/skia_output_device.h
@@ -72,7 +72,7 @@ virtual ~SkiaOutputDevice(); // Changes the size of draw surface and invalidates it's contents. - virtual void Reshape(const gfx::Size& size, + virtual bool Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha,
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc index 1965d33b..88cd49e 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -327,7 +327,7 @@ FinishSwapBuffers(result, size, latency_info); } -void SkiaOutputDeviceBufferQueue::Reshape(const gfx::Size& size, +bool SkiaOutputDeviceBufferQueue::Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha, @@ -336,13 +336,14 @@ gl::ColorSpaceUtils::GetGLSurfaceColorSpace(color_space); if (!gl_surface_->Resize(size, device_scale_factor, surface_color_space, has_alpha)) { - LOG(FATAL) << "Failed to resize."; - // TODO(vasilyt): Handle the failure. + DLOG(ERROR) << "Failed to resize."; + return false; } color_space_ = color_space; image_size_ = size; FreeAllSurfaces(); + return true; } SkSurface* SkiaOutputDeviceBufferQueue::BeginPaint() {
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h index fb314ae..7387f69f 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
@@ -38,7 +38,7 @@ void PostSubBuffer(const gfx::Rect& rect, BufferPresentedCallback feedback, std::vector<ui::LatencyInfo> latency_info) override; - void Reshape(const gfx::Size& size, + bool Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha,
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.cc b/components/viz/service/display_embedder/skia_output_device_gl.cc index 2836685..88319a5 100644 --- a/components/viz/service/display_embedder/skia_output_device_gl.cc +++ b/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -82,7 +82,7 @@ SkiaOutputDeviceGL::~SkiaOutputDeviceGL() {} -void SkiaOutputDeviceGL::Reshape(const gfx::Size& size, +bool SkiaOutputDeviceGL::Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha, @@ -93,8 +93,8 @@ gl::ColorSpaceUtils::GetGLSurfaceColorSpace(color_space); if (!gl_surface_->Resize(size, device_scale_factor, surface_color_space, has_alpha)) { - LOG(FATAL) << "Failed to resize."; - // TODO(penghuang): Handle the failure. + DLOG(ERROR) << "Failed to resize."; + return false; } SkSurfaceProps surface_props = SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType); @@ -112,6 +112,7 @@ gr_context_, render_target, origin, color_type, color_space.ToSkColorSpace(), &surface_props); DCHECK(sk_surface_); + return true; } void SkiaOutputDeviceGL::SwapBuffers(
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.h b/components/viz/service/display_embedder/skia_output_device_gl.h index 798234e..c31edc57 100644 --- a/components/viz/service/display_embedder/skia_output_device_gl.h +++ b/components/viz/service/display_embedder/skia_output_device_gl.h
@@ -53,7 +53,7 @@ } // SkiaOutputDevice implementation: - void Reshape(const gfx::Size& size, + bool Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha,
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc index 075d6134..9d38dda 100644 --- a/components/viz/service/display_embedder/skia_output_device_offscreen.cc +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -36,7 +36,7 @@ DiscardBackbuffer(); } -void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size, +bool SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha, @@ -47,6 +47,7 @@ size_ = size; sk_color_space_ = color_space.ToSkColorSpace(); EnsureBackbuffer(); + return true; } void SkiaOutputDeviceOffscreen::SwapBuffers(
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.h b/components/viz/service/display_embedder/skia_output_device_offscreen.h index 1d126478..6791a3e 100644 --- a/components/viz/service/display_embedder/skia_output_device_offscreen.h +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.h
@@ -25,7 +25,7 @@ ~SkiaOutputDeviceOffscreen() override; // SkiaOutputDevice implementation: - void Reshape(const gfx::Size& size, + bool Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha,
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc index 428816b..d347a2e4 100644 --- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -41,7 +41,7 @@ } } -void SkiaOutputDeviceVulkan::Reshape(const gfx::Size& size, +bool SkiaOutputDeviceVulkan::Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha, @@ -65,6 +65,7 @@ sk_surfaces_.resize(vulkan_surface_->swap_chain()->num_images()); sk_color_space_ = std::move(sk_color_space); } + return true; } void SkiaOutputDeviceVulkan::SwapBuffers(
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.h b/components/viz/service/display_embedder/skia_output_device_vulkan.h index 5cc1c8d..1b13f6be 100644 --- a/components/viz/service/display_embedder/skia_output_device_vulkan.h +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.h
@@ -31,7 +31,7 @@ ~SkiaOutputDeviceVulkan() override; // SkiaOutputDevice implementation: - void Reshape(const gfx::Size& size, + bool Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha,
diff --git a/components/viz/service/display_embedder/skia_output_device_x11.cc b/components/viz/service/display_embedder/skia_output_device_x11.cc index c2a9f30..0ca2e67 100644 --- a/components/viz/service/display_embedder/skia_output_device_x11.cc +++ b/components/viz/service/display_embedder/skia_output_device_x11.cc
@@ -41,16 +41,19 @@ XFreeGC(display_, gc_); } -void SkiaOutputDeviceX11::Reshape(const gfx::Size& size, +bool SkiaOutputDeviceX11::Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha, gfx::OverlayTransform transform) { - SkiaOutputDeviceOffscreen::Reshape(size, device_scale_factor, color_space, - has_alpha, transform); + if (!SkiaOutputDeviceOffscreen::Reshape(size, device_scale_factor, + color_space, has_alpha, transform)) { + return false; + } auto ii = SkImageInfo::MakeN32(size.width(), size.height(), kOpaque_SkAlphaType); pixels_.reserve(ii.computeMinByteSize()); + return true; } void SkiaOutputDeviceX11::SwapBuffers(
diff --git a/components/viz/service/display_embedder/skia_output_device_x11.h b/components/viz/service/display_embedder/skia_output_device_x11.h index 4f9bec06..f298298 100644 --- a/components/viz/service/display_embedder/skia_output_device_x11.h +++ b/components/viz/service/display_embedder/skia_output_device_x11.h
@@ -23,7 +23,7 @@ DidSwapBufferCompleteCallback did_swap_buffer_complete_callback); ~SkiaOutputDeviceX11() override; - void Reshape(const gfx::Size& size, + bool Reshape(const gfx::Size& size, float device_scale_factor, const gfx::ColorSpace& color_space, bool has_alpha,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 944edcba..c914400 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -676,8 +676,11 @@ size_ = size; color_space_ = color_space; - output_device_->Reshape(size_, device_scale_factor, color_space, has_alpha, - transform); + if (!output_device_->Reshape(size_, device_scale_factor, color_space, + has_alpha, transform)) { + MarkContextLost(); + return; + } if (characterization) { // Start a paint temporarily for getting sk surface characterization.
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc index 97a0b25c..2737f3f 100644 --- a/components/viz/service/gl/gpu_service_impl.cc +++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -131,12 +131,6 @@ base::RetainedRef(std::move(runner)), std::move(callback)); } -void DestroyBinding(mojo::BindingSet<mojom::GpuService>* binding, - base::WaitableEvent* wait) { - binding->CloseAllBindings(); - wait->Signal(); -} - } // namespace GpuServiceImpl::GpuServiceImpl( @@ -163,8 +157,7 @@ #if BUILDFLAG(ENABLE_VULKAN) vulkan_implementation_(vulkan_implementation), #endif - exit_callback_(std::move(exit_callback)), - bindings_(std::make_unique<mojo::BindingSet<mojom::GpuService>>()) { + exit_callback_(std::move(exit_callback)) { DCHECK(!io_runner_->BelongsToCurrentThread()); DCHECK(exit_callback_); @@ -214,11 +207,18 @@ bind_task_tracker_.TryCancelAll(); logging::SetLogMessageHandler(nullptr); g_log_callback.Get().Reset(); + + // Destroy the receiver on the IO thread. base::WaitableEvent wait; - if (io_runner_->PostTask( - FROM_HERE, base::BindOnce(&DestroyBinding, bindings_.get(), &wait))) { + auto destroy_receiver_task = base::BindOnce( + [](mojo::Receiver<mojom::GpuService>* receiver, + base::WaitableEvent* wait) { + receiver->reset(); + wait->Signal(); + }, + &receiver_, &wait); + if (io_runner_->PostTask(FROM_HERE, std::move(destroy_receiver_task))) wait.Wait(); - } if (watchdog_thread_) watchdog_thread_->OnGpuProcessTearDown(); @@ -338,15 +338,17 @@ watchdog_thread()->AddPowerObserver(); } -void GpuServiceImpl::Bind(mojom::GpuServiceRequest request) { +void GpuServiceImpl::Bind( + mojo::PendingReceiver<mojom::GpuService> pending_receiver) { if (main_runner_->BelongsToCurrentThread()) { bind_task_tracker_.PostTask( io_runner_.get(), FROM_HERE, base::BindOnce(&GpuServiceImpl::Bind, base::Unretained(this), - std::move(request))); + std::move(pending_receiver))); return; } - bindings_->AddBinding(this, std::move(request)); + DCHECK(!receiver_.is_bound()); + receiver_.Bind(std::move(pending_receiver)); } void GpuServiceImpl::DisableGpuCompositing() { @@ -727,13 +729,22 @@ bool is_gpu_host, bool cache_shaders_on_disk, EstablishGpuChannelCallback callback) { - if (gpu::IsReservedClientId(client_id)) { - // This returns a null handle, which is treated by the client as a failure - // case. - std::move(callback).Run(mojo::ScopedMessagePipeHandle()); - return; - } + // This should always be called on the IO thread first. if (io_runner_->BelongsToCurrentThread()) { + if (IsExiting()) { + // We are already exiting so there is no point in responding. Close the + // receiver so we can safely drop the callback. + receiver_.reset(); + return; + } + + if (gpu::IsReservedClientId(client_id)) { + // This returns a null handle, which is treated by the client as a failure + // case. + std::move(callback).Run(mojo::ScopedMessagePipeHandle()); + return; + } + EstablishGpuChannelCallback wrap_callback = base::BindOnce( [](scoped_refptr<base::SingleThreadTaskRunner> runner, EstablishGpuChannelCallback cb,
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h index 466f20ed..d0887e9e 100644 --- a/components/viz/service/gl/gpu_service_impl.h +++ b/components/viz/service/gl/gpu_service_impl.h
@@ -32,7 +32,8 @@ #include "gpu/ipc/service/gpu_config.h" #include "gpu/ipc/service/x_util.h" #include "gpu/vulkan/buildflags.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" #include "services/viz/privileged/mojom/gl/gpu_host.mojom.h" @@ -98,7 +99,7 @@ gpu::SyncPointManager* sync_point_manager = nullptr, gpu::SharedImageManager* shared_image_manager = nullptr, base::WaitableEvent* shutdown_event = nullptr); - void Bind(mojom::GpuServiceRequest request); + void Bind(mojo::PendingReceiver<mojom::GpuService> pending_receiver); scoped_refptr<gpu::SharedContextState> GetContextState(); @@ -358,9 +359,10 @@ base::Time start_time_; - // Used to track the task to bind a GpuServiceRequest on the io thread. + // Used to track the task to bind |receiver_| on the IO thread. base::CancelableTaskTracker bind_task_tracker_; - std::unique_ptr<mojo::BindingSet<mojom::GpuService>> bindings_; + // Should only be accessed on the IO thread after creation. + mojo::Receiver<mojom::GpuService> receiver_{this}; #if defined(OS_WIN) // Used to track if the Dx Diag task on a different thread is still running.
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 63ac0dd..d85a4dba 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -1656,6 +1656,13 @@ return false; } +base::string16 BrowserAccessibilityAndroid::GetTargetUrl() const { + if (ui::IsImage(GetRole()) || ui::IsLink(GetRole())) + return GetString16Attribute(ax::mojom::StringAttribute::kUrl); + + return {}; +} + bool BrowserAccessibilityAndroid::HasNonEmptyValue() const { return IsEditableText() && !GetValue().empty(); }
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h index 8143ac7..0ba2681 100644 --- a/content/browser/accessibility/browser_accessibility_android.h +++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -151,6 +151,9 @@ std::vector<int32_t>* word_ends, int offset); + // Return the target of a link or the source of an image. + base::string16 GetTargetUrl() const; + // Used to keep track of when to stop reporting content_invalid. // Timer only applies if node has focus. void ResetContentInvalidTimer();
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc index 1ad1431..adbbfd64 100644 --- a/content/browser/accessibility/web_contents_accessibility_android.cc +++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -736,7 +736,8 @@ base::android::ConvertUTF16ToJavaString(env, node->GetHint()), node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelStart), node->GetIntAttribute(ax::mojom::IntAttribute::kTextSelEnd), - node->HasImage(), node->IsContentInvalid()); + node->HasImage(), node->IsContentInvalid(), + base::android::ConvertUTF16ToJavaString(env, node->GetTargetUrl())); Java_WebContentsAccessibilityImpl_setAccessibilityNodeInfoLollipopAttributes( env, obj, info, node->CanOpenPopup(), node->IsContentInvalid(),
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index 2fe8a97..8f0757b 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -2358,7 +2358,7 @@ protected: base::FieldTrialParams GetFeatureParams() override { - return {{"experimental extended supported feature set", "true"}}; + return {{"service_worker_supported", "true"}}; } }; @@ -2619,7 +2619,7 @@ GeolocationBackForwardCacheBrowserTest() : geo_override_(0.0, 0.0) {} base::FieldTrialParams GetFeatureParams() override { - return {{"experimental extended supported feature set", "true"}}; + return {{"geolocation_supported", "true"}}; } device::ScopedGeolocationOverrider geo_override_; @@ -3047,6 +3047,14 @@ // not be stored in back-forward cache. EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); delete_observer_rfh_b.WaitUntilDeleted(); + + // 6) Go back to B. + web_contents()->GetController().GoBack(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + + // Nothing is recorded when the domain does not match. + ExpectOutcomeIsEmpty(FROM_HERE); + ExpectNotRestoredIsEmpty(FROM_HERE); } // Check the BackForwardCache is disabled when the WebUSB feature is used.
diff --git a/content/browser/code_cache/generated_code_cache.cc b/content/browser/code_cache/generated_code_cache.cc index 69e2c59..257223cc 100644 --- a/content/browser/code_cache/generated_code_cache.cc +++ b/content/browser/code_cache/generated_code_cache.cc
@@ -6,7 +6,9 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/string_number_conversions.h" #include "content/public/common/url_constants.h" +#include "crypto/sha2.h" #include "net/base/completion_once_callback.h" #include "net/base/url_util.h" #include "url/gurl.h" @@ -67,20 +69,51 @@ return key; } -constexpr int kResponseTimeSizeInBytes = sizeof(int64_t); -constexpr int kDataSizeInBytes = sizeof(uint32_t); -constexpr int kHeaderSizeInBytes = kResponseTimeSizeInBytes + kDataSizeInBytes; +constexpr size_t kResponseTimeSizeInBytes = sizeof(int64_t); +constexpr size_t kDataSizeInBytes = sizeof(uint32_t); +constexpr size_t kHeaderSizeInBytes = + kResponseTimeSizeInBytes + kDataSizeInBytes; +// The SHA-256 checksum is used as the key for the de-duplicated code data. We +// must convert the checksum to a string key in a way that is guaranteed not to +// match a key generated by |GetCacheKey|. A simple way to do this is to convert +// it to a hex number string, which is twice as long as the checksum. +constexpr size_t kSHAKeySizeInBytes = 2 * crypto::kSHA256Length; + // This is the threshold for storing the header and cached code in stream 0, // which is read into memory on opening an entry. JavaScript code caching stores // time stamps with no data, or timestamps with just a tag, and we observe many -// 8 and 16 byte reads and writes. Make the threshold larger to speed up many +// 8 and 16 byte reads and writes. Make the threshold larger to speed up small // code entries too. -constexpr int kSmallDataLimit = 4096; +constexpr size_t kSmallDataLimit = 4096; +// This is the maximum size for code that will be stored under the key generated +// by |GetCacheKey|. Each origin will get its own copy of the generated code for +// a given resource. Code that is larger than this limit will be stored under a +// key derived from the code checksum, and each origin using a given resource +// gets its own small entry under the key generated by |GetCacheKey| that holds +// the hash, enabling a two stage lookup. +constexpr size_t kLargeDataLimit = 64 * 1024; -void WriteSmallDataHeader(scoped_refptr<net::IOBufferWithSize> buffer, - const base::Time& response_time, - uint32_t data_size) { - DCHECK_LE(kHeaderSizeInBytes, buffer->size()); +// Checks that the header data in the small buffer is valid. We may read cache +// entries that were written by a previous version of Chrome which use obsolete +// formats. These reads should fail and be doomed as soon as possible. +bool IsValidHeader(scoped_refptr<net::IOBufferWithSize> small_buffer) { + size_t buffer_size = small_buffer->size(); + if (buffer_size < kHeaderSizeInBytes) + return false; + uint32_t data_size; + memcpy(&data_size, small_buffer->data() + kResponseTimeSizeInBytes, + kDataSizeInBytes); + if (data_size <= kSmallDataLimit) + return buffer_size == kHeaderSizeInBytes + data_size; + if (data_size <= kLargeDataLimit) + return buffer_size == kHeaderSizeInBytes; + return buffer_size == kHeaderSizeInBytes + kSHAKeySizeInBytes; +} + +void WriteCommonDataHeader(scoped_refptr<net::IOBufferWithSize> buffer, + const base::Time& response_time, + uint32_t data_size) { + DCHECK_LE(static_cast<int>(kHeaderSizeInBytes), buffer->size()); int64_t serialized_time = response_time.ToDeltaSinceWindowsEpoch().InMicroseconds(); memcpy(buffer->data(), &serialized_time, kResponseTimeSizeInBytes); @@ -89,15 +122,16 @@ kDataSizeInBytes); } -void ReadSmallDataHeader(scoped_refptr<net::IOBufferWithSize> buffer, - base::Time* response_time, - uint32_t* data_size) { - DCHECK_LE(kHeaderSizeInBytes, buffer->size()); - int64_t raw_response_time = *(reinterpret_cast<int64_t*>(buffer->data())); +void ReadCommonDataHeader(scoped_refptr<net::IOBufferWithSize> buffer, + base::Time* response_time, + uint32_t* data_size) { + DCHECK_LE(static_cast<int>(kHeaderSizeInBytes), buffer->size()); + int64_t raw_response_time; + memcpy(&raw_response_time, buffer->data(), kResponseTimeSizeInBytes); *response_time = base::Time::FromDeltaSinceWindowsEpoch( base::TimeDelta::FromMicroseconds(raw_response_time)); - *data_size = - *(reinterpret_cast<uint32_t*>(buffer->data() + kResponseTimeSizeInBytes)); + memcpy(data_size, buffer->data() + kResponseTimeSizeInBytes, + kDataSizeInBytes); } static_assert(mojo_base::BigBuffer::kMaxInlineBytes <= @@ -171,7 +205,7 @@ key_(key), small_buffer_(small_buffer), large_buffer_(large_buffer) { - DCHECK_EQ(Operation::kWrite, op_); + DCHECK(Operation::kWrite == op_ || Operation::kWriteWithSHAKey == op_); } PendingOperation(Operation op, @@ -181,6 +215,21 @@ DCHECK_EQ(Operation::kFetch, op_); } + PendingOperation(Operation op, + const std::string& key, + const base::Time& response_time, + scoped_refptr<net::IOBufferWithSize> small_buffer, + scoped_refptr<BigIOBuffer> large_buffer, + ReadDataCallback read_callback) + : op_(op), + key_(key), + response_time_(response_time), + small_buffer_(small_buffer), + large_buffer_(large_buffer), + read_callback_(std::move(read_callback)) { + DCHECK_EQ(Operation::kFetchWithSHAKey, op_); + } + PendingOperation(Operation op, const std::string& key) : op_(op), key_(key) { DCHECK_EQ(Operation::kDelete, op_); } @@ -212,12 +261,19 @@ large_buffer_ = large_buffer; } + // This returns the site-specific response time for merged code entries. + const base::Time& response_time() const { + DCHECK_EQ(Operation::kFetchWithSHAKey, op_); + return response_time_; + } + // These are called by write and fetch operations to track buffer completions // and signal when the operation has finished, and whether it was successful. bool succeeded() const { return succeeded_; } bool AddBufferCompletion(bool succeeded) { - DCHECK(op_ == Operation::kWrite || op_ == Operation::kFetch); + DCHECK(op_ == Operation::kWrite || op_ == Operation::kWriteWithSHAKey || + op_ == Operation::kFetch || op_ == Operation::kFetchWithSHAKey); if (!succeeded) succeeded_ = false; DCHECK_GT(2, completions_); @@ -228,6 +284,7 @@ private: const Operation op_; const std::string key_; + const base::Time response_time_; scoped_refptr<net::IOBufferWithSize> small_buffer_; scoped_refptr<BigIOBuffer> large_buffer_; ReadDataCallback read_callback_; @@ -275,37 +332,67 @@ return; } - // If data is small, combine the header and data into a single write. + // Reject buffers that are large enough to cause overflow problems. + if (data.size() >= std::numeric_limits<int32_t>::max()) + return; + scoped_refptr<net::IOBufferWithSize> small_buffer; scoped_refptr<BigIOBuffer> large_buffer; uint32_t data_size = static_cast<uint32_t>(data.size()); + // We have three different cache entry layouts, depending on data size. if (data_size <= kSmallDataLimit) { + // 1. Small + // [stream0] response time, size, data + // [stream1] <empty> small_buffer = base::MakeRefCounted<net::IOBufferWithSize>( kHeaderSizeInBytes + data.size()); // Copy |data| into the small buffer. memcpy(small_buffer->data() + kHeaderSizeInBytes, data.data(), data.size()); - // We write 0 bytes and truncate stream 1 to clear any stale data. + // Write 0 bytes and truncate stream 1 to clear any stale data. large_buffer = base::MakeRefCounted<BigIOBuffer>(mojo_base::BigBuffer()); - } else { + } else if (data_size <= kLargeDataLimit) { + // 2. Large + // [stream0] response time, size + // [stream1] data small_buffer = base::MakeRefCounted<net::IOBufferWithSize>(kHeaderSizeInBytes); large_buffer = base::MakeRefCounted<BigIOBuffer>(std::move(data)); + } else { + // 3. Very Large + // [stream0] response time, size, checksum + // [stream1] <empty> + // [stream0 (checksum key entry)] <empty> + // [stream1 (checksum key entry)] data + uint8_t result[crypto::kSHA256Length]; + crypto::SHA256HashString( + base::StringPiece(reinterpret_cast<char*>(data.data()), data.size()), + result, base::size(result)); + std::string checksum_key = base::HexEncode(result, base::size(result)); + small_buffer = base::MakeRefCounted<net::IOBufferWithSize>( + kHeaderSizeInBytes + kSHAKeySizeInBytes); + // Copy |checksum_key| into the small buffer. + DCHECK_EQ(kSHAKeySizeInBytes, checksum_key.length()); + memcpy(small_buffer->data() + kHeaderSizeInBytes, checksum_key.data(), + kSHAKeySizeInBytes); + // Write 0 bytes and truncate stream 1 to clear any stale data. + large_buffer = base::MakeRefCounted<BigIOBuffer>(mojo_base::BigBuffer()); + + // Issue another write operation for the code, with the checksum as the key + // and nothing in the header. + auto small_buffer2 = base::MakeRefCounted<net::IOBufferWithSize>(0); + auto large_buffer2 = base::MakeRefCounted<BigIOBuffer>(std::move(data)); + auto op2 = std::make_unique<PendingOperation>(Operation::kWriteWithSHAKey, + checksum_key, small_buffer2, + large_buffer2); + EnqueueOperation(std::move(op2)); } - WriteSmallDataHeader(small_buffer, response_time, data_size); + WriteCommonDataHeader(small_buffer, response_time, data_size); // Create the write operation. std::string key = GetCacheKey(url, origin_lock); auto op = std::make_unique<PendingOperation>(Operation::kWrite, key, small_buffer, large_buffer); - - if (backend_state_ != kInitialized) { - // Insert it into the list of pending operations while the backend is - // still being opened. - pending_ops_.emplace(std::move(op)); - return; - } - - EnqueueOperationAndIssueIfNext(std::move(op)); + EnqueueOperation(std::move(op)); } void GeneratedCodeCache::FetchEntry(const GURL& url, @@ -321,14 +408,7 @@ std::string key = GetCacheKey(url, origin_lock); auto op = std::make_unique<PendingOperation>(Operation::kFetch, key, std::move(read_data_callback)); - if (backend_state_ != kInitialized) { - // Insert it into the list of pending operations while the backend is - // still being opened. - pending_ops_.emplace(std::move(op)); - return; - } - - EnqueueOperationAndIssueIfNext(std::move(op)); + EnqueueOperation(std::move(op)); } void GeneratedCodeCache::DeleteEntry(const GURL& url, const GURL& origin_lock) { @@ -340,15 +420,7 @@ std::string key = GetCacheKey(url, origin_lock); auto op = std::make_unique<PendingOperation>(Operation::kDelete, key); - - if (backend_state_ != kInitialized) { - // Insert it into the list of pending operations while the backend is - // still being opened. - pending_ops_.emplace(std::move(op)); - return; - } - - EnqueueOperationAndIssueIfNext(std::move(op)); + EnqueueOperation(std::move(op)); } void GeneratedCodeCache::CreateBackend() { @@ -386,6 +458,18 @@ IssuePendingOperations(); } +void GeneratedCodeCache::EnqueueOperation( + std::unique_ptr<PendingOperation> op) { + if (backend_state_ != kInitialized) { + // Insert it into the list of pending operations while the backend is + // still being opened. + pending_ops_.emplace(std::move(op)); + return; + } + + EnqueueOperationAndIssueIfNext(std::move(op)); +} + void GeneratedCodeCache::IssuePendingOperations() { // Issue any operations that were received while creating the backend. while (!pending_ops_.empty()) { @@ -407,9 +491,11 @@ void GeneratedCodeCache::IssueOperation(PendingOperation* op) { switch (op->operation()) { case kFetch: + case kFetchWithSHAKey: FetchEntryImpl(op); break; case kWrite: + case kWriteWithSHAKey: WriteEntryImpl(op); break; case kDelete: @@ -422,7 +508,8 @@ } void GeneratedCodeCache::WriteEntryImpl(PendingOperation* op) { - DCHECK_EQ(Operation::kWrite, op->operation()); + DCHECK(Operation::kWrite == op->operation() || + Operation::kWriteWithSHAKey == op->operation()); if (backend_state_ != kInitialized) { // Silently fail the request. CloseOperationAndIssueNext(op); @@ -442,7 +529,8 @@ void GeneratedCodeCache::OpenCompleteForWrite( PendingOperation* op, disk_cache::EntryResult entry_result) { - DCHECK_EQ(Operation::kWrite, op->operation()); + DCHECK(Operation::kWrite == op->operation() || + Operation::kWriteWithSHAKey == op->operation()); if (entry_result.net_error() != net::OK) { CollectStatistics(CacheEntryStatus::kError); CloseOperationAndIssueNext(op); @@ -459,6 +547,20 @@ // There should be a valid entry if the open was successful. DCHECK(entry); + // For merged entries, don't write if the entry already exists. + if (op->operation() == Operation::kWriteWithSHAKey) { + int small_size = entry->GetDataSize(kSmallDataStream); + int large_size = entry->GetDataSize(kLargeDataStream); + if (small_size == 0 && large_size == op->large_buffer()->size()) { + // Skip overwriting with identical data. + CloseOperationAndIssueNext(op); + return; + } + // Otherwise, there shouldn't be any data for this entry yet. + DCHECK_EQ(0, small_size); + DCHECK_EQ(0, large_size); + } + // Write the small data first, truncating. auto small_buffer = op->small_buffer(); int result = entry->WriteData( @@ -486,7 +588,8 @@ void GeneratedCodeCache::WriteSmallBufferComplete(PendingOperation* op, int rv) { - DCHECK_EQ(Operation::kWrite, op->operation()); + DCHECK(Operation::kWrite == op->operation() || + Operation::kWriteWithSHAKey == op->operation()); if (op->AddBufferCompletion(rv == op->small_buffer()->size())) { WriteComplete(op); } @@ -494,14 +597,16 @@ void GeneratedCodeCache::WriteLargeBufferComplete(PendingOperation* op, int rv) { - DCHECK_EQ(Operation::kWrite, op->operation()); + DCHECK(Operation::kWrite == op->operation() || + Operation::kWriteWithSHAKey == op->operation()); if (op->AddBufferCompletion(rv == op->large_buffer()->size())) { WriteComplete(op); } } void GeneratedCodeCache::WriteComplete(PendingOperation* op) { - DCHECK_EQ(Operation::kWrite, op->operation()); + DCHECK(Operation::kWrite == op->operation() || + Operation::kWriteWithSHAKey == op->operation()); if (!op->succeeded()) { // The write failed; record the failure and doom the entry here. CollectStatistics(CacheEntryStatus::kWriteFailed); @@ -511,7 +616,8 @@ } void GeneratedCodeCache::FetchEntryImpl(PendingOperation* op) { - DCHECK_EQ(Operation::kFetch, op->operation()); + DCHECK(Operation::kFetch == op->operation() || + Operation::kFetchWithSHAKey == op->operation()); if (backend_state_ != kInitialized) { op->TakeReadCallback().Run(base::Time(), mojo_base::BigBuffer()); CloseOperationAndIssueNext(op); @@ -531,7 +637,8 @@ void GeneratedCodeCache::OpenCompleteForRead( PendingOperation* op, disk_cache::EntryResult entry_result) { - DCHECK_EQ(Operation::kFetch, op->operation()); + DCHECK(Operation::kFetch == op->operation() || + Operation::kFetchWithSHAKey == op->operation()); if (entry_result.net_error() != net::OK) { CollectStatistics(CacheEntryStatus::kMiss); op->TakeReadCallback().Run(base::Time(), mojo_base::BigBuffer()); @@ -544,13 +651,20 @@ DCHECK(entry); int small_size = entry->GetDataSize(kSmallDataStream); - scoped_refptr<net::IOBufferWithSize> small_buffer = - base::MakeRefCounted<net::IOBufferWithSize>(small_size); - op->set_small_buffer(small_buffer); int large_size = entry->GetDataSize(kLargeDataStream); - scoped_refptr<BigIOBuffer> large_buffer = - base::MakeRefCounted<BigIOBuffer>(large_size); - op->set_large_buffer(large_buffer); + scoped_refptr<net::IOBufferWithSize> small_buffer; + scoped_refptr<BigIOBuffer> large_buffer; + if (op->operation() == Operation::kFetch) { + small_buffer = base::MakeRefCounted<net::IOBufferWithSize>(small_size); + op->set_small_buffer(small_buffer); + large_buffer = base::MakeRefCounted<BigIOBuffer>(large_size); + op->set_large_buffer(large_buffer); + } else { + small_buffer = op->small_buffer(); + large_buffer = op->large_buffer(); + DCHECK_EQ(small_size, small_buffer->size()); + DCHECK_EQ(large_size, large_buffer->size()); + } // Read the small data first. int result = entry->ReadData( @@ -577,8 +691,11 @@ } void GeneratedCodeCache::ReadSmallBufferComplete(PendingOperation* op, int rv) { - DCHECK_EQ(Operation::kFetch, op->operation()); - bool succeeded = rv == op->small_buffer()->size() && rv >= kHeaderSizeInBytes; + DCHECK(Operation::kFetch == op->operation() || + Operation::kFetchWithSHAKey == op->operation()); + bool no_header = op->operation() == Operation::kFetchWithSHAKey; + bool succeeded = (rv == op->small_buffer()->size() && + (no_header || IsValidHeader(op->small_buffer()))); CollectStatistics(succeeded ? CacheEntryStatus::kHit : CacheEntryStatus::kMiss); @@ -591,30 +708,52 @@ } void GeneratedCodeCache::ReadLargeBufferComplete(PendingOperation* op, int rv) { - DCHECK_EQ(Operation::kFetch, op->operation()); + DCHECK(Operation::kFetch == op->operation() || + Operation::kFetchWithSHAKey == op->operation()); if (op->AddBufferCompletion(rv == op->large_buffer()->size())) ReadComplete(op); } void GeneratedCodeCache::ReadComplete(PendingOperation* op) { - DCHECK_EQ(Operation::kFetch, op->operation()); + DCHECK(Operation::kFetch == op->operation() || + Operation::kFetchWithSHAKey == op->operation()); if (!op->succeeded()) { op->TakeReadCallback().Run(base::Time(), mojo_base::BigBuffer()); // Doom this entry since it is inaccessible. DoomEntry(op); } else { - base::Time response_time; - uint32_t data_size = 0; - ReadSmallDataHeader(op->small_buffer(), &response_time, &data_size); - if (data_size <= kSmallDataLimit) { - // Small data, copy the data from the small buffer. - DCHECK_EQ(0, op->large_buffer()->size()); - mojo_base::BigBuffer data(data_size); - memcpy(data.data(), op->small_buffer()->data() + kHeaderSizeInBytes, - data_size); - op->TakeReadCallback().Run(response_time, std::move(data)); + if (op->operation() != Operation::kFetchWithSHAKey) { + base::Time response_time; + uint32_t data_size = 0; + ReadCommonDataHeader(op->small_buffer(), &response_time, &data_size); + if (data_size <= kSmallDataLimit) { + // Small data. Copy the data from the small buffer. + DCHECK_EQ(0, op->large_buffer()->size()); + mojo_base::BigBuffer data(data_size); + memcpy(data.data(), op->small_buffer()->data() + kHeaderSizeInBytes, + data_size); + op->TakeReadCallback().Run(response_time, std::move(data)); + } else if (data_size <= kLargeDataLimit) { + // Large data below the merging threshold. Return the large buffer. + op->TakeReadCallback().Run(response_time, + op->large_buffer()->TakeBuffer()); + } else { + // Very large data. Create the second fetch using the checksum as key. + DCHECK_EQ(static_cast<int>(kHeaderSizeInBytes + kSHAKeySizeInBytes), + op->small_buffer()->size()); + std::string checksum_key( + op->small_buffer()->data() + kHeaderSizeInBytes, + kSHAKeySizeInBytes); + auto small_buffer = base::MakeRefCounted<net::IOBufferWithSize>(0); + auto large_buffer = base::MakeRefCounted<BigIOBuffer>(data_size); + auto op2 = std::make_unique<PendingOperation>( + Operation::kFetchWithSHAKey, checksum_key, response_time, + small_buffer, large_buffer, op->TakeReadCallback()); + EnqueueOperation(std::move(op2)); + } } else { - op->TakeReadCallback().Run(response_time, + // Large merged code data with no header. |op| holds the response time. + op->TakeReadCallback().Run(op->response_time(), op->large_buffer()->TakeBuffer()); } } @@ -622,7 +761,7 @@ } void GeneratedCodeCache::DeleteEntryImpl(PendingOperation* op) { - DCHECK(op->operation() == Operation::kDelete); + DCHECK_EQ(Operation::kDelete, op->operation()); DoomEntry(op); CloseOperationAndIssueNext(op); }
diff --git a/content/browser/code_cache/generated_code_cache.h b/content/browser/code_cache/generated_code_cache.h index 71304e0f..6d6d033 100644 --- a/content/browser/code_cache/generated_code_cache.h +++ b/content/browser/code_cache/generated_code_cache.h
@@ -119,7 +119,14 @@ enum BackendState { kInitializing, kInitialized, kFailed }; // The operation requested. - enum Operation { kFetch, kWrite, kDelete, kGetBackend }; + enum Operation { + kFetch, + kFetchWithSHAKey, + kWrite, + kWriteWithSHAKey, + kDelete, + kGetBackend + }; // Data streams corresponding to each entry. enum { kSmallDataStream = 0, kLargeDataStream = 1 }; @@ -130,6 +137,9 @@ scoped_refptr<base::RefCountedData<ScopedBackendPtr>> backend_ptr, int rv); + // Adds operation to the appropriate queue. + void EnqueueOperation(std::unique_ptr<PendingOperation> op); + // Issues ops that were received while the backend was being initialized. void IssuePendingOperations(); void IssueOperation(PendingOperation* op);
diff --git a/content/browser/code_cache/generated_code_cache_unittest.cc b/content/browser/code_cache/generated_code_cache_unittest.cc index 953ae5a..e924c6f 100644 --- a/content/browser/code_cache/generated_code_cache_unittest.cc +++ b/content/browser/code_cache/generated_code_cache_unittest.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/files/scoped_temp_dir.h" +#include "base/strings/string_number_conversions.h" #include "base/test/task_environment.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h" @@ -17,8 +18,15 @@ class GeneratedCodeCacheTest : public testing::Test { public: - static const int kLargeSizeInBytes = 8192; - static const int kMaxSizeInBytes = 1024 * 1024; + // This should be larger than |kSmallDataLimit| in generated_code_cache.cc. + static const size_t kLargeSizeInBytes = 8192; + // This should be larger than |kLargeDataLimit| in generated_code_cache.cc. + // Additionally, this shouldn't exceed 1/8 of the maximum cache size below, + // |kMaxSizeInBytes|. + static const size_t kVeryLargeSizeInBytes = 128 * 1024; + static const size_t kMaxSizeInBytes = 1024 * 1024; + static_assert(kMaxSizeInBytes / kVeryLargeSizeInBytes > 0UL, + "Cache will be too small to hold a very large item"); static constexpr char kInitialUrl[] = "http://example.com/script.js"; static constexpr char kInitialOrigin[] = "http://example.com"; static constexpr char kInitialData[] = "InitialData"; @@ -121,7 +129,7 @@ constexpr char GeneratedCodeCacheTest::kInitialUrl[]; constexpr char GeneratedCodeCacheTest::kInitialOrigin[]; constexpr char GeneratedCodeCacheTest::kInitialData[]; -const int GeneratedCodeCacheTest::kMaxSizeInBytes; +const size_t GeneratedCodeCacheTest::kMaxSizeInBytes; TEST_F(GeneratedCodeCacheTest, CheckResponseTime) { GURL url(kInitialUrl); @@ -131,7 +139,6 @@ std::string data = "SerializedCodeForScript"; base::Time response_time = base::Time::Now(); WriteToCache(url, origin_lock, data, response_time); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -160,7 +167,6 @@ std::string data = "SerializedCodeForScript"; base::Time response_time = base::Time::Now(); WriteToCache(new_url, origin_lock, data, response_time); - task_environment_.RunUntilIdle(); FetchFromCache(new_url, origin_lock); task_environment_.RunUntilIdle(); @@ -177,7 +183,22 @@ std::string large_data(kLargeSizeInBytes, 'x'); base::Time response_time = base::Time::Now(); WriteToCache(new_url, origin_lock, large_data, response_time); + FetchFromCache(new_url, origin_lock); task_environment_.RunUntilIdle(); + + ASSERT_TRUE(received_); + EXPECT_EQ(large_data, received_data_); + EXPECT_EQ(response_time, received_response_time_); +} + +TEST_F(GeneratedCodeCacheTest, WriteVeryLargeEntry) { + GURL new_url("http://example1.com/script.js"); + GURL origin_lock = GURL(kInitialOrigin); + + InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); + std::string large_data(kVeryLargeSizeInBytes, 'x'); + base::Time response_time = base::Time::Now(); + WriteToCache(new_url, origin_lock, large_data, response_time); FetchFromCache(new_url, origin_lock); task_environment_.RunUntilIdle(); @@ -206,7 +227,6 @@ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); base::Time response_time = base::Time::Now(); WriteToCache(url, origin_lock, std::string(), response_time); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -223,7 +243,6 @@ base::Time response_time = base::Time::Now(); std::string too_big_data(kMaxSizeInBytes * 8, 0); WriteToCache(url, origin_lock, too_big_data, response_time); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -245,7 +264,6 @@ base::Time response_time = base::Time::Now(); std::string too_big_data(kMaxSizeInBytes * 8, 0); WriteToCache(url, origin_lock, too_big_data, response_time); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -275,7 +293,6 @@ std::string data = "SerializedCodeForScript"; base::Time response_time = base::Time::Now(); WriteToCache(new_url, origin_lock, data, response_time); - task_environment_.RunUntilIdle(); FetchFromCache(new_url, origin_lock); task_environment_.RunUntilIdle(); @@ -292,7 +309,22 @@ std::string large_data(kLargeSizeInBytes, 'x'); base::Time response_time = base::Time::Now(); WriteToCache(new_url, origin_lock, large_data, response_time); + FetchFromCache(new_url, origin_lock); task_environment_.RunUntilIdle(); + + ASSERT_TRUE(received_); + EXPECT_EQ(large_data, received_data_); + EXPECT_EQ(response_time, received_response_time_); +} + +TEST_F(GeneratedCodeCacheTest, WriteVeryLargeEntryPendingOp) { + GURL new_url("http://example1.com/script1.js"); + GURL origin_lock = GURL(kInitialOrigin); + + InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); + std::string large_data(kVeryLargeSizeInBytes, 'x'); + base::Time response_time = base::Time::Now(); + WriteToCache(new_url, origin_lock, large_data, response_time); FetchFromCache(new_url, origin_lock); task_environment_.RunUntilIdle(); @@ -322,7 +354,6 @@ std::string new_data = "SerializedCodeForScriptOverwrite"; base::Time response_time = base::Time::Now(); WriteToCache(url, origin_lock, new_data, response_time); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -339,7 +370,6 @@ std::string new_data(kLargeSizeInBytes, 'x'); base::Time response_time = base::Time::Now(); WriteToCache(url, origin_lock, new_data, response_time); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -359,7 +389,25 @@ std::string new_data = large_data + "Overwrite"; response_time = base::Time::Now(); WriteToCache(url, origin_lock, new_data, response_time); + FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); + + ASSERT_TRUE(received_); + EXPECT_EQ(new_data, received_data_); + EXPECT_EQ(response_time, received_response_time_); +} + +TEST_F(GeneratedCodeCacheTest, UpdateDataOfVeryLargeExistingEntry) { + GURL url(kInitialUrl); + GURL origin_lock = GURL(kInitialOrigin); + + InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); + std::string large_data(kVeryLargeSizeInBytes, 'x'); + base::Time response_time = base::Time::Now(); + WriteToCache(url, origin_lock, large_data, response_time); + std::string new_data = large_data + "Overwrite"; + response_time = base::Time::Now(); + WriteToCache(url, origin_lock, new_data, response_time); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -379,7 +427,25 @@ std::string new_data = "SerializedCodeForScriptOverwrite"; response_time = base::Time::Now(); WriteToCache(url, origin_lock, new_data, response_time); + FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); + + ASSERT_TRUE(received_); + EXPECT_EQ(new_data, received_data_); + EXPECT_EQ(response_time, received_response_time_); +} + +TEST_F(GeneratedCodeCacheTest, TruncateDataOfVeryLargeExistingEntry) { + GURL url(kInitialUrl); + GURL origin_lock = GURL(kInitialOrigin); + + InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); + std::string large_data(kVeryLargeSizeInBytes, 'x'); + base::Time response_time = base::Time::Now(); + WriteToCache(url, origin_lock, large_data, response_time); + std::string new_data = "SerializedCodeForScriptOverwrite"; + response_time = base::Time::Now(); + WriteToCache(url, origin_lock, new_data, response_time); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -409,7 +475,6 @@ std::string data_second_resource = "SerializedCodeForSecondResource"; WriteToCache(second_url, origin_lock, data_second_resource, base::Time()); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -433,7 +498,6 @@ std::string data_origin1 = "SerializedCodeForSecondOrigin"; WriteToCache(url, origin_lock1, data_origin1, base::Time()); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -446,6 +510,74 @@ EXPECT_EQ(data_origin1, received_data_); } +TEST_F(GeneratedCodeCacheTest, VeryLargeEntriesAreMerged) { + GURL url("http://example.com/script.js"); + InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); + + // Write more copies of the same resource than the cache can hold unless they + // are merged by content. + for (size_t i = 0; i < 2 * kMaxSizeInBytes / kVeryLargeSizeInBytes; ++i) { + GURL origin_lock = GURL(std::string("http://example") + + base::NumberToString(i) + std::string(".com")); + std::string large_data(kVeryLargeSizeInBytes, 'x'); + WriteToCache(url, origin_lock, large_data, base::Time()); + } + + for (size_t i = 0; i < 2 * kMaxSizeInBytes / kVeryLargeSizeInBytes; ++i) { + GURL origin_lock = GURL(std::string("http://example") + + base::NumberToString(i) + std::string(".com")); + std::string large_data(kVeryLargeSizeInBytes, 'x'); + FetchFromCache(url, origin_lock); + task_environment_.RunUntilIdle(); + ASSERT_TRUE(received_); + EXPECT_EQ(large_data, received_data_); + received_ = false; + received_data_ = std::string(); + } +} + +TEST_F(GeneratedCodeCacheTest, StressVeryLargeEntries) { + GURL url("http://example.com/script.js"); + InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); + // Fill the cache with very large data keyed by the SHA-256 checksum. + char data1 = 0; + for (size_t i = 0; i < kMaxSizeInBytes / kVeryLargeSizeInBytes - 1; + ++i, ++data1) { + GURL origin_lock = GURL(std::string("http://example") + + base::NumberToString(i) + std::string(".com")); + std::string large_data(kVeryLargeSizeInBytes, data1); + WriteToCache(url, origin_lock, large_data, base::Time()); + } + + // Fill the cache with new data. The old entries should be purged to make + // room for the new ones. + char data2 = -128; + for (size_t i = 0; i < kMaxSizeInBytes / kVeryLargeSizeInBytes - 1; + ++i, ++data2) { + GURL origin_lock = GURL(std::string("http://example") + + base::NumberToString(i) + std::string(".com")); + std::string large_data(kVeryLargeSizeInBytes, data2); + WriteToCache(url, origin_lock, large_data, base::Time()); + } + + data2 = -128; + for (size_t i = 0; i < kMaxSizeInBytes / kVeryLargeSizeInBytes - 1; + ++i, ++data2) { + GURL origin_lock = GURL(std::string("http://example") + + base::NumberToString(i) + std::string(".com")); + FetchFromCache(url, origin_lock); + task_environment_.RunUntilIdle(); + // We can't depend too strongly on the disk cache storage heuristic. Verify + // that if we received data, it's what we wrote. + if (!received_null_) { + std::string large_data(kVeryLargeSizeInBytes, data2); + EXPECT_EQ(large_data, received_data_); + received_ = false; + received_data_ = std::string(); + } + } +} + TEST_F(GeneratedCodeCacheTest, FetchSucceedsEmptyOriginLock) { GURL url("http://example.com/script.js"); GURL origin_lock = GURL(""); @@ -453,7 +585,6 @@ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); std::string data = "SerializedCodeForEmptyOrigin"; WriteToCache(url, origin_lock, data, base::Time()); - task_environment_.RunUntilIdle(); FetchFromCache(url, origin_lock); task_environment_.RunUntilIdle(); @@ -469,11 +600,9 @@ InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript); std::string empty_origin_data = "SerializedCodeForEmptyOrigin"; WriteToCache(url, empty_origin_lock, empty_origin_data, base::Time()); - task_environment_.RunUntilIdle(); std::string valid_origin_data = "SerializedCodeForValidOrigin"; WriteToCache(url, origin_lock, valid_origin_data, base::Time()); - task_environment_.RunUntilIdle(); FetchFromCache(url, empty_origin_lock); task_environment_.RunUntilIdle();
diff --git a/content/browser/frame_host/back_forward_cache_impl.cc b/content/browser/frame_host/back_forward_cache_impl.cc index bcea784..f91a907 100644 --- a/content/browser/frame_host/back_forward_cache_impl.cc +++ b/content/browser/frame_host/back_forward_cache_impl.cc
@@ -75,11 +75,16 @@ } } -bool IsExtendedSupportEnabled() { - static constexpr base::FeatureParam<bool> extended_support_enabled( - &features::kBackForwardCache, - "experimental extended supported feature set", false); - return extended_support_enabled.Get(); +bool IsServiceWorkerSupported() { + static constexpr base::FeatureParam<bool> service_worker_supported( + &features::kBackForwardCache, "service_worker_supported", false); + return service_worker_supported.Get(); +} + +bool IsGeolocationSupported() { + static constexpr base::FeatureParam<bool> geolocation_supported( + &features::kBackForwardCache, "geolocation_supported", false); + return geolocation_supported.Get(); } uint64_t GetDisallowedFeatures(RenderFrameHostImpl* rfh) { @@ -115,9 +120,12 @@ uint64_t result = kAlwaysDisallowedFeatures; - if (!IsExtendedSupportEnabled()) { + if (!IsServiceWorkerSupported()) { result |= ToFeatureBit(WebSchedulerTrackedFeature::kServiceWorkerControlledPage); + } + + if (!IsGeolocationSupported()) { result |= ToFeatureBit( WebSchedulerTrackedFeature::kRequestedGeolocationPermission); }
diff --git a/content/browser/frame_host/back_forward_cache_impl.h b/content/browser/frame_host/back_forward_cache_impl.h index 4c5ff272..641298fc 100644 --- a/content/browser/frame_host/back_forward_cache_impl.h +++ b/content/browser/frame_host/back_forward_cache_impl.h
@@ -150,6 +150,11 @@ // via experiment. static base::TimeDelta GetTimeToLiveInBackForwardCache(); + // Checks if the url's host and path matches with the |allowed_urls_| host and + // path. This is controlled by "allowed_websites" param on BackForwardCache + // feature and if the param is not set, it will allow all websites by default. + bool IsAllowed(const GURL& current_url); + // Returns the task runner that should be used by the eviction timer. scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() { return task_runner_for_testing_ ? task_runner_for_testing_ @@ -180,11 +185,6 @@ CanStoreDocumentResult CanStoreRenderFrameHost( RenderFrameHostImpl* render_frame_host); - // Checks if the url's host and path matches with the |allowed_urls_| host and - // path. This is controlled by "allowed_websites" param on BackForwardCache - // feature and if the param is not set, it will allow all websites by default. - bool IsAllowed(const GURL& current_url); - // Contains the set of stored Entries. // Invariant: // - Ordered from the most recently used to the last recently used.
diff --git a/content/browser/frame_host/back_forward_cache_metrics.cc b/content/browser/frame_host/back_forward_cache_metrics.cc index a7b5658d..78f2265c 100644 --- a/content/browser/frame_host/back_forward_cache_metrics.cc +++ b/content/browser/frame_host/back_forward_cache_metrics.cc
@@ -95,11 +95,12 @@ } void BackForwardCacheMetrics::DidCommitNavigation( - NavigationRequest* navigation) { + NavigationRequest* navigation, + bool back_forward_cache_allowed) { bool is_history_navigation = navigation->GetPageTransition() & ui::PAGE_TRANSITION_FORWARD_BACK; if (navigation->IsInMainFrame() && !navigation->IsSameDocument()) { - if (is_history_navigation) + if (is_history_navigation && back_forward_cache_allowed) RecordMetricsForHistoryNavigationCommit(navigation); not_restored_reasons_.reset(); } @@ -198,10 +199,6 @@ BackForwardCacheMetrics::EvictedAfterDocumentRestoredReason::kRestored); } - // TODO(hajimehoshi): By |BackForwardCache::IsAllowed(navigation->GetURL())|, - // check whether the page matches the experiment condition, and do not record - // anything in this case. - UMA_HISTOGRAM_ENUMERATION("BackForwardCache.HistoryNavigationOutcome", outcome);
diff --git a/content/browser/frame_host/back_forward_cache_metrics.h b/content/browser/frame_host/back_forward_cache_metrics.h index 0e0613c..3473ae8 100644 --- a/content/browser/frame_host/back_forward_cache_metrics.h +++ b/content/browser/frame_host/back_forward_cache_metrics.h
@@ -111,7 +111,10 @@ void MainFrameDidStartNavigationToDocument(); // Notifies that an associated entry has committed a navigation. - void DidCommitNavigation(NavigationRequest* navigation_request); + // |back_forward_cache_allowed| indicates whether back-forward cache is + // allowed for the URL of |navigation_request|. + void DidCommitNavigation(NavigationRequest* navigation_request, + bool back_forward_cache_allowed); // Records when another navigation commits away from the most recent entry // associated with |this|. This is the point in time that the previous
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index ce88050..6d52381 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -1141,7 +1141,8 @@ std::move(back_forward_cache_metrics)); } active_entry->back_forward_cache_metrics()->DidCommitNavigation( - navigation_request); + navigation_request, + back_forward_cache_.IsAllowed(navigation_request->GetURL())); // Grab the corresponding FrameNavigationEntry for a few updates, but only if // the SiteInstance matches (to avoid updating the wrong entry by mistake).
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h index a08c40d..998a3f70 100644 --- a/content/browser/frame_host/render_frame_host_delegate.h +++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -460,6 +460,19 @@ // Determine if the frame is of a low priority. virtual bool IsFrameLowPriority(const RenderFrameHost* render_frame_host); + // Registers a new URL handler for the given protocol. + virtual void RegisterProtocolHandler(RenderFrameHostImpl* host, + const std::string& scheme, + const GURL& url, + const base::string16& title, + bool user_gesture) {} + + // Unregisters a given URL handler for the given protocol. + virtual void UnregisterProtocolHandler(RenderFrameHostImpl* host, + const std::string& scheme, + const GURL& url, + bool user_gesture) {} + protected: virtual ~RenderFrameHostDelegate() {} };
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 3c62948..fd3e99fa 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1848,8 +1848,9 @@ // process's channel. remote_associated_interfaces_.reset(); - // Ensure that the AssociatedRemote<blink::mojom::Frame> works after a crash. - frame_remote_.reset(); + // Ensure that the AssociatedRemote<blink::mojom::LocalFrame> works after a + // crash. + local_frame_remote_.reset(); // Any termination disablers in content loaded by the new process will // be sent again. @@ -3190,16 +3191,16 @@ } void RenderFrameHostImpl::RequestTextSurroundingSelection( - blink::mojom::Frame::GetTextSurroundingSelectionCallback callback, + blink::mojom::LocalFrame::GetTextSurroundingSelectionCallback callback, int max_length) { DCHECK(!callback.is_null()); - GetAssociatedFrameRemote()->GetTextSurroundingSelection(max_length, - std::move(callback)); + GetAssociatedLocalFrameRemote()->GetTextSurroundingSelection( + max_length, std::move(callback)); } void RenderFrameHostImpl::SendInterventionReport(const std::string& id, const std::string& message) { - GetAssociatedFrameRemote()->SendInterventionReport(id, message); + GetAssociatedLocalFrameRemote()->SendInterventionReport(id, message); } void RenderFrameHostImpl::AllowBindings(int bindings_flags) { @@ -3497,6 +3498,19 @@ delegate_->FullscreenStateChanged(this, is_fullscreen); } +void RenderFrameHostImpl::RegisterProtocolHandler(const std::string& scheme, + const GURL& url, + const base::string16& title, + bool user_gesture) { + delegate_->RegisterProtocolHandler(this, scheme, url, title, user_gesture); +} + +void RenderFrameHostImpl::UnregisterProtocolHandler(const std::string& scheme, + const GURL& url, + bool user_gesture) { + delegate_->UnregisterProtocolHandler(this, scheme, url, user_gesture); +} + void RenderFrameHostImpl::LifecycleStateChanged( blink::mojom::FrameLifecycleState state) { frame_lifecycle_state_ = state; @@ -5956,11 +5970,11 @@ return find_in_page_; } -const mojo::AssociatedRemote<blink::mojom::Frame>& -RenderFrameHostImpl::GetAssociatedFrameRemote() { - if (!frame_remote_) - GetRemoteAssociatedInterfaces()->GetInterface(&frame_remote_); - return frame_remote_; +const mojo::AssociatedRemote<blink::mojom::LocalFrame>& +RenderFrameHostImpl::GetAssociatedLocalFrameRemote() { + if (!local_frame_remote_) + GetRemoteAssociatedInterfaces()->GetInterface(&local_frame_remote_); + return local_frame_remote_; } void RenderFrameHostImpl::ResetLoadingState() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 54c01d4..7b95855 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -282,7 +282,7 @@ size_t GetProxyCount() override; bool HasSelection() override; void RequestTextSurroundingSelection( - blink::mojom::Frame::GetTextSurroundingSelectionCallback callback, + blink::mojom::LocalFrame::GetTextSurroundingSelectionCallback callback, int max_length) override; void SendInterventionReport(const std::string& id, const std::string& message) override; @@ -814,8 +814,9 @@ // Returns remote to renderer side FindInPage associated with this frame. const mojo::AssociatedRemote<blink::mojom::FindInPage>& GetFindInPage(); - // Returns associated remote for the blink::mojom::Frame Mojo interface. - const mojo::AssociatedRemote<blink::mojom::Frame>& GetAssociatedFrameRemote(); + // Returns associated remote for the blink::mojom::LocalFrame Mojo interface. + const mojo::AssociatedRemote<blink::mojom::LocalFrame>& + GetAssociatedLocalFrameRemote(); // Resets the loading state. Following this call, the RenderFrameHost will be // in a non-loading state. @@ -1206,6 +1207,13 @@ void EnterFullscreen(blink::mojom::FullscreenOptionsPtr options) override; void ExitFullscreen() override; void FullscreenStateChanged(bool is_fullscreen) override; + void RegisterProtocolHandler(const std::string& scheme, + const GURL& url, + const base::string16& title, + bool user_gesture) override; + void UnregisterProtocolHandler(const std::string& scheme, + const GURL& url, + bool user_gesture) override; protected: friend class RenderFrameHostFactory; @@ -2162,7 +2170,7 @@ mojo::AssociatedRemote<blink::mojom::FindInPage> find_in_page_; // Holder of Mojo connection with the Frame service in Blink. - mojo::AssociatedRemote<blink::mojom::Frame> frame_remote_; + mojo::AssociatedRemote<blink::mojom::LocalFrame> local_frame_remote_; // Holds a NavigationRequest when it's about to commit, ie. after // OnCrossDocumentCommitProcessed has returned a positive answer for this
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 68c4f29b..72d89244 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3059,6 +3059,7 @@ switches::kEnableWebGLImageChromium, switches::kEnableWebVR, switches::kFileUrlPathAlias, + switches::kForceDarkMode, switches::kForceDeviceScaleFactor, switches::kForceDisableWebRtcApmInAudioService, switches::kForceDisplayColorProfile,
diff --git a/content/browser/scheduler/browser_io_thread_delegate.cc b/content/browser/scheduler/browser_io_thread_delegate.cc index f0e5516..0b3aa31e 100644 --- a/content/browser/scheduler/browser_io_thread_delegate.cc +++ b/content/browser/scheduler/browser_io_thread_delegate.cc
@@ -110,4 +110,10 @@ } } +const scoped_refptr<base::SequencedTaskRunner>& +BrowserIOThreadDelegate::GetTaskRunnerForCurrentTask() const { + DCHECK(sequence_manager_); + return sequence_manager_->GetTaskRunnerForCurrentTask(); +} + } // namespace content
diff --git a/content/browser/scheduler/browser_io_thread_delegate.h b/content/browser/scheduler/browser_io_thread_delegate.h index 0954c5e..69699369 100644 --- a/content/browser/scheduler/browser_io_thread_delegate.h +++ b/content/browser/scheduler/browser_io_thread_delegate.h
@@ -55,6 +55,10 @@ scoped_refptr<Handle> GetHandle() { return task_queues_->GetHandle(); } + // Must be called on the IO thread. + const scoped_refptr<base::SequencedTaskRunner>& GetTaskRunnerForCurrentTask() + const; + private: class TLSMultiplexer;
diff --git a/content/browser/scheduler/browser_task_executor.cc b/content/browser/scheduler/browser_task_executor.cc index 4f786a1..b8b4a1b8 100644 --- a/content/browser/scheduler/browser_task_executor.cc +++ b/content/browser/scheduler/browser_task_executor.cc
@@ -64,6 +64,12 @@ } } +const scoped_refptr<base::SequencedTaskRunner>& GetNullTaskRunner() { + static const base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> + null_task_runner; + return *null_task_runner; +} + } // namespace BaseBrowserTaskExecutor::BaseBrowserTaskExecutor() = default; @@ -397,6 +403,13 @@ return BrowserThread::UI; } +const scoped_refptr<base::SequencedTaskRunner>& +BrowserTaskExecutor::GetContinuationTaskRunner() { + NOTREACHED() + << "Should have been routed to UIThreadExecutor or IOThreadExecutor"; + return GetNullTaskRunner(); +} + BrowserTaskExecutor::UIThreadExecutor::UIThreadExecutor( std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler) : browser_ui_thread_scheduler_(std::move(browser_ui_thread_scheduler)) { @@ -428,6 +441,11 @@ return BrowserThread::UI; } +const scoped_refptr<base::SequencedTaskRunner>& +BrowserTaskExecutor::UIThreadExecutor::GetContinuationTaskRunner() { + return browser_ui_thread_scheduler_->GetTaskRunnerForCurrentTask(); +} + BrowserTaskExecutor::IOThreadExecutor::IOThreadExecutor( std::unique_ptr<BrowserIOThreadDelegate> browser_io_thread_delegate) : browser_io_thread_delegate_(std::move(browser_io_thread_delegate)) { @@ -455,4 +473,10 @@ return BrowserThread::IO; } +const scoped_refptr<base::SequencedTaskRunner>& +BrowserTaskExecutor::IOThreadExecutor::GetContinuationTaskRunner() { + DCHECK(browser_io_thread_delegate_); + return browser_io_thread_delegate_->GetTaskRunnerForCurrentTask(); +} + } // namespace content
diff --git a/content/browser/scheduler/browser_task_executor.h b/content/browser/scheduler/browser_task_executor.h index 8754d97d..4a419e81 100644 --- a/content/browser/scheduler/browser_task_executor.h +++ b/content/browser/scheduler/browser_task_executor.h
@@ -173,6 +173,10 @@ BrowserTaskQueues::Validator* validator); #endif // DCHECK_IS_ON() + // base::TaskExecutor implementation. + const scoped_refptr<base::SequencedTaskRunner>& GetContinuationTaskRunner() + override; + private: friend class BrowserIOThreadDelegate; friend class BrowserTaskExecutorTest; @@ -186,6 +190,10 @@ ~UIThreadExecutor() override; + // base::TaskExecutor implementation. + const scoped_refptr<base::SequencedTaskRunner>& GetContinuationTaskRunner() + override; + scoped_refptr<BrowserUIThreadScheduler::Handle> GetUIThreadHandle(); void SetIOThreadHandle( @@ -209,6 +217,10 @@ ~IOThreadExecutor() override; + // base::TaskExecutor implementation. + const scoped_refptr<base::SequencedTaskRunner>& GetContinuationTaskRunner() + override; + scoped_refptr<BrowserUIThreadScheduler::Handle> GetIOThreadHandle(); void SetUIThreadHandle(
diff --git a/content/browser/scheduler/browser_task_executor_unittest.cc b/content/browser/scheduler/browser_task_executor_unittest.cc index 9ef50ad..5dbac91 100644 --- a/content/browser/scheduler/browser_task_executor_unittest.cc +++ b/content/browser/scheduler/browser_task_executor_unittest.cc
@@ -15,6 +15,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/test/bind_test_util.h" +#include "base/test/gtest_util.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" @@ -132,6 +133,14 @@ NOTREACHED(); return BrowserThread::UI; } + + const scoped_refptr<base::SequencedTaskRunner>& GetContinuationTaskRunner() + override { + return dummy_; + } + + private: + scoped_refptr<base::SequencedTaskRunner> dummy_; }; template <BrowserThread::ID ID> @@ -310,4 +319,35 @@ {base::CurrentThread(), BrowserTaskType::kNavigation})); } +TEST_F(BrowserTaskExecutorTest, GetContinuationTaskRunner) { + // Ensure task queue priorities are set. + BrowserTaskExecutor::PostFeatureListSetup(); + std::vector<int> order; + base::RunLoop run_loop; + + auto task1 = base::BindLambdaForTesting([&]() { + order.push_back(1); + run_loop.Quit(); + }); + auto task2 = base::BindLambdaForTesting([&]() { order.push_back(2); }); + auto task3 = base::BindLambdaForTesting([&]() { order.push_back(3); }); + + base::PostTask(FROM_HERE, {BrowserThread::UI}, task1); + + // Post a bootstrap task whose continuation tasks should run before |task1|. + base::PostTask( + FROM_HERE, {BrowserThread::UI, BrowserTaskType::kBootstrap}, + base::BindLambdaForTesting([&]() { + base::GetContinuationTaskRunner()->PostTask(FROM_HERE, task2); + base::GetContinuationTaskRunner()->PostTask(FROM_HERE, task3); + })); + + run_loop.Run(); + EXPECT_THAT(order, ElementsAre(2, 3, 1)); +} + +TEST_F(BrowserTaskExecutorTest, GetContinuationTaskRunnerWithNoTaskExecuting) { + EXPECT_DCHECK_DEATH(base::GetContinuationTaskRunner()); +} + } // namespace content
diff --git a/content/browser/scheduler/browser_ui_thread_scheduler.cc b/content/browser/scheduler/browser_ui_thread_scheduler.cc index 0925f8f..81d6a51 100644 --- a/content/browser/scheduler/browser_ui_thread_scheduler.cc +++ b/content/browser/scheduler/browser_ui_thread_scheduler.cc
@@ -63,7 +63,14 @@ void BrowserUIThreadScheduler::CommonSequenceManagerSetup( base::sequence_manager::SequenceManager* sequence_manager) { - sequence_manager->EnableCrashKeys("ui_scheduler_async_stack"); + sequence_manager_ = sequence_manager; + sequence_manager_->EnableCrashKeys("ui_scheduler_async_stack"); +} + +const scoped_refptr<base::SequencedTaskRunner>& +BrowserUIThreadScheduler::GetTaskRunnerForCurrentTask() const { + DCHECK(sequence_manager_); + return sequence_manager_->GetTaskRunnerForCurrentTask(); } } // namespace content
diff --git a/content/browser/scheduler/browser_ui_thread_scheduler.h b/content/browser/scheduler/browser_ui_thread_scheduler.h index b1681be..3a98ec0 100644 --- a/content/browser/scheduler/browser_ui_thread_scheduler.h +++ b/content/browser/scheduler/browser_ui_thread_scheduler.h
@@ -41,6 +41,10 @@ scoped_refptr<Handle> GetHandle() const { return handle_; } + // Must be called on the UI thread. + const scoped_refptr<base::SequencedTaskRunner>& GetTaskRunnerForCurrentTask() + const; + private: friend class BrowserTaskExecutor; @@ -56,6 +60,7 @@ std::unique_ptr<base::sequence_manager::SequenceManager> owned_sequence_manager_; + base::sequence_manager::SequenceManager* sequence_manager_ = nullptr; BrowserTaskQueues task_queues_; scoped_refptr<Handle> handle_;
diff --git a/content/browser/speech/tts_controller_impl.cc b/content/browser/speech/tts_controller_impl.cc index 7ba7e7e5..6db04b3 100644 --- a/content/browser/speech/tts_controller_impl.cc +++ b/content/browser/speech/tts_controller_impl.cc
@@ -331,8 +331,9 @@ } void TtsControllerImpl::SpeakNow(std::unique_ptr<TtsUtterance> utterance) { - // TODO(crbug/1003410): Change to always have a valid TtsControllerDelegate. - // This may involve modifying tests to register a mock implementation. + // Note: this would only happen if a content embedder failed to provide + // their own TtsControllerDelegate. Chrome provides one, and Content Shell + // provides a mock one for web tests. if (!GetTtsControllerDelegate()) { utterance->OnTtsEvent(TTS_EVENT_CANCELLED, kInvalidCharIndex, kInvalidLength, std::string());
diff --git a/content/browser/speech/tts_platform_fuzzer.cc b/content/browser/speech/tts_platform_fuzzer.cc index 2b4e0d6..d60a85c 100644 --- a/content/browser/speech/tts_platform_fuzzer.cc +++ b/content/browser/speech/tts_platform_fuzzer.cc
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <objbase.h> - #include "base/bind.h" #include "build/build_config.h" #include "content/public/browser/tts_platform.h" +#if defined(OS_WIN) +#include <objbase.h> +#endif + namespace content { // Entry point for LibFuzzer.
diff --git a/content/browser/speech/tts_platform_impl.cc b/content/browser/speech/tts_platform_impl.cc index 7ce56ec..f4c1a4d 100644 --- a/content/browser/speech/tts_platform_impl.cc +++ b/content/browser/speech/tts_platform_impl.cc
@@ -5,11 +5,8 @@ #include "content/browser/speech/tts_platform_impl.h" #include "build/build_config.h" - -#if defined(OS_CHROMEOS) #include "content/public/browser/content_browser_client.h" #include "content/public/common/content_client.h" -#endif #include <string> @@ -17,11 +14,21 @@ // static TtsPlatform* TtsPlatform::GetInstance() { -#if defined(OS_CHROMEOS) - // Chrome TTS platform has chrome/ dependencies. - return GetContentClient()->browser()->GetTtsPlatform(); -#elif defined(OS_FUCHSIA) - // There is no platform TTS definition for Fuchsia. +#if !defined(NO_CONTENT_CLIENT) + TtsPlatform* result = GetContentClient()->browser()->GetTtsPlatform(); + if (result) + return result; +#endif + +#if defined(OS_FUCHSIA) || defined(OS_CHROMEOS) + // There is no platform TTS definition for Fuchsia. On Chrome OS it's + // provided by the content client. + // + // If this code is reached in production it implies that somebody is + // trying to do TTS on a platform where the content client implementation + // is not provided, that's probably not intended. It's not important + // if this is hit in something like a content-only unit test. + NOTREACHED(); return nullptr; #else return TtsPlatformImpl::GetInstance();
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index a615d6200..c0542f59 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -601,7 +601,6 @@ is_overlay_content_(false), showing_context_menu_(false), text_autosizer_page_info_({0, 0, 1.f}), - native_theme_observer_(this), had_inner_webcontents_(false) { frame_tree_.SetFrameRemoveListener( base::Bind(&WebContentsImpl::OnFrameRemoved, @@ -616,11 +615,6 @@ binders_.Add(base::BindRepeating( &WebContentsImpl::OnColorChooserFactoryRequest, base::Unretained(this))); - - ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForWeb(); - native_theme_observer_.Add(native_theme); - using_dark_colors_ = native_theme->ShouldUseDarkColors(); - preferred_color_scheme_ = native_theme->GetPreferredColorScheme(); } WebContentsImpl::~WebContentsImpl() { @@ -918,10 +912,6 @@ IPC_MESSAGE_HANDLER(FrameHostMsg_DidRunContentWithCertificateErrors, OnDidRunContentWithCertificateErrors) IPC_MESSAGE_HANDLER(FrameHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset) - IPC_MESSAGE_HANDLER(FrameHostMsg_RegisterProtocolHandler, - OnRegisterProtocolHandler) - IPC_MESSAGE_HANDLER(FrameHostMsg_UnregisterProtocolHandler, - OnUnregisterProtocolHandler) IPC_MESSAGE_HANDLER(FrameHostMsg_UpdatePageImportanceSignals, OnUpdatePageImportanceSignals) IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateFaviconURL, OnUpdateFaviconURL) @@ -4936,11 +4926,11 @@ listener->FileSelectionCanceled(); } -void WebContentsImpl::OnRegisterProtocolHandler(RenderFrameHostImpl* source, - const std::string& protocol, - const GURL& url, - const base::string16& title, - bool user_gesture) { +void WebContentsImpl::RegisterProtocolHandler(RenderFrameHostImpl* source, + const std::string& protocol, + const GURL& url, + const base::string16& title, + bool user_gesture) { // TODO(nick): Should we consider |source| here or pass it to the delegate? // TODO(nick): Do we need to apply FilterURL to |url|? if (!delegate_) @@ -4956,10 +4946,10 @@ delegate_->RegisterProtocolHandler(this, protocol, url, user_gesture); } -void WebContentsImpl::OnUnregisterProtocolHandler(RenderFrameHostImpl* source, - const std::string& protocol, - const GURL& url, - bool user_gesture) { +void WebContentsImpl::UnregisterProtocolHandler(RenderFrameHostImpl* source, + const std::string& protocol, + const GURL& url, + bool user_gesture) { // TODO(nick): Should we consider |source| here or pass it to the delegate? // TODO(nick): Do we need to apply FilterURL to |url|? if (!delegate_) @@ -7364,27 +7354,6 @@ GetMainFrame()->SetVisibilityForChildViews(visible); } -void WebContentsImpl::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) { - DCHECK(native_theme_observer_.IsObserving(observed_theme)); - - bool using_dark_colors = observed_theme->ShouldUseDarkColors(); - ui::NativeTheme::PreferredColorScheme preferred_color_scheme = - observed_theme->GetPreferredColorScheme(); - bool preferences_changed = false; - - if (using_dark_colors_ != using_dark_colors) { - using_dark_colors_ = using_dark_colors; - preferences_changed = true; - } - if (preferred_color_scheme_ != preferred_color_scheme) { - preferred_color_scheme_ = preferred_color_scheme; - preferences_changed = true; - } - - if (preferences_changed) - NotifyPreferencesChanged(); -} - mojom::FrameInputHandler* WebContentsImpl::GetFocusedFrameInputHandler() { auto* focused_frame = GetFocusedFrame(); if (!focused_frame)
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 787ae013..75d84cde 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -22,7 +22,6 @@ #include "base/observer_list.h" #include "base/optional.h" #include "base/process/process.h" -#include "base/scoped_observer.h" #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" @@ -75,7 +74,6 @@ #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" #include "ui/native_theme/native_theme.h" -#include "ui/native_theme/native_theme_observer.h" #if defined(OS_ANDROID) #include "content/public/browser/android/child_process_importance.h" @@ -153,8 +151,7 @@ public blink::mojom::ColorChooserFactory, public NotificationObserver, public NavigationControllerDelegate, - public NavigatorDelegate, - public ui::NativeThemeObserver { + public NavigatorDelegate { public: class FriendWrapper; @@ -641,6 +638,15 @@ void OnThemeColorChanged(RenderFrameHostImpl* source, const base::Optional<SkColor>& theme_color) override; bool IsFrameLowPriority(const RenderFrameHost* render_frame_host) override; + void RegisterProtocolHandler(RenderFrameHostImpl* source, + const std::string& protocol, + const GURL& url, + const base::string16& title, + bool user_gesture) override; + void UnregisterProtocolHandler(RenderFrameHostImpl* source, + const std::string& protocol, + const GURL& url, + bool user_gesture) override; // RenderViewHostDelegate ---------------------------------------------------- RenderViewHostDelegateView* GetDelegateView() override; @@ -1307,15 +1313,6 @@ RenderViewHostImpl* source, const blink::WebTextAutosizerPageInfo& page_info); - void OnRegisterProtocolHandler(RenderFrameHostImpl* source, - const std::string& protocol, - const GURL& url, - const base::string16& title, - bool user_gesture); - void OnUnregisterProtocolHandler(RenderFrameHostImpl* source, - const std::string& protocol, - const GURL& url, - bool user_gesture); void OnDomOperationResponse(RenderFrameHostImpl* source, const std::string& json_string); void OnUpdatePageImportanceSignals(RenderFrameHostImpl* source, @@ -1523,9 +1520,6 @@ // |current_fullscreen_frame_| and notify observers whenever it changes. void FullscreenFrameSetUpdated(); - // ui::NativeThemeObserver: - void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override; - // Data for core operation --------------------------------------------------- // Delegate for notifying our owner about stuff. Not owned by us. @@ -1909,15 +1903,6 @@ // with OOPIF renderers. blink::WebTextAutosizerPageInfo text_autosizer_page_info_; - // Observe native theme for changes to dark mode, and preferred color scheme. - // Used to notify the renderer of preferred color scheme changes. - ScopedObserver<ui::NativeTheme, ui::NativeThemeObserver> - native_theme_observer_; - - bool using_dark_colors_ = false; - ui::NativeTheme::PreferredColorScheme preferred_color_scheme_ = - ui::NativeTheme::PreferredColorScheme::kNoPreference; - // TODO(crbug.com/934637): Remove this field when pdf/any inner web contents // user gesture is properly propagated. This is a temporary fix for history // intervention to be disabled for pdfs (crbug.com/965434).
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index 0c77f019..df2fe81 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -3444,17 +3444,15 @@ .Times(1); { - FrameHostMsg_RegisterProtocolHandler message( - main_test_rfh()->GetRoutingID(), "mailto", handler_url1, - base::string16(), /*user_gesture=*/true); - contents()->OnMessageReceived(main_test_rfh(), message); + contents()->RegisterProtocolHandler(main_test_rfh(), "mailto", handler_url1, + base::string16(), + /*user_gesture=*/true); } { - FrameHostMsg_RegisterProtocolHandler message( - main_test_rfh()->GetRoutingID(), "mailto", handler_url2, - base::string16(), /*user_gesture=*/true); - contents()->OnMessageReceived(main_test_rfh(), message); + contents()->RegisterProtocolHandler(main_test_rfh(), "mailto", handler_url2, + base::string16(), + /*user_gesture=*/true); } contents()->SetDelegate(nullptr); @@ -3475,10 +3473,9 @@ .Times(0); { - FrameHostMsg_RegisterProtocolHandler message( - main_test_rfh()->GetRoutingID(), "mailto", data_handler, - base::string16(), /*user_gesture=*/true); - contents()->OnMessageReceived(main_test_rfh(), message); + contents()->RegisterProtocolHandler(main_test_rfh(), "mailto", data_handler, + base::string16(), + /*user_gesture=*/true); } contents()->SetDelegate(nullptr);
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index eefb49f..065cdaf 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -310,6 +310,8 @@ kEnableOnly}, {wf::EnableDocumentPolicy, features::kDocumentPolicy, kUseFeatureState}, + {wf::EnableNeverSlowMode, features::kNeverSlowMode, + kUseFeatureState}, }; for (const auto& mapping : blinkFeatureToBaseFeatureMapping) { const bool featureEnabled =
diff --git a/content/child/webthemeengine_impl_android.cc b/content/child/webthemeengine_impl_android.cc index 2e703d6..82eafb55 100644 --- a/content/child/webthemeengine_impl_android.cc +++ b/content/child/webthemeengine_impl_android.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/system/sys_info.h" +#include "content/child/webthemeengine_impl_conversions.h" #include "skia/ext/platform_canvas.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_size.h" @@ -27,74 +28,6 @@ } } -static ui::NativeTheme::Part NativeThemePart(WebThemeEngine::Part part) { - switch (part) { - case WebThemeEngine::kPartScrollbarDownArrow: - return ui::NativeTheme::kScrollbarDownArrow; - case WebThemeEngine::kPartScrollbarLeftArrow: - return ui::NativeTheme::kScrollbarLeftArrow; - case WebThemeEngine::kPartScrollbarRightArrow: - return ui::NativeTheme::kScrollbarRightArrow; - case WebThemeEngine::kPartScrollbarUpArrow: - return ui::NativeTheme::kScrollbarUpArrow; - case WebThemeEngine::kPartScrollbarHorizontalThumb: - return ui::NativeTheme::kScrollbarHorizontalThumb; - case WebThemeEngine::kPartScrollbarVerticalThumb: - return ui::NativeTheme::kScrollbarVerticalThumb; - case WebThemeEngine::kPartScrollbarHorizontalTrack: - return ui::NativeTheme::kScrollbarHorizontalTrack; - case WebThemeEngine::kPartScrollbarVerticalTrack: - return ui::NativeTheme::kScrollbarVerticalTrack; - case WebThemeEngine::kPartScrollbarCorner: - return ui::NativeTheme::kScrollbarCorner; - case WebThemeEngine::kPartCheckbox: - return ui::NativeTheme::kCheckbox; - case WebThemeEngine::kPartRadio: - return ui::NativeTheme::kRadio; - case WebThemeEngine::kPartButton: - return ui::NativeTheme::kPushButton; - case WebThemeEngine::kPartTextField: - return ui::NativeTheme::kTextField; - case WebThemeEngine::kPartMenuList: - return ui::NativeTheme::kMenuList; - case WebThemeEngine::kPartSliderTrack: - return ui::NativeTheme::kSliderTrack; - case WebThemeEngine::kPartSliderThumb: - return ui::NativeTheme::kSliderThumb; - case WebThemeEngine::kPartInnerSpinButton: - return ui::NativeTheme::kInnerSpinButton; - case WebThemeEngine::kPartProgressBar: - return ui::NativeTheme::kProgressBar; - default: - return ui::NativeTheme::kScrollbarDownArrow; - } -} - -static ui::NativeTheme::State NativeThemeState(WebThemeEngine::State state) { - switch (state) { - case WebThemeEngine::kStateDisabled: - return ui::NativeTheme::kDisabled; - case WebThemeEngine::kStateHover: - return ui::NativeTheme::kHovered; - case WebThemeEngine::kStateNormal: - return ui::NativeTheme::kNormal; - case WebThemeEngine::kStatePressed: - return ui::NativeTheme::kPressed; - default: - return ui::NativeTheme::kDisabled; - } -} - -static ui::NativeTheme::ColorScheme NativeColorScheme( - WebColorScheme color_scheme) { - switch (color_scheme) { - case WebColorScheme::kLight: - return ui::NativeTheme::ColorScheme::kLight; - case WebColorScheme::kDark: - return ui::NativeTheme::ColorScheme::kDark; - } -} - static void GetNativeThemeExtraParams( WebThemeEngine::Part part, WebThemeEngine::State state, @@ -229,11 +162,27 @@ } blink::ForcedColors WebThemeEngineAndroid::ForcedColors() const { - return forced_colors_; + return ui::NativeTheme::GetInstanceForWeb()->UsesHighContrastColors() + ? blink::ForcedColors::kActive + : blink::ForcedColors::kNone; } void WebThemeEngineAndroid::SetForcedColors( const blink::ForcedColors forced_colors) { - forced_colors_ = forced_colors; + ui::NativeTheme::GetInstanceForWeb()->set_high_contrast( + forced_colors == blink::ForcedColors::kActive); +} + +blink::PreferredColorScheme WebThemeEngineAndroid::PreferredColorScheme() + const { + ui::NativeTheme::PreferredColorScheme preferred_color_scheme = + ui::NativeTheme::GetInstanceForWeb()->GetPreferredColorScheme(); + return WebPreferredColorScheme(preferred_color_scheme); +} + +void WebThemeEngineAndroid::SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) { + ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( + NativePreferredColorScheme(preferred_color_scheme)); } } // namespace content
diff --git a/content/child/webthemeengine_impl_android.h b/content/child/webthemeengine_impl_android.h index 7387bce1..0c113a88 100644 --- a/content/child/webthemeengine_impl_android.h +++ b/content/child/webthemeengine_impl_android.h
@@ -24,9 +24,9 @@ blink::WebColorScheme color_scheme) override; blink::ForcedColors ForcedColors() const override; void SetForcedColors(const blink::ForcedColors forced_colors) override; - - private: - blink::ForcedColors forced_colors_ = blink::ForcedColors::kNone; + blink::PreferredColorScheme PreferredColorScheme() const override; + void SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) override; }; } // namespace content
diff --git a/content/child/webthemeengine_impl_conversions.cc b/content/child/webthemeengine_impl_conversions.cc index db004c1..47ebce82 100644 --- a/content/child/webthemeengine_impl_conversions.cc +++ b/content/child/webthemeengine_impl_conversions.cc
@@ -117,4 +117,28 @@ } } +ui::NativeTheme::PreferredColorScheme NativePreferredColorScheme( + blink::PreferredColorScheme preferred_color_scheme) { + switch (preferred_color_scheme) { + case blink::PreferredColorScheme::kDark: + return ui::NativeTheme::PreferredColorScheme::kDark; + case blink::PreferredColorScheme::kLight: + return ui::NativeTheme::PreferredColorScheme::kLight; + case blink::PreferredColorScheme::kNoPreference: + return ui::NativeTheme::PreferredColorScheme::kNoPreference; + } +} + +blink::PreferredColorScheme WebPreferredColorScheme( + ui::NativeTheme::PreferredColorScheme preferred_color_scheme) { + switch (preferred_color_scheme) { + case ui::NativeTheme::PreferredColorScheme::kDark: + return blink::PreferredColorScheme::kDark; + case ui::NativeTheme::PreferredColorScheme::kLight: + return blink::PreferredColorScheme::kLight; + case ui::NativeTheme::PreferredColorScheme::kNoPreference: + return blink::PreferredColorScheme::kNoPreference; + } +} + } // namespace content
diff --git a/content/child/webthemeengine_impl_conversions.h b/content/child/webthemeengine_impl_conversions.h index fdd2e56..4d7dbba 100644 --- a/content/child/webthemeengine_impl_conversions.h +++ b/content/child/webthemeengine_impl_conversions.h
@@ -27,6 +27,12 @@ CONTENT_EXPORT ui::NativeTheme::SystemThemeColor NativeSystemThemeColor( blink::WebThemeEngine::SystemThemeColor theme_color); +CONTENT_EXPORT ui::NativeTheme::PreferredColorScheme NativePreferredColorScheme( + blink::PreferredColorScheme preferred_color_scheme); + +CONTENT_EXPORT blink::PreferredColorScheme WebPreferredColorScheme( + ui::NativeTheme::PreferredColorScheme preferred_color_scheme); + } // namespace content #endif // CONTENT_CHILD_WEBTHEMEENGINE_IMPL_CONVERSIONS_H_
diff --git a/content/child/webthemeengine_impl_default.cc b/content/child/webthemeengine_impl_default.cc index bf8bd544..84db298 100644 --- a/content/child/webthemeengine_impl_default.cc +++ b/content/child/webthemeengine_impl_default.cc
@@ -244,4 +244,17 @@ forced_colors == blink::ForcedColors::kActive); } +blink::PreferredColorScheme WebThemeEngineDefault::PreferredColorScheme() + const { + ui::NativeTheme::PreferredColorScheme preferred_color_scheme = + ui::NativeTheme::GetInstanceForWeb()->GetPreferredColorScheme(); + return WebPreferredColorScheme(preferred_color_scheme); +} + +void WebThemeEngineDefault::SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) { + ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( + NativePreferredColorScheme(preferred_color_scheme)); +} + } // namespace content
diff --git a/content/child/webthemeengine_impl_default.h b/content/child/webthemeengine_impl_default.h index 181223b8..73579db 100644 --- a/content/child/webthemeengine_impl_default.h +++ b/content/child/webthemeengine_impl_default.h
@@ -41,6 +41,9 @@ #endif blink::ForcedColors ForcedColors() const override; void SetForcedColors(const blink::ForcedColors forced_colors) override; + blink::PreferredColorScheme PreferredColorScheme() const override; + void SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) override; }; } // namespace content
diff --git a/content/child/webthemeengine_impl_mac.cc b/content/child/webthemeengine_impl_mac.cc index 9cb279ef..dd902863 100644 --- a/content/child/webthemeengine_impl_mac.cc +++ b/content/child/webthemeengine_impl_mac.cc
@@ -4,14 +4,33 @@ #include "content/child/webthemeengine_impl_mac.h" +#include "content/child/webthemeengine_impl_conversions.h" +#include "ui/native_theme/native_theme.h" + namespace content { blink::ForcedColors WebThemeEngineMac::ForcedColors() const { - return forced_colors_; + return ui::NativeTheme::GetInstanceForWeb()->UsesHighContrastColors() + ? blink::ForcedColors::kActive + : blink::ForcedColors::kNone; } void WebThemeEngineMac::SetForcedColors( const blink::ForcedColors forced_colors) { - forced_colors_ = forced_colors; + ui::NativeTheme::GetInstanceForWeb()->set_high_contrast( + forced_colors == blink::ForcedColors::kActive); } + +blink::PreferredColorScheme WebThemeEngineMac::PreferredColorScheme() const { + ui::NativeTheme::PreferredColorScheme preferred_color_scheme = + ui::NativeTheme::GetInstanceForWeb()->GetPreferredColorScheme(); + return WebPreferredColorScheme(preferred_color_scheme); +} + +void WebThemeEngineMac::SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) { + ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( + NativePreferredColorScheme(preferred_color_scheme)); +} + } // namespace content
diff --git a/content/child/webthemeengine_impl_mac.h b/content/child/webthemeengine_impl_mac.h index d4c4075f..b3dafa1 100644 --- a/content/child/webthemeengine_impl_mac.h +++ b/content/child/webthemeengine_impl_mac.h
@@ -15,9 +15,9 @@ blink::ForcedColors ForcedColors() const override; void SetForcedColors(const blink::ForcedColors forced_colors) override; - - private: - blink::ForcedColors forced_colors_ = blink::ForcedColors::kNone; + blink::PreferredColorScheme PreferredColorScheme() const override; + void SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) override; }; } // namespace content
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 3eadf41..2f392889 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -1319,19 +1319,6 @@ bool /* out - success */, base::string16 /* out - This is ignored.*/) -// Register a new handler for URL requests with the given scheme. -IPC_MESSAGE_ROUTED4(FrameHostMsg_RegisterProtocolHandler, - std::string /* scheme */, - GURL /* url */, - base::string16 /* title */, - bool /* user_gesture */) - -// Unregister the registered handler for URL requests with the given scheme. -IPC_MESSAGE_ROUTED3(FrameHostMsg_UnregisterProtocolHandler, - std::string /* scheme */, - GURL /* url */, - bool /* user_gesture */) - // Sent when the renderer loads a resource from its memory cache. // The security info is non empty if the resource was originally loaded over // a secure connection.
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/KitKatWebContentsAccessibility.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/KitKatWebContentsAccessibility.java index be0c4d1..0c4efa5 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/KitKatWebContentsAccessibility.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/KitKatWebContentsAccessibility.java
@@ -37,11 +37,14 @@ protected void setAccessibilityNodeInfoKitKatAttributes(AccessibilityNodeInfo node, boolean isRoot, boolean isEditableText, String role, String roleDescription, String hint, int selectionStartIndex, int selectionEndIndex, boolean hasImage, - boolean contentInvalid) { + boolean contentInvalid, String targetUrl) { Bundle bundle = node.getExtras(); bundle.putCharSequence("AccessibilityNodeInfo.chromeRole", role); bundle.putCharSequence("AccessibilityNodeInfo.roleDescription", roleDescription); bundle.putCharSequence("AccessibilityNodeInfo.hint", hint); + if (!targetUrl.isEmpty()) { + bundle.putCharSequence("AccessibilityNodeInfo.targetUrl", targetUrl); + } if (hasImage) bundle.putCharSequence("AccessibilityNodeInfo.hasImage", "true"); if (isRoot) { bundle.putCharSequence(
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/OWebContentsAccessibility.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/OWebContentsAccessibility.java index 86ba4f0fa..e2485c3 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/OWebContentsAccessibility.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/OWebContentsAccessibility.java
@@ -42,10 +42,10 @@ protected void setAccessibilityNodeInfoKitKatAttributes(AccessibilityNodeInfo node, boolean isRoot, boolean isEditableText, String role, String roleDescription, String hint, int selectionStartIndex, int selectionEndIndex, boolean hasImage, - boolean contentInvalid) { + boolean contentInvalid, String targetUrl) { super.setAccessibilityNodeInfoKitKatAttributes(node, isRoot, isEditableText, role, roleDescription, hint, selectionStartIndex, selectionEndIndex, hasImage, - contentInvalid); + contentInvalid, targetUrl); node.setHintText(hint); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java index 55ed58db..983e5d4 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -1282,7 +1282,7 @@ protected void setAccessibilityNodeInfoKitKatAttributes(AccessibilityNodeInfo node, boolean isRoot, boolean isEditableText, String role, String roleDescription, String hint, int selectionStartIndex, int selectionEndIndex, boolean hasImage, - boolean contentInvalid) { + boolean contentInvalid, String targetUrl) { // Requires KitKat or higher. }
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h index 2e76b75d..e2ec3799 100644 --- a/content/public/browser/render_frame_host.h +++ b/content/public/browser/render_frame_host.h
@@ -298,7 +298,7 @@ // Text surrounding selection. virtual void RequestTextSurroundingSelection( - blink::mojom::Frame::GetTextSurroundingSelectionCallback callback, + blink::mojom::LocalFrame::GetTextSurroundingSelectionCallback callback, int max_length) = 0; // Generates an intervention report in this frame.
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h index 5411d32d..a5e7cc1 100644 --- a/content/public/common/common_param_traits_macros.h +++ b/content/public/common/common_param_traits_macros.h
@@ -83,9 +83,6 @@ content::AutoplayPolicy, content::AutoplayPolicy::kNoUserGestureRequired, content::AutoplayPolicy::kDocumentUserActivationRequired) -IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::PreferredColorScheme, - blink::PreferredColorScheme::kNoPreference, - blink::PreferredColorScheme::kLight) IPC_STRUCT_TRAITS_BEGIN(blink::WebPoint) IPC_STRUCT_TRAITS_MEMBER(x) @@ -250,7 +247,6 @@ IPC_STRUCT_TRAITS_MEMBER(media_controls_enabled) IPC_STRUCT_TRAITS_MEMBER(do_not_update_selection_on_mutating_selection_range) IPC_STRUCT_TRAITS_MEMBER(autoplay_policy) - IPC_STRUCT_TRAITS_MEMBER(preferred_color_scheme) IPC_STRUCT_TRAITS_MEMBER(low_priority_iframes_threshold) IPC_STRUCT_TRAITS_MEMBER(picture_in_picture_enabled) IPC_STRUCT_TRAITS_MEMBER(translate_service_available)
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index c72c051..23ccfec3 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -318,6 +318,9 @@ #endif }; +const base::Feature kNeverSlowMode{"NeverSlowMode", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Kill switch for Web Notification content images. const base::Feature kNotificationContentImage{"NotificationContentImage", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 52ed2e3..a0d728c 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -75,6 +75,7 @@ CONTENT_EXPORT extern const base::Feature kNavigationImmediateResponseBody; CONTENT_EXPORT extern const base::Feature kNetworkQualityEstimatorWebHoldback; CONTENT_EXPORT extern const base::Feature kNetworkServiceInProcess; +CONTENT_EXPORT extern const base::Feature kNeverSlowMode; CONTENT_EXPORT extern const base::Feature kNotificationContentImage; CONTENT_EXPORT extern const base::Feature kNotificationTriggers; CONTENT_EXPORT extern const base::Feature kOriginPolicy;
diff --git a/content/public/common/web_preferences.cc b/content/public/common/web_preferences.cc index 4b76594..e326282 100644 --- a/content/public/common/web_preferences.cc +++ b/content/public/common/web_preferences.cc
@@ -225,7 +225,6 @@ media_controls_enabled(true), do_not_update_selection_on_mutating_selection_range(false), autoplay_policy(AutoplayPolicy::kDocumentUserActivationRequired), - preferred_color_scheme(blink::PreferredColorScheme::kNoPreference), low_priority_iframes_threshold(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN), picture_in_picture_enabled(true), translate_service_available(false),
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h index 700cba90..5649702b 100644 --- a/content/public/common/web_preferences.h +++ b/content/public/common/web_preferences.h
@@ -14,7 +14,6 @@ #include "build/build_config.h" #include "content/common/content_export.h" #include "net/nqe/effective_connection_type.h" -#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/mojom/v8_cache_options.mojom.h" #include "ui/base/pointer/pointer_device.h" #include "url/gurl.h" @@ -313,12 +312,6 @@ // Defines the current autoplay policy. AutoplayPolicy autoplay_policy; - // The preferred color scheme for the web content. The scheme is used to - // evaluate the prefers-color-scheme media query and resolve UA color scheme - // to be used based on the supported-color-schemes META tag and CSS property. - blink::PreferredColorScheme preferred_color_scheme = - blink::PreferredColorScheme::kNoPreference; - // Network quality threshold below which resources from iframes are assigned // either kVeryLow or kVeryLow Blink priority. net::EffectiveConnectionType low_priority_iframes_threshold;
diff --git a/content/public/test/browser_task_environment_unittest.cc b/content/public/test/browser_task_environment_unittest.cc index cca1c2c..854221d 100644 --- a/content/public/test/browser_task_environment_unittest.cc +++ b/content/public/test/browser_task_environment_unittest.cc
@@ -11,12 +11,15 @@ #include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" #include "base/test/bind_test_util.h" +#include "base/test/gtest_util.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using base::test::TaskEnvironment; +using ::testing::IsNull; +using ::testing::NotNull; namespace content { @@ -223,4 +226,37 @@ run_loop.Run(); } +TEST(BrowserTaskEnvironmentTest, GetCurrentTaskWithNoTaskRunning) { + BrowserTaskEnvironment task_environment; + EXPECT_DCHECK_DEATH(base::GetContinuationTaskRunner()); +} + +TEST(BrowserTaskEnvironmentTest, GetContinuationTaskRunnerUI) { + BrowserTaskEnvironment task_environment; + base::RunLoop run_loop; + auto ui_task_runner = base::CreateSingleThreadTaskRunner({BrowserThread::UI}); + + ui_task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() { + EXPECT_EQ(ui_task_runner, + base::GetContinuationTaskRunner()); + run_loop.Quit(); + })); + + run_loop.Run(); +} + +TEST(BrowserTaskEnvironmentTest, GetContinuationTaskRunnerIO) { + BrowserTaskEnvironment task_environment; + base::RunLoop run_loop; + auto io_task_runner = base::CreateSingleThreadTaskRunner({BrowserThread::IO}); + + io_task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() { + EXPECT_EQ(io_task_runner, + base::GetContinuationTaskRunner()); + run_loop.Quit(); + })); + + run_loop.Run(); +} + } // namespace content
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 17fa7ba..64db446a 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -5705,21 +5705,6 @@ disabler_type)); } -void RenderFrameImpl::RegisterProtocolHandler(const WebString& scheme, - const WebURL& url, - const WebString& title) { - bool user_gesture = WebUserGestureIndicator::IsProcessingUserGesture(frame_); - Send(new FrameHostMsg_RegisterProtocolHandler(routing_id_, scheme.Utf8(), url, - title.Utf16(), user_gesture)); -} - -void RenderFrameImpl::UnregisterProtocolHandler(const WebString& scheme, - const WebURL& url) { - bool user_gesture = WebUserGestureIndicator::IsProcessingUserGesture(frame_); - Send(new FrameHostMsg_UnregisterProtocolHandler(routing_id_, scheme.Utf8(), - url, user_gesture)); -} - void RenderFrameImpl::DidSerializeDataForFrame( const WebVector<char>& data, WebFrameSerializerClient::FrameSerializationStatus status) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 0a72aee..4b86c0a 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -836,11 +836,6 @@ void SuddenTerminationDisablerChanged( bool present, blink::SuddenTerminationDisablerType disabler_type) override; - void RegisterProtocolHandler(const blink::WebString& scheme, - const blink::WebURL& url, - const blink::WebString& title) override; - void UnregisterProtocolHandler(const blink::WebString& scheme, - const blink::WebURL& url) override; void CheckIfAudioSinkExistsAndIsAuthorized( const blink::WebString& sink_id, blink::WebSetSinkIdCompleteCallback callback) override;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index a77b6dd..de3feca4 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -2166,6 +2166,7 @@ params->is_dark_mode, params->is_high_contrast, params->preferred_color_scheme, params->colors); blink::SystemColorsChanged(); + blink::ColorSchemeChanged(); } void RenderThreadImpl::PurgePluginListCache(bool reload_pages) {
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 39bcb489..899cf3b7 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -918,7 +918,6 @@ prefs.data_saver_holdback_web_api_enabled); settings->SetLazyLoadEnabled(prefs.lazy_load_enabled); - settings->SetPreferredColorScheme(prefs.preferred_color_scheme); for (const auto& ect_distance_pair : prefs.lazy_frame_loading_distance_thresholds_px) {
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 0721224b..a2e3c78 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -310,6 +310,9 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kForceHighContrast)) theme_engine->SetForcedColors(blink::ForcedColors::kActive); + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceDarkMode)) + theme_engine->SetPreferredColorScheme(blink::PreferredColorScheme::kDark); return theme_engine; }
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 5ff14b45..f3f65eb 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -201,6 +201,10 @@ "browser/web_test/web_test_permission_manager.h", "browser/web_test/web_test_push_messaging_service.cc", "browser/web_test/web_test_push_messaging_service.h", + "browser/web_test/web_test_tts_controller_delegate.cc", + "browser/web_test/web_test_tts_controller_delegate.h", + "browser/web_test/web_test_tts_platform.cc", + "browser/web_test/web_test_tts_platform.h", "common/power_monitor_test_impl.cc", "common/power_monitor_test_impl.h", "common/shell_content_client.cc",
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 9ab3197..30911a65 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -417,17 +417,6 @@ return new ShellSpeechRecognitionManagerDelegate(); } -void ShellContentBrowserClient::OverrideWebkitPrefs( - RenderViewHost* render_view_host, - WebPreferences* prefs) { - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kForceDarkMode)) { - prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; - } else { - prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; - } -} - base::FilePath ShellContentBrowserClient::GetFontLookupTableCacheDir() { return browser_context()->GetPath().Append( FILE_PATH_LITERAL("FontLookupTableCache"));
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index f1e2c35..da8f30f 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -70,8 +70,6 @@ std::unique_ptr<ClientCertificateDelegate> delegate) override; SpeechRecognitionManagerDelegate* CreateSpeechRecognitionManagerDelegate() override; - void OverrideWebkitPrefs(RenderViewHost* render_view_host, - WebPreferences* prefs) override; base::FilePath GetFontLookupTableCacheDir() override; DevToolsManagerDelegate* GetDevToolsManagerDelegate() override; void OpenURL(SiteInstance* site_instance,
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.cc b/content/shell/browser/web_test/web_test_content_browser_client.cc index 5faaea37..c7ff828a 100644 --- a/content/shell/browser/web_test/web_test_content_browser_client.cc +++ b/content/shell/browser/web_test/web_test_content_browser_client.cc
@@ -33,6 +33,8 @@ #include "content/shell/browser/web_test/web_test_browser_context.h" #include "content/shell/browser/web_test/web_test_browser_main_parts.h" #include "content/shell/browser/web_test/web_test_message_filter.h" +#include "content/shell/browser/web_test/web_test_tts_controller_delegate.h" +#include "content/shell/browser/web_test/web_test_tts_platform.h" #include "content/shell/common/web_test/web_test_switches.h" #include "content/shell/renderer/web_test/blink_test_helpers.h" #include "content/test/mock_clipboard_host.h" @@ -324,6 +326,15 @@ switches::kRunWebTests); } +content::TtsControllerDelegate* +WebTestContentBrowserClient::GetTtsControllerDelegate() { + return WebTestTtsControllerDelegate::GetInstance(); +} + +content::TtsPlatform* WebTestContentBrowserClient::GetTtsPlatform() { + return WebTestTtsPlatform::GetInstance(); +} + void WebTestContentBrowserClient::ExposeInterfacesToFrame( service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>* registry) {
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.h b/content/shell/browser/web_test/web_test_content_browser_client.h index 435f204..987f222 100644 --- a/content/shell/browser/web_test/web_test_content_browser_client.h +++ b/content/shell/browser/web_test/web_test_content_browser_client.h
@@ -73,6 +73,9 @@ bool* no_javascript_access) override; bool CanAcceptUntrustedExchangesIfNeeded() override; + content::TtsControllerDelegate* GetTtsControllerDelegate() override; + content::TtsPlatform* GetTtsPlatform() override; + // ShellContentBrowserClient overrides. void ExposeInterfacesToFrame( service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>*
diff --git a/content/shell/browser/web_test/web_test_tts_controller_delegate.cc b/content/shell/browser/web_test/web_test_tts_controller_delegate.cc new file mode 100644 index 0000000..d88d4d4c7 --- /dev/null +++ b/content/shell/browser/web_test/web_test_tts_controller_delegate.cc
@@ -0,0 +1,34 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/shell/browser/web_test/web_test_tts_controller_delegate.h" + +// static +WebTestTtsControllerDelegate* WebTestTtsControllerDelegate::GetInstance() { + return base::Singleton<WebTestTtsControllerDelegate>::get(); +} + +int WebTestTtsControllerDelegate::GetMatchingVoice( + content::TtsUtterance* utterance, + std::vector<content::VoiceData>& voices) { + return -1; +} + +void WebTestTtsControllerDelegate::UpdateUtteranceDefaultsFromPrefs( + content::TtsUtterance* utterance, + double* rate, + double* pitch, + double* volume) {} + +void WebTestTtsControllerDelegate::SetTtsEngineDelegate( + content::TtsEngineDelegate* delegate) {} + +content::TtsEngineDelegate* +WebTestTtsControllerDelegate::GetTtsEngineDelegate() { + return nullptr; +} + +WebTestTtsControllerDelegate::WebTestTtsControllerDelegate() {} + +WebTestTtsControllerDelegate::~WebTestTtsControllerDelegate() {}
diff --git a/content/shell/browser/web_test/web_test_tts_controller_delegate.h b/content/shell/browser/web_test/web_test_tts_controller_delegate.h new file mode 100644 index 0000000..32eeb21 --- /dev/null +++ b/content/shell/browser/web_test/web_test_tts_controller_delegate.h
@@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_TTS_CONTROLLER_DELEGATE_H_ +#define CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_TTS_CONTROLLER_DELEGATE_H_ + +#include "base/memory/singleton.h" +#include "content/public/browser/tts_controller_delegate.h" + +// Dummy implementation of TtsControllerDelegate for web tests. +// Currently does nothing interesting but could be extended to enable more +// detailed testing. +class WebTestTtsControllerDelegate : public content::TtsControllerDelegate { + public: + static WebTestTtsControllerDelegate* GetInstance(); + + // content::TtsControllerDelegate overrides. + int GetMatchingVoice(content::TtsUtterance* utterance, + std::vector<content::VoiceData>& voices) override; + void UpdateUtteranceDefaultsFromPrefs(content::TtsUtterance* utterance, + double* rate, + double* pitch, + double* volume) override; + void SetTtsEngineDelegate(content::TtsEngineDelegate* delegate) override; + content::TtsEngineDelegate* GetTtsEngineDelegate() override; + + private: + WebTestTtsControllerDelegate(); + ~WebTestTtsControllerDelegate() override; + + friend struct base::DefaultSingletonTraits<WebTestTtsControllerDelegate>; + + DISALLOW_COPY_AND_ASSIGN(WebTestTtsControllerDelegate); +}; + +#endif // CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_TTS_CONTROLLER_DELEGATE_H_
diff --git a/content/shell/browser/web_test/web_test_tts_platform.cc b/content/shell/browser/web_test/web_test_tts_platform.cc new file mode 100644 index 0000000..3f83df65 --- /dev/null +++ b/content/shell/browser/web_test/web_test_tts_platform.cc
@@ -0,0 +1,68 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/shell/browser/web_test/web_test_tts_platform.h" + +#include "content/public/browser/tts_controller.h" + +// static +WebTestTtsPlatform* WebTestTtsPlatform::GetInstance() { + return base::Singleton<WebTestTtsPlatform>::get(); +} + +bool WebTestTtsPlatform::PlatformImplAvailable() { + return true; +} + +bool WebTestTtsPlatform::LoadBuiltInTtsEngine( + content::BrowserContext* browser_context) { + return false; +} + +void WebTestTtsPlatform::Speak( + int utterance_id, + const std::string& utterance, + const std::string& lang, + const content::VoiceData& voice, + const content::UtteranceContinuousParameters& params, + base::OnceCallback<void(bool)> on_speak_finished) { + std::move(on_speak_finished).Run(true); + content::TtsController* controller = content::TtsController::GetInstance(); + int len = int{utterance.size()}; + controller->OnTtsEvent(utterance_id, content::TTS_EVENT_START, 0, len, + std::string()); + controller->OnTtsEvent(utterance_id, content::TTS_EVENT_END, len, 0, + std::string()); +} + +bool WebTestTtsPlatform::StopSpeaking() { + return true; +} + +bool WebTestTtsPlatform::IsSpeaking() { + return false; +} + +void WebTestTtsPlatform::GetVoices( + std::vector<content::VoiceData>* out_voices) {} + +void WebTestTtsPlatform::Pause() {} + +void WebTestTtsPlatform::Resume() {} + +void WebTestTtsPlatform::WillSpeakUtteranceWithVoice( + content::TtsUtterance* utterance, + const content::VoiceData& voice_data) {} + +std::string WebTestTtsPlatform::GetError() { + return {}; +} + +void WebTestTtsPlatform::ClearError() {} + +void WebTestTtsPlatform::SetError(const std::string& error) {} + +WebTestTtsPlatform::WebTestTtsPlatform() {} + +WebTestTtsPlatform::~WebTestTtsPlatform() {}
diff --git a/content/shell/browser/web_test/web_test_tts_platform.h b/content/shell/browser/web_test/web_test_tts_platform.h new file mode 100644 index 0000000..8624a3e --- /dev/null +++ b/content/shell/browser/web_test/web_test_tts_platform.h
@@ -0,0 +1,48 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_TTS_PLATFORM_H_ +#define CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_TTS_PLATFORM_H_ + +#include "base/memory/singleton.h" +#include "content/public/browser/tts_platform.h" + +// Dummy implementation of TtsPlatform for web tests. +// Currently does nothing interesting but could be extended to enable more +// detailed testing. +class WebTestTtsPlatform : public content::TtsPlatform { + public: + static WebTestTtsPlatform* GetInstance(); + + // content::TtsControllerDelegate overrides. + bool PlatformImplAvailable() override; + bool LoadBuiltInTtsEngine(content::BrowserContext* browser_context) override; + void Speak(int utterance_id, + const std::string& utterance, + const std::string& lang, + const content::VoiceData& voice, + const content::UtteranceContinuousParameters& params, + base::OnceCallback<void(bool)> on_speak_finished) override; + bool StopSpeaking() override; + bool IsSpeaking() override; + void GetVoices(std::vector<content::VoiceData>* out_voices) override; + void Pause() override; + void Resume() override; + void WillSpeakUtteranceWithVoice( + content::TtsUtterance* utterance, + const content::VoiceData& voice_data) override; + std::string GetError() override; + void ClearError() override; + void SetError(const std::string& error) override; + + private: + WebTestTtsPlatform(); + virtual ~WebTestTtsPlatform(); + + friend struct base::DefaultSingletonTraits<WebTestTtsPlatform>; + + DISALLOW_COPY_AND_ASSIGN(WebTestTtsPlatform); +}; + +#endif // CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_TTS_PLATFORM_H_
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn index 6a180f3a..85375e4 100644 --- a/content/test/fuzzer/BUILD.gn +++ b/content/test/fuzzer/BUILD.gn
@@ -230,12 +230,17 @@ "//content/common/content_export.h", ] + # Don't try to link the code that calls GetContentClient(), because + # then we'd need to link in most of //content. + defines = [ "NO_CONTENT_CLIENT" ] + # TODO(https://crbug.com/927728): Refactor target to not require this. check_includes = false deps = [ "//base", "//base/test:test_support", + "//third_party/webrtc/rtc_base:rtc_base_approved", "//ui/base", "//url:url", ]
diff --git a/content/test/fuzzer/browser_accessibility_fuzzer.cc b/content/test/fuzzer/browser_accessibility_fuzzer.cc index 1766042b..3bff297 100644 --- a/content/test/fuzzer/browser_accessibility_fuzzer.cc +++ b/content/test/fuzzer/browser_accessibility_fuzzer.cc
@@ -5,11 +5,17 @@ #include <fuzzer/FuzzedDataProvider.h> #include "base/at_exit.h" +#include "base/command_line.h" #include "content/browser/accessibility/browser_accessibility.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/accessibility/one_shot_accessibility_tree_search.h" #include "content/browser/accessibility/test_browser_accessibility_delegate.h" +struct Env { + Env() { base::CommandLine::Init(0, nullptr); } + base::AtExitManager at_exit; +}; + namespace content { // Return an accessibility role to use in a tree to fuzz. Out of the @@ -62,8 +68,7 @@ // the fuzz input. Once the tree is constructed, fuzz by calling some // functions that walk the tree in various ways to ensure they don't crash. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - base::AtExitManager at_exit; - + static Env env; FuzzedDataProvider fdp(data, size); // The tree structure is always the same, only the data changes.
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md index a6e15dd..4d20df1 100644 --- a/docs/threading_and_tasks.md +++ b/docs/threading_and_tasks.md
@@ -241,16 +241,47 @@ sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB)); ``` -### Posting to the Current Sequence +### Posting to the Current (Virtual) Thread + +The preferred way of posting to the current thread is via the +`base::CurrentThread` trait. + +```cpp +// The task will run on the current (virtual) thread's default task queue. +base::PostTask(FROM_HERE, {base::CurrentThread()}, base::BindOnce(&Task)); +``` + +You can optionally specify additional traits. This is important because some +threads such as the Browser UI thread, Browser IO thread and the Blink main +thread have multiple task queues funneled onto the same thread and the default +priority may not be suitable your task. + +E.g. you can explicitly set the priority: + +```cpp +// The task will run on the current (virtual) thread's best effort queue. +// NOTE only the Browser UI and Browser IO threads support task priority (for +// now), other (virtual) threads will silently ignore traits used in combination +// with `base::CurrentThread`. +base::PostTask(FROM_HERE, + {base::CurrentThread(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&Task)); +``` The `base::SequencedTaskRunner` to which the current task was posted can be obtained via -[`base::SequencedTaskRunnerHandle::Get()`](https://cs.chromium.org/chromium/src/base/threading/sequenced_task_runner_handle.h). +[`base::GetContinuationTaskRunner()`](https://cs.chromium.org/chromium/src/base/task/post_task.h). + +On some threads there is only one task runner so the current sequence is the +same as the current thread. That's not the case in the Browser UI, Browser IO or +Blink main threads. Additionally the notion of the current sequence doesn't +exist for parallel threadpool tasks or when there's no task running, and +`base::GetContinuationTaskRunner()` will DCHECK in those circumstances. *** note -**NOTE:** it is invalid to call `base::SequencedTaskRunnerHandle::Get()` from a -parallel task, but it is valid from a single-threaded task (a -`base::SingleThreadTaskRunner` is a `base::SequencedTaskRunner`). +**NOTE:** While its invalid to call `base::GetContinuationTaskRunner()` from a +parallel task, it is valid from a sequenced or a single-threaded task. I.e. from +a `base::SequencedTaskRunner` or a `base::SingleThreadTaskRunner`. *** ```cpp @@ -259,10 +290,37 @@ // (in particular, it will run after the current task completes). // It is also guaranteed that it won’t run concurrently with any // task posted to that SequencedTaskRunner. -base::SequencedTaskRunnerHandle::Get()-> +base::GetContinuationTaskRunner()-> PostTask(FROM_HERE, base::BindOnce(&Task)); ``` +You can also obtain the current thread's default task runner via the +`base::CurrentThread` trait, however you can specify additional traits. This is +important because some threads such as the Browser UI thread and the Blink main +thread have multiple task queues funneled onto the same thread and the default +priority may not suit your task. E.g. you can explicitly set the priority: + +```cpp +// The task will run on the current (virtual) thread's best effort queue. +// NOTE only the Browser UI and Browser IO threads support task priority, other +// (virtual) threads will silently ignore traits used in combination with +// `base::CurrentThread`. +base::PostTask(FROM_HERE, + {base::CurrentThread(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&Task)); +``` + +If you need to obtain a task runner with these traits you can do so via + `base::CreateSequencedTaskRunner()`. + +```cpp +// Tasks posted to |task_runner| will run on the current (virtual) thread's best +// effort queue. +auto task_runner = base::CreateSequencedTaskRunner( + {base::CurrentThread(), base::TaskPriority::BEST_EFFORT}); +``` + + ## Using Sequences Instead of Locks Usage of locks is discouraged in Chrome. Sequences inherently provide @@ -380,33 +438,6 @@ threads](#prefer-sequences-to-physical-threads) and that this thus should rarely be necessary. -### Posting to the Current Thread - -*** note -**IMPORTANT:** To post a task that needs mutual exclusion with the current -sequence of tasks but doesn’t absolutely need to run on the current thread, use -`base::SequencedTaskRunnerHandle::Get()` instead of -`base::ThreadTaskRunnerHandle::Get()` (ref. [Posting to the Current -Sequence](#Posting-to-the-Current-Sequence)). That will better document the -requirements of the posted task and will avoid unnecessarily making your API -thread-affine. In a single-thread task, `base::SequencedTaskRunnerHandle::Get()` -is equivalent to `base::ThreadTaskRunnerHandle::Get()`. -*** - -To post a task to the current thread, use -[`base::ThreadTaskRunnerHandle`](https://cs.chromium.org/chromium/src/base/threading/thread_task_runner_handle.h). - -```cpp -// The task will run on the current thread in the future. -base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&Task)); -``` - -*** note -**NOTE:** It is invalid to call `base::ThreadTaskRunnerHandle::Get()` from a parallel -or a sequenced task. -*** - ## Posting Tasks to a COM Single-Thread Apartment (STA) Thread (Windows) Tasks that need to run on a COM Single-Thread Apartment (STA) thread must be @@ -490,6 +521,17 @@ base::PostTask( FROM_HERE, {content::BrowserThread::UI}, base::BindOnce(...)); + +// This task will run on the current virtual thread (sequence). +base::PostTask( + FROM_HERE, {base::CurrentThread()}, + base::BindOnce(...)); + +// This task will run on the current virtual thread (sequence) with best effort +// priority. +base::PostTask( + FROM_HERE, {base::CurrentThread(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(...)); ``` ## Keeping the Browser Responsive @@ -771,5 +813,38 @@ Note that this still allows removing all layers of plumbing between //chrome and that component since unit tests will use the leaf layer directly. +## Old APIs + +The codebase contains several old APIs for retrieving the current thread and +current sequence's task runners. These are being migrated to new APIs and +shouldn't be used in new code. + +[`base::ThreadTaskRunnerHandle`](https://cs.chromium.org/chromium/src/base/threading/thread_task_runner_handle.h) +returns the default task runner for the current thread. All call sites will be +migrated to use base::CurrentThread instead. + +```cpp +// The task will run on the current thread in the future. +base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&Task)); +``` + +[`base::SequencedTaskRunnerHandle::Get()`](https://cs.chromium.org/chromium/src/base/threading/sequenced_task_runner_handle.h) +returns either the thread's default task runner (Browser UI thread, Browser IO +thread, Blink mail thread) or in a sequenced thread pool task it returns the +current sequence. All call sites will be migrated to either use +base::CurrentThread or `base::GetContinuationTaskRunner()` depending on the +callsite. + +```cpp +// The task will run after any task that has already been posted +// to the SequencedTaskRunner to which the current task was posted +// (in particular, it will run after the current task completes). +// It is also guaranteed that it won’t run concurrently with any +// task posted to that SequencedTaskRunner. +base::SequencedTaskRunnerHandle::Get()-> + PostTask(FROM_HERE, base::BindOnce(&Task)); +``` + ## FAQ See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more examples.
diff --git a/extensions/browser/api/display_source/display_source_apitestbase.cc b/extensions/browser/api/display_source/display_source_apitestbase.cc index c46d83f..955fd16f 100644 --- a/extensions/browser/api/display_source/display_source_apitestbase.cc +++ b/extensions/browser/api/display_source/display_source_apitestbase.cc
@@ -13,6 +13,7 @@ #include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/log/net_log_source.h" #include "net/socket/udp_socket.h" @@ -65,9 +66,9 @@ void StopWatchingAvailableSinks() override; - std::string GetLocalAddress() const override; + net::IPAddress GetLocalAddress() const override; - std::string GetSinkAddress() const override; + net::IPAddress GetSinkAddress() const override; void SendMessage(const std::string& message) override; @@ -366,12 +367,12 @@ void MockDisplaySourceConnectionDelegate::StopWatchingAvailableSinks() {} -std::string MockDisplaySourceConnectionDelegate::GetLocalAddress() const { - return "127.0.0.1"; +net::IPAddress MockDisplaySourceConnectionDelegate::GetLocalAddress() const { + return net::IPAddress::IPv4Localhost(); } -std::string MockDisplaySourceConnectionDelegate::GetSinkAddress() const { - return "127.0.0.1"; +net::IPAddress MockDisplaySourceConnectionDelegate::GetSinkAddress() const { + return net::IPAddress::IPv4Localhost(); } void MockDisplaySourceConnectionDelegate::SendMessage(
diff --git a/extensions/browser/api/display_source/display_source_connection_delegate.h b/extensions/browser/api/display_source/display_source_connection_delegate.h index b5cc019..ce6e5cd 100644 --- a/extensions/browser/api/display_source/display_source_connection_delegate.h +++ b/extensions/browser/api/display_source/display_source_connection_delegate.h
@@ -9,6 +9,7 @@ #include "base/observer_list.h" #include "components/keyed_service/core/keyed_service.h" #include "extensions/common/api/display_source.h" +#include "net/base/ip_address.h" namespace extensions { @@ -34,10 +35,10 @@ virtual const DisplaySourceSinkInfo& GetConnectedSink() const = 0; // Returns the local address of the source. - virtual std::string GetLocalAddress() const = 0; + virtual net::IPAddress GetLocalAddress() const = 0; // Returns the address of the connected sink. - virtual std::string GetSinkAddress() const = 0; + virtual net::IPAddress GetSinkAddress() const = 0; // Sends a control message to the connected sink. // If an error occurs 'Observer::OnConnectionError' is invoked.
diff --git a/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc b/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc index 7a00e4f..280f0c4 100644 --- a/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc +++ b/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc
@@ -66,25 +66,16 @@ WiFiDisplayMediaServiceImpl::~WiFiDisplayMediaServiceImpl() {} -void WiFiDisplayMediaServiceImpl::SetDesinationPoint( - const std::string& ip_address, - int32_t port, - const SetDesinationPointCallback& callback) { +void WiFiDisplayMediaServiceImpl::SetDestinationPoint( + const net::IPEndPoint& ip_end_point, + const SetDestinationPointCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - net::IPAddress address; - if (!address.AssignFromIPLiteral(std::string(ip_address))) { - DVLOG(1) << "Failed to parse IP address from " << ip_address; - callback.Run(false); - return; - } - net::IPEndPoint end_point(address, static_cast<uint16_t>(port)); - rtp_socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(), nullptr, net::NetLogSource())); - if (rtp_socket_->Open(end_point.GetFamily()) != net::OK || - rtp_socket_->Connect(end_point) != net::OK) { - DVLOG(1) << "Could not connect to " << end_point.ToString(); + if (rtp_socket_->Open(ip_end_point.GetFamily()) != net::OK || + rtp_socket_->Connect(ip_end_point) != net::OK) { + DVLOG(1) << "Could not connect to " << ip_end_point.ToString(); callback.Run(false); rtp_socket_.reset(); return;
diff --git a/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.h b/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.h index 27fe93b2..a3d7d33 100644 --- a/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.h +++ b/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.h
@@ -26,9 +26,9 @@ static void BindToRequest(mojom::WiFiDisplayMediaServiceRequest request, content::RenderFrameHost* render_frame_host); - void SetDesinationPoint(const std::string& ip_address, - int32_t port, - const SetDesinationPointCallback& callback) override; + void SetDestinationPoint( + const net::IPEndPoint& ip_end_point, + const SetDestinationPointCallback& callback) override; void SendMediaPacket(mojom::WiFiDisplayMediaPacketPtr packet) override; private:
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 2a6857f..c7c163b 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -7,6 +7,7 @@ import("//components/nacl/features.gni") import("//extensions/buildflags/buildflags.gni") import("//mojo/public/tools/bindings/mojom.gni") +import("//testing/libfuzzer/fuzzer_test.gni") # TODO(crbug.com/731689): Assert that extensions are enabled. @@ -484,4 +485,14 @@ "//tools/metrics/histograms/enums.xml", ] } + + fuzzer_test("extension_fuzzer") { + sources = [ + "extension_fuzzer.cc", + ] + deps = [ + ":common", + "//base", + ] + } } # enable_extensions
diff --git a/extensions/common/extension_fuzzer.cc b/extensions/common/extension_fuzzer.cc new file mode 100644 index 0000000..9f96615 --- /dev/null +++ b/extensions/common/extension_fuzzer.cc
@@ -0,0 +1,20 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> + +#include "extensions/common/extension.h" + +namespace extensions { + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + std::string key_contents(reinterpret_cast<const char*>(data), size); + std::string key_bytes; + Extension::ParsePEMKeyBytes(key_contents, &key_bytes); + + return 0; +} + +} // namespace extensions
diff --git a/extensions/common/mojom/wifi_display_session_service.mojom b/extensions/common/mojom/wifi_display_session_service.mojom index a5e6048..3ba92e2 100644 --- a/extensions/common/mojom/wifi_display_session_service.mojom +++ b/extensions/common/mojom/wifi_display_session_service.mojom
@@ -4,6 +4,9 @@ module extensions.mojom; +import "services/network/public/mojom/ip_address.mojom"; +import "services/network/public/mojom/ip_endpoint.mojom"; + struct WiFiDisplayMediaPacket { array<uint8> data; }; @@ -29,7 +32,8 @@ interface WiFiDisplaySessionServiceClient { // Notification of a successfull connection to a sink. - OnConnected(string local_ip_address, string sink_ip_address); + OnConnected(network.mojom.IPAddress local_ip_address, + network.mojom.IPAddress sink_ip_address); // Notification of a handled connection request. OnConnectRequestHandled(bool success, string error_message); @@ -54,7 +58,7 @@ // connected sink. interface WiFiDisplayMediaService { // Sets the destination point for sending media stream. - SetDesinationPoint(string ip_address, int32 port) => (bool success); + SetDestinationPoint(network.mojom.IPEndPoint ip_end_point) => (bool success); // Sends media packet to the destination point. SendMediaPacket(WiFiDisplayMediaPacket packet);
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc index b9ed185..7f5edee6 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc
@@ -87,7 +87,7 @@ WiFiDisplayMediaManager::WiFiDisplayMediaManager( const blink::WebMediaStreamTrack& video_track, const blink::WebMediaStreamTrack& audio_track, - const std::string& sink_ip_address, + const net::IPAddress& sink_ip_address, service_manager::InterfaceProvider* interface_provider, const ErrorCallback& error_callback) : video_track_(video_track),
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h index 7f95330d..aeae270c 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h
@@ -34,7 +34,7 @@ WiFiDisplayMediaManager( const blink::WebMediaStreamTrack& video_track, const blink::WebMediaStreamTrack& audio_track, - const std::string& sink_ip_address, + const net::IPAddress& sink_ip_address, service_manager::InterfaceProvider* interface_provider, const ErrorCallback& error_callback); @@ -79,7 +79,7 @@ std::unique_ptr<WiFiDisplayVideoSink> video_sink_; service_manager::InterfaceProvider* interface_provider_; - std::string sink_ip_address_; + net::IPAddress sink_ip_address_; std::pair<int, int> sink_rtp_ports_; wds::H264VideoFormat optimal_video_format_; wds::AudioCodec optimal_audio_codec_;
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc index d78323d..77d7036 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.cc
@@ -23,26 +23,25 @@ wds::SessionType type, const WiFiDisplayVideoEncoder::InitParameters& video_parameters, const wds::AudioCodec& audio_codec, - const std::string& sink_ip_address, + const net::IPAddress& sink_ip_address, const std::pair<int, int>& sink_rtp_ports, const RegisterMediaServiceCallback& service_callback, const ErrorCallback& error_callback) - : type_(type), - video_parameters_(video_parameters), - audio_codec_(audio_codec), - sink_ip_address_(sink_ip_address), - sink_rtp_ports_(sink_rtp_ports), - service_callback_(service_callback), - error_callback_(error_callback), - weak_factory_(this) { -} + : type_(type), + video_parameters_(video_parameters), + audio_codec_(audio_codec), + sink_ip_address_(sink_ip_address), + sink_rtp_ports_(sink_rtp_ports), + service_callback_(service_callback), + error_callback_(error_callback), + weak_factory_(this) {} // static std::unique_ptr<WiFiDisplayMediaPipeline> WiFiDisplayMediaPipeline::Create( wds::SessionType type, const WiFiDisplayVideoEncoder::InitParameters& video_parameters, const wds::AudioCodec& audio_codec, - const std::string& sink_ip_address, + const net::IPAddress& sink_ip_address, const std::pair<int, int>& sink_rtp_ports, const RegisterMediaServiceCallback& service_callback, const ErrorCallback& error_callback) { @@ -206,9 +205,9 @@ DCHECK(media_service_); auto error_callback = base::Bind(error_callback_, kErrorUnableSendMedia); media_service_.set_connection_error_handler(error_callback); - media_service_->SetDesinationPoint( - sink_ip_address_, - static_cast<int32_t>(sink_rtp_ports_.first), + media_service_->SetDestinationPoint( + net::IPEndPoint(sink_ip_address_, + static_cast<uint16_t>(sink_rtp_ports_.first)), callback); }
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.h index 0f0027e..1b1ca674 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.h +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.h
@@ -40,7 +40,7 @@ wds::SessionType type, const WiFiDisplayVideoEncoder::InitParameters& video_parameters, const wds::AudioCodec& audio_codec, - const std::string& sink_ip_address, + const net::IPAddress& sink_ip_address, const std::pair<int, int>& sink_rtp_ports, const RegisterMediaServiceCallback& service_callback, const ErrorCallback& error_callback); @@ -63,7 +63,7 @@ wds::SessionType type, const WiFiDisplayVideoEncoder::InitParameters& video_parameters, const wds::AudioCodec& audio_codec, - const std::string& sink_ip_address, + const net::IPAddress& sink_ip_address, const std::pair<int, int>& sink_rtp_ports, const RegisterMediaServiceCallback& service_callback, const ErrorCallback& error_callback); @@ -93,7 +93,7 @@ wds::SessionType type_; WiFiDisplayVideoEncoder::InitParameters video_parameters_; wds::AudioCodec audio_codec_; - std::string sink_ip_address_; + net::IPAddress sink_ip_address_; std::pair<int, int> sink_rtp_ports_; RegisterMediaServiceCallback service_callback_;
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc index 9f2436ca..1d7bddd 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
@@ -72,8 +72,8 @@ teminate_completion_callback_ = callback; } -void WiFiDisplaySession::OnConnected(const std::string& local_ip_address, - const std::string& sink_ip_address) { +void WiFiDisplaySession::OnConnected(const net::IPAddress& local_ip_address, + const net::IPAddress& sink_ip_address) { DCHECK_EQ(DisplaySourceSession::Established, state_); local_ip_address_ = local_ip_address; media_manager_.reset( @@ -124,7 +124,7 @@ } std::string WiFiDisplaySession::GetLocalIPAddress() const { - return local_ip_address_; + return local_ip_address_.ToString(); } int WiFiDisplaySession::GetNextCSeq(int* initial_peer_cseq) const {
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h index 00558ed2..a45c4ecf 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.h
@@ -41,8 +41,8 @@ void Terminate(const CompletionCallback& callback) override; // WiFiDisplaySessionServiceClient overrides. - void OnConnected(const std::string& local_ip_address, - const std::string& sink_ip_address) override; + void OnConnected(const net::IPAddress& local_ip_address, + const net::IPAddress& sink_ip_address) override; void OnConnectRequestHandled(bool success, const std::string& error) override; void OnTerminated() override; void OnDisconnectRequestHandled(bool success, @@ -77,7 +77,7 @@ std::unique_ptr<WiFiDisplayMediaManager> media_manager_; mojo::Remote<mojom::WiFiDisplaySessionService> service_; mojo::Receiver<WiFiDisplaySessionServiceClient> receiver_{this}; - std::string local_ip_address_; + net::IPAddress local_ip_address_; std::map<int, std::unique_ptr<base::RepeatingTimer>> timers_; DisplaySourceSessionParams params_;
diff --git a/fuchsia/engine/browser/url_request_rewrite_rules_manager.cc b/fuchsia/engine/browser/url_request_rewrite_rules_manager.cc index a7e5ece..38985d8 100644 --- a/fuchsia/engine/browser/url_request_rewrite_rules_manager.cc +++ b/fuchsia/engine/browser/url_request_rewrite_rules_manager.cc
@@ -99,6 +99,14 @@ } // namespace +UrlRequestRewriteRulesManager::ActiveFrame::ActiveFrame( + content::RenderFrameHost* rfh, + mojo::AssociatedRemote<mojom::UrlRequestRulesReceiver> ar) + : render_frame_host(rfh), associated_remote(std::move(ar)) {} +UrlRequestRewriteRulesManager::ActiveFrame::ActiveFrame( + UrlRequestRewriteRulesManager::ActiveFrame&&) = default; +UrlRequestRewriteRulesManager::ActiveFrame::~ActiveFrame() = default; + // static UrlRequestRewriteRulesManager* UrlRequestRewriteRulesManager::ForFrameTreeNodeId(int frame_tree_node_id) { @@ -136,8 +144,9 @@ std::move(rules))); // Send the updated rules to the receivers. - for (const auto& receiver_pair : rules_receivers_per_frame_id_) { - receiver_pair.second->OnRulesUpdated(mojo::Clone(cached_rules_->data)); + for (const auto& receiver_pair : active_frames_) { + receiver_pair.second.associated_remote->OnRulesUpdated( + mojo::Clone(cached_rules_->data)); } // TODO(crbug.com/976975): Only call the callback when there are pending @@ -158,12 +167,11 @@ content::RenderFrameHost* render_frame_host) { int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId(); - if (rules_receivers_per_frame_id_.find(frame_tree_node_id) != - rules_receivers_per_frame_id_.end()) { + if (active_frames_.find(frame_tree_node_id) != active_frames_.end()) { // This happens on cross-process navigations. It is not necessary to refresh // the global map in this case as RenderFrameDeleted will not have been // called for this RenderFrameHost. - size_t deleted = rules_receivers_per_frame_id_.erase(frame_tree_node_id); + size_t deleted = active_frames_.erase(frame_tree_node_id); DCHECK(deleted == 1); } else { // Register this instance of UrlRequestRewriteRulesManager as the URL @@ -177,24 +185,32 @@ mojo::AssociatedRemote<mojom::UrlRequestRulesReceiver> rules_receiver; render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface( &rules_receiver); - auto iter = rules_receivers_per_frame_id_.emplace(frame_tree_node_id, - std::move(rules_receiver)); + ActiveFrame active_frame(render_frame_host, std::move(rules_receiver)); + auto iter = + active_frames_.emplace(frame_tree_node_id, std::move(active_frame)); DCHECK(iter.second); base::AutoLock auto_lock(lock_); if (cached_rules_) { // Send an initial set of rules. - iter.first->second->OnRulesUpdated(mojo::Clone(cached_rules_->data)); + iter.first->second.associated_remote->OnRulesUpdated( + mojo::Clone(cached_rules_->data)); } } void UrlRequestRewriteRulesManager::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId(); + auto iter = active_frames_.find(frame_tree_node_id); + DCHECK(iter != active_frames_.end()); + // On cross-process navigations, the new RenderFrameHost is created before + // the old one is deleted. When that happens, the map has already been + // updated, so it is safe to return here. + if (iter->second.render_frame_host != render_frame_host) + return; + + active_frames_.erase(iter); size_t deleted = GetRewriterMap().erase(frame_tree_node_id); DCHECK(deleted == 1); - - deleted = rules_receivers_per_frame_id_.erase(frame_tree_node_id); - DCHECK(deleted == 1); }
diff --git a/fuchsia/engine/browser/url_request_rewrite_rules_manager.h b/fuchsia/engine/browser/url_request_rewrite_rules_manager.h index d1e0056f..3dee2cbd 100644 --- a/fuchsia/engine/browser/url_request_rewrite_rules_manager.h +++ b/fuchsia/engine/browser/url_request_rewrite_rules_manager.h
@@ -45,6 +45,19 @@ GetCachedRules() override; private: + // Helper struct containing a RenderFrameHost and its corresponding + // AssociatedRemote. + struct ActiveFrame { + ActiveFrame(content::RenderFrameHost* render_frame_host, + mojo::AssociatedRemote<mojom::UrlRequestRulesReceiver> + associated_remote); + ActiveFrame(ActiveFrame&& other); + ~ActiveFrame(); + + content::RenderFrameHost* render_frame_host; + mojo::AssociatedRemote<mojom::UrlRequestRulesReceiver> associated_remote; + }; + // Test-only constructor. explicit UrlRequestRewriteRulesManager(); @@ -56,9 +69,8 @@ scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules> cached_rules_ GUARDED_BY(lock_); - // Map of frames rules receivers per FrameTreeNode ID. - std::map<int, mojo::AssociatedRemote<mojom::UrlRequestRulesReceiver>> - rules_receivers_per_frame_id_; + // Map of FrameTreeNode Ids to their current ActiveFrame. + std::map<int, ActiveFrame> active_frames_; DISALLOW_COPY_AND_ASSIGN(UrlRequestRewriteRulesManager); };
diff --git a/fuchsia/engine/common/web_engine_url_loader_throttle.cc b/fuchsia/engine/common/web_engine_url_loader_throttle.cc index 14ff2d7..58ef985 100644 --- a/fuchsia/engine/common/web_engine_url_loader_throttle.cc +++ b/fuchsia/engine/common/web_engine_url_loader_throttle.cc
@@ -5,6 +5,7 @@ #include "fuchsia/engine/common/web_engine_url_loader_throttle.h" #include "base/strings/string_util.h" +#include "url/url_constants.h" namespace { @@ -55,6 +56,11 @@ return; GURL new_url = replace_url->new_url; + if (new_url.SchemeIs(url::kDataScheme)) { + request->url = new_url; + return; + } + if (new_url.has_scheme() && new_url.scheme().compare(request->url.scheme()) != 0) { // No cross-scheme redirect allowed.
diff --git a/fuchsia/engine/common/web_engine_url_loader_throttle_unittest.cc b/fuchsia/engine/common/web_engine_url_loader_throttle_unittest.cc index 93e370b..53e91d0a 100644 --- a/fuchsia/engine/common/web_engine_url_loader_throttle_unittest.cc +++ b/fuchsia/engine/common/web_engine_url_loader_throttle_unittest.cc
@@ -90,3 +90,37 @@ throttle.WillStartRequest(&request4, &defer); EXPECT_FALSE(request4.headers.HasHeader("Header")); } + +// Tests URL replacement rules that replace to a data URL do not append query or +// ref from the original URL. +TEST_F(WebEngineURLLoaderThrottleTest, DataReplacementUrl) { + const char kCssDataURI[] = "data:text/css,"; + + mojom::UrlRequestRewriteReplaceUrlPtr replace_url = + mojom::UrlRequestRewriteReplaceUrl::New(); + replace_url->url_ends_with = ".css"; + replace_url->new_url = GURL(kCssDataURI); + mojom::UrlRequestRewritePtr rewrite = + mojom::UrlRequestRewrite::NewReplaceUrl(std::move(replace_url)); + std::vector<mojom::UrlRequestRewritePtr> rewrites; + rewrites.push_back(std::move(rewrite)); + mojom::UrlRequestRewriteRulePtr rule = mojom::UrlRequestRewriteRule::New(); + rule->hosts_filter = base::Optional<std::vector<std::string>>({"*.test.net"}); + rule->rewrites = std::move(rewrites); + + std::vector<mojom::UrlRequestRewriteRulePtr> rules; + rules.push_back(std::move(rule)); + + TestCachedRulesProvider provider; + provider.SetCachedRules( + base::MakeRefCounted<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>( + std::move(rules))); + + WebEngineURLLoaderThrottle throttle(&provider); + bool defer = false; + + network::ResourceRequest request; + request.url = GURL("http://test.net/style.css?query#ref"); + throttle.WillStartRequest(&request, &defer); + EXPECT_EQ(request.url, base::StringPiece(kCssDataURI)); +}
diff --git a/fuchsia/runners/cast/cast_runner.cc b/fuchsia/runners/cast/cast_runner.cc index 85b00fd..99b30242 100644 --- a/fuchsia/runners/cast/cast_runner.cc +++ b/fuchsia/runners/cast/cast_runner.cc
@@ -5,6 +5,7 @@ #include "fuchsia/runners/cast/cast_runner.h" #include <fuchsia/sys/cpp/fidl.h> +#include <fuchsia/web/cpp/fidl.h> #include <memory> #include <string> #include <utility> @@ -88,9 +89,9 @@ return; } - // The application configuration asynchronously via the per-component - // ApplicationConfigManager, the pointer to that service must be kept live - // until the request completes, or CastRunner is deleted. + // The application configuration is obtained asynchronously via the + // per-component ApplicationConfigManager. The pointer to that service must be + // kept live until the request completes or CastRunner is deleted. auto pending_component = std::make_unique<CastComponent::CastComponentParams>(); pending_component->startup_context = @@ -99,16 +100,6 @@ pending_component->startup_context->incoming_services()); pending_component->controller_request = std::move(controller_request); - // Request the configuration for the specified application. - pending_component->agent_manager->ConnectToAgentService( - kAgentComponentUrl, pending_component->app_config_manager.NewRequest()); - pending_component->app_config_manager.set_error_handler( - [this, pending_component = pending_component.get()](zx_status_t status) { - ZX_LOG(ERROR, status) << "ApplicationConfigManager disconnected."; - GetConfigCallback(pending_component, - chromium::cast::ApplicationConfig()); - }); - // Get binding details from the Agent. fidl::InterfaceHandle<chromium::cast::ApiBindings> api_bindings_client; pending_component->agent_manager->ConnectToAgentService( @@ -141,6 +132,15 @@ MaybeStartComponent(pending_component); }); + // Request the configuration for the specified application. + pending_component->agent_manager->ConnectToAgentService( + kAgentComponentUrl, pending_component->app_config_manager.NewRequest()); + pending_component->app_config_manager.set_error_handler( + [this, pending_component = pending_component.get()](zx_status_t status) { + ZX_LOG(ERROR, status) << "ApplicationConfigManager disconnected."; + GetConfigCallback(pending_component, + chromium::cast::ApplicationConfig()); + }); const std::string cast_app_id(cast_url.GetContent()); pending_component->app_config_manager->GetConfig( cast_app_id, [this, pending_component = pending_component.get()]( @@ -170,10 +170,15 @@ auto it = pending_components_.find(pending_component); DCHECK(it != pending_components_.end()); - // If no configuration was returned then ignore the request. + if (app_config.IsEmpty()) { + pending_components_.erase(it); + DLOG(WARNING) << "No application config was found."; + return; + } + if (!app_config.has_web_url()) { pending_components_.erase(it); - DLOG(WARNING) << "No ApplicationConfig was found."; + DLOG(WARNING) << "Only web-based applications are supported."; return; }
diff --git a/fuchsia/runners/cast/cast_runner.h b/fuchsia/runners/cast/cast_runner.h index 9752fb28..2928b0a 100644 --- a/fuchsia/runners/cast/cast_runner.h +++ b/fuchsia/runners/cast/cast_runner.h
@@ -5,6 +5,8 @@ #ifndef FUCHSIA_RUNNERS_CAST_CAST_RUNNER_H_ #define FUCHSIA_RUNNERS_CAST_CAST_RUNNER_H_ +#include <fuchsia/sys/cpp/fidl.h> +#include <fuchsia/web/cpp/fidl.h> #include <memory> #include <set> #include <vector>
diff --git a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc index ada152e..40e01f92 100644 --- a/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc +++ b/gpu/command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc
@@ -709,7 +709,7 @@ } TEST_P(GLCopyTextureCHROMIUMES3Test, BigTexture) { - if (ShouldSkipBGRA()) + if (ShouldSkipTest() || ShouldSkipBGRA()) return; width_ = 1080; height_ = 1080;
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index dfe512e..4b98aab3 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -892,16 +892,16 @@ GpuDriverBugWorkarounds workarounds( GetGpuFeatureInfo().enabled_gpu_driver_bug_workarounds); - // Work around issues with recovery by allowing a new GPU process to - // launch. - if (workarounds.exit_on_context_lost) - gpu_channel_manager_delegate_->MaybeExitOnContextLost(); - // Lose all other contexts. if (gl::GLContext::LosesAllContextsOnContextLost() || (context_state_ && context_state_->use_virtualized_gl_contexts())) { gpu_channel_manager_delegate_->LoseAllContexts(); } + + // Work around issues with recovery by allowing a new GPU process to + // launch. + if (workarounds.exit_on_context_lost) + gpu_channel_manager_delegate_->MaybeExitOnContextLost(); } } }
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc index cda3158..1cacaa4c 100644 --- a/gpu/ipc/service/gpu_channel_manager.cc +++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -516,16 +516,16 @@ if (synthetic_loss) return; - // Work around issues with recovery by allowing a new GPU process to launch. - if (gpu_driver_bug_workarounds_.exit_on_context_lost) - delegate_->MaybeExitOnContextLost(); - // Lose all other contexts. if (gl::GLContext::LosesAllContextsOnContextLost() || (shared_context_state_ && shared_context_state_->use_virtualized_gl_contexts())) { delegate_->LoseAllContexts(); } + + // Work around issues with recovery by allowing a new GPU process to launch. + if (gpu_driver_bug_workarounds_.exit_on_context_lost) + delegate_->MaybeExitOnContextLost(); } void GpuChannelManager::ScheduleGrContextCleanup() {
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index a02048f..b658a9e 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -560,6 +560,10 @@ flag_descriptions::kDisableAnimationOnLowBatteryName, flag_descriptions::kDisableAnimationOnLowBatteryDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDisableAnimationOnLowBattery)}, + {"messages-save-card-infobar", + flag_descriptions::kSaveCardInfobarMessagesUIName, + flag_descriptions::kSaveCardInfobarMessagesUIDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(kSaveCardInfobarMessagesUI)}, }; // Add all switches from experimental flags to |command_line|.
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 64885a2..a7e7738 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -292,6 +292,10 @@ const char kPasswordLeakDetectionDescription[] = "Enables the detection of leaked passwords."; +const char kSaveCardInfobarMessagesUIName[] = "Save Card Infobar Messages UI"; +const char kSaveCardInfobarMessagesUIDescription[] = + "When enabled, Save Card Infobar uses the new Messages UI."; + const char kSearchIconToggleName[] = "Change the icon for the search button"; const char kSearchIconToggleDescription[] = "Different icons for the search button.";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index d7253278..2aa9c79 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -249,6 +249,11 @@ extern const char kPasswordLeakDetectionName[]; extern const char kPasswordLeakDetectionDescription[]; +// Title and description for the flag that enables Messages UI on +// SaveCard Infobars. +extern const char kSaveCardInfobarMessagesUIName[]; +extern const char kSaveCardInfobarMessagesUIDescription[]; + // Title and description for the flag to toggle the flag of the search button. extern const char kSearchIconToggleName[]; extern const char kSearchIconToggleDescription[];
diff --git a/ios/chrome/browser/infobars/infobar_badge_model.mm b/ios/chrome/browser/infobars/infobar_badge_model.mm index 37043d9..dd06741 100644 --- a/ios/chrome/browser/infobars/infobar_badge_model.mm +++ b/ios/chrome/browser/infobars/infobar_badge_model.mm
@@ -44,6 +44,8 @@ return BadgeType::kBadgeTypePasswordSave; case InfobarType::kInfobarTypePasswordUpdate: return BadgeType::kBadgeTypePasswordUpdate; + case InfobarType::kInfobarTypeSaveCard: + return BadgeType::kBadgeTypeSaveCard; default: NOTREACHED() << "This infobar should not have a badge"; return BadgeType::kBadgeTypeNone;
diff --git a/ios/chrome/browser/infobars/infobar_metrics_recorder.mm b/ios/chrome/browser/infobars/infobar_metrics_recorder.mm index 2543699..f937279 100644 --- a/ios/chrome/browser/infobars/infobar_metrics_recorder.mm +++ b/ios/chrome/browser/infobars/infobar_metrics_recorder.mm
@@ -64,6 +64,19 @@ const char kInfobarSaveCardBadgeTappedHistogram[] = "Mobile.Messages.Badge.Tapped.InfobarTypeSaveCard"; +// Histogram names for InfobarTypeTranslate. +// Banner. +const char kInfobarTranslateBannerEventHistogram[] = + "Mobile.Messages.Banner.Event.InfobarTypeTranslate"; +const char kInfobarTranslateBannerDismissTypeHistogram[] = + "Mobile.Messages.Banner.Dismiss.InfobarTypeTranslate"; +// Modal. +const char kInfobarTranslateModalEventHistogram[] = + "Mobile.Messages.Modal.Event.InfobarTypeTranslate"; +// Badge. +const char kInfobarTranslateBadgeTappedHistogram[] = + "Mobile.Messages.Badge.Tapped.InfobarTypeTranslate"; + } // namespace @interface InfobarMetricsRecorder () @@ -99,6 +112,9 @@ case InfobarType::kInfobarTypeSaveCard: UMA_HISTOGRAM_ENUMERATION(kInfobarSaveCardBannerEventHistogram, event); break; + case InfobarType::kInfobarTypeTranslate: + UMA_HISTOGRAM_ENUMERATION(kInfobarTranslateBannerEventHistogram, event); + break; } } @@ -120,6 +136,10 @@ UMA_HISTOGRAM_ENUMERATION(kInfobarSaveCardBannerDismissTypeHistogram, dismissType); break; + case InfobarType::kInfobarTypeTranslate: + UMA_HISTOGRAM_ENUMERATION(kInfobarTranslateBannerDismissTypeHistogram, + dismissType); + break; } } @@ -143,6 +163,9 @@ case InfobarType::kInfobarTypeSaveCard: UMA_HISTOGRAM_ENUMERATION(kInfobarSaveCardModalEventHistogram, event); break; + case InfobarType::kInfobarTypeTranslate: + UMA_HISTOGRAM_ENUMERATION(kInfobarTranslateModalEventHistogram, event); + break; } } @@ -162,6 +185,9 @@ case InfobarType::kInfobarTypeSaveCard: UMA_HISTOGRAM_ENUMERATION(kInfobarSaveCardBadgeTappedHistogram, state); break; + case InfobarType::kInfobarTypeTranslate: + UMA_HISTOGRAM_ENUMERATION(kInfobarTranslateBadgeTappedHistogram, state); + break; } }
diff --git a/ios/chrome/browser/infobars/infobar_type.h b/ios/chrome/browser/infobars/infobar_type.h index 5971ab04..0694210 100644 --- a/ios/chrome/browser/infobars/infobar_type.h +++ b/ios/chrome/browser/infobars/infobar_type.h
@@ -16,6 +16,8 @@ kInfobarTypePasswordUpdate = 2, // Message Infobar for Saving a Credit Card. kInfobarTypeSaveCard = 3, + // Message Infobar for Translating a page. + kInfobarTypeTranslate = 4, }; #endif // IOS_CHROME_BROWSER_INFOBARS_INFOBAR_TYPE_H_
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn index 8439b23f..b6ee5e30 100644 --- a/ios/chrome/browser/translate/BUILD.gn +++ b/ios/chrome/browser/translate/BUILD.gn
@@ -2,6 +2,18 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +source_set("public") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "translate_infobar_delegate_observer_bridge.h", + "translate_infobar_delegate_observer_bridge.mm", + ] + deps = [ + "//base", + "//components/translate/core/browser", + ] +} + source_set("translate") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ @@ -15,8 +27,6 @@ "translate_accept_languages_factory.h", "translate_infobar_controller.h", "translate_infobar_controller.mm", - "translate_infobar_delegate_observer_bridge.h", - "translate_infobar_delegate_observer_bridge.mm", "translate_infobar_tags.h", "translate_option_selection_delegate.h", "translate_option_selection_handler.h", @@ -28,6 +38,7 @@ "translate_service_ios.mm", ] deps = [ + ":public", "//base", "//components/infobars/core", "//components/keyed_service/core", @@ -69,6 +80,7 @@ "translate_service_ios_unittest.cc", ] deps = [ + ":public", ":translate", "//base", "//base/test:test_support", @@ -108,7 +120,7 @@ "//ios/chrome/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/ui/popup_menu:constants", - "//ios/chrome/browser/ui/translate", + "//ios/chrome/browser/ui/translate:legacy_translate", "//ios/chrome/browser/ui/translate:translate_ui", "//ios/chrome/browser/ui/util:util", "//ios/chrome/test/app:test_support",
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm index d5e8fba..ff3f1f56 100644 --- a/ios/chrome/browser/translate/translate_egtest.mm +++ b/ios/chrome/browser/translate/translate_egtest.mm
@@ -29,7 +29,7 @@ #import "ios/chrome/browser/chrome_url_util.h" #include "ios/chrome/browser/translate/chrome_ios_translate_client.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h" -#import "ios/chrome/browser/ui/translate/translate_infobar_coordinator.h" +#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.h" #import "ios/chrome/browser/ui/translate/translate_infobar_view.h" #import "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/ui/badges/badge_button_factory.mm b/ios/chrome/browser/ui/badges/badge_button_factory.mm index 1d3768c1..9b06b848 100644 --- a/ios/chrome/browser/ui/badges/badge_button_factory.mm +++ b/ios/chrome/browser/ui/badges/badge_button_factory.mm
@@ -26,6 +26,8 @@ break; case BadgeType::kBadgeTypePasswordUpdate: return [self passwordsUpdateBadgeButton]; + case BadgeType::kBadgeTypeSaveCard: + return [self saveCardBadgeButton]; case BadgeType::kBadgeTypeIncognito: return [self incognitoBadgeButton]; case BadgeType::kBadgeTypeOverflow: @@ -68,6 +70,19 @@ return button; } +- (BadgeButton*)saveCardBadgeButton { + BadgeButton* button = + [self createButtonForType:BadgeType::kBadgeTypePasswordUpdate + imageNamed:@"infobar_save_card_icon" + renderingMode:UIImageRenderingModeAlwaysTemplate]; + [button addTarget:self.delegate + action:@selector(saveCardBadgeButtonTapped:) + forControlEvents:UIControlEventTouchUpInside]; + button.accessibilityIdentifier = kBadgeButtonSaveCardAccessibilityIdentifier; + // TODO(crbug.com/1014652): Create a11y label hint. + return button; +} + - (BadgeButton*)incognitoBadgeButton { BadgeButton* button = [self createButtonForType:BadgeType::kBadgeTypeIncognito
diff --git a/ios/chrome/browser/ui/badges/badge_constants.h b/ios/chrome/browser/ui/badges/badge_constants.h index 0fb1223b..dee73f23 100644 --- a/ios/chrome/browser/ui/badges/badge_constants.h +++ b/ios/chrome/browser/ui/badges/badge_constants.h
@@ -12,6 +12,7 @@ extern NSString* const kBadgeButtonUpdatePasswordAccessibilityIdentifier; extern NSString* const kBadgeButtonIncognitoAccessibilityIdentifier; extern NSString* const kBadgeButtonOverflowAccessibilityIdentifier; +extern NSString* const kBadgeButtonSaveCardAccessibilityIdentifier; // A11y identifier for the Badge Popup Menu Table View. extern NSString* const kBadgePopupMenuTableViewAccessibilityIdentifier;
diff --git a/ios/chrome/browser/ui/badges/badge_constants.mm b/ios/chrome/browser/ui/badges/badge_constants.mm index a49b4b5..1242804 100644 --- a/ios/chrome/browser/ui/badges/badge_constants.mm +++ b/ios/chrome/browser/ui/badges/badge_constants.mm
@@ -20,6 +20,9 @@ NSString* const kBadgeButtonOverflowAccessibilityIdentifier = @"badgeButtonOverflowAXID"; +NSString* const kBadgeButtonSaveCardAccessibilityIdentifier = + @"badgeButtonSaveCardAXID"; + NSString* const kBadgePopupMenuTableViewAccessibilityIdentifier = @"badgePopupMenuOverflowAXID";
diff --git a/ios/chrome/browser/ui/badges/badge_delegate.h b/ios/chrome/browser/ui/badges/badge_delegate.h index 538eeb4f..c80a0f0 100644 --- a/ios/chrome/browser/ui/badges/badge_delegate.h +++ b/ios/chrome/browser/ui/badges/badge_delegate.h
@@ -10,6 +10,9 @@ // Action when a Passwords badge is tapped. - (void)passwordsBadgeButtonTapped:(id)sender; +// Action when a Save Card badge is tapped. +- (void)saveCardBadgeButtonTapped:(id)sender; + // Action when the overflow badge is tapped. - (void)overflowBadgeButtonTapped:(id)sender; @end
diff --git a/ios/chrome/browser/ui/badges/badge_mediator.mm b/ios/chrome/browser/ui/badges/badge_mediator.mm index 0b031b0..90b4dfc 100644 --- a/ios/chrome/browser/ui/badges/badge_mediator.mm +++ b/ios/chrome/browser/ui/badges/badge_mediator.mm
@@ -140,6 +140,10 @@ [metricsRecorder recordBadgeTappedInState:state]; } +- (void)saveCardBadgeButtonTapped:(id)sender { + // TODO(crbug.com/1014652): Implement. +} + - (void)overflowBadgeButtonTapped:(id)sender { NSMutableArray<id<BadgeItem>>* popupMenuBadges = [[NSMutableArray alloc] init];
diff --git a/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm b/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm index 8e3294e..5cfc8d2 100644 --- a/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm +++ b/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm
@@ -55,6 +55,12 @@ _actionIdentifier = PopupMenuActionShowUpdatePasswordOptions; _title = @"Update Password"; break; + case BadgeType::kBadgeTypeSaveCard: + _actionIdentifier = PopupMenuActionShowSaveCardOptions; + // TODO(crbug.com/1014652): Replace with final String. Its currently + // "Save Card" on the delegate and "Save Credit Card on mocks. + _title = @"Save Credit Card"; + break; case BadgeType::kBadgeTypeIncognito: NOTREACHED() << "A BadgePopupMenuItem should not be an Incognito badge"; break; @@ -81,6 +87,10 @@ badgeImage = [[UIImage imageNamed:@"infobar_passwords_icon"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; break; + case BadgeType::kBadgeTypeSaveCard: + badgeImage = [[UIImage imageNamed:@"infobar_save_card_icon"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + break; case BadgeType::kBadgeTypeIncognito: NOTREACHED() << "A popup menu item should not be of type kBadgeTypeIncognito";
diff --git a/ios/chrome/browser/ui/badges/badge_type.h b/ios/chrome/browser/ui/badges/badge_type.h index 4f3a1139..02b0a155 100644 --- a/ios/chrome/browser/ui/badges/badge_type.h +++ b/ios/chrome/browser/ui/badges/badge_type.h
@@ -19,6 +19,8 @@ kBadgeTypeIncognito = 3, // Badge type for when there are more than one badge to be displayed. kBadgeTypeOverflow = 4, + // Badge type for Save Credit Card Infobar. + kBadgeTypeSaveCard = 5, }; #endif // IOS_CHROME_BROWSER_UI_BADGES_BADGE_TYPE_H_
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn index b8cdaa22..acd3635 100644 --- a/ios/chrome/browser/ui/bookmarks/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -153,7 +153,11 @@ } source_set("eg_tests") { - configs += [ "//build/config/compiler:enable_arc" ] + defines = [ "CHROME_EARL_GREY_1" ] + configs += [ + "//build/config/compiler:enable_arc", + "//build/config/ios:xctest_config", + ] testonly = true sources = [ "bookmarks_egtest.mm", @@ -183,13 +187,11 @@ "//ios/chrome/test/app:test_support", "//ios/chrome/test/earl_grey:test_support", "//ios/public/provider/chrome/browser/signin:test_support", + "//ios/testing/earl_grey:earl_grey_support", "//ios/third_party/earl_grey:earl_grey+link", "//ios/web/public/test/http_server", "//ui/base", "//url", ] - libs = [ - "UIKit.framework", - "XCTest.framework", - ] + libs = [ "UIKit.framework" ] }
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index 9fcb88c..aa5663f 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import <EarlGrey/EarlGrey.h> #import <UIKit/UIKit.h> #import <XCTest/XCTest.h> #include <vector> @@ -41,6 +40,7 @@ #import "ios/chrome/test/earl_grey/chrome_test_case.h" #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h" #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h" +#import "ios/testing/earl_grey/earl_grey_test.h" #import "ios/web/public/test/http_server/http_server.h" #include "ios/web/public/test/http_server/http_server_util.h" #include "ui/base/l10n/l10n_util.h" @@ -104,8 +104,8 @@ grey_anyOf(grey_accessibilityLabel(previousViewControllerLabel), grey_accessibilityLabel(@"Back"), nil); - return grey_allOf(grey_kindOfClass([UIButton class]), - grey_ancestor(grey_kindOfClass([UINavigationBar class])), + return grey_allOf(grey_kindOfClassName(@"UIButton"), + grey_ancestor(grey_kindOfClassName(@"UINavigationBar")), buttonLabelMatcher, nil); } @@ -397,7 +397,7 @@ [[EarlGrey selectElementWithMatcher:grey_allOf( grey_accessibilityID(@"Mobile Bookmarks"), - grey_kindOfClass([UITableViewCell class]), + grey_kindOfClassName(@"UITableViewCell"), nil)] assertWithMatcher:grey_nil()]; // Open the first folder, to be able to go back twice on the bookmarks. @@ -977,8 +977,7 @@ + (void)openBookmarkFolder:(NSString*)bookmarkFolder { [[EarlGrey selectElementWithMatcher:grey_allOf( - grey_kindOfClass( - NSClassFromString(@"UITableViewCell")), + grey_kindOfClassName(@"UITableViewCell"), grey_descendant(grey_text(bookmarkFolder)), nil)] performAction:grey_tap()]; } @@ -1515,8 +1514,7 @@ + (void)verifyBookmarkFolderIsSeen:(NSString*)bookmarkFolder { [[EarlGrey selectElementWithMatcher:grey_allOf( - grey_kindOfClass( - NSClassFromString(@"UITableViewCell")), + grey_kindOfClassName(@"UITableViewCell"), grey_descendant(grey_text(bookmarkFolder)), nil)] assertWithMatcher:grey_sufficientlyVisible()]; @@ -1850,7 +1848,7 @@ // Verify the delete confirmation button shows up. [[[EarlGrey selectElementWithMatcher:BookmarksDeleteSwipeButton()] - inRoot:grey_kindOfClass(NSClassFromString(@"UITableView"))] + inRoot:grey_kindOfClassName(@"UITableView")] assertWithMatcher:grey_notNil()]; // Change to edit mode @@ -1861,7 +1859,7 @@ // Verify the delete confirmation button is gone after entering edit mode. [[[EarlGrey selectElementWithMatcher:BookmarksDeleteSwipeButton()] - inRoot:grey_kindOfClass(NSClassFromString(@"UITableView"))] + inRoot:grey_kindOfClassName(@"UITableView")] assertWithMatcher:grey_nil()]; // Swipe action on "Second URL". This should not bring out delete @@ -1872,7 +1870,7 @@ // Verify the delete confirmation button doesn't appear. [[[EarlGrey selectElementWithMatcher:BookmarksDeleteSwipeButton()] - inRoot:grey_kindOfClass(NSClassFromString(@"UITableView"))] + inRoot:grey_kindOfClassName(@"UITableView")] assertWithMatcher:grey_nil()]; // Cancel edit mode @@ -1886,7 +1884,7 @@ // Verify the delete confirmation button shows up. (swipe-to-delete is // re-enabled). [[[EarlGrey selectElementWithMatcher:BookmarksDeleteSwipeButton()] - inRoot:grey_kindOfClass(NSClassFromString(@"UITableView"))] + inRoot:grey_kindOfClassName(@"UITableView")] assertWithMatcher:grey_notNil()]; } @@ -4634,8 +4632,7 @@ [BookmarksTestCase openMobileBookmarks]; // Verify search bar is enabled. - [[EarlGrey selectElementWithMatcher:grey_kindOfClass( - NSClassFromString(@"UISearchBar"))] + [[EarlGrey selectElementWithMatcher:grey_kindOfClassName(@"UISearchBar")] assertWithMatcher:grey_userInteractionEnabled()]; // Change to edit mode @@ -4645,16 +4642,14 @@ performAction:grey_tap()]; // Verify search bar is disabled. - [[EarlGrey selectElementWithMatcher:grey_kindOfClass( - NSClassFromString(@"UISearchBar"))] + [[EarlGrey selectElementWithMatcher:grey_kindOfClassName(@"UISearchBar")] assertWithMatcher:grey_not(grey_userInteractionEnabled())]; // Cancel edito mode. [BookmarksTestCase closeContextBarEditMode]; // Verify search bar is enabled. - [[EarlGrey selectElementWithMatcher:grey_kindOfClass( - NSClassFromString(@"UISearchBar"))] + [[EarlGrey selectElementWithMatcher:grey_kindOfClassName(@"UISearchBar")] assertWithMatcher:grey_userInteractionEnabled()]; }
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 27f483d..9a965698a 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -149,7 +149,7 @@ "//ios/chrome/browser/ui/toolbar/public:feature_flags", "//ios/chrome/browser/ui/toolbar_container", "//ios/chrome/browser/ui/toolbar_container:feature_flags", - "//ios/chrome/browser/ui/translate", + "//ios/chrome/browser/ui/translate:legacy_translate", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/voice", "//ios/chrome/browser/upgrade",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index 69cf64bb..e7abc15 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -42,7 +42,7 @@ #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" #import "ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_coordinator.h" #import "ios/chrome/browser/ui/snackbar/snackbar_coordinator.h" -#import "ios/chrome/browser/ui/translate/translate_infobar_coordinator.h" +#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/url_loading/url_loading_service.h" #import "ios/chrome/browser/url_loading/url_loading_service_factory.h" @@ -144,7 +144,7 @@ // Coordinator for the translate infobar's language selection and translate // option popup menus. @property(nonatomic, strong) - TranslateInfobarCoordinator* translateInfobarCoordinator; + LegacyTranslateInfobarCoordinator* translateInfobarCoordinator; @end @@ -300,7 +300,7 @@ self.formInputAccessoryCoordinator.navigator = self; [self.formInputAccessoryCoordinator start]; - self.translateInfobarCoordinator = [[TranslateInfobarCoordinator alloc] + self.translateInfobarCoordinator = [[LegacyTranslateInfobarCoordinator alloc] initWithBaseViewController:self.viewController browserState:self.browserState webStateList:self.tabModel.webStateList
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn index 4dd1402f..bd9b0cc 100644 --- a/ios/chrome/browser/ui/infobars/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -74,6 +74,7 @@ "resources:infobar_passwords_icon", "resources:infobar_popup_blocker", "resources:infobar_reveal_password_icon", + "resources:infobar_save_card_icon", "resources:infobar_settings_icon", "resources:infobar_warning", "//base",
diff --git a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn index 18fd99c..b5833bd8 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/coordinators/BUILD.gn
@@ -14,16 +14,20 @@ "infobar_password_coordinator.mm", "infobar_save_card_coordinator.h", "infobar_save_card_coordinator.mm", + "infobar_translate_coordinator.h", + "infobar_translate_coordinator.mm", ] deps = [ "//base", "//components/autofill/core/browser", "//components/infobars/core", + "//components/translate/core/browser", "//ios/chrome/app/strings:ios_strings_grit", "//ios/chrome/browser/infobars:public", "//ios/chrome/browser/infobars:public", "//ios/chrome/browser/passwords:infobar_delegates", "//ios/chrome/browser/passwords:public", + "//ios/chrome/browser/translate:public", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/fullscreen",
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.h b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.h new file mode 100644 index 0000000..3d22041e --- /dev/null +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.h
@@ -0,0 +1,30 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_COORDINATORS_INFOBAR_TRANSLATE_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_COORDINATORS_INFOBAR_TRANSLATE_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/infobars/coordinators/infobar_coordinator.h" + +namespace translate { +class TranslateInfoBarDelegate; +} // namespace translate + +// Coordinator that creates and manages the Translate Infobar. +@interface TranslateInfobarCoordinator : InfobarCoordinator + +// Designated initializer. |infoBarDelegate| is used to configure the +// Infobar and subsequently perform related actions. +- (instancetype)initWithInfoBarDelegate: + (translate::TranslateInfoBarDelegate*)infoBarDelegate + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithInfoBarDelegate: + (infobars::InfoBarDelegate*)infoBarDelegate + badgeSupport:(BOOL)badgeSupport + type:(InfobarType)infobarType NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_COORDINATORS_INFOBAR_TRANSLATE_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.mm new file mode 100644 index 0000000..b907a7c65 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.mm
@@ -0,0 +1,120 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/infobars/coordinators/infobar_translate_coordinator.h" + +#include "components/translate/core/browser/translate_infobar_delegate.h" +#include "ios/chrome/browser/infobars/infobar_controller_delegate.h" +#import "ios/chrome/browser/infobars/infobar_type.h" +#import "ios/chrome/browser/translate/translate_infobar_delegate_observer_bridge.h" +#import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h" +#import "ios/chrome/browser/ui/infobars/infobar_container.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface TranslateInfobarCoordinator () <TranslateInfobarDelegateObserving> { + // Observer to listen for changes to the TranslateStep. + std::unique_ptr<TranslateInfobarDelegateObserverBridge> + _translateInfobarDelegateObserver; +} + +// Delegate that holds the Translate Infobar information and actions. +@property(nonatomic, readonly) + translate::TranslateInfoBarDelegate* translateInfoBarDelegate; + +@end + +@implementation TranslateInfobarCoordinator + +- (instancetype)initWithInfoBarDelegate: + (translate::TranslateInfoBarDelegate*)infoBarDelegate { + self = [super initWithInfoBarDelegate:infoBarDelegate + badgeSupport:YES + type:InfobarType::kInfobarTypeTranslate]; + if (self) { + _translateInfoBarDelegate = infoBarDelegate; + _translateInfobarDelegateObserver = + std::make_unique<TranslateInfobarDelegateObserverBridge>( + infoBarDelegate, self); + } + return self; +} + +#pragma mark - TranslateInfobarDelegateObserving + +- (void)translateInfoBarDelegate:(translate::TranslateInfoBarDelegate*)delegate + didChangeTranslateStep:(translate::TranslateStep)step + withErrorType:(translate::TranslateErrors::Type)errorType { + // TODO(crbug.com/1014959): implement +} + +- (BOOL)translateInfoBarDelegateDidDismissWithoutInteraction: + (translate::TranslateInfoBarDelegate*)delegate { + // TODO(crbug.com/1014959): implement + return YES; +} + +#pragma mark - ChromeCoordinator + +- (void)start { + if (!self.started) { + self.started = YES; + // TODO(crbug.com/1014959): Configure BannerViewController. + } +} + +- (void)stop { + [super stop]; + if (self.started) { + self.started = NO; + // RemoveInfoBar() will delete the InfobarIOS that owns this Coordinator + // from memory. + self.delegate->RemoveInfoBar(); + [self.infobarContainer childCoordinatorStopped:self]; + } +} + +#pragma mark - InfobarCoordinatorImplementation + +- (void)performInfobarAction { + // TODO(crbug.com/1014959): implement +} + +- (void)infobarWasDismissed { + // TODO(crbug.com/1014959): implement +} + +#pragma mark - Banner + +- (void)infobarBannerWasPresented { + // TODO(crbug.com/1014959): implement +} + +- (void)dismissBannerWhenInteractionIsFinished { + // TODO(crbug.com/1014959): implement +} + +- (void)infobarBannerWillBeDismissed:(BOOL)userInitiated { + // TODO(crbug.com/1014959): implement +} + +#pragma mark - Modal + +- (BOOL)configureModalViewController { + // TODO(crbug.com/1014959): implement + return NO; +} + +- (void)infobarModalPresentedFromBanner:(BOOL)presentedFromBanner { + // TODO(crbug.com/1014959): implement +} + +- (CGFloat)infobarModalHeightForWidth:(CGFloat)width { + // TODO(crbug.com/1014959): implement + return 0.0; +} + +@end
diff --git a/ios/chrome/browser/ui/infobars/infobar_feature.h b/ios/chrome/browser/ui/infobars/infobar_feature.h index a459f54..516921c 100644 --- a/ios/chrome/browser/ui/infobars/infobar_feature.h +++ b/ios/chrome/browser/ui/infobars/infobar_feature.h
@@ -13,15 +13,24 @@ extern const base::Feature kInfobarUIReboot; // Feature to choose whether Confirm Infobars use the new Messages UI or the -// legacy one. In order for it to work kInfobarUIReboot also needs to be +// legacy one. Also, in order for it to work kInfobarUIReboot needs to be // enabled. // Use IsConfirmInfobarMessagesUIEnabled() instead of this constant directly. extern const base::Feature kConfirmInfobarMessagesUI; +// Feature to choose whether Save Card Infobar uses the new Messages UI or the +// legacy one. Also, in order for it to work kInfobarUIReboot needs to be +// enabled. +// Use IsSaveCardInfobarMessagesUIEnabled() instead of this constant directly. +extern const base::Feature kSaveCardInfobarMessagesUI; + // Whether the Messages Infobar UI is enabled. bool IsInfobarUIRebootEnabled(); // Whether the Confirm Infobar Messages UI is enabled. bool IsConfirmInfobarMessagesUIEnabled(); +// Whether the SaveCard Infobar Messages UI is enabled. +bool IsSaveCardInfobarMessagesUIEnabled(); + #endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_FEATURE_H_
diff --git a/ios/chrome/browser/ui/infobars/infobar_feature.mm b/ios/chrome/browser/ui/infobars/infobar_feature.mm index 3520d0d..fb24b3d 100644 --- a/ios/chrome/browser/ui/infobars/infobar_feature.mm +++ b/ios/chrome/browser/ui/infobars/infobar_feature.mm
@@ -17,6 +17,13 @@ const base::Feature kConfirmInfobarMessagesUI{"ConfirmInfobarMessagesUI", base::FEATURE_ENABLED_BY_DEFAULT}; +// Feature enabled by default since it will always be checked along +// kInfobarUIReboot, effectively working as a kill switch. Meaning that if +// kInfobarUIReboot is not enabled this feature won't work. +// TODO(crbug.com/1014652): Enable by Default once feature should be tested. +const base::Feature kSaveCardInfobarMessagesUI{ + "SaveCardInfobarMessagesUI", base::FEATURE_DISABLED_BY_DEFAULT}; + bool IsInfobarUIRebootEnabled() { return base::FeatureList::IsEnabled(kInfobarUIReboot); } @@ -25,3 +32,8 @@ return base::FeatureList::IsEnabled(kConfirmInfobarMessagesUI) && IsInfobarUIRebootEnabled(); } + +bool IsSaveCardInfobarMessagesUIEnabled() { + return base::FeatureList::IsEnabled(kSaveCardInfobarMessagesUI) && + IsInfobarUIRebootEnabled(); +}
diff --git a/ios/chrome/browser/ui/infobars/resources/BUILD.gn b/ios/chrome/browser/ui/infobars/resources/BUILD.gn index 87bd745f..8848552 100644 --- a/ios/chrome/browser/ui/infobars/resources/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/resources/BUILD.gn
@@ -64,3 +64,11 @@ "infobar_settings_icon.imageset/infobar_settings_icon@3x.png", ] } + +imageset("infobar_save_card_icon") { + sources = [ + "infobar_save_card_icon.imageset/Contents.json", + "infobar_save_card_icon.imageset/infobar_save_card_icon@2x.png", + "infobar_save_card_icon.imageset/infobar_save_card_icon@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/Contents.json b/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/Contents.json new file mode 100644 index 0000000..bee027b --- /dev/null +++ b/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/Contents.json
@@ -0,0 +1,18 @@ +{ + "images": [ + { + "idiom": "universal", + "scale": "2x", + "filename": "infobar_save_card_icon@2x.png" + }, + { + "idiom": "universal", + "scale": "3x", + "filename": "infobar_save_card_icon@3x.png" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +}
diff --git a/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/infobar_save_card_icon@2x.png b/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/infobar_save_card_icon@2x.png new file mode 100644 index 0000000..92f672f --- /dev/null +++ b/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/infobar_save_card_icon@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/infobar_save_card_icon@3x.png b/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/infobar_save_card_icon@3x.png new file mode 100644 index 0000000..2834e94b --- /dev/null +++ b/ios/chrome/browser/ui/infobars/resources/infobar_save_card_icon.imageset/infobar_save_card_icon@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index 3bffff55..39747c2 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -69,7 +69,7 @@ "//ios/chrome/browser/ui/reading_list", "//ios/chrome/browser/ui/recent_tabs", "//ios/chrome/browser/ui/snackbar", - "//ios/chrome/browser/ui/translate", + "//ios/chrome/browser/ui/translate:legacy_translate", "//ios/chrome/browser/url_loading", "//ios/chrome/browser/web", "//ios/chrome/browser/web:tab_helper_delegates",
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn index 7b2dd363..ce4ce58 100644 --- a/ios/chrome/browser/ui/omnibox/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -84,10 +84,24 @@ "//ios/chrome/browser/ui:feature_flags", ] public_deps = [ + ":omnibox_icon_type_constants", "//ios/chrome/app/theme", ] } +# This target can also be used on EG2 tests, so it should only contain constants +source_set("omnibox_icon_type_constants") { + configs += [ "//build/config/compiler:enable_arc" ] + + sources = [ + "omnibox_icon_type.h", + "omnibox_icon_type.mm", + ] + deps = [ + "//base", + ] +} + source_set("omnibox_internal") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ @@ -161,6 +175,7 @@ "//url", ] public_deps = [ + ":omnibox_icon_type_constants", "//components/omnibox/browser", ] libs = [
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_icon_type.h b/ios/chrome/browser/ui/omnibox/omnibox_icon_type.h new file mode 100644 index 0000000..2ce52198 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_icon_type.h
@@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_TYPE_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_TYPE_H_ + +#import <Foundation/Foundation.h> + +// All available icons for security states. +enum LocationBarSecurityIconType { + INSECURE = 0, + SECURE, + DANGEROUS, + LOCATION_BAR_SECURITY_ICON_TYPE_COUNT, +}; + +// Returns the asset name (to be used in -[UIImage imageNamed:]). +NSString* GetLocationBarSecurityIconTypeAssetName( + LocationBarSecurityIconType icon); + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_ICON_TYPE_H_
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_icon_type.mm b/ios/chrome/browser/ui/omnibox/omnibox_icon_type.mm new file mode 100644 index 0000000..64ee4b03 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_icon_type.mm
@@ -0,0 +1,26 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/omnibox/omnibox_icon_type.h" + +#include "base/logging.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +NSString* GetLocationBarSecurityIconTypeAssetName( + LocationBarSecurityIconType iconType) { + switch (iconType) { + case INSECURE: + return @"location_bar_insecure"; + case SECURE: + return @"location_bar_secure"; + case DANGEROUS: + return @"location_bar_dangerous"; + case LOCATION_BAR_SECURITY_ICON_TYPE_COUNT: + NOTREACHED(); + return @"location_bar_insecure"; + } +}
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_util.h b/ios/chrome/browser/ui/omnibox/omnibox_util.h index f542fafc..44df11d 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_util.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_util.h
@@ -9,6 +9,7 @@ #include "components/omnibox/browser/autocomplete_match_type.h" #include "components/security_state/core/security_state.h" +#import "ios/chrome/browser/ui/omnibox/omnibox_icon_type.h" #include "ios/chrome/browser/ui/omnibox/omnibox_suggestion_icon_util.h" #pragma mark - Suggestion icons. @@ -27,18 +28,6 @@ #pragma mark - Security icons. -// All available icons for security states. -enum LocationBarSecurityIconType { - INSECURE = 0, - SECURE, - DANGEROUS, - LOCATION_BAR_SECURITY_ICON_TYPE_COUNT, -}; - -// Returns the asset name (to be used in -[UIImage imageNamed:]). -NSString* GetLocationBarSecurityIconTypeAssetName( - LocationBarSecurityIconType icon); - // Returns the asset with "always template" rendering mode. UIImage* GetLocationBarSecurityIcon(LocationBarSecurityIconType icon);
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_util.mm b/ios/chrome/browser/ui/omnibox/omnibox_util.mm index 8b945fc..430e061 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_util.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_util.mm
@@ -78,21 +78,6 @@ #pragma mark - Security icons. -NSString* GetLocationBarSecurityIconTypeAssetName( - LocationBarSecurityIconType iconType) { - switch (iconType) { - case INSECURE: - return @"location_bar_insecure"; - case SECURE: - return @"location_bar_secure"; - case DANGEROUS: - return @"location_bar_dangerous"; - case LOCATION_BAR_SECURITY_ICON_TYPE_COUNT: - NOTREACHED(); - return @"location_bar_insecure"; - } -} - // Returns the asset with "always template" rendering mode. UIImage* GetLocationBarSecurityIcon(LocationBarSecurityIconType iconType) { NSString* imageName = GetLocationBarSecurityIconTypeAssetName(iconType);
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm index 2c082ea..eb2e5641 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -394,7 +394,8 @@ model()->set_focus_source(OmniboxFocusSource::OMNIBOX); } - model()->OnSetFocus(false); + model()->OnSetFocus(/*control_down=*/false, + /*suppress_on_focus_suggestions=*/false); } // If the omnibox is displaying a URL and the popup is not showing, set the
diff --git a/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h b/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h index b095e72..ff8e121 100644 --- a/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h +++ b/ios/chrome/browser/ui/popup_menu/public/cells/popup_menu_item.h
@@ -51,6 +51,7 @@ // Badge overflow popup menu PopupMenuActionShowSavePasswordOptions, PopupMenuActionShowUpdatePasswordOptions, + PopupMenuActionShowSaveCardOptions, }; // Protocol defining a popup item.
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_egtest.mm b/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_egtest.mm index f965837..72d7f6ce 100644 --- a/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_egtest.mm +++ b/ios/chrome/browser/ui/settings/autofill/autofill_add_credit_card_egtest.mm
@@ -89,16 +89,13 @@ @implementation AutofillAddCreditCardTestCase -- (void)launchAppForTestMethod { +- (void)setUp { + [super setUp]; [[AppLaunchManager sharedManager] ensureAppLaunchedWithFeaturesEnabled:{kSettingsAddPaymentMethod, kCreditCardScanner} disabled:{} forceRestart:NO]; -} - -- (void)setUp { - [super setUp]; GREYAssertTrue([ChromeEarlGrey isSettingsAddPaymentMethodEnabled], @"SettingsAddPaymentMethod should be enabled"); GREYAssertTrue([ChromeEarlGrey isCreditCardScannerEnabled],
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn index fa35a00..e534702 100644 --- a/ios/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -135,7 +135,11 @@ } source_set("eg_tests") { - configs += [ "//build/config/compiler:enable_arc" ] + defines = [ "CHROME_EARL_GREY_1" ] + configs += [ + "//build/config/compiler:enable_arc", + "//build/config/ios:xctest_config", + ] testonly = true sources = [ "tab_grid_egtest.mm", @@ -150,7 +154,31 @@ "//ios/chrome/browser/ui/tab_grid:tab_grid_ui", "//ios/chrome/test/app:test_support", "//ios/chrome/test/earl_grey:test_support", + "//ios/testing/earl_grey:earl_grey_support", "//ios/web/public/test/http_server", ] - libs = [ "XCTest.framework" ] + libs = [ "UIKit.framework" ] +} + +source_set("eg2_tests") { + defines = [ "CHROME_EARL_GREY_2" ] + configs += [ + "//build/config/compiler:enable_arc", + "//build/config/ios:xctest_config", + ] + testonly = true + sources = [ + "tab_grid_transition_egtest.mm", + ] + + deps = [ + ":tab_grid_ui_constants", + "//base", + "//ios/chrome/app/strings", + "//ios/chrome/test/earl_grey:eg_test_support+eg2", + "//ios/testing/earl_grey:eg_test_support+eg2", + "//ios/third_party/earl_grey2:test_lib", + "//net:test_support", + ] + libs = [ "UIKit.framework" ] }
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm index aa3ab5c..f64dc83 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm
@@ -2,22 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import <EarlGrey/EarlGrey.h> #import <UIKit/UIKit.h> #import <XCTest/XCTest.h> #include "base/bind.h" -#include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" -#import "base/test/ios/wait_util.h" -#import "ios/chrome/app/main_controller.h" -#import "ios/chrome/browser/tabs/tab_model.h" #include "ios/chrome/grit/ios_strings.h" -#import "ios/chrome/test/app/chrome_test_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" +#import "ios/testing/earl_grey/earl_grey_test.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "net/test/embedded_test_server/request_handler_util.h" @@ -26,26 +21,24 @@ #error "This file requires ARC support." #endif -using chrome_test_util::ButtonWithAccessibilityLabelId; using chrome_test_util::TabGridDoneButton; using chrome_test_util::TabGridIncognitoTabsPanelButton; using chrome_test_util::TabGridNewIncognitoTabButton; using chrome_test_util::TabGridNewTabButton; using chrome_test_util::TabGridOpenButton; using chrome_test_util::TabGridOpenTabsPanelButton; -// using chrome_test_util::TabletTabSwitcherCloseButton; -// using chrome_test_util::TabletTabSwitcherIncognitoTabsPanelButton; -// using chrome_test_util::TabletTabSwitcherNewIncognitoTabButton; -// using chrome_test_util::TabletTabSwitcherNewTabButton; -// using chrome_test_util::TabletTabSwitcherOpenButton; -// using chrome_test_util::TabletTabSwitcherOpenTabsPanelButton; namespace { -// Returns the tab model for non-incognito tabs. -TabModel* GetNormalTabModel() { - return chrome_test_util::GetMainController() - .interfaceProvider.mainInterface.tabModel; +// Rotates the device to the given orientation. +void RotateDevice(UIDeviceOrientation orientation) { +#if defined(CHROME_EARL_GREY_1) + [EarlGrey rotateDeviceToOrientation:orientation errorOrNil:nil]; +#elif defined(CHROME_EARL_GREY_2) + [EarlGrey rotateDeviceToOrientation:orientation error:nil]; +#else +#error +#endif } // Shows the tab switcher by tapping the switcher button. Works on both phone @@ -115,8 +108,7 @@ // Rotate the device back to portrait if needed, since some tests attempt to run // in landscape. - (void)tearDown { - [EarlGrey rotateDeviceToOrientation:UIDeviceOrientationPortrait - errorOrNil:nil]; + RotateDevice(UIDeviceOrientationPortrait); [super tearDown]; } @@ -150,7 +142,7 @@ // Tests entering the tab switcher when one incognito tab is open. - (void)testEnterSwitcherWithOneIncognitoTab { [ChromeEarlGreyUI openNewIncognitoTab]; - [GetNormalTabModel() closeAllTabs]; + [ChromeEarlGrey closeAllNormalTabs]; ShowTabSwitcher(); } @@ -158,7 +150,7 @@ // Tests entering the tab switcher when more than one incognito tab is open. - (void)testEnterSwitcherWithMultipleIncognitoTabs { [ChromeEarlGreyUI openNewIncognitoTab]; - [GetNormalTabModel() closeAllTabs]; + [ChromeEarlGrey closeAllNormalTabs]; [ChromeEarlGreyUI openNewIncognitoTab]; [ChromeEarlGreyUI openNewIncognitoTab]; @@ -182,7 +174,7 @@ // Tests entering the tab switcher by closing the last incognito tab. - (void)testEnterSwitcherByClosingLastIncognitoTab { [ChromeEarlGreyUI openNewIncognitoTab]; - [GetNormalTabModel() closeAllTabs]; + [ChromeEarlGrey closeAllNormalTabs]; [ChromeEarlGrey closeAllTabsInCurrentMode]; } @@ -228,7 +220,7 @@ // Set up by creating a new incognito tab and closing all normal tabs. [ChromeEarlGreyUI openNewIncognitoTab]; - [GetNormalTabModel() closeAllTabs]; + [ChromeEarlGrey closeAllNormalTabs]; // Enter the switcher and open a new incognito tab using the new tab button. ShowTabSwitcher(); @@ -311,7 +303,7 @@ [ChromeEarlGrey loadURL:[self makeURLForTitle:tab2_title]]; [ChromeEarlGreyUI openNewIncognitoTab]; [ChromeEarlGrey loadURL:[self makeURLForTitle:tab3_title]]; - [GetNormalTabModel() closeAllTabs]; + [ChromeEarlGrey closeAllNormalTabs]; ShowTabSwitcher(); SelectTab(tab1_title); @@ -378,24 +370,21 @@ [ChromeEarlGrey loadURL:[self makeURLForTitle:tab_title]]; // Show the tab switcher and return to the BVC, in portrait. - [EarlGrey rotateDeviceToOrientation:UIDeviceOrientationPortrait - errorOrNil:nil]; + RotateDevice(UIDeviceOrientationPortrait); ShowTabSwitcher(); SelectTab(tab_title); [ChromeEarlGrey waitForWebStateContainingText:base::SysNSStringToUTF8(tab_title)]; // Show the tab switcher and return to the BVC, in landscape. - [EarlGrey rotateDeviceToOrientation:UIDeviceOrientationLandscapeLeft - errorOrNil:nil]; + RotateDevice(UIDeviceOrientationLandscapeLeft); ShowTabSwitcher(); SelectTab(tab_title); [ChromeEarlGrey waitForWebStateContainingText:base::SysNSStringToUTF8(tab_title)]; // Show the tab switcher and return to the BVC, in portrait. - [EarlGrey rotateDeviceToOrientation:UIDeviceOrientationPortrait - errorOrNil:nil]; + RotateDevice(UIDeviceOrientationPortrait); ShowTabSwitcher(); SelectTab(tab_title); [ChromeEarlGrey
diff --git a/ios/chrome/browser/ui/translate/BUILD.gn b/ios/chrome/browser/ui/translate/BUILD.gn index 16de7a7..df7ffbd 100644 --- a/ios/chrome/browser/ui/translate/BUILD.gn +++ b/ios/chrome/browser/ui/translate/BUILD.gn
@@ -2,13 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("translate") { +source_set("legacy_translate") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "translate_infobar_coordinator.h", - "translate_infobar_coordinator.mm", - "translate_infobar_mediator.h", - "translate_infobar_mediator.mm", + "legacy_translate_infobar_coordinator.h", + "legacy_translate_infobar_coordinator.mm", + "legacy_translate_infobar_mediator.h", + "legacy_translate_infobar_mediator.mm", ] deps = [ ":translate_ui", @@ -77,7 +77,7 @@ "translate_infobar_mediator_unittest.mm", ] deps = [ - ":translate", + ":legacy_translate", "//components/language/ios/browser", "//components/translate/core/browser:test_support", "//ios/chrome/browser/browser_state:test_support",
diff --git a/ios/chrome/browser/ui/translate/translate_infobar_coordinator.h b/ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.h similarity index 82% rename from ios/chrome/browser/ui/translate/translate_infobar_coordinator.h rename to ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.h index abd28aa7..3a1353e 100644 --- a/ios/chrome/browser/ui/translate/translate_infobar_coordinator.h +++ b/ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_TRANSLATE_INFOBAR_COORDINATOR_H_ -#define IOS_CHROME_BROWSER_UI_TRANSLATE_TRANSLATE_INFOBAR_COORDINATOR_H_ +#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_LEGACY_TRANSLATE_INFOBAR_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_TRANSLATE_LEGACY_TRANSLATE_INFOBAR_COORDINATOR_H_ #import <UIKit/UIKit.h> @@ -20,7 +20,7 @@ // Coordinator responsible for presenting and dismissing the translate infobar's // language selection popup menu, translate options popup menu, and translate // options notifications. -@interface TranslateInfobarCoordinator : ChromeCoordinator +@interface LegacyTranslateInfobarCoordinator : ChromeCoordinator // Creates a coordinator that uses |viewController|, |browserState|, and // |webStateList|. @@ -38,4 +38,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_TRANSLATE_INFOBAR_COORDINATOR_H_ +#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_LEGACY_TRANSLATE_INFOBAR_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/translate/translate_infobar_coordinator.mm b/ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.mm similarity index 93% rename from ios/chrome/browser/ui/translate/translate_infobar_coordinator.mm rename to ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.mm index 638f643..cdd2a6a 100644 --- a/ios/chrome/browser/ui/translate/translate_infobar_coordinator.mm +++ b/ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.mm
@@ -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 "ios/chrome/browser/ui/translate/translate_infobar_coordinator.h" +#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.h" #include "base/logging.h" #include "base/mac/foundation_util.h" @@ -19,7 +19,7 @@ #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_table_view_controller_delegate.h" #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_ui_constants.h" #import "ios/chrome/browser/ui/translate/cells/select_language_popup_menu_item.h" -#import "ios/chrome/browser/ui/translate/translate_infobar_mediator.h" +#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.h" #import "ios/chrome/browser/ui/translate/translate_notification_presenter.h" #import "ios/chrome/browser/ui/util/layout_guide_names.h" @@ -30,17 +30,18 @@ NSString* const kLanguageSelectorPopupMenuId = @"kLanguageSelectorPopupMenuId"; NSString* const kTranslateOptionsPopupMenuId = @"kTranslateOptionsPopupMenuId"; -@interface TranslateInfobarCoordinator () <LanguageSelectionHandler, - PopupMenuPresenterDelegate, - PopupMenuTableViewControllerDelegate, - TranslateOptionSelectionHandler> +@interface LegacyTranslateInfobarCoordinator () < + LanguageSelectionHandler, + PopupMenuPresenterDelegate, + PopupMenuTableViewControllerDelegate, + TranslateOptionSelectionHandler> // The WebStateList this coordinator observes. @property(nonatomic, assign) WebStateList* webStateList; // Presenter for the popup menu, managing the animations. @property(nonatomic, strong) PopupMenuPresenter* popupMenuPresenter; // Mediator for the popup menu. -@property(nonatomic, strong) TranslateInfobarMediator* mediator; +@property(nonatomic, strong) LegacyTranslateInfobarMediator* mediator; // Presenter for the translate notifications. @property(nonatomic, strong) TranslateNotificationPresenter* notificationPresenter; @@ -59,7 +60,7 @@ @end -@implementation TranslateInfobarCoordinator +@implementation LegacyTranslateInfobarCoordinator - (instancetype)initWithBaseViewController:(UIViewController*)viewController browserState: @@ -85,7 +86,7 @@ self.notificationPresenter = [[TranslateNotificationPresenter alloc] initWithDispatcher:self.dispatcher]; - self.mediator = [[TranslateInfobarMediator alloc] + self.mediator = [[LegacyTranslateInfobarMediator alloc] initWithSelectionHandler:self notificationHandler:self.notificationPresenter]; self.mediator.webStateList = self.webStateList;
diff --git a/ios/chrome/browser/ui/translate/translate_infobar_mediator.h b/ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.h similarity index 88% rename from ios/chrome/browser/ui/translate/translate_infobar_mediator.h rename to ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.h index cdd59d9..8286f5dd 100644 --- a/ios/chrome/browser/ui/translate/translate_infobar_mediator.h +++ b/ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_TRANSLATE_INFOBAR_MEDIATOR_H_ -#define IOS_CHROME_BROWSER_UI_TRANSLATE_TRANSLATE_INFOBAR_MEDIATOR_H_ +#ifndef IOS_CHROME_BROWSER_UI_TRANSLATE_LEGACY_TRANSLATE_INFOBAR_MEDIATOR_H_ +#define IOS_CHROME_BROWSER_UI_TRANSLATE_LEGACY_TRANSLATE_INFOBAR_MEDIATOR_H_ #import <Foundation/Foundation.h> @@ -28,7 +28,7 @@ // the translate infobar's language selection popup menu as well as translate // options popup menus. Also installs the UI handler for the translate options // notfications. -@interface TranslateInfobarMediator : NSObject +@interface LegacyTranslateInfobarMediator : NSObject // |selectionHandler| presents and dismisses the language selection UI as well // as the translate option selection UI. |notificationHandler| presents and @@ -65,4 +65,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_TRANSLATE_INFOBAR_MEDIATOR_H_ +#endif // IOS_CHROME_BROWSER_UI_TRANSLATE_LEGACY_TRANSLATE_INFOBAR_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/translate/translate_infobar_mediator.mm b/ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.mm similarity index 97% rename from ios/chrome/browser/ui/translate/translate_infobar_mediator.mm rename to ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.mm index 84900f65..72644ef 100644 --- a/ios/chrome/browser/ui/translate/translate_infobar_mediator.mm +++ b/ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.mm
@@ -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 "ios/chrome/browser/ui/translate/translate_infobar_mediator.h" +#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.h" #include <memory> @@ -28,7 +28,7 @@ #error "This file requires ARC support." #endif -@interface TranslateInfobarMediator () <WebStateListObserving> { +@interface LegacyTranslateInfobarMediator () <WebStateListObserving> { // WebStateList observers. std::unique_ptr<WebStateListObserverBridge> _webStateListObserverBridge; std::unique_ptr<ScopedObserver<WebStateList, WebStateListObserver>> @@ -46,7 +46,7 @@ @end -@implementation TranslateInfobarMediator +@implementation LegacyTranslateInfobarMediator - (instancetype) initWithSelectionHandler:
diff --git a/ios/chrome/browser/ui/translate/translate_infobar_mediator_unittest.mm b/ios/chrome/browser/ui/translate/translate_infobar_mediator_unittest.mm index ad5cfc5..8f8a9b5b 100644 --- a/ios/chrome/browser/ui/translate/translate_infobar_mediator_unittest.mm +++ b/ios/chrome/browser/ui/translate/translate_infobar_mediator_unittest.mm
@@ -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 "ios/chrome/browser/ui/translate/translate_infobar_mediator.h" +#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_mediator.h" #include <memory> @@ -81,7 +81,7 @@ niceMockForProtocol:@protocol(TestSelectionHandlerProtocol)]), notification_handler_([OCMockObject niceMockForProtocol:@protocol(TranslateNotificationHandler)]), - mediator_([[TranslateInfobarMediator alloc] + mediator_([[LegacyTranslateInfobarMediator alloc] initWithSelectionHandler:selection_handler_ notificationHandler:notification_handler_]) { CreateTranslateClient(); @@ -95,7 +95,7 @@ id notification_handler() { return notification_handler_; } - TranslateInfobarMediator* mediator() { return mediator_; } + LegacyTranslateInfobarMediator* mediator() { return mediator_; } void CreateTranslateClient() { auto web_state = std::make_unique<web::TestWebState>(); @@ -145,7 +145,7 @@ MockTranslateInfoBarDelegateFactory delegate_factory_; id selection_handler_; id notification_handler_; - TranslateInfobarMediator* mediator_; + LegacyTranslateInfobarMediator* mediator_; DISALLOW_COPY_AND_ASSIGN(TranslateInfobarMediatorTest); }; @@ -160,7 +160,7 @@ EXPECT_EQ(nil, translate_client->translate_option_selection_handler()); EXPECT_EQ(nil, translate_client->translate_notification_handler()); - TranslateInfobarMediator* translate_infobar_mediator = mediator(); + LegacyTranslateInfobarMediator* translate_infobar_mediator = mediator(); translate_infobar_mediator.webStateList = web_state_list(); EXPECT_EQ(selection_handler(), @@ -191,7 +191,7 @@ EXPECT_CALL(*GetDelegate(), ShouldAlwaysTranslate()) .WillOnce(testing::Return(true)); - TranslateInfobarMediator* translate_infobar_mediator = mediator(); + LegacyTranslateInfobarMediator* translate_infobar_mediator = mediator(); translate_infobar_mediator.type = TranslatePopupMenuTypeTranslateOptionSelection; translate_infobar_mediator.infobarDelegate = GetDelegate(); @@ -243,7 +243,7 @@ EXPECT_CALL(*GetDelegate(), language_name_at(2)) .WillOnce(testing::Return(base::UTF8ToUTF16("French"))); - TranslateInfobarMediator* translate_infobar_mediator = mediator(); + LegacyTranslateInfobarMediator* translate_infobar_mediator = mediator(); translate_infobar_mediator.type = TranslatePopupMenuTypeLanguageSelection; translate_infobar_mediator.infobarDelegate = GetDelegate(); translate_infobar_mediator.unavailableLanguageIndex = 1;
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn index 18d9d454..7b1e966b 100644 --- a/ios/chrome/test/app/BUILD.gn +++ b/ios/chrome/test/app/BUILD.gn
@@ -8,12 +8,13 @@ sources = [ "bookmarks_test_util.h", "bookmarks_test_util.mm", + "browsing_data_test_util.h", + "browsing_data_test_util.mm", "chrome_test_util.h", "chrome_test_util.mm", "histogram_test_util.h", "histogram_test_util.mm", "history_test_util.h", - "history_test_util.mm", "navigation_test_util.h", "navigation_test_util.mm", "password_test_util.h", @@ -60,6 +61,7 @@ "//ios/chrome/browser/content_settings", "//ios/chrome/browser/history", "//ios/chrome/browser/infobars", + "//ios/chrome/browser/main", "//ios/chrome/browser/metrics", "//ios/chrome/browser/metrics:metrics_internal", "//ios/chrome/browser/signin", @@ -85,6 +87,7 @@ "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/signin:test_support", "//ios/web", + "//ios/web/public/security", "//ios/web/public/test", "//net", "//net:test_support",
diff --git a/ios/chrome/test/app/browsing_data_test_util.h b/ios/chrome/test/app/browsing_data_test_util.h new file mode 100644 index 0000000..8101e74 --- /dev/null +++ b/ios/chrome/test/app/browsing_data_test_util.h
@@ -0,0 +1,26 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_TEST_APP_BROWSING_DATA_TEST_UTIL_H_ +#define IOS_CHROME_TEST_APP_BROWSING_DATA_TEST_UTIL_H_ + +#include "base/compiler_specific.h" + +namespace chrome_test_util { + +// Clears browsing history and returns whether clearing the history was +// successful or timed out. +bool ClearBrowsingHistory() WARN_UNUSED_RESULT; + +// Clears browsing data and returns whether clearing was successful or timed +// out. +bool ClearAllBrowsingData(bool off_the_record) WARN_UNUSED_RESULT; + +// Clears user decisions cache and returns whether clearing was successful or +// timed out. +bool ClearCertificatePolicyCache(bool off_the_record) WARN_UNUSED_RESULT; + +} // namespace chrome_test_util + +#endif // IOS_CHROME_TEST_APP_BROWSING_DATA_TEST_UTIL_H_
diff --git a/ios/chrome/test/app/browsing_data_test_util.mm b/ios/chrome/test/app/browsing_data_test_util.mm new file mode 100644 index 0000000..15da666 --- /dev/null +++ b/ios/chrome/test/app/browsing_data_test_util.mm
@@ -0,0 +1,72 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/test/app/browsing_data_test_util.h" + +#include "base/task/post_task.h" +#import "base/test/ios/wait_util.h" +#include "components/browsing_data/core/browsing_data_utils.h" +#import "ios/chrome/app/main_controller.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/browsing_data/browsing_data_remove_mask.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#include "ios/web/public/security/certificate_policy_cache.h" +#include "ios/web/public/thread/web_task_traits.h" +#include "ios/web/public/thread/web_thread.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using base::test::ios::WaitUntilConditionOrTimeout; + +namespace { + +bool ClearBrowsingData(bool off_the_record, BrowsingDataRemoveMask mask) { + ios::ChromeBrowserState* browser_state = + off_the_record ? chrome_test_util::GetCurrentIncognitoBrowserState() + : chrome_test_util::GetOriginalBrowserState(); + + __block bool did_complete = false; + [chrome_test_util::GetMainController() + removeBrowsingDataForBrowserState:browser_state + timePeriod:browsing_data::TimePeriod::ALL_TIME + removeMask:mask + completionBlock:^{ + did_complete = true; + }]; + return WaitUntilConditionOrTimeout( + base::test::ios::kWaitForClearBrowsingDataTimeout, ^{ + return did_complete; + }); +} +} // namespace + +namespace chrome_test_util { + +bool ClearBrowsingHistory() { + return ClearBrowsingData(/*off_the_record=*/false, + BrowsingDataRemoveMask::REMOVE_HISTORY); +} + +bool ClearAllBrowsingData(bool off_the_record) { + return ClearBrowsingData(off_the_record, BrowsingDataRemoveMask::REMOVE_ALL); +} + +bool ClearCertificatePolicyCache(bool off_the_record) { + ios::ChromeBrowserState* browser_state = + off_the_record ? GetCurrentIncognitoBrowserState() + : GetOriginalBrowserState(); + auto cache = web::BrowserState::GetCertificatePolicyCache(browser_state); + __block BOOL policies_cleared = NO; + base::PostTask(FROM_HERE, {web::WebThread::IO}, base::BindOnce(^{ + cache->ClearCertificatePolicies(); + policies_cleared = YES; + })); + return WaitUntilConditionOrTimeout(2, ^{ + return policies_cleared; + }); +} + +} // namespace chrome_test_util
diff --git a/ios/chrome/test/app/history_test_util.h b/ios/chrome/test/app/history_test_util.h index 616f094f..a782f0e 100644 --- a/ios/chrome/test/app/history_test_util.h +++ b/ios/chrome/test/app/history_test_util.h
@@ -5,14 +5,6 @@ #ifndef IOS_CHROME_TEST_APP_HISTORY_TEST_UTIL_H_ #define IOS_CHROME_TEST_APP_HISTORY_TEST_UTIL_H_ -#include "base/compiler_specific.h" - -namespace chrome_test_util { - -// Clears browsing history and returns whether clearing the history was -// successful or timed out. -bool ClearBrowsingHistory() WARN_UNUSED_RESULT; - -} // namespace chrome_test_util +#import "ios/chrome/test/app/browsing_data_test_util.h" #endif // IOS_CHROME_TEST_APP_HISTORY_TEST_UTIL_H_
diff --git a/ios/chrome/test/app/history_test_util.mm b/ios/chrome/test/app/history_test_util.mm deleted file mode 100644 index 756f5ca..0000000 --- a/ios/chrome/test/app/history_test_util.mm +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/test/app/history_test_util.h" - -#import "base/test/ios/wait_util.h" -#include "components/browsing_data/core/browsing_data_utils.h" -#import "ios/chrome/app/main_controller.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/browsing_data/browsing_data_remove_mask.h" -#import "ios/chrome/test/app/chrome_test_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace chrome_test_util { - -bool ClearBrowsingHistory() { - __block bool did_complete = false; - [GetMainController() - removeBrowsingDataForBrowserState:GetOriginalBrowserState() - timePeriod:browsing_data::TimePeriod::ALL_TIME - removeMask:BrowsingDataRemoveMask::REMOVE_HISTORY - completionBlock:^{ - did_complete = true; - }]; - return base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForClearBrowsingDataTimeout, ^{ - return did_complete; - }); -} - -} // namespace chrome_test_util
diff --git a/ios/chrome/test/app/tab_test_util.h b/ios/chrome/test/app/tab_test_util.h index 08335c5..36f8f9f 100644 --- a/ios/chrome/test/app/tab_test_util.h +++ b/ios/chrome/test/app/tab_test_util.h
@@ -78,6 +78,9 @@ // Evicts the tabs associated with the non-current browser mode. void EvictOtherTabModelTabs(); +// Closes all normal (non-incognito) tabs. Return YES on success. +BOOL CloseAllNormalTabs() WARN_UNUSED_RESULT; + // Closes all incognito tabs. Return YES on success. BOOL CloseAllIncognitoTabs() WARN_UNUSED_RESULT;
diff --git a/ios/chrome/test/app/tab_test_util.mm b/ios/chrome/test/app/tab_test_util.mm index 9abc22b..1d2b512 100644 --- a/ios/chrome/test/app/tab_test_util.mm +++ b/ios/chrome/test/app/tab_test_util.mm
@@ -9,6 +9,7 @@ #import "base/mac/foundation_util.h" #import "ios/chrome/app/main_controller_private.h" #include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/metrics/tab_usage_recorder.h" #include "ios/chrome/browser/system_flags.h" #import "ios/chrome/browser/tabs/tab_model.h" @@ -208,6 +209,17 @@ enabler->SetWebUsageEnabled(true); } +BOOL CloseAllNormalTabs() { + MainController* main_controller = GetMainController(); + DCHECK(main_controller); + + Browser* browser = main_controller.interfaceProvider.mainInterface.browser; + DCHECK(browser); + browser->GetWebStateList()->CloseAllWebStates( + WebStateList::CLOSE_USER_ACTION); + return YES; +} + BOOL CloseAllIncognitoTabs() { MainController* main_controller = GetMainController(); DCHECK(main_controller);
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h index db8260b..12625096 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -208,6 +208,10 @@ // normal after closing all tabs. - (void)closeAllTabsInCurrentMode; +// Closes all normal (non-incognito) tabs and waits for the UI to complete +// within a timeout, or a GREYAssert is induced. +- (void)closeAllNormalTabs; + // Closes all incognito tabs and waits for the UI to complete within a // timeout, or a GREYAssert is induced. - (void)closeAllIncognitoTabs;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index 647da8c3..0dcd3a1 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -20,16 +20,16 @@ #import <WebKit/WebKit.h> #import "ios/chrome/browser/ui/static_content/static_html_view_controller.h" // nogncheck -#import "ios/chrome/test/app/chrome_test_util.h" // nogncheck -#import "ios/chrome/test/app/history_test_util.h" // nogncheck -#include "ios/chrome/test/app/navigation_test_util.h" // nogncheck -#import "ios/chrome/test/app/sync_test_util.h" // nogncheck -#import "ios/chrome/test/app/tab_test_util.h" // nogncheck -#import "ios/web/public/deprecated/crw_js_injection_receiver.h" // nogncheck -#import "ios/web/public/test/earl_grey/js_test_util.h" // nogncheck -#import "ios/web/public/test/web_view_content_test_util.h" // nogncheck -#import "ios/web/public/test/web_view_interaction_test_util.h" // nogncheck -#import "ios/web/public/web_state.h" // nogncheck +#import "ios/chrome/test/app/browsing_data_test_util.h" // nogncheck +#import "ios/chrome/test/app/chrome_test_util.h" // nogncheck +#include "ios/chrome/test/app/navigation_test_util.h" // nogncheck +#import "ios/chrome/test/app/sync_test_util.h" // nogncheck +#import "ios/chrome/test/app/tab_test_util.h" // nogncheck +#import "ios/web/public/deprecated/crw_js_injection_receiver.h" // nogncheck +#import "ios/web/public/test/earl_grey/js_test_util.h" // nogncheck +#import "ios/web/public/test/web_view_content_test_util.h" // nogncheck +#import "ios/web/public/test/web_view_interaction_test_util.h" // nogncheck +#import "ios/web/public/web_state.h" // nogncheck #endif using base::test::ios::kWaitForJSCompletionTimeout; @@ -213,6 +213,12 @@ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; } +- (void)closeAllNormalTabs { + EG_TEST_HELPER_ASSERT_NO_ERROR( + [ChromeEarlGreyAppInterface closeAllNormalTabs]); + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; +} + - (void)closeAllIncognitoTabs { EG_TEST_HELPER_ASSERT_NO_ERROR( [ChromeEarlGreyAppInterface closeAllIncognitoTabs]); @@ -317,14 +323,8 @@ #pragma mark - WebState Utilities (EG2) - (void)tapWebStateElementWithID:(NSString*)elementID { - NSError* error = nil; - bool success = [ChromeEarlGreyAppInterface tapWebStateElementWithID:elementID - error:error]; - EG_TEST_HELPER_ASSERT_NO_ERROR(error); - NSString* description = - [NSString stringWithFormat:@"Failed to tap web state element with ID: %@", - elementID]; - EG_TEST_HELPER_ASSERT_TRUE(success, description); + EG_TEST_HELPER_ASSERT_NO_ERROR( + [ChromeEarlGreyAppInterface tapWebStateElementWithID:elementID]); } - (void)tapWebStateElementInIFrameWithID:(const std::string&)elementID {
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h index 823bca5..7e5a107f 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
@@ -97,6 +97,10 @@ // normal after closing all tabs. + (void)closeAllTabsInCurrentMode; +// Closes all normal (non-incognito) tabs. If not succeed returns an NSError +// indicating why the operation failed, otherwise nil. ++ (NSError*)closeAllNormalTabs; + // Closes all incognito tabs. If not succeed returns an NSError indicating why // the operation failed, otherwise nil. + (NSError*)closeAllIncognitoTabs; @@ -133,8 +137,9 @@ + (NSError*)tapWebStateElementInIFrameWithID:(NSString*)elementID; // Taps html element with |elementID| in the current web state. -// On failure returns NO and |error| is set to include a message. -+ (BOOL)tapWebStateElementWithID:(NSString*)elementID error:(NSError*)error; +// If not succeed returns an NSError indicating why the +// operation failed, otherwise nil. ++ (NSError*)tapWebStateElementWithID:(NSString*)elementID; // Waits for the current web state to contain an element matching |selector|. // If not succeed returns an NSError indicating why the operation failed,
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm index 5dc06ca1..74a7f79e 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -18,8 +18,8 @@ #import "ios/chrome/browser/ui/util/named_guide.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" #import "ios/chrome/test/app/bookmarks_test_util.h" +#import "ios/chrome/test/app/browsing_data_test_util.h" #import "ios/chrome/test/app/chrome_test_util.h" -#import "ios/chrome/test/app/history_test_util.h" #include "ios/chrome/test/app/navigation_test_util.h" #include "ios/chrome/test/app/settings_test_util.h" #import "ios/chrome/test/app/signin_test_util.h" @@ -165,6 +165,15 @@ chrome_test_util::CloseAllTabsInCurrentMode(); } ++ (NSError*)closeAllNormalTabs { + bool success = chrome_test_util::CloseAllNormalTabs(); + if (!success) { + return testing::NSErrorWithLocalizedDescription( + @"Could not close all normal tabs"); + } + return nil; +} + + (NSError*)closeAllIncognitoTabs { bool success = chrome_test_util::CloseAllIncognitoTabs(); if (!success) { @@ -210,10 +219,19 @@ return nil; } -+ (BOOL)tapWebStateElementWithID:(NSString*)elementID error:(NSError*)error { - return web::test::TapWebViewElementWithId( ++ (NSError*)tapWebStateElementWithID:(NSString*)elementID { + NSError* error = nil; + bool success = web::test::TapWebViewElementWithId( chrome_test_util::GetCurrentWebState(), base::SysNSStringToUTF8(elementID), &error); + if (!success || error) { + NSString* errorDescription = + [NSString stringWithFormat: + @"Failed to tap web state element with ID=%@! Error: %@", + elementID, error]; + return testing::NSErrorWithLocalizedDescription(errorDescription); + } + return nil; } + (NSError*)waitForWebStateContainingElement:(ElementSelector*)selector {
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn index 6cc65c55..4f88ab0 100644 --- a/ios/chrome/test/earl_grey2/BUILD.gn +++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -60,6 +60,7 @@ "//ios/chrome/browser/ui/safe_mode:eg2_tests", "//ios/chrome/browser/ui/settings/autofill:eg2_tests", "//ios/chrome/browser/ui/side_swipe:eg2_tests", + "//ios/chrome/browser/ui/tab_grid:eg2_tests", "//ios/chrome/browser/ui/tabs:eg2_tests", "//ios/chrome/browser/ui/toolbar:eg2_tests", ]
diff --git a/ios/showcase/badges/sc_badge_coordinator.mm b/ios/showcase/badges/sc_badge_coordinator.mm index 6441788..f28ba73 100644 --- a/ios/showcase/badges/sc_badge_coordinator.mm +++ b/ios/showcase/badges/sc_badge_coordinator.mm
@@ -115,6 +115,9 @@ - (void)passwordsBadgeButtonTapped:(id)sender { } +- (void)saveCardBadgeButtonTapped:(id)sender { +} + - (void)overflowBadgeButtonTapped:(id)sender { self.badgePopupMenuCoordinator = [[BadgePopupMenuCoordinator alloc] initWithBaseViewController:self.containerViewController];
diff --git a/ios/web/web_thread_impl.cc b/ios/web/web_thread_impl.cc index fb55070..20ab2bd 100644 --- a/ios/web/web_thread_impl.cc +++ b/ios/web/web_thread_impl.cc
@@ -14,6 +14,7 @@ #include "base/lazy_instance.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" +#include "base/no_destructor.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/task/post_task.h" @@ -145,6 +146,13 @@ return accepting_tasks; } +const scoped_refptr<base::SequencedTaskRunner>& GetNullTaskRunner() { + static const base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>> + null_task_runner; + return *null_task_runner; +} + +// Task executor for UI and IO threads. class WebThreadTaskExecutor : public base::TaskExecutor { public: WebThreadTaskExecutor() {} @@ -178,12 +186,22 @@ return GetTaskRunnerForThread(GetWebThreadIdentifier(traits)); } + const scoped_refptr<base::SequencedTaskRunner>& GetContinuationTaskRunner() + override { + NOTREACHED() << "WebThreadTaskExecutor isn't registered via " + "base::SetTaskExecutorForCurrentThread"; + return GetNullTaskRunner(); + } + private: WebThread::ID GetWebThreadIdentifier(const base::TaskTraits& traits) { DCHECK_EQ(traits.extension_id(), WebTaskTraitsExtension::kExtensionId); WebThread::ID id = traits.GetExtension<WebTaskTraitsExtension>().web_thread(); DCHECK_LT(id, WebThread::ID_COUNT); + DCHECK(!traits.use_current_thread()) + << "WebThreadTaskExecutor isn't registered via " + "base::SetTaskExecutorForCurrentThread"; // TODO(crbug.com/872372): Support shutdown behavior on UI/IO threads. if (traits.shutdown_behavior_set_explicitly()) { @@ -218,6 +236,13 @@ : identifier_(identifier) { DCHECK(task_runner); + if (identifier == WebThread::UI) { + DCHECK(task_runner->BelongsToCurrentThread()); + // TODO(scheduler-dev): Pass the backing SequenceManager in here to ensure + // GetContinuationTaskRunner DCHECKS when there's no task running. + ui_thread_tls_executor_.emplace(nullptr, task_runner); + } + WebThreadGlobals& globals = g_globals.Get(); base::AutoLock lock(globals.lock);
diff --git a/ios/web/web_thread_impl.h b/ios/web/web_thread_impl.h index 401dc2f6..51df75bd 100644 --- a/ios/web/web_thread_impl.h +++ b/ios/web/web_thread_impl.h
@@ -7,6 +7,7 @@ #include "base/callback.h" #include "base/memory/scoped_refptr.h" +#include "base/task/simple_task_executor.h" #include "base/threading/thread.h" #include "ios/web/public/thread/web_thread.h" @@ -65,6 +66,10 @@ // The identifier of this thread. Only one thread can exist with a given // identifier at a given time. ID identifier_; + + // Here to support base::CurrentThread and base::GetContinuationTaskRunner on + // the UI thread. + base::Optional<base::SimpleTaskExecutor> ui_thread_tls_executor_; }; } // namespace web
diff --git a/ios/web/web_thread_unittest.cc b/ios/web/web_thread_unittest.cc index 13011d811..98b4ca83 100644 --- a/ios/web/web_thread_unittest.cc +++ b/ios/web/web_thread_unittest.cc
@@ -6,12 +6,16 @@ #include "base/bind.h" #include "base/task/post_task.h" +#include "base/test/bind_test_util.h" #include "ios/web/public/test/web_task_environment.h" #include "ios/web/public/thread/web_task_traits.h" #include "ios/web/web_thread_impl.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +using testing::NotNull; + namespace web { class WebThreadTest : public PlatformTest { @@ -64,4 +68,37 @@ run_loop.Run(); } +TEST_F(WebThreadTest, CurrentThread) { + base::RunLoop run_loop; + + base::PostTask( + FROM_HERE, {base::CurrentThread()}, base::BindLambdaForTesting([&]() { + PostTask(FROM_HERE, {base::CurrentThread()}, run_loop.QuitClosure()); + })); + + run_loop.Run(); +} + +TEST_F(WebThreadTest, GetContinuationTaskRunner) { + base::RunLoop run_loop; + auto task_runner = + base::CreateSingleThreadTaskRunner({base::CurrentThread()}); + + task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() { + EXPECT_EQ(task_runner, + base::GetContinuationTaskRunner()); + run_loop.Quit(); + })); + + run_loop.Run(); +} + +TEST_F(WebThreadTest, GetContinuationTaskRunnerWithNoTaskRunning) { + // TODO(scheduler-dev): GetContinuationTaskRunner should DCHECK if there's no + // task running. + EXPECT_EQ(base::CreateSequencedTaskRunner({base::CurrentThread()}), + base::GetContinuationTaskRunner()); + EXPECT_THAT(base::GetContinuationTaskRunner().get(), NotNull()); +} + } // namespace web
diff --git a/media/gpu/v4l2/v4l2_slice_video_decoder.cc b/media/gpu/v4l2/v4l2_slice_video_decoder.cc index aca260b0..246eb1c 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decoder.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decoder.cc
@@ -502,6 +502,12 @@ if (!StopStreamV4L2Queue()) return false; + if (!output_queue_->DeallocateBuffers()) { + SetState(State::kError); + return false; + } + DCHECK_GT(num_output_frames, 0u); + if (!SetCodedSizeOnInputQueue(pic_size)) { VLOGF(1) << "Failed to set coded size on input queue"; return false; @@ -523,12 +529,6 @@ return false; } - // Allocate new output buffers. - if (!output_queue_->DeallocateBuffers()) { - SetState(State::kError); - return false; - } - DCHECK_GT(num_output_frames, 0u); if (output_queue_->AllocateBuffers(num_output_frames, V4L2_MEMORY_DMABUF) == 0) { VLOGF(1) << "Failed to request output buffers.";
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc index 5c255885..da04609d 100644 --- a/net/base/address_tracker_linux.cc +++ b/net/base/address_tracker_linux.cc
@@ -8,6 +8,7 @@ #include <linux/if.h> #include <stdint.h> #include <sys/ioctl.h> +#include <utility> #include "base/bind_helpers.h" #include "base/files/scoped_file.h" @@ -26,9 +27,7 @@ // Some kernel functions such as wireless_send_event and rtnetlink_ifinfo_prep // may send spurious messages over rtnetlink. RTM_NEWLINK messages where // ifi_change == 0 and rta_type == IFLA_WIRELESS should be ignored. -bool IgnoreWirelessChange(const struct nlmsghdr* header, - const struct ifinfomsg* msg) { - size_t length = IFLA_PAYLOAD(header); +bool IgnoreWirelessChange(const struct ifinfomsg* msg, int length) { for (const struct rtattr* attr = IFLA_RTA(msg); RTA_OK(attr, length); attr = RTA_NEXT(attr, length)) { if (attr->rta_type == IFLA_WIRELESS && msg->ifi_change == 0) @@ -39,13 +38,20 @@ // Retrieves address from NETLINK address message. // Sets |really_deprecated| for IPv6 addresses with preferred lifetimes of 0. +// Precondition: |header| must already be validated with NLMSG_OK. bool GetAddress(const struct nlmsghdr* header, + int header_length, IPAddress* out, bool* really_deprecated) { if (really_deprecated) *really_deprecated = false; + + // Extract the message and update |header_length| to be the number of + // remaining bytes. const struct ifaddrmsg* msg = reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); + header_length -= NLMSG_HDRLEN; + size_t address_length = 0; switch (msg->ifa_family) { case AF_INET: @@ -64,18 +70,27 @@ // have the IFA_LOCAL attribute. uint8_t* address = NULL; uint8_t* local = NULL; - size_t length = IFA_PAYLOAD(header); + int length = IFA_PAYLOAD(header); + if (length > header_length) { + LOG(ERROR) << "ifaddrmsg length exceeds bounds"; + return false; + } for (const struct rtattr* attr = reinterpret_cast<const struct rtattr*>(IFA_RTA(msg)); - RTA_OK(attr, length); - attr = RTA_NEXT(attr, length)) { + RTA_OK(attr, length); attr = RTA_NEXT(attr, length)) { switch (attr->rta_type) { case IFA_ADDRESS: - DCHECK_GE(RTA_PAYLOAD(attr), address_length); + if (RTA_PAYLOAD(attr) < address_length) { + LOG(ERROR) << "attr does not have enough bytes to read an address"; + return false; + } address = reinterpret_cast<uint8_t*>(RTA_DATA(attr)); break; case IFA_LOCAL: - DCHECK_GE(RTA_PAYLOAD(attr), address_length); + if (RTA_PAYLOAD(attr) < address_length) { + LOG(ERROR) << "attr does not have enough bytes to read an address"; + return false; + } local = reinterpret_cast<uint8_t*>(RTA_DATA(attr)); break; case IFA_CACHEINFO: { @@ -314,14 +329,19 @@ } void AddressTrackerLinux::HandleMessage(const char* buffer, - size_t length, + int length, bool* address_changed, bool* link_changed, bool* tunnel_changed) { DCHECK(buffer); + // Note that NLMSG_NEXT decrements |length| to reflect the number of bytes + // remaining in |buffer|. for (const struct nlmsghdr* header = reinterpret_cast<const struct nlmsghdr*>(buffer); - NLMSG_OK(header, length); header = NLMSG_NEXT(header, length)) { + length >= 0 && NLMSG_OK(header, static_cast<__u32>(length)); + header = NLMSG_NEXT(header, length)) { + // The |header| pointer should never precede |buffer|. + DCHECK_LE(buffer, reinterpret_cast<const char*>(header)); switch (header->nlmsg_type) { case NLMSG_DONE: return; @@ -337,7 +357,7 @@ reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); if (IsInterfaceIgnored(msg->ifa_index)) break; - if (GetAddress(header, &address, &really_deprecated)) { + if (GetAddress(header, length, &address, &really_deprecated)) { AddressTrackerAutoLock lock(*this, address_map_lock_); // Routers may frequently (every few seconds) output the IPv6 ULA // prefix which can cause the linux kernel to frequently output two @@ -366,7 +386,7 @@ reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header)); if (IsInterfaceIgnored(msg->ifa_index)) break; - if (GetAddress(header, &address, NULL)) { + if (GetAddress(header, length, &address, nullptr)) { AddressTrackerAutoLock lock(*this, address_map_lock_); if (address_map_.erase(address)) *address_changed = true; @@ -377,7 +397,7 @@ reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header)); if (IsInterfaceIgnored(msg->ifi_index)) break; - if (IgnoreWirelessChange(header, msg)) { + if (IgnoreWirelessChange(msg, IFLA_PAYLOAD(header))) { VLOG(2) << "Ignoring RTM_NEWLINK message"; break; } @@ -468,8 +488,7 @@ current_connection_type_ = type; } -int AddressTrackerLinux::GetThreadsWaitingForConnectionTypeInitForTesting() -{ +int AddressTrackerLinux::GetThreadsWaitingForConnectionTypeInitForTesting() { AddressTrackerAutoLock lock(*this, connection_type_lock_); return threads_waiting_for_connection_type_initialization_; }
diff --git a/net/base/address_tracker_linux.h b/net/base/address_tracker_linux.h index f3d38fc..a2c11162 100644 --- a/net/base/address_tracker_linux.h +++ b/net/base/address_tracker_linux.h
@@ -13,6 +13,8 @@ #include <stddef.h> #include <map> +#include <memory> +#include <string> #include <unordered_set> #include "base/callback.h" @@ -120,7 +122,7 @@ // to true if |online_links_| changed with regards to a tunnel interface while // reading the message from |buffer|. void HandleMessage(const char* buffer, - size_t length, + int length, bool* address_changed, bool* link_changed, bool* tunnel_changed);
diff --git a/net/cert/cert_verifier.h b/net/cert/cert_verifier.h index 9b7ff450..801efe22 100644 --- a/net/cert/cert_verifier.h +++ b/net/cert/cert_verifier.h
@@ -151,18 +151,23 @@ // Returns OK if successful or an error code upon failure. // // The |*verify_result| structure, including the |verify_result->cert_status| - // bitmask, is always filled out regardless of the return value. If the + // bitmask, is always filled out regardless of the return value. If the // certificate has multiple errors, the corresponding status flags are set in // |verify_result->cert_status|, and the error code for the most serious // error is returned. // - // |callback| must not be null. ERR_IO_PENDING is returned if the operation + // |callback| must not be null. ERR_IO_PENDING is returned if the operation // could not be completed synchronously, in which case the result code will // be passed to the callback when available. // - // On asynchronous completion (when Verify returns ERR_IO_PENDING) |out_req| - // will be reset with a pointer to the request. Freeing this pointer before - // the request has completed will cancel it. + // |*out_req| is used to store a request handle in the event of asynchronous + // completion (when Verify returns ERR_IO_PENDING). Provided that neither + // the CertVerifier nor the Request have been deleted, |callback| will be + // invoked once the underlying verification finishes. If either the + // CertVerifier or the Request are deleted, then |callback| will be Reset() + // and will not be invoked. It is fine for |out_req| to outlive the + // CertVerifier, and it is fine to reset |out_req| or delete the + // CertVerifier during the processing of |callback|. // // If Verify() completes synchronously then |out_req| *may* be reset to // nullptr. However it is not guaranteed that all implementations will reset
diff --git a/net/cert/coalescing_cert_verifier.cc b/net/cert/coalescing_cert_verifier.cc index 06099903..3cd16ef 100644 --- a/net/cert/coalescing_cert_verifier.cc +++ b/net/cert/coalescing_cert_verifier.cc
@@ -354,6 +354,8 @@ } void CoalescingCertVerifier::Request::Complete(int result) { + DCHECK(job_); // There must be a pending/non-aborted job to complete. + *verify_result_ = job_->verify_result(); // On successful completion, the Job removes the Request from its set; @@ -368,12 +370,16 @@ } void CoalescingCertVerifier::Request::OnJobAbort() { + DCHECK(job_); // There must be a pending job to abort. + // If the Job is deleted before the Request, just clean up. The Request will // eventually be deleted by the caller. net_log_.AddEvent(NetLogEventType::CANCELLED); net_log_.EndEvent(NetLogEventType::CERT_VERIFIER_REQUEST); job_ = nullptr; + // Note: May delete |this|, if the caller made |callback_| own the Request. + callback_.Reset(); } CoalescingCertVerifier::CoalescingCertVerifier(
diff --git a/net/cert/trial_comparison_cert_verifier.cc b/net/cert/trial_comparison_cert_verifier.cc index d91f542..fa1b557 100644 --- a/net/cert/trial_comparison_cert_verifier.cc +++ b/net/cert/trial_comparison_cert_verifier.cc
@@ -242,11 +242,12 @@ // Called when the Job has completed, and used to invoke the client // callback. - // Note: |this| may be deleted after calling this. + // Note: |this| may be deleted after calling this method. void OnJobComplete(int result, const CertVerifyResult& verify_result); // Called when the Job is aborted (e.g. the underlying // TrialComparisonCertVerifier is being deleted). + // Note: |this| may be deleted after calling this method. void OnJobAborted(); private: @@ -275,7 +276,9 @@ TrialComparisonCertVerifier::Job::~Job() { if (request_) { + // Note: May delete |request_|. request_->OnJobAborted(); + request_ = nullptr; } if (parent_) { @@ -628,6 +631,9 @@ void TrialComparisonCertVerifier::Job::Request::OnJobAborted() { DCHECK(parent_); parent_ = nullptr; + + // DANGER: |this| may be deleted when this callback is destroyed. + client_callback_.Reset(); } TrialComparisonCertVerifier::TrialComparisonCertVerifier(
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index f9767a3..09942bc 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -137,6 +137,8 @@ "daemon_process.cc", "daemon_process.h", "daemon_process_win.cc", + "desktop_capturer_checker.cc", + "desktop_capturer_checker.h", "desktop_capturer_proxy.cc", "desktop_capturer_proxy.h", "desktop_display_info.cc",
diff --git a/remoting/host/desktop_capturer_checker.cc b/remoting/host/desktop_capturer_checker.cc new file mode 100644 index 0000000..8bad7378 --- /dev/null +++ b/remoting/host/desktop_capturer_checker.cc
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/host/desktop_capturer_checker.h" + +#include <stddef.h> + +#include <utility> + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "remoting/host/client_session_control.h" +#include "remoting/proto/control.pb.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_capturer_differ_wrapper.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_region.h" + +namespace remoting { + +DesktopCapturerChecker::DesktopCapturerChecker() {} + +DesktopCapturerChecker::~DesktopCapturerChecker() {} + +void DesktopCapturerChecker::TriggerSingleCapture() { + DCHECK(!capturer_); + + webrtc::DesktopCaptureOptions options = + webrtc::DesktopCaptureOptions::CreateDefault(); + capturer_ = webrtc::DesktopCapturer::CreateScreenCapturer(options); + DCHECK(capturer_) + << "Failed to initialize screen capturer for DesktopCapturerChecker."; + capturer_->Start(this); + capturer_->CaptureFrame(); +} + +void DesktopCapturerChecker::OnCaptureResult( + webrtc::DesktopCapturer::Result result, + std::unique_ptr<webrtc::DesktopFrame> frame) { + // Ignore capture result. +} + +} // namespace remoting
diff --git a/remoting/host/desktop_capturer_checker.h b/remoting/host/desktop_capturer_checker.h new file mode 100644 index 0000000..44b8315 --- /dev/null +++ b/remoting/host/desktop_capturer_checker.h
@@ -0,0 +1,37 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_HOST_DESKTOP_CAPTURER_CHECKER_H_ +#define REMOTING_HOST_DESKTOP_CAPTURER_CHECKER_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/macros.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h" + +namespace remoting { + +// DesktopCapturerChecker is a simple DesktopCapturer that captures a single +// screen image (which is ignored). The purpose of this class is to trigger +// the native API's permission check when a screen capture is attempted. +class DesktopCapturerChecker : public webrtc::DesktopCapturer::Callback { + public: + DesktopCapturerChecker(); + ~DesktopCapturerChecker() override; + + void TriggerSingleCapture(); + + private: + // webrtc::DesktopCapturer::Callback implementation. + void OnCaptureResult(webrtc::DesktopCapturer::Result result, + std::unique_ptr<webrtc::DesktopFrame> frame) override; + + std::unique_ptr<webrtc::DesktopCapturer> capturer_; + DISALLOW_COPY_AND_ASSIGN(DesktopCapturerChecker); +}; + +} // namespace remoting + +#endif // REMOTING_HOST_DESKTOP_CAPTURER_CHECKER_H_
diff --git a/remoting/host/mac/permission_utils.mm b/remoting/host/mac/permission_utils.mm index e88586a8..d2fed1e 100644 --- a/remoting/host/mac/permission_utils.mm +++ b/remoting/host/mac/permission_utils.mm
@@ -9,7 +9,9 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/mac/foundation_util.h" #include "base/mac/mac_util.h" +#include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_refptr.h" #include "base/single_thread_task_runner.h" @@ -109,9 +111,28 @@ namespace remoting { namespace mac { +// Heuristic to check screen capture permission. See http://crbug.com/993692 +// Copied from +// chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm +// TODO(garykac) Move webrtc version where it can be shared. bool CanRecordScreen() { - // Return true for now to avoid showing the dialog constantly. - // TODO(b/1012545) Perform real check for Screen Capture. + if (@available(macOS 10.15, *)) { + base::ScopedCFTypeRef<CFArrayRef> window_list(CGWindowListCopyWindowInfo( + kCGWindowListOptionOnScreenOnly, kCGNullWindowID)); + NSUInteger num_windows = CFArrayGetCount(window_list); + NSUInteger num_windows_with_name = 0; + for (NSDictionary* dict in base::mac::CFToNSCast(window_list.get())) { + if ([dict objectForKey:base::mac::CFToNSCast(kCGWindowName)]) { + num_windows_with_name++; + } else { + // No kCGWindowName detected implies no permission. + break; + } + } + return num_windows == num_windows_with_name; + } + + // Previous to 10.15, screen capture was always allowed. return true; }
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index d40aa6c..2ae52b8 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -117,6 +117,7 @@ #if defined(OS_MACOSX) #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" +#include "remoting/host/desktop_capturer_checker.h" #include "remoting/host/mac/permission_utils.h" #endif // defined(OS_MACOSX) @@ -454,6 +455,10 @@ ShutdownWatchdog* shutdown_watchdog_; +#if defined(OS_MACOSX) + std::unique_ptr<DesktopCapturerChecker> capture_checker_; +#endif // defined(OS_MACOSX) + DISALLOW_COPY_AND_ASSIGN(HostProcess); }; @@ -1556,8 +1561,16 @@ // Ensure we are not running as root (i.e. at the login screen). DCHECK_NE(getuid(), 0U); + // Capture a single screen image to trigger OS permission checks which will + // add our binary to the list of apps that can be granted permission. This + // is only needed for OS X 10.15 and later. + if (!base::mac::IsAtLeastOS10_15()) { + capture_checker_.reset(new DesktopCapturerChecker()); + capture_checker_->TriggerSingleCapture(); + } + mac::PromptUserToChangeTrustStateIfNeeded(context_->ui_task_runner()); -#endif +#endif // defined(OS_MACOSX) host_->Start(host_owner_);
diff --git a/services/network/resource_scheduler/resource_scheduler_params_manager.cc b/services/network/resource_scheduler/resource_scheduler_params_manager.cc index cb5bab59..3b50cde 100644 --- a/services/network/resource_scheduler/resource_scheduler_params_manager.cc +++ b/services/network/resource_scheduler/resource_scheduler_params_manager.cc
@@ -51,10 +51,10 @@ // either downlink or uplink traffic and are expected to cause traffic // contention with the P2P traffic on slow connections. if (throttled_traffic_annotation_tags.empty()) { - // 6019475: safe_browsing_module_loader - // 82509217: safe_browsing_v4_update // 727528: metrics_report_uma - throttled_traffic_annotation_tags = "6019475,82509217,727528"; + // 727478: metrics_report_uma + // 18300705: gcm_channel_status_request + throttled_traffic_annotation_tags = "727528,727478,18300705"; } const std::vector<std::string>& tokens =
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 97efe6d..f4a1571 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -278,9 +278,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3", + "gpu": "10de:1cb3-23.21.13.8792", "os": "Windows-2008ServerR2-SP1", - "pool": "chrome.tests.perf" + "pool": "chrome.tests.perf", + "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)" } ], "expiration": 7200, @@ -315,9 +316,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3", + "gpu": "10de:1cb3-23.21.13.8792", "os": "Windows-2008ServerR2-SP1", - "pool": "chrome.tests.perf" + "pool": "chrome.tests.perf", + "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)" } ], "expiration": 7200, @@ -352,9 +354,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3", + "gpu": "10de:1cb3-23.21.13.8792", "os": "Windows-2008ServerR2-SP1", - "pool": "chrome.tests.perf" + "pool": "chrome.tests.perf", + "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)" } ], "expiration": 7200, @@ -391,9 +394,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3", + "gpu": "10de:1cb3-23.21.13.8792", "os": "Windows-2008ServerR2-SP1", - "pool": "chrome.tests.perf" + "pool": "chrome.tests.perf", + "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)" } ], "expiration": 7200, @@ -430,9 +434,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3", + "gpu": "10de:1cb3-23.21.13.8792", "os": "Windows-2008ServerR2-SP1", - "pool": "chrome.tests.perf" + "pool": "chrome.tests.perf", + "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)" } ], "expiration": 7200, @@ -471,9 +476,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3", + "gpu": "10de:1cb3-23.21.13.8792", "os": "Windows-2008ServerR2-SP1", - "pool": "chrome.tests.perf" + "pool": "chrome.tests.perf", + "synthetic_product_name": "PowerEdge R220 [01] (Dell Inc.)" } ], "expiration": 7200, @@ -1906,9 +1912,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "1002:6821", - "os": "Mac-10.13", - "pool": "chrome.tests.perf" + "gpu": "1002:6821-4.0.20-3.2.8", + "os": "Mac-10.13.3", + "pool": "chrome.tests.perf", + "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0" } ], "expiration": 7200, @@ -1943,9 +1950,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "1002:6821", - "os": "Mac-10.13", - "pool": "chrome.tests.perf" + "gpu": "1002:6821-4.0.20-3.2.8", + "os": "Mac-10.13.3", + "pool": "chrome.tests.perf", + "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0" } ], "expiration": 7200, @@ -1980,9 +1988,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "1002:6821", - "os": "Mac-10.13", - "pool": "chrome.tests.perf" + "gpu": "1002:6821-4.0.20-3.2.8", + "os": "Mac-10.13.3", + "pool": "chrome.tests.perf", + "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0" } ], "expiration": 7200, @@ -2017,9 +2026,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "1002:6821", - "os": "Mac-10.13", - "pool": "chrome.tests.perf" + "gpu": "1002:6821-4.0.20-3.2.8", + "os": "Mac-10.13.3", + "pool": "chrome.tests.perf", + "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0" } ], "expiration": 7200, @@ -2054,9 +2064,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "1002:6821", - "os": "Mac-10.13", - "pool": "chrome.tests.perf" + "gpu": "1002:6821-4.0.20-3.2.8", + "os": "Mac-10.13.3", + "pool": "chrome.tests.perf", + "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0" } ], "expiration": 7200, @@ -2091,9 +2102,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "1002:6821", - "os": "Mac-10.13", - "pool": "chrome.tests.perf" + "gpu": "1002:6821-4.0.20-3.2.8", + "os": "Mac-10.13.3", + "pool": "chrome.tests.perf", + "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0" } ], "expiration": 7200, @@ -2132,9 +2144,10 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "1002:6821", - "os": "Mac-10.13", - "pool": "chrome.tests.perf" + "gpu": "1002:6821-4.0.20-3.2.8", + "os": "Mac-10.13.3", + "pool": "chrome.tests.perf", + "synthetic_product_name": "MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0" } ], "expiration": 7200,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 894f5b3..d0aa39bc 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3262,6 +3262,21 @@ ] } ], + "LowerJavaScriptPriorityWhenForceDeferred": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Control_20190905", + "disable_features": [ + "LowerJavaScriptPriorityWhenForceDeferred" + ] + } + ] + } + ], "LsdPermissionPrompt": [ { "platforms": [ @@ -4308,7 +4323,7 @@ { "name": "Enabled_20190712", "params": { - "throttled_traffic_annotation_tags": "6019475,82509217,727528" + "throttled_traffic_annotation_tags": "727528,727478,18300705" }, "enable_features": [ "PauseBrowserInitiatedHeavyTrafficForP2P"
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 2e938bb31..90f0d65c 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -397,7 +397,7 @@ // are force deferred by the intervention. const base::Feature kLowerJavaScriptPriorityWhenForceDeferred{ "LowerJavaScriptPriorityWhenForceDeferred", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kHtmlImportsRequestInitiatorLock{ "HtmlImportsRequestInitiatorLock", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index a011b6a..e00ffea 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -113,7 +113,6 @@ "web/modules/peerconnection/mock_peer_connection_dependency_factory.h", "web/modules/peerconnection/mock_peer_connection_impl.h", "web/modules/peerconnection/mock_web_rtc_peer_connection_handler_client.h", - "web/modules/peerconnection/webrtc_stats_report_obtainer.h", ] deps = [ ":blink_headers",
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index 7cfb700..9893bacc 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -6,6 +6,7 @@ import "mojo/public/mojom/base/string16.mojom"; import "third_party/blink/public/mojom/frame/fullscreen.mojom"; +import "url/mojom/url.mojom"; // Implemented in Browser, this interface defines frame-specific methods that will // be invoked from the render process (e.g. content::RenderFrameHostImpl). @@ -26,6 +27,21 @@ // Notifies the browser that the current frame has either become or is no // longer fullscreen. FullscreenStateChanged(bool is_fullscreen); + + // Register a new handler for URL requests with the given scheme. |scheme|, + // |url|, and |title| are provided directly from javascript. See + // https://html.spec.whatwg.org/multipage/system-state.html#custom-handlers + // |user_gesture| indicates if the javascript API was called in context of + // having an active transient user gesture. + RegisterProtocolHandler(string scheme, url.mojom.Url url, + mojo_base.mojom.String16 title, bool user_gesture); + + // Unregister the registered handler for URL requests with the given scheme. + // |scheme|, and |url| are provided directly from javascript. See + // https://html.spec.whatwg.org/multipage/system-state.html#custom-handlers + // |user_gesture| indicates if the javascript API was called in context of + // having an active transient user gesture. + UnregisterProtocolHandler(string scheme, url.mojom.Url url, bool user_gesture); }; // Implemented in Blink, this interface defines frame-specific methods that will @@ -36,8 +52,7 @@ // content. In the future this interface will likely host more methods as the // Onion Soup project advances, which can potentially lead to the removal of // content/common/frame.mojom if enough code is moved to Blink. -// TODO(dtapuska): Rename to LocalFrame -interface Frame { +interface LocalFrame { // Retrieves the text surrounding the current selection for the frame up to // the length specified by |max_length|, along with its start and end offsets. GetTextSurroundingSelection(uint32 max_length)
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index d0b1bcb..0f9f6c37 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -103,7 +103,6 @@ BLINK_PLATFORM_EXPORT static void EnableDisplayCutoutAPI(bool); BLINK_PLATFORM_EXPORT static void EnableDocumentPolicy(bool); BLINK_PLATFORM_EXPORT static void EnableFallbackCursorMode(bool); - BLINK_PLATFORM_EXPORT static void EnableFastMobileScrolling(bool); BLINK_PLATFORM_EXPORT static void EnableFeaturePolicyForSandbox(bool); BLINK_PLATFORM_EXPORT static void EnableFileSystem(bool); BLINK_PLATFORM_EXPORT static void EnableForceSynchronousHTMLParsing(bool); @@ -128,6 +127,7 @@ bool); BLINK_PLATFORM_EXPORT static void EnableNavigatorContentUtils(bool); BLINK_PLATFORM_EXPORT static void EnableNetInfoDownlinkMax(bool); + BLINK_PLATFORM_EXPORT static void EnableNeverSlowMode(bool); BLINK_PLATFORM_EXPORT static void EnableUpdateHoverAtBeginFrame(bool); BLINK_PLATFORM_EXPORT static void EnableNotificationConstructor(bool); BLINK_PLATFORM_EXPORT static void EnableNotificationContentImage(bool);
diff --git a/third_party/blink/public/platform/web_theme_engine.h b/third_party/blink/public/platform/web_theme_engine.h index 2b55c0b..d642462 100644 --- a/third_party/blink/public/platform/web_theme_engine.h +++ b/third_party/blink/public/platform/web_theme_engine.h
@@ -34,6 +34,7 @@ #include "base/optional.h" #include "base/time/time.h" #include "third_party/blink/public/common/css/forced_colors.h" +#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/platform/web_color_scheme.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_scrollbar_overlay_color_theme.h" @@ -228,6 +229,11 @@ virtual ForcedColors ForcedColors() const { return ForcedColors::kNone; } virtual void SetForcedColors(const blink::ForcedColors forced_colors) {} + virtual blink::PreferredColorScheme PreferredColorScheme() const { + return PreferredColorScheme::kNoPreference; + } + virtual void SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) {} }; } // namespace blink
diff --git a/third_party/blink/public/web/modules/peerconnection/DEPS b/third_party/blink/public/web/modules/peerconnection/DEPS index 45e1ae23..8fae56ee 100644 --- a/third_party/blink/public/web/modules/peerconnection/DEPS +++ b/third_party/blink/public/web/modules/peerconnection/DEPS
@@ -11,7 +11,7 @@ ] specific_include_rules = { - ".*obtainer\.h|mock.*\.h": [ + "mock.*\.h": [ "+base/run_loop.h", "+testing/gmock/include/gmock/gmock.h", ],
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h index dc80421..76df720 100644 --- a/third_party/blink/public/web/web_local_frame_client.h +++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -778,17 +778,6 @@ SuddenTerminationDisablerType) { } - // Navigator Content Utils -------------------------------------------- - - // Registers a new URL handler for the given protocol. - virtual void RegisterProtocolHandler(const WebString& scheme, - const WebURL& url, - const WebString& title) {} - - // Unregisters a given URL handler for the given protocol. - virtual void UnregisterProtocolHandler(const WebString& scheme, - const WebURL& url) {} - // Audio Output Devices API -------------------------------------------- // Checks that the given audio sink exists and is authorized. The result is
diff --git a/third_party/blink/public/web/web_render_theme.h b/third_party/blink/public/web/web_render_theme.h index 6f8ce80..6dcbfa24 100644 --- a/third_party/blink/public/web/web_render_theme.h +++ b/third_party/blink/public/web/web_render_theme.h
@@ -49,6 +49,8 @@ BLINK_EXPORT void SystemColorsChanged(); +BLINK_EXPORT void ColorSchemeChanged(); + } // namespace blink #endif
diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h index eda37279..2e6c32b7 100644 --- a/third_party/blink/public/web/web_settings.h +++ b/third_party/blink/public/web/web_settings.h
@@ -34,7 +34,6 @@ #include <unicode/uscript.h> #include "third_party/blink/public/common/css/navigation_controls.h" -#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/platform/pointer_properties.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_effective_connection_type.h" @@ -296,7 +295,6 @@ virtual void SetLazyImageFirstKFullyLoad3G(int) = 0; virtual void SetLazyImageFirstKFullyLoad4G(int) = 0; virtual void SetForceDarkModeEnabled(bool) = 0; - virtual void SetPreferredColorScheme(PreferredColorScheme) = 0; virtual void SetNavigationControls(NavigationControls) = 0; protected:
diff --git a/third_party/blink/renderer/bindings/BUILD.gn b/third_party/blink/renderer/bindings/BUILD.gn index 65761237..68b953ef 100644 --- a/third_party/blink/renderer/bindings/BUILD.gn +++ b/third_party/blink/renderer/bindings/BUILD.gn
@@ -87,6 +87,9 @@ # generator to the new one. inputs += [ "${bindings_scripts_dir}/web_idl/migration_adapter.idl" ] + # Additional IDL files to test and demonstrate the new IDL compiler. + inputs += [ "${bindings_scripts_dir}/web_idl/idl_compiler_test.idl" ] + component = "core" output = "${bindings_output_dir}/web_idl_in_core.pickle" deps = [
diff --git a/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps b/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps index 81cf5542..12784d5 100644 --- a/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps +++ b/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps
@@ -12,6 +12,7 @@ web_idl/code_generator_info.py web_idl/composition_parts.py web_idl/constant.py +web_idl/constructor.py web_idl/database.py web_idl/database_builder.py web_idl/dictionary.py
diff --git a/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps b/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps index f4c2e39..c0fe6ad 100644 --- a/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps +++ b/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps
@@ -22,6 +22,7 @@ web_idl/code_generator_info.py web_idl/composition_parts.py web_idl/constant.py +web_idl/constructor.py web_idl/database.py web_idl/database_builder.py web_idl/dictionary.py
diff --git a/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps b/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps index 28c6e59e..3a97e26 100644 --- a/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps +++ b/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
@@ -34,6 +34,7 @@ web_idl/code_generator_info.py web_idl/composition_parts.py web_idl/constant.py +web_idl/constructor.py web_idl/database.py web_idl/database_builder.py web_idl/dictionary.py
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py b/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py index e016654..6ea2b295 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/constructor.py
@@ -2,54 +2,92 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import exceptions - +from .code_generator_info import CodeGeneratorInfo +from .composition_parts import Identifier +from .composition_parts import WithCodeGeneratorInfo from .composition_parts import WithComponent from .composition_parts import WithDebugInfo +from .composition_parts import WithExposure +from .composition_parts import WithExtendedAttributes from .composition_parts import WithOwner +from .exposure import Exposure +from .function_like import FunctionLike +from .make_copy import make_copy +from .overload_group import OverloadGroup -class Constrcutor(object): - def is_custom(self): - """ - Returns True if this Constructor is defined in the form of - [CustomConstructor=(...)] - @return bool - """ - raise exceptions.NotImplementedError() +class Constructor(FunctionLike, WithExtendedAttributes, WithCodeGeneratorInfo, + WithExposure, WithOwner, WithComponent, WithDebugInfo): + """https://heycam.github.io/webidl/#idl-constructors""" - @property - def return_type(self): - """ - Returns IDL interface type to construct. - @return IdlInterfaceType - """ - raise exceptions.NotImplementedError() + class IR(FunctionLike.IR, WithExtendedAttributes, WithCodeGeneratorInfo, + WithExposure, WithComponent, WithDebugInfo): + def __init__(self, + arguments, + return_type, + extended_attributes=None, + component=None, + debug_info=None): + FunctionLike.IR.__init__( + self, + identifier=Identifier('constructor'), + arguments=arguments, + return_type=return_type) + WithExtendedAttributes.__init__(self, extended_attributes) + WithCodeGeneratorInfo.__init__(self) + WithExposure.__init__(self) + WithComponent.__init__(self, component=component) + WithDebugInfo.__init__(self, debug_info) - @property - def arguments(self): - """ - Returns a list of arguments - @return tuple(Argument) - """ - raise exceptions.NotImplementedError() + def __init__(self, ir, owner): + assert isinstance(ir, Constructor.IR) - @property - def overloaded_index(self): - """ - Returns its index in ConstructorGroup - @return int - """ - raise exceptions.NotImplementedError() + FunctionLike.__init__(self, ir) + WithExtendedAttributes.__init__(self, ir.extended_attributes) + WithCodeGeneratorInfo.__init__( + self, CodeGeneratorInfo(ir.code_generator_info)) + WithExposure.__init__(self, Exposure(ir.exposure)) + WithOwner.__init__(self, owner) + WithComponent.__init__(self, components=ir.components) + WithDebugInfo.__init__(self, ir.debug_info) -class ConstructorGroup(object): - def constructors(self): - """ - Returns a list of constructors - @return tuple(Constructor) - """ - raise exceptions.NotImplementedError() +class ConstructorGroup(OverloadGroup, WithCodeGeneratorInfo, WithExposure, + WithOwner, WithDebugInfo): + """ + Represents a group of constructors for an interface. + + The number of constructors in this group may be 1 or 2+. In the latter + case, the constructors are overloaded. + """ + + class IR(OverloadGroup.IR, WithCodeGeneratorInfo, WithExposure, + WithDebugInfo): + def __init__(self, + constructors, + code_generator_info=None, + debug_info=None): + OverloadGroup.IR.__init__(self, constructors) + WithCodeGeneratorInfo.__init__(self, code_generator_info) + WithExposure.__init__(self) + WithDebugInfo.__init__(self, debug_info) + + def __init__(self, ir, constructors, owner): + assert isinstance(ir, ConstructorGroup.IR) + assert isinstance(constructors, (list, tuple)) + assert all( + isinstance(constructor, Constructor) + for constructor in constructors) + assert all(constructor.identifier == ir.identifier + for constructor in constructors) + + ir = make_copy(ir) + OverloadGroup.__init__(self, functions=constructors) + WithCodeGeneratorInfo.__init__( + self, CodeGeneratorInfo(ir.code_generator_info)) + WithExposure.__init__(self, Exposure(ir.exposure)) + WithOwner.__init__(self, owner) + WithDebugInfo.__init__(self, ir.debug_info) class NamedConstructor(object):
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py index 6f86478..d5bfc7de 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
@@ -8,6 +8,7 @@ from .callback_function import CallbackFunction from .callback_interface import CallbackInterface from .composition_parts import Identifier +from .constructor import ConstructorGroup from .database import Database from .database import DatabaseBody from .dictionary import Dictionary @@ -283,14 +284,20 @@ for old_ir in old_irs: assert not old_ir.operation_groups + assert not old_ir.constructor_groups new_ir = make_copy(old_ir) sort_key = lambda x: x.identifier new_ir.operation_groups = [ OperationGroup.IR(operations=list(operations)) for identifier, operations in itertools.groupby( - sorted(old_ir.operations, key=sort_key), key=sort_key) + sorted(new_ir.operations, key=sort_key), key=sort_key) if identifier ] + new_ir.constructor_groups = [ + ConstructorGroup.IR(constructors=list(constructors)) + for identifier, constructors in itertools.groupby( + sorted(new_ir.constructors, key=sort_key), key=sort_key) + ] self._ir_map.add(new_ir) def _create_public_objects(self):
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler_test.idl b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler_test.idl new file mode 100644 index 0000000..8f9a330 --- /dev/null +++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler_test.idl
@@ -0,0 +1,12 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + Exposed=Window +] interface TestInterfaceConstructor { + constructor(); + constructor(DOMString arg1); + [Custom] constructor(Node node); + [RuntimeEnabled=Hoge] constructor(long num); +};
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/interface.py b/third_party/blink/renderer/bindings/scripts/web_idl/interface.py index a1ba381..b018b68d 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/interface.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
@@ -11,6 +11,8 @@ from .composition_parts import WithExtendedAttributes from .composition_parts import WithOwner from .constant import Constant +from .constructor import Constructor +from .constructor import ConstructorGroup from .exposure import Exposure from .idl_type import IdlType from .ir_map import IRMap @@ -34,6 +36,7 @@ inherited=None, attributes=None, constants=None, + constructors=None, operations=None, stringifier=None, iterable=None, @@ -47,6 +50,8 @@ assert inherited is None or isinstance(inherited, RefById) assert attributes is None or isinstance(attributes, (list, tuple)) assert constants is None or isinstance(constants, (list, tuple)) + assert constructors is None or isinstance(constructors, + (list, tuple)) assert operations is None or isinstance(operations, (list, tuple)) assert stringifier is None or isinstance(stringifier, Stringifier.IR) @@ -56,6 +61,7 @@ attributes = attributes or [] constants = constants or [] + constructors = constructors or [] operations = operations or [] assert all( isinstance(attribute, Attribute.IR) @@ -63,6 +69,9 @@ assert all( isinstance(constant, Constant.IR) for constant in constants) assert all( + isinstance(constructor, Constructor.IR) + for constructor in constructors) + assert all( isinstance(operation, Operation.IR) for operation in operations) @@ -89,6 +98,8 @@ self.inherited = inherited self.attributes = list(attributes) self.constants = list(constants) + self.constructors = list(constructors) + self.constructor_groups = [] self.operations = list(operations) self.operation_groups = [] self.stringifier = stringifier @@ -101,6 +112,8 @@ yield attribute for constant in self.constants: yield constant + for constructor in self.constructors: + yield constructor for operation in self.operations: yield operation @@ -126,6 +139,19 @@ self._constants = tuple([ Constant(constant_ir, owner=self) for constant_ir in ir.constants ]) + self._constructors = tuple([ + Constructor(constructor_ir, owner=self) + for constructor_ir in ir.constructors + ]) + self._constructor_groups = tuple([ + ConstructorGroup( + constructor_group_ir, + filter( + lambda x: x.identifier == constructor_group_ir.identifier, + self._constructors), + owner=self) for constructor_group_ir in ir.constructor_groups + ]) + assert len(self._constructor_groups) <= 1 self._operations = tuple([ Operation(operation_ir, owner=self) for operation_ir in ir.operations @@ -179,6 +205,20 @@ return self._constants @property + def constructors(self): + """Returns constructors.""" + return self._constructors + + @property + def constructor_groups(self): + """ + Returns groups of constructors. + + Constructors are grouped as operations are. There is 0 or 1 group. + """ + return self._constructor_groups + + @property def operations(self): """ Returns all operations, including special operations without an @@ -201,11 +241,6 @@ return self._operation_groups @property - def constructors(self): - """Returns a constructor group.""" - assert False, "Not implemented yet." - - @property def named_constructor(self): """Returns a named constructor or None.""" assert False, "Not implemented yet."
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py index 370262a..6ef994b 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
@@ -12,6 +12,7 @@ from .composition_parts import Identifier from .composition_parts import Location from .constant import Constant +from .constructor import Constructor from .dictionary import Dictionary from .dictionary import DictionaryMember from .enumeration import Enumeration @@ -112,18 +113,26 @@ setlike = self._take_setlike(child_nodes) extended_attributes = self._take_extended_attributes(child_nodes) - members = map(self._build_interface_or_namespace_member, child_nodes) + identifier = Identifier(node.GetName()) + members = [ + self._build_interface_or_namespace_member( + child, interface_identifier=identifier) + for child in child_nodes + ] attributes = [] constants = [] + constructors = [] operations = [] for member in members: if isinstance(member, Attribute.IR): attributes.append(member) + elif isinstance(member, Constant.IR): + constants.append(member) + elif isinstance(member, Constructor.IR): + constructors.append(member) elif isinstance(member, Operation.IR): if member.identifier: operations.append(member) - elif isinstance(member, Constant.IR): - constants.append(member) else: assert False @@ -134,12 +143,13 @@ # TODO(peria): Create indexed/named property handlers from |operations|. return Interface.IR( - identifier=Identifier(node.GetName()), + identifier=identifier, is_partial=bool(node.GetProperty('PARTIAL')), is_mixin=bool(node.GetProperty('MIXIN')), inherited=inherited, attributes=attributes, constants=constants, + constructors=constructors, operations=operations, stringifier=stringifier, iterable=iterable, @@ -179,8 +189,10 @@ component=self._component, debug_info=self._build_debug_info(node)) - def _build_interface_or_namespace_member( - self, node, fallback_extended_attributes=None): + def _build_interface_or_namespace_member(self, + node, + fallback_extended_attributes=None, + interface_identifier=None): def build_attribute(node): child_nodes = list(node.GetChildren()) idl_type = self._take_type(child_nodes) @@ -214,6 +226,23 @@ component=self._component, debug_info=self._build_debug_info(node)) + def build_constructor(node): + assert interface_identifier is not None + child_nodes = list(node.GetChildren()) + arguments = self._take_arguments(child_nodes) + extended_attributes = self._take_extended_attributes( + child_nodes) or fallback_extended_attributes + assert len(child_nodes) == 0 + return_type = self._idl_type_factory.reference_type( + ref_to_idl_type=self._create_ref_to_idl_type( + interface_identifier)) + return Constructor.IR( + arguments=arguments, + return_type=return_type, + extended_attributes=extended_attributes, + component=self._component, + debug_info=self._build_debug_info(node)) + def build_operation(node): child_nodes = list(node.GetChildren()) arguments = self._take_arguments(child_nodes) @@ -233,6 +262,7 @@ build_functions = { 'Attribute': build_attribute, 'Const': build_constant, + 'Constructor': build_constructor, 'Operation': build_operation, } return build_functions[node.GetClass()](node)
diff --git a/third_party/blink/renderer/controller/blink_initializer.cc b/third_party/blink/renderer/controller/blink_initializer.cc index a537eb7..ac83dad 100644 --- a/third_party/blink/renderer/controller/blink_initializer.cc +++ b/third_party/blink/renderer/controller/blink_initializer.cc
@@ -48,7 +48,6 @@ #include "third_party/blink/renderer/core/animation/animation_clock.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/display_cutout_client_impl.h" -#include "third_party/blink/renderer/core/frame/frame_impl.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/platform/bindings/microtask.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" @@ -196,8 +195,6 @@ } frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating( &DevToolsFrontendImpl::BindMojoRequest, WrapWeakPersistent(&frame))); - frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating( - &FrameImpl::BindToReceiver, WrapWeakPersistent(&frame))); frame.GetInterfaceRegistry()->AddInterface(WTF::BindRepeating( &LocalFrame::PauseSubresourceLoading, WrapWeakPersistent(&frame)));
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index a47c7811..196a7fcd 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -263,6 +263,8 @@ "html/forms/mock_file_chooser.h", "testing/callback_function_test.cc", "testing/callback_function_test.h", + "testing/color_scheme_helper.cc", + "testing/color_scheme_helper.h", "testing/death_aware_script_wrappable.cc", "testing/death_aware_script_wrappable.h", "testing/dictionary_test.cc",
diff --git a/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc b/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc index 4749ee01..405e1b1 100644 --- a/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc +++ b/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc
@@ -8,6 +8,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/html/html_head_element.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" @@ -64,8 +65,9 @@ ScopedCSSColorSchemeForTest css_feature_scope(true); ScopedMetaColorSchemeForTest meta_feature_scope(true); GetDocument().GetSettings()->SetForceDarkModeEnabled(true); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); GetDocument().head()->SetInnerHTMLFromString(R"HTML( <meta name="color-scheme" content="dark"> )HTML");
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc index 5d561f8d..7610fc1 100644 --- a/third_party/blink/renderer/core/animation/animation.cc +++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -505,7 +505,7 @@ // are waiting on a start time will get updated from NotifyStartTime. // Finished animations may not trigger an Update call if finished in the same // frame that they are started. Calling ApplyUpdates for this specific case - // ensures that the finished promise and event are properly triggered. + // ensures the proper propagation of events. AnimationPlayState play_state = CalculateAnimationPlayState(); bool finished = play_state == kFinished; if (pending_pause_ || (pending_play_ && (start_time_ || finished))) { @@ -1151,12 +1151,8 @@ ApplyPendingPlaybackRate(); - if (pending_finish_notification_) - CommitFinishNotification(); - DCHECK(!pending_play_); DCHECK(!pending_pause_); - DCHECK(!pending_finish_notification_); DCHECK(!active_playback_rate_); // TODO(crbug.com/960944): Deprecate.
diff --git a/third_party/blink/renderer/core/animation/animation_test.cc b/third_party/blink/renderer/core/animation/animation_test.cc index 291be88..4aab40ad 100644 --- a/third_party/blink/renderer/core/animation/animation_test.cc +++ b/third_party/blink/renderer/core/animation/animation_test.cc
@@ -52,6 +52,8 @@ #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" +#include "third_party/blink/renderer/platform/bindings/microtask.h" +#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/testing/histogram_tester.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" @@ -189,7 +191,9 @@ SimulateFrame(last_frame_time); } - void SimulateMicrotask() { animation->CommitAllUpdatesForTesting(); } + void SimulateMicrotask() { + Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate()); + } Persistent<DocumentTimeline> timeline; Persistent<Animation> animation;
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index af5cd93..55c500eb 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -103,7 +103,7 @@ } } // namespace -using namespace css_test_helpers; +using css_test_helpers::RegisterProperty; class AnimationCompositorAnimationsTest : public PaintTestConfigurations, public RenderingTest {
diff --git a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc index ad90d4a..1b38fa5a 100644 --- a/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_color_interpolation_type.cc
@@ -18,8 +18,6 @@ namespace blink { -using namespace cssvalue; - enum InterpolableColorIndex : unsigned { kRed, kGreen, @@ -88,7 +86,7 @@ std::unique_ptr<InterpolableValue> CSSColorInterpolationType::MaybeCreateInterpolableColor(const CSSValue& value) { - if (auto* color_value = DynamicTo<CSSColorValue>(value)) + if (auto* color_value = DynamicTo<cssvalue::CSSColorValue>(value)) return CreateInterpolableColor(color_value->Value()); auto* identifier_value = DynamicTo<CSSIdentifierValue>(value); if (!identifier_value) @@ -296,7 +294,7 @@ const StyleResolverState& state) const { const InterpolableList& color_pair = ToInterpolableList(interpolable_value); Color color = ResolveInterpolableColor(*color_pair.Get(kUnvisited), state); - return CSSColorValue::Create(color.Rgb()); + return cssvalue::CSSColorValue::Create(color.Rgb()); } void CSSColorInterpolationType::Composite(
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index 19fd2ee..a363958 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -29,6 +29,8 @@ #include "third_party/blink/renderer/core/css/style_engine.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/platform/web_theme_engine.h" #include "third_party/blink/renderer/core/css/css_default_style_sheets.h" #include "third_party/blink/renderer/core/css/css_font_family_value.h" #include "third_party/blink/renderer/core/css/css_font_selector.h" @@ -101,8 +103,11 @@ viewport_resolver_ = MakeGarbageCollected<ViewportStyleResolver>(document); if (IsMaster()) global_rule_set_ = MakeGarbageCollected<CSSGlobalRuleSet>(); - if (auto* settings = GetDocument().GetSettings()) - preferred_color_scheme_ = settings->GetPreferredColorScheme(); + if (Platform::Current() && Platform::Current()->ThemeEngine()) { + preferred_color_scheme_ = + Platform::Current()->ThemeEngine()->PreferredColorScheme(); + forced_colors_ = Platform::Current()->ThemeEngine()->ForcedColors(); + } } StyleEngine::~StyleEngine() = default; @@ -1928,11 +1933,16 @@ void StyleEngine::UpdateColorScheme() { auto* settings = GetDocument().GetSettings(); - if (!settings) + auto* web_theme_engine = + Platform::Current() ? Platform::Current()->ThemeEngine() : nullptr; + if (!settings || !web_theme_engine) return; + ForcedColors old_forced_colors = forced_colors_; + forced_colors_ = web_theme_engine->ForcedColors(); + PreferredColorScheme old_preferred_color_scheme = preferred_color_scheme_; - preferred_color_scheme_ = settings->GetPreferredColorScheme(); + preferred_color_scheme_ = web_theme_engine->PreferredColorScheme(); if (const auto* overrides = GetDocument().GetPage()->GetMediaFeatureOverrides()) { MediaQueryExpValue value = overrides->GetOverride("prefers-color-scheme"); @@ -1948,7 +1958,8 @@ preferred_color_scheme_ = PreferredColorScheme::kNoPreference; } - if (preferred_color_scheme_ != old_preferred_color_scheme) + if (forced_colors_ != old_forced_colors || + preferred_color_scheme_ != old_preferred_color_scheme) PlatformColorsChanged(); UpdateColorSchemeBackground(); } @@ -1974,7 +1985,7 @@ bool use_dark_background = false; if (preferred_color_scheme_ == PreferredColorScheme::kDark && - !GetDocument().InForcedColorsMode()) { + forced_colors_ != ForcedColors::kActive) { const ComputedStyle* style = nullptr; if (auto* root_element = GetDocument().documentElement()) style = root_element->GetComputedStyle();
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index bbca1d3..2d5bb11 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -33,6 +33,7 @@ #include <memory> #include <utility> #include "base/auto_reset.h" +#include "third_party/blink/public/common/css/forced_colors.h" #include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/renderer/core/core_export.h" @@ -367,6 +368,7 @@ PreferredColorScheme GetPreferredColorScheme() const { return preferred_color_scheme_; } + ForcedColors GetForcedColors() const { return forced_colors_; } void UpdateColorSchemeBackground(); void Trace(blink::Visitor*) override; @@ -571,12 +573,15 @@ // scheme is used to opt-out of forced darkening. Member<const CSSValue> meta_color_scheme_; - // The preferred color scheme is set in settings, but may be overridden by the - // ForceDarkMode setting where the preferred_color_scheme_ will be set to - // kNoPreference to avoid dark styling to be applied before auto darkening. + // The preferred color scheme is set in WebThemeEngine, but may be overridden + // by the ForceDarkMode setting where the preferred_color_scheme_ will be set + // to kNoPreference to avoid dark styling to be applied before auto darkening. PreferredColorScheme preferred_color_scheme_ = PreferredColorScheme::kNoPreference; + // Forced colors is set in WebThemeEngine. + ForcedColors forced_colors_ = ForcedColors::kNone; + friend class NodeTest; friend class StyleEngineTest; friend class WhitespaceAttacherTest;
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 637c3d3..7d01aee 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -36,6 +36,7 @@ #include "third_party/blink/renderer/core/html/html_style_element.h" #include "third_party/blink/renderer/core/layout/layout_text_fragment.h" #include "third_party/blink/renderer/core/page/viewport_description.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/platform/geometry/float_size.h" #include "third_party/blink/renderer/platform/heap/heap.h" @@ -1510,8 +1511,9 @@ GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 128, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( @@ -1522,8 +1524,9 @@ ScopedMediaQueryPrefersColorSchemeForTest feature_scope(true); GetDocument().GetSettings()->SetForceDarkModeEnabled(true); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); GetDocument().body()->SetInnerHTMLFromString(R"HTML( <style> @@ -1588,13 +1591,12 @@ GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); - Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kActive); - GetDocument().PlatformColorsChanged(); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 128, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); - Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kNone); } TEST_F(StyleEngineTest, MediaQueriesChangeForcedColorsAndPreferredColorScheme) { @@ -1624,53 +1626,52 @@ )HTML"); // ForcedColors = kNone, PreferredColorScheme = kLight - Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kNone); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kNone); + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kLight); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(255, 0, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); // ForcedColors = kNone, PreferredColorScheme = kDark - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 128, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); // ForcedColors = kActive, PreferredColorScheme = kDark - Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kActive); - GetDocument().PlatformColorsChanged(); + color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(255, 165, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); // ForcedColors = kActive, PreferredColorScheme = kNoPreference - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kNoPreference); + color_scheme_helper.SetPreferredColorScheme( + GetDocument(), PreferredColorScheme::kNoPreference); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(255, 255, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); // ForcedColors = kActive, PreferredColorScheme = kLight - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kLight); + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kLight); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 0, 255), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); - Platform::Current()->ThemeEngine()->SetForcedColors(ForcedColors::kNone); } TEST_F(StyleEngineTest, MediaQueriesColorSchemeOverride) { ScopedMediaQueryPrefersColorSchemeForTest feature_scope(true); - EXPECT_EQ(PreferredColorScheme::kNoPreference, - GetDocument().GetSettings()->GetPreferredColorScheme()); + EXPECT_EQ(PreferredColorScheme::kLight, + Platform::Current()->ThemeEngine()->PreferredColorScheme()); GetDocument().body()->SetInnerHTMLFromString(R"HTML( <style> @@ -2126,8 +2127,9 @@ TEST_F(StyleEngineTest, ColorSchemeBaseBackgroundChange) { ScopedCSSColorSchemeForTest enable_color_scheme(true); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(Color::kWhite, GetDocument().View()->BaseBackgroundColor()); @@ -2161,8 +2163,9 @@ TEST_F(StyleEngineTest, InternalRootColor) { ScopedCSSColorSchemeForTest enable_color_scheme(true); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); GetDocument().body()->SetInnerHTMLFromString(R"HTML( <style>
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 521652f..9926239 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -8001,7 +8001,6 @@ return; GetStyleEngine().PlatformColorsChanged(); - MediaQueryAffectingValueChanged(); } bool Document::IsSecureContext(String& error_message) const {
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc index 99eebc46..c323ac69 100644 --- a/third_party/blink/renderer/core/dom/document_test.cc +++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/page/validation_message_client.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/heap.h" @@ -1181,8 +1182,9 @@ EXPECT_FALSE(listener->IsNotified()); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); UpdateAllLifecyclePhasesForTest(); GetDocument().ServiceScriptedAnimations(base::TimeTicks());
diff --git a/third_party/blink/renderer/core/exported/web_render_theme.cc b/third_party/blink/renderer/core/exported/web_render_theme.cc index f9c5e80..c11a859 100644 --- a/third_party/blink/renderer/core/exported/web_render_theme.cc +++ b/third_party/blink/renderer/core/exported/web_render_theme.cc
@@ -57,4 +57,8 @@ LayoutTheme::GetTheme().PlatformColorsDidChange(); } +void ColorSchemeChanged() { + LayoutTheme::GetTheme().ColorSchemeDidChange(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.cc b/third_party/blink/renderer/core/exported/web_settings_impl.cc index 61697b65..ef2e399 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.cc +++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc
@@ -778,11 +778,6 @@ settings_->SetForceDarkModeEnabled(enabled); } -void WebSettingsImpl::SetPreferredColorScheme( - PreferredColorScheme color_scheme) { - settings_->SetPreferredColorScheme(color_scheme); -} - void WebSettingsImpl::SetNavigationControls( NavigationControls navigation_controls) { settings_->SetNavigationControls(navigation_controls);
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.h b/third_party/blink/renderer/core/exported/web_settings_impl.h index f902029b..b2cdd82 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.h +++ b/third_party/blink/renderer/core/exported/web_settings_impl.h
@@ -222,7 +222,6 @@ void SetLazyImageFirstKFullyLoad4G(int) override; void SetForceDarkModeEnabled(bool) override; - void SetPreferredColorScheme(PreferredColorScheme) override; void SetNavigationControls(NavigationControls) override; bool RenderVSyncNotificationEnabled() const {
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 3359f86..10b3935 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -118,6 +118,7 @@ #include "third_party/blink/renderer/core/paint/paint_layer_painter.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/scroll/scroll_types.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/fake_web_plugin.h" #include "third_party/blink/renderer/core/timing/dom_window_performance.h" #include "third_party/blink/renderer/core/timing/event_timing.h" @@ -578,8 +579,9 @@ ScopedCSSColorSchemeForTest enable_color_scheme(true); WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->SettingsImpl()->SetPreferredColorScheme( - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(*(web_view->GetPage()), + PreferredColorScheme::kLight); web_view->SetBaseBackgroundColor(SK_ColorBLUE); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); @@ -591,8 +593,8 @@ LocalFrameView* frame_view = web_view->MainFrameImpl()->GetFrame()->View(); EXPECT_EQ(Color(0, 0, 255), frame_view->BaseBackgroundColor()); - web_view->SettingsImpl()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(*(web_view->GetPage()), + PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(Color::kBlack, frame_view->BaseBackgroundColor()); @@ -602,8 +604,8 @@ web_view->SetBaseBackgroundColor(SK_ColorBLUE); EXPECT_EQ(Color::kBlack, frame_view->BaseBackgroundColor()); - web_view->SettingsImpl()->SetPreferredColorScheme( - PreferredColorScheme::kLight); + color_scheme_helper.SetPreferredColorScheme(*(web_view->GetPage()), + PreferredColorScheme::kLight); UpdateAllLifecyclePhases(); EXPECT_EQ(Color(0, 0, 255), frame_view->BaseBackgroundColor()); }
diff --git a/third_party/blink/renderer/core/frame/BUILD.gn b/third_party/blink/renderer/core/frame/BUILD.gn index 882c5152..381effd 100644 --- a/third_party/blink/renderer/core/frame/BUILD.gn +++ b/third_party/blink/renderer/core/frame/BUILD.gn
@@ -63,8 +63,6 @@ "frame_client.h", "frame_console.cc", "frame_console.h", - "frame_impl.cc", - "frame_impl.h", "frame_lifecycle.cc", "frame_lifecycle.h", "frame_overlay.cc",
diff --git a/third_party/blink/renderer/core/frame/frame_impl.cc b/third_party/blink/renderer/core/frame/frame_impl.cc deleted file mode 100644 index 50d773f..0000000 --- a/third_party/blink/renderer/core/frame/frame_impl.cc +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/frame/frame_impl.h" - -#include <utility> - -#include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/core/editing/surrounding_text.h" -#include "third_party/blink/renderer/core/frame/intervention.h" -#include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/platform/heap/persistent.h" -#include "third_party/blink/renderer/platform/wtf/functional.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" - -namespace blink { - -// static -const char FrameImpl::kSupplementName[] = "FrameImpl"; - -// static -void FrameImpl::BindToReceiver( - LocalFrame* frame, - mojo::PendingAssociatedReceiver<mojom::blink::Frame> receiver) { - if (!frame) - return; - frame->ProvideSupplement( - MakeGarbageCollected<FrameImpl>(*frame, std::move(receiver))); -} - -// static -FrameImpl* FrameImpl::From(LocalFrame* frame) { - if (!frame) - return nullptr; - return frame->RequireSupplement<FrameImpl>(); -} - -FrameImpl::FrameImpl( - LocalFrame& frame, - mojo::PendingAssociatedReceiver<mojom::blink::Frame> receiver) - : Supplement<LocalFrame>(frame), - receiver_(this, - std::move(receiver), - frame.GetTaskRunner(blink::TaskType::kInternalDefault)) {} - -FrameImpl::~FrameImpl() = default; - -void FrameImpl::GetTextSurroundingSelection( - uint32_t max_length, - GetTextSurroundingSelectionCallback callback) { - blink::SurroundingText surrounding_text(GetSupplementable(), max_length); - - // |surrounding_text| might not be correctly initialized, for example if - // |frame_->SelectionRange().IsNull()|, in other words, if there was no - // selection. - if (surrounding_text.IsEmpty()) { - // Don't use WTF::String's default constructor so that we make sure that we - // always send a valid empty string over the wire instead of a null pointer. - std::move(callback).Run(g_empty_string, 0, 0); - return; - } - - std::move(callback).Run(surrounding_text.TextContent(), - surrounding_text.StartOffsetInTextContent(), - surrounding_text.EndOffsetInTextContent()); -} - -void FrameImpl::SendInterventionReport(const String& id, - const String& message) { - Intervention::GenerateReport(GetSupplementable(), id, message); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/frame/frame_impl.h b/third_party/blink/renderer/core/frame/frame_impl.h deleted file mode 100644 index 8b8ab63..0000000 --- a/third_party/blink/renderer/core/frame/frame_impl.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_IMPL_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_IMPL_H_ - -#include "mojo/public/cpp/bindings/associated_receiver.h" -#include "mojo/public/cpp/bindings/pending_associated_receiver.h" -#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h" -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/heap/member.h" -#include "third_party/blink/renderer/platform/supplementable.h" - -namespace blink { - -class LocalFrame; - -// Implementation of mojom::blink::Frame -class CORE_EXPORT FrameImpl final : public GarbageCollected<FrameImpl>, - public Supplement<LocalFrame>, - public mojom::blink::Frame { - USING_GARBAGE_COLLECTED_MIXIN(FrameImpl); - - public: - static const char kSupplementName[]; - - static void BindToReceiver( - LocalFrame* frame, - mojo::PendingAssociatedReceiver<mojom::blink::Frame> receiver); - - static FrameImpl* From(LocalFrame* frame); - - explicit FrameImpl( - LocalFrame& frame, - mojo::PendingAssociatedReceiver<mojom::blink::Frame> receiver); - ~FrameImpl() override; - - void GetTextSurroundingSelection( - uint32_t max_length, - GetTextSurroundingSelectionCallback callback) final; - - void SendInterventionReport(const String& id, const String& message) final; - - private: - mojo::AssociatedReceiver<mojom::blink::Frame> receiver_{this}; - - DISALLOW_COPY_AND_ASSIGN(FrameImpl); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_IMPL_H_
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 6665411..b763d49 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -68,12 +68,14 @@ #include "third_party/blink/renderer/core/editing/serializers/serialization.h" #include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h" #include "third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h" +#include "third_party/blink/renderer/core/editing/surrounding_text.h" #include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h" #include "third_party/blink/renderer/core/frame/ad_tracker.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/event_handler_registry.h" #include "third_party/blink/renderer/core/frame/frame_console.h" #include "third_party/blink/renderer/core/frame/frame_overlay.h" +#include "third_party/blink/renderer/core/frame/intervention.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" @@ -150,6 +152,8 @@ GetRemoteNavigationAssociatedInterfaces()->GetInterface( local_frame_host_remote_.BindNewEndpointAndPassReceiver()); + GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating( + &LocalFrame::BindToReceiver, WrapWeakPersistent(this))); loader_.Init(); } @@ -1802,4 +1806,38 @@ return *local_frame_host_remote_.get(); } +void LocalFrame::GetTextSurroundingSelection( + uint32_t max_length, + GetTextSurroundingSelectionCallback callback) { + blink::SurroundingText surrounding_text(this, max_length); + + // |surrounding_text| might not be correctly initialized, for example if + // |frame_->SelectionRange().IsNull()|, in other words, if there was no + // selection. + if (surrounding_text.IsEmpty()) { + // Don't use WTF::String's default constructor so that we make sure that we + // always send a valid empty string over the wire instead of a null pointer. + std::move(callback).Run(g_empty_string, 0, 0); + return; + } + + std::move(callback).Run(surrounding_text.TextContent(), + surrounding_text.StartOffsetInTextContent(), + surrounding_text.EndOffsetInTextContent()); +} + +void LocalFrame::SendInterventionReport(const String& id, + const String& message) { + Intervention::GenerateReport(this, id, message); +} + +void LocalFrame::BindToReceiver( + blink::LocalFrame* frame, + mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver) { + DCHECK(frame); + frame->receiver_.Bind( + std::move(receiver), + frame->GetTaskRunner(blink::TaskType::kInternalDefault)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 808e398..26f10434 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -33,7 +33,9 @@ #include "base/macros.h" #include "base/time/default_tick_clock.h" +#include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" +#include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/unique_receiver_set.h" #include "third_party/blink/public/common/frame/occlusion_state.h" @@ -112,7 +114,8 @@ class CORE_EXPORT LocalFrame final : public Frame, public FrameScheduler::Delegate, - public Supplementable<LocalFrame> { + public Supplementable<LocalFrame>, + public mojom::blink::LocalFrame { USING_GARBAGE_COLLECTED_MIXIN(LocalFrame); public: @@ -307,7 +310,7 @@ // // Navigation-associated interfaces are currently implemented as // channel-associated interfaces. See - // https://chromium.googlesource.com/chromium/src/+/master/ipc#Using-Channel_associated-Interfaces. + // https://chromium.googlesource.com/chromium/src/+/master/docs/mojo_ipc_conversion.md#Channel_Associated-Interfaces AssociatedInterfaceProvider* GetRemoteNavigationAssociatedInterfaces(); LocalFrameClient* Client() const; @@ -453,6 +456,12 @@ void DidChangeVisibleToHitTesting() override; + // blink::mojom::LocalFrame overrides: + void GetTextSurroundingSelection( + uint32_t max_length, + GetTextSurroundingSelectionCallback callback) final; + void SendInterventionReport(const String& id, const String& message) final; + private: friend class FrameNavigationDisabler; @@ -505,6 +514,10 @@ void EvictFromBackForwardCache(); + static void BindToReceiver( + blink::LocalFrame* frame, + mojo::PendingAssociatedReceiver<mojom::blink::LocalFrame> receiver); + std::unique_ptr<FrameScheduler> frame_scheduler_; // Holds all PauseSubresourceLoadingHandles allowing either |this| to delete @@ -589,6 +602,7 @@ base::Optional<mojom::FrameLifecycleState> pending_lifecycle_state_; mojo::AssociatedRemote<mojom::blink::LocalFrameHost> local_frame_host_remote_; + mojo::AssociatedReceiver<mojom::blink::LocalFrame> receiver_{this}; }; inline FrameLoader& LocalFrame::Loader() const {
diff --git a/third_party/blink/renderer/core/frame/settings.h b/third_party/blink/renderer/core/frame/settings.h index fc30f6b..db04f412 100644 --- a/third_party/blink/renderer/core/frame/settings.h +++ b/third_party/blink/renderer/core/frame/settings.h
@@ -32,7 +32,6 @@ #include "base/macros.h" #include "third_party/blink/public/common/css/navigation_controls.h" -#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" #include "third_party/blink/public/platform/pointer_properties.h" #include "third_party/blink/public/platform/web_effective_connection_type.h"
diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5 index 4f8a89ef..8133f308 100644 --- a/third_party/blink/renderer/core/frame/settings.json5 +++ b/third_party/blink/renderer/core/frame/settings.json5
@@ -1055,15 +1055,6 @@ type: "int", }, - // Preferred color scheme from the OS/application passed to the renderer for - // evaluating the prefers-color-scheme media query. - { - name: "preferredColorScheme", - initial: "PreferredColorScheme::kNoPreference", - invalidate: "ColorScheme", - type: "PreferredColorScheme", - }, - // Preferred motion-reduction setting from the OS/application passed to the // renderer for evaluating the prefers-reduced-motion media query. {
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc index 516470158..0a19f7e 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -44,6 +44,7 @@ #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/scroll/scrollbar_theme_overlay.h" #include "third_party/blink/renderer/core/scroll/smooth_scroll_sequencer.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" #include "third_party/blink/renderer/platform/geometry/double_point.h" @@ -2202,10 +2203,6 @@ // Make sure a non-composited background-attachment:fixed background gets // resized by browser controls. TEST_P(VisualViewportTest, ResizeNonCompositedAndFixedBackground) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) return; @@ -2696,7 +2693,9 @@ TEST_F(VisualViewportSimTest, UsedColorSchemeFromRootElement) { ScopedCSSColorSchemeForTest color_scheme_enabled(true); - WebView().GetSettings()->SetPreferredColorScheme(PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(*(WebView().GetPage()), + PreferredColorScheme::kDark); WebView().MainFrameWidget()->Resize(WebSize(400, 600)); const VisualViewport& visual_viewport =
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 247152a..8141b17 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -184,7 +184,6 @@ #include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/frame/find_in_page.h" #include "third_party/blink/renderer/core/frame/frame_console.h" -#include "third_party/blink/renderer/core/frame/frame_impl.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index 3927456..95b60ca1 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -861,7 +861,6 @@ LogUpdateAttributeIfIsolatedWorldAndInDocument("input", params); TextControlElement::ParseAttribute(params); } - input_type_view_->AttributeChanged(); } void HTMLInputElement::ParserDidSetAttributes() {
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.cc b/third_party/blink/renderer/core/html/forms/input_type_view.cc index 4cb696c2..ed41b3c 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.cc +++ b/third_party/blink/renderer/core/html/forms/input_type_view.cc
@@ -144,8 +144,6 @@ void InputTypeView::UpdateView() {} -void InputTypeView::AttributeChanged() {} - void InputTypeView::MultipleAttributeChanged() {} void InputTypeView::DisabledAttributeChanged() {}
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.h b/third_party/blink/renderer/core/html/forms/input_type_view.h index 9da2af76..ef47dea 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.h +++ b/third_party/blink/renderer/core/html/forms/input_type_view.h
@@ -114,7 +114,6 @@ virtual void AltAttributeChanged(); virtual void SrcAttributeChanged(); virtual void UpdateView(); - virtual void AttributeChanged(); virtual void MultipleAttributeChanged(); virtual void DisabledAttributeChanged(); virtual void ReadonlyAttributeChanged();
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc index 816a88d..cd398da 100644 --- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -374,9 +374,7 @@ } } -void TextFieldInputType::AttributeChanged() { - // TODO(crbug.com/1012774): Updating on any attribute update should be - // unnecessary. We should figure out what attributes affect. +void TextFieldInputType::ValueAttributeChanged() { UpdateView(); }
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.h b/third_party/blink/renderer/core/html/forms/text_field_input_type.h index 70c4aa1..595bed48 100644 --- a/third_party/blink/renderer/core/html/forms/text_field_input_type.h +++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.h
@@ -56,7 +56,7 @@ void CreateShadowSubtree() override; void DestroyShadowSubtree() override; - void AttributeChanged() override; + void ValueAttributeChanged() override; void DisabledAttributeChanged() override; void ReadonlyAttributeChanged() override; bool SupportsReadOnly() const override;
diff --git a/third_party/blink/renderer/core/html/html_meta_element_test.cc b/third_party/blink/renderer/core/html/html_meta_element_test.cc index 11fcd11..63bdd6c 100644 --- a/third_party/blink/renderer/core/html/html_meta_element_test.cc +++ b/third_party/blink/renderer/core/html/html_meta_element_test.cc
@@ -15,6 +15,7 @@ #include "third_party/blink/renderer/core/frame/viewport_data.h" #include "third_party/blink/renderer/core/html/html_head_element.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -221,8 +222,9 @@ } TEST_F(HTMLMetaElementTest, ColorSchemeForcedDarkeningAndMQ) { - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); auto* media_query = GetDocument().GetMediaQueryMatcher().MatchMedia( "(prefers-color-scheme: dark)");
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 2108aee..667f66c 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -401,16 +401,6 @@ if (!GetFrameView()) return; - // On low-powered/mobile devices, preventing blitting on a scroll can cause - // noticeable delays when scrolling a page with a fixed background image. As - // an optimization, assuming there are no fixed positoned elements on the - // page, we can acclerate scrolling (via blitting) if we ignore the CSS - // property "background-attachment: fixed". - bool ignore_fixed_background_attachment = - RuntimeEnabledFeatures::FastMobileScrollingEnabled(); - if (ignore_fixed_background_attachment) - return; - SetIsBackgroundAttachmentFixedObject( !BackgroundTransfersToView() && StyleRef().HasFixedAttachmentBackgroundImage());
diff --git a/third_party/blink/renderer/core/layout/layout_theme.cc b/third_party/blink/renderer/core/layout/layout_theme.cc index a453aa7..d48db917 100644 --- a/third_party/blink/renderer/core/layout/layout_theme.cc +++ b/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -656,6 +656,10 @@ Page::PlatformColorsChanged(); } +void LayoutTheme::ColorSchemeDidChange() { + Page::ColorSchemeChanged(); +} + void LayoutTheme::SetCaretBlinkInterval(base::TimeDelta interval) { caret_blink_interval_ = interval; }
diff --git a/third_party/blink/renderer/core/layout/layout_theme.h b/third_party/blink/renderer/core/layout/layout_theme.h index a62bbd3..bd180253 100644 --- a/third_party/blink/renderer/core/layout/layout_theme.h +++ b/third_party/blink/renderer/core/layout/layout_theme.h
@@ -186,6 +186,7 @@ return kDefaultCompositionBackgroundColor; } virtual void PlatformColorsDidChange(); + virtual void ColorSchemeDidChange(); void SetCaretBlinkInterval(base::TimeDelta); virtual base::TimeDelta CaretBlinkInterval() const;
diff --git a/third_party/blink/renderer/core/layout/layout_theme_test.cc b/third_party/blink/renderer/core/layout/layout_theme_test.cc index 6731290..ff7f66b 100644 --- a/third_party/blink/renderer/core/layout/layout_theme_test.cc +++ b/third_party/blink/renderer/core/layout/layout_theme_test.cc
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/core/page/focus_controller.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/platform/graphics/color.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" @@ -119,8 +120,9 @@ initial_style->VisitedDependentColor(GetCSSPropertyColor())); // Change color scheme to dark. - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); UpdateAllLifecyclePhasesForTest(); document_element_style = GetDocument().documentElement()->GetComputedStyle(); @@ -159,8 +161,9 @@ style->VisitedDependentColor(GetCSSPropertyColor())); // Change color scheme to dark. - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); UpdateAllLifecyclePhasesForTest(); style = dark_element->GetComputedStyle();
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc index 72ca0a6..0894ef6c 100644 --- a/third_party/blink/renderer/core/layout/scrollbars_test.cc +++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/scroll/scrollbar_theme_overlay_mock.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" @@ -1478,8 +1479,19 @@ return painted_color_scheme_[part]; } + blink::PreferredColorScheme PreferredColorScheme() const override { + return preferred_color_scheme_; + } + + void SetPreferredColorScheme( + const blink::PreferredColorScheme preferred_color_scheme) override { + preferred_color_scheme_ = preferred_color_scheme; + } + private: std::array<WebColorScheme, kPartProgressBar + 1> painted_color_scheme_; + blink::PreferredColorScheme preferred_color_scheme_ = + blink::PreferredColorScheme::kNoPreference; }; constexpr int StubWebThemeEngine::kMinimumHorizontalLength; @@ -2750,8 +2762,9 @@ </div> )HTML"); - GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(GetDocument(), + PreferredColorScheme::kDark); Compositor().BeginFrame();
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 53bcdbe..37a23f2 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -345,6 +345,15 @@ } } +void Page::ColorSchemeChanged() { + for (const Page* page : AllPages()) + for (Frame* frame = page->MainFrame(); frame; + frame = frame->Tree().TraverseNext()) { + if (auto* local_frame = DynamicTo<LocalFrame>(frame)) + local_frame->GetDocument()->ColorSchemeChanged(); + } +} + void Page::InitialStyleChanged() { for (Frame* frame = MainFrame(); frame; frame = frame->Tree().TraverseNext()) {
diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h index e2106445..f6da631 100644 --- a/third_party/blink/renderer/core/page/page.h +++ b/third_party/blink/renderer/core/page/page.h
@@ -136,6 +136,7 @@ HeapVector<Member<Page>> RelatedPages(); static void PlatformColorsChanged(); + static void ColorSchemeChanged(); void InitialStyleChanged(); void UpdateAcceleratedCompositingSettings();
diff --git a/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc index d003626..84a4e7a 100644 --- a/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/main_thread_scrolling_reasons_test.cc
@@ -105,10 +105,6 @@ TEST_F(MainThreadScrollingReasonsTest, BackgroundAttachmentFixedShouldTriggerMainThreadScroll) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - RegisterMockedHttpURLLoad("iframe-background-attachment-fixed.html"); RegisterMockedHttpURLLoad("iframe-background-attachment-fixed-inner.html"); RegisterMockedHttpURLLoad("white-1x1.png"); @@ -196,10 +192,6 @@ // kHasNonLayerViewportConstrainedObject should be updated on all frames TEST_F(MainThreadScrollingReasonsTest, RecalculateMainThreadScrollingReasonsUponResize) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false); RegisterMockedHttpURLLoad("has-non-layer-viewport-constrained-objects.html"); RegisterMockedHttpURLLoad("white-1x1.png");
diff --git a/third_party/blink/renderer/core/paint/background_image_geometry.cc b/third_party/blink/renderer/core/paint/background_image_geometry.cc index 634297c..0047b92c 100644 --- a/third_party/blink/renderer/core/paint/background_image_geometry.cc +++ b/third_party/blink/renderer/core/paint/background_image_geometry.cc
@@ -375,17 +375,6 @@ namespace { -bool ShouldUseFixedAttachment(const FillLayer& fill_layer) { - if (RuntimeEnabledFeatures::FastMobileScrollingEnabled()) { - // As a side effect of an optimization to blit on scroll, we do not honor - // the CSS property "background-attachment: fixed" because it may result in - // rendering artifacts. Note, these artifacts only appear if we are blitting - // on scroll of a page that has fixed background images. - return false; - } - return fill_layer.Attachment() == EFillAttachment::kFixed; -} - LayoutRect FixedAttachmentPositioningArea(const LayoutBoxModelObject& obj, const LayoutBoxModelObject* container, const GlobalPaintFlags flags) { @@ -653,7 +642,7 @@ LayoutRect& snapped_positioning_area, LayoutPoint& unsnapped_box_offset, LayoutPoint& snapped_box_offset) { - if (ShouldUseFixedAttachment(fill_layer)) { + if (fill_layer.Attachment() == EFillAttachment::kFixed) { // No snapping for fixed attachment. SetHasNonLocalGeometry(); offset_in_background_ = LayoutPoint(); @@ -1040,7 +1029,7 @@ unsnapped_dest_rect_ = snapped_dest_rect_ = LayoutRect(); } - if (ShouldUseFixedAttachment(fill_layer)) + if (fill_layer.Attachment() == EFillAttachment::kFixed) UseFixedAttachment(paint_rect.Location()); // Clip the final output rect to the paint rect, maintaining snapping.
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc index 6766e80e..6a0de25 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
@@ -909,10 +909,6 @@ } TEST_P(PaintLayerScrollableAreaTest, ViewScrollWithFixedAttachmentBackground) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - SetBodyInnerHTML(R"HTML( <style> html, #fixed-background { @@ -930,8 +926,12 @@ <div style="height: 3000px"></div> )HTML"); + EXPECT_EQ(kBackgroundPaintInScrollingContents, + GetLayoutView().GetBackgroundPaintLocation()); auto* fixed_background_div = ToLayoutBox(GetLayoutObjectByElementId("fixed-background")); + EXPECT_EQ(kBackgroundPaintInGraphicsLayer, + fixed_background_div->GetBackgroundPaintLocation()); auto* div_scrollable_area = fixed_background_div->GetScrollableArea(); auto* view_scrollable_area = GetLayoutView().GetScrollableArea(); @@ -958,6 +958,59 @@ EXPECT_TRUE(GetLayoutView().NeedsPaintPropertyUpdate()); } +TEST_P(PaintLayerScrollableAreaTest, + ViewScrollWithFixedAttachmentBackgroundPreferCompositingToLCDText) { + GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled( + true); + SetBodyInnerHTML(R"HTML( + <style> + html, #fixed-background { + background: linear-gradient(black, white) fixed; + } + #fixed-background { + width: 200px; + height: 200px; + overflow: scroll; + } + </style> + <div id="fixed-background"> + <div style="height: 3000px"></div> + </div> + <div style="height: 3000px"></div> + )HTML"); + + EXPECT_EQ(kBackgroundPaintInGraphicsLayer, + GetLayoutView().GetBackgroundPaintLocation()); + auto* fixed_background_div = + ToLayoutBox(GetLayoutObjectByElementId("fixed-background")); + EXPECT_EQ(kBackgroundPaintInGraphicsLayer, + fixed_background_div->GetBackgroundPaintLocation()); + auto* div_scrollable_area = fixed_background_div->GetScrollableArea(); + auto* view_scrollable_area = GetLayoutView().GetScrollableArea(); + + // Programmatically changing the view's scroll offset. Should invalidate all + // objects with fixed attachment background except the layout view. + view_scrollable_area->SetScrollOffset(ScrollOffset(0, 1), + kProgrammaticScroll); + EXPECT_TRUE(fixed_background_div->ShouldDoFullPaintInvalidation()); + EXPECT_TRUE(fixed_background_div->BackgroundNeedsFullPaintInvalidation()); + EXPECT_FALSE(fixed_background_div->NeedsPaintPropertyUpdate()); + EXPECT_FALSE(GetLayoutView().ShouldDoFullPaintInvalidation()); + EXPECT_FALSE(GetLayoutView().BackgroundNeedsFullPaintInvalidation()); + EXPECT_TRUE(GetLayoutView().NeedsPaintPropertyUpdate()); + UpdateAllLifecyclePhasesForTest(); + + // Programmatically changing the div's scroll offset. Should invalidate the + // scrolled div with fixed attachment background. + div_scrollable_area->SetScrollOffset(ScrollOffset(0, 1), kProgrammaticScroll); + EXPECT_TRUE(fixed_background_div->ShouldDoFullPaintInvalidation()); + EXPECT_TRUE(fixed_background_div->BackgroundNeedsFullPaintInvalidation()); + EXPECT_TRUE(fixed_background_div->NeedsPaintPropertyUpdate()); + EXPECT_FALSE(GetLayoutView().ShouldDoFullPaintInvalidation()); + EXPECT_FALSE(GetLayoutView().BackgroundNeedsFullPaintInvalidation()); + EXPECT_TRUE(GetLayoutView().NeedsPaintPropertyUpdate()); +} + TEST_P(PaintLayerScrollableAreaTest, HitTestOverlayScrollbars) { SetBodyInnerHTML(R"HTML( <style>
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index 297d4df..2b207e6 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -4165,10 +4165,6 @@ } TEST_P(PaintPropertyTreeBuilderTest, MainThreadScrollReasonsWithoutScrolling) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - SetBodyInnerHTML(R"HTML( <style> #overflow {
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc index f0f94855..0f47171 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -64,10 +64,6 @@ TEST_P(PaintPropertyTreeUpdateTest, BackgroundAttachmentFixedMainThreadScrollReasonsWithNestedScrollers) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - SetBodyInnerHTML(R"HTML( <style> #overflowA { @@ -151,10 +147,6 @@ } TEST_P(PaintPropertyTreeUpdateTest, ParentFrameMainThreadScrollReasons) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - SetBodyInnerHTML(R"HTML( <style> body { margin: 0; } @@ -191,10 +183,6 @@ } TEST_P(PaintPropertyTreeUpdateTest, ChildFrameMainThreadScrollReasons) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - SetBodyInnerHTML(R"HTML( <style>body { margin: 0; }</style> <iframe></iframe> @@ -234,10 +222,6 @@ TEST_P(PaintPropertyTreeUpdateTest, BackgroundAttachmentFixedMainThreadScrollReasonsWithFixedScroller) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - SetBodyInnerHTML(R"HTML( <style> #overflowA {
diff --git a/third_party/blink/renderer/core/paint/view_painter_test.cc b/third_party/blink/renderer/core/paint/view_painter_test.cc index 19650fd..0b5af6cd 100644 --- a/third_party/blink/renderer/core/paint/view_painter_test.cc +++ b/third_party/blink/renderer/core/paint/view_painter_test.cc
@@ -109,10 +109,6 @@ } TEST_P(ViewPainterTest, DocumentFixedBackgroundLowDPI) { - // This test needs the |FastMobileScrolling| feature to be disabled - // although it is stable on Android. - ScopedFastMobileScrollingForTest fast_mobile_scrolling(false); - RunFixedBackgroundTest(false); }
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc index 9facd9e..b4f0895 100644 --- a/third_party/blink/renderer/core/style/computed_style_test.cc +++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/style/shape_value.h" #include "third_party/blink/renderer/core/style/style_difference.h" #include "third_party/blink/renderer/core/style/style_generated_image.h" +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" @@ -512,8 +513,9 @@ std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr); const ComputedStyle* initial = &ComputedStyle::InitialStyle(); - dummy_page_holder_->GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(dummy_page_holder_->GetDocument(), + PreferredColorScheme::kDark); StyleResolverState state(dummy_page_holder_->GetDocument(), *dummy_page_holder_->GetDocument().documentElement(), initial, initial); @@ -549,8 +551,9 @@ CSSPropertyID::kColor, "-internal-light-dark-color(black, white)", ua_context); - dummy_page_holder_->GetDocument().GetSettings()->SetPreferredColorScheme( - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper; + color_scheme_helper.SetPreferredColorScheme(dummy_page_holder_->GetDocument(), + PreferredColorScheme::kDark); StyleResolverState state(dummy_page_holder_->GetDocument(), *dummy_page_holder_->GetDocument().documentElement(), initial, initial);
diff --git a/third_party/blink/renderer/core/testing/color_scheme_helper.cc b/third_party/blink/renderer/core/testing/color_scheme_helper.cc new file mode 100644 index 0000000..31e49a25 --- /dev/null +++ b/third_party/blink/renderer/core/testing/color_scheme_helper.cc
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/testing/color_scheme_helper.h" + +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/platform/web_theme_engine.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/page/page.h" + +namespace blink { + +ColorSchemeHelper::ColorSchemeHelper() { + DCHECK(Platform::Current() && Platform::Current()->ThemeEngine()); + web_theme_engine_ = Platform::Current()->ThemeEngine(); + default_preferred_color_scheme_ = web_theme_engine_->PreferredColorScheme(); + default_forced_colors_ = web_theme_engine_->ForcedColors(); +} + +ColorSchemeHelper::~ColorSchemeHelper() { + // Reset preferred color scheme and forced colors to their original values. + web_theme_engine_->SetPreferredColorScheme(default_preferred_color_scheme_); + web_theme_engine_->SetForcedColors(default_forced_colors_); +} + +void ColorSchemeHelper::SetPreferredColorScheme( + Document& document, + const PreferredColorScheme preferred_color_scheme) { + web_theme_engine_->SetPreferredColorScheme(preferred_color_scheme); + document.ColorSchemeChanged(); +} + +void ColorSchemeHelper::SetPreferredColorScheme( + Page& page, + const PreferredColorScheme preferred_color_scheme) { + web_theme_engine_->SetPreferredColorScheme(preferred_color_scheme); + page.ColorSchemeChanged(); +} + +void ColorSchemeHelper::SetForcedColors(Document& document, + const ForcedColors forced_colors) { + web_theme_engine_->SetForcedColors(forced_colors); + document.ColorSchemeChanged(); +} + +void ColorSchemeHelper::SetForcedColors(Page& page, + const ForcedColors forced_colors) { + web_theme_engine_->SetForcedColors(forced_colors); + page.ColorSchemeChanged(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/testing/color_scheme_helper.h b/third_party/blink/renderer/core/testing/color_scheme_helper.h new file mode 100644 index 0000000..3059873 --- /dev/null +++ b/third_party/blink/renderer/core/testing/color_scheme_helper.h
@@ -0,0 +1,43 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_COLOR_SCHEME_HELPER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_COLOR_SCHEME_HELPER_H_ + +#include "third_party/blink/public/common/css/forced_colors.h" +#include "third_party/blink/public/common/css/preferred_color_scheme.h" + +namespace blink { + +class Document; +class Page; +class WebThemeEngine; + +// ColorSchemeHelper is used to update the values of PreferredColorScheme and +// ForcedColors for testing. ColorSchemeHelper will reset PreferredColorScheme +// and ForcedColors back to their default values upon deconstruction. +class ColorSchemeHelper { + public: + ColorSchemeHelper(); + ~ColorSchemeHelper(); + + void SetPreferredColorScheme( + Document& document, + const PreferredColorScheme preferred_color_scheme); + void SetPreferredColorScheme( + Page& page, + const PreferredColorScheme preferred_color_scheme); + void SetForcedColors(Document& document, const ForcedColors forced_colors); + void SetForcedColors(Page& page, const ForcedColors forced_colors); + + private: + WebThemeEngine* web_theme_engine_ = nullptr; + PreferredColorScheme default_preferred_color_scheme_ = + PreferredColorScheme::kNoPreference; + ForcedColors default_forced_colors_ = ForcedColors::kNone; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_COLOR_SCHEME_HELPER_H_
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc index f7abdf58..d57909f 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -22,6 +22,15 @@ void FakeLocalFrameHost::FullscreenStateChanged(bool is_fullscreen) {} +void FakeLocalFrameHost::RegisterProtocolHandler(const WTF::String& scheme, + const ::blink::KURL& url, + const ::WTF::String& title, + bool user_gesture) {} + +void FakeLocalFrameHost::UnregisterProtocolHandler(const WTF::String& scheme, + const ::blink::KURL& url, + bool user_gesture) {} + void FakeLocalFrameHost::BindFrameHostReceiver( mojo::ScopedInterfaceEndpointHandle handle) { receiver_.Bind(mojo::PendingAssociatedReceiver<mojom::blink::LocalFrameHost>(
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/third_party/blink/renderer/core/testing/fake_local_frame_host.h index d3bf0d0d..d308bf3 100644 --- a/third_party/blink/renderer/core/testing/fake_local_frame_host.h +++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -24,6 +24,13 @@ void EnterFullscreen(mojom::blink::FullscreenOptionsPtr options) override; void ExitFullscreen() override; void FullscreenStateChanged(bool is_fullscreen) override; + void RegisterProtocolHandler(const WTF::String& scheme, + const ::blink::KURL& url, + const ::WTF::String& title, + bool user_gesture) override; + void UnregisterProtocolHandler(const WTF::String& scheme, + const ::blink::KURL& url, + bool user_gesture) override; private: void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc index 8755a6e4..f237419 100644 --- a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc +++ b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc
@@ -136,10 +136,8 @@ NavigatorContentUtils* navigator_content_utils = Supplement<Navigator>::From<NavigatorContentUtils>(navigator); if (!navigator_content_utils) { - WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(&frame); navigator_content_utils = MakeGarbageCollected<NavigatorContentUtils>( - navigator, - MakeGarbageCollected<NavigatorContentUtilsClient>(web_frame)); + navigator, MakeGarbageCollected<NavigatorContentUtilsClient>(&frame)); ProvideTo(navigator, navigator_content_utils); } return *navigator_content_utils;
diff --git a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc index 6731062..cd766f6 100644 --- a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc +++ b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc
@@ -4,30 +4,32 @@ #include "third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h" -#include "third_party/blink/public/web/web_local_frame_client.h" -#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" namespace blink { -NavigatorContentUtilsClient::NavigatorContentUtilsClient( - WebLocalFrameImpl* web_frame) - : web_frame_(web_frame) {} +NavigatorContentUtilsClient::NavigatorContentUtilsClient(LocalFrame* frame) + : frame_(frame) {} void NavigatorContentUtilsClient::Trace(blink::Visitor* visitor) { - visitor->Trace(web_frame_); + visitor->Trace(frame_); } void NavigatorContentUtilsClient::RegisterProtocolHandler(const String& scheme, const KURL& url, const String& title) { - web_frame_->Client()->RegisterProtocolHandler(scheme, url, title); + bool user_gesture = LocalFrame::HasTransientUserActivation(frame_, false); + frame_->GetLocalFrameHostRemote().RegisterProtocolHandler(scheme, url, title, + user_gesture); } void NavigatorContentUtilsClient::UnregisterProtocolHandler( const String& scheme, const KURL& url) { - web_frame_->Client()->UnregisterProtocolHandler(scheme, url); + bool user_gesture = LocalFrame::HasTransientUserActivation(frame_, false); + frame_->GetLocalFrameHostRemote().UnregisterProtocolHandler(scheme, url, + user_gesture); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h index 0f299809..ac034c0 100644 --- a/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h +++ b/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h
@@ -12,12 +12,12 @@ namespace blink { class KURL; -class WebLocalFrameImpl; +class LocalFrame; class MODULES_EXPORT NavigatorContentUtilsClient : public GarbageCollected<NavigatorContentUtilsClient> { public: - explicit NavigatorContentUtilsClient(WebLocalFrameImpl*); + explicit NavigatorContentUtilsClient(LocalFrame*); virtual ~NavigatorContentUtilsClient() = default; virtual void RegisterProtocolHandler(const String& scheme, @@ -29,7 +29,7 @@ virtual void Trace(blink::Visitor*); private: - Member<WebLocalFrameImpl> web_frame_; + Member<LocalFrame> frame_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/third_party/blink/renderer/modules/peerconnection/BUILD.gn index dd58e136..a336e832 100644 --- a/third_party/blink/renderer/modules/peerconnection/BUILD.gn +++ b/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -151,7 +151,8 @@ "mock_peer_connection_dependency_factory.cc", "mock_peer_connection_impl.cc", "mock_web_rtc_peer_connection_handler_client.cc", - "webrtc_stats_report_obtainer.cc", + "test_webrtc_stats_report_obtainer.cc", + "test_webrtc_stats_report_obtainer.h", ] deps = [
diff --git a/third_party/blink/renderer/modules/peerconnection/DEPS b/third_party/blink/renderer/modules/peerconnection/DEPS index c0f90696..420338e 100644 --- a/third_party/blink/renderer/modules/peerconnection/DEPS +++ b/third_party/blink/renderer/modules/peerconnection/DEPS
@@ -21,7 +21,7 @@ ] specific_include_rules = { - ".*test\.cc" : [ + ".*test.*": [ "+base/run_loop.h", "+base/test/bind_test_util.h", "+base/test/test_timeouts.h",
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc index c0bba3eb..ae44df44 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl_test.cc
@@ -19,8 +19,8 @@ #include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h" #include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h" #include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h" -#include "third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h" #include "third_party/blink/public/web/web_heap.h" +#include "third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.h" #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" #include "third_party/webrtc/api/stats/rtc_stats_report.h" #include "third_party/webrtc/api/stats/rtcstats_objects.h" @@ -80,9 +80,9 @@ std::move(state)); } - scoped_refptr<blink::WebRTCStatsReportObtainer> GetStats() { - scoped_refptr<blink::WebRTCStatsReportObtainer> obtainer = - new blink::WebRTCStatsReportObtainer(); + scoped_refptr<blink::TestWebRTCStatsReportObtainer> GetStats() { + scoped_refptr<blink::TestWebRTCStatsReportObtainer> obtainer = + base::MakeRefCounted<TestWebRTCStatsReportObtainer>(); receiver_->GetStats(obtainer->GetStatsCallbackWrapper(), {}); return obtainer; }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc index e2f91b3..2255495 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl_test.cc
@@ -22,8 +22,8 @@ #include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_dependency_factory.h" #include "third_party/blink/public/web/modules/peerconnection/mock_peer_connection_impl.h" #include "third_party/blink/public/web/modules/peerconnection/webrtc_media_stream_track_adapter_map.h" -#include "third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h" #include "third_party/blink/public/web/web_heap.h" +#include "third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.h" #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" #include "third_party/webrtc/api/stats/rtc_stats_report.h" #include "third_party/webrtc/api/stats/rtcstats_objects.h" @@ -118,9 +118,9 @@ std::move(run_loop)); } - scoped_refptr<blink::WebRTCStatsReportObtainer> CallGetStats() { - scoped_refptr<blink::WebRTCStatsReportObtainer> obtainer = - new blink::WebRTCStatsReportObtainer(); + scoped_refptr<blink::TestWebRTCStatsReportObtainer> CallGetStats() { + scoped_refptr<blink::TestWebRTCStatsReportObtainer> obtainer = + base::MakeRefCounted<TestWebRTCStatsReportObtainer>(); sender_->GetStats(obtainer->GetStatsCallbackWrapper(), {}); return obtainer; }
diff --git a/third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.cc b/third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.cc new file mode 100644 index 0000000..ba2848d --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.cc
@@ -0,0 +1,36 @@ +// Copyright (c) 2017 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/modules/peerconnection/test_webrtc_stats_report_obtainer.h" + +#include "base/bind.h" +#include "base/callback.h" + +namespace blink { + +TestWebRTCStatsReportObtainer::TestWebRTCStatsReportObtainer() {} + +TestWebRTCStatsReportObtainer::~TestWebRTCStatsReportObtainer() {} + +blink::WebRTCStatsReportCallback +TestWebRTCStatsReportObtainer::GetStatsCallbackWrapper() { + return base::BindOnce(&TestWebRTCStatsReportObtainer::OnStatsDelivered, this); +} + +blink::WebRTCStatsReport* TestWebRTCStatsReportObtainer::report() const { + return report_.get(); +} + +blink::WebRTCStatsReport* TestWebRTCStatsReportObtainer::WaitForReport() { + run_loop_.Run(); + return report_.get(); +} + +void TestWebRTCStatsReportObtainer::OnStatsDelivered( + std::unique_ptr<blink::WebRTCStatsReport> report) { + report_ = std::move(report); + run_loop_.Quit(); +} + +} // namespace blink
diff --git a/third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h b/third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.h similarity index 64% rename from third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h rename to third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.h index db742376..affd519 100644 --- a/third_party/blink/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h +++ b/third_party/blink/renderer/modules/peerconnection/test_webrtc_stats_report_obtainer.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_STATS_REPORT_OBTAINER_H_ -#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_STATS_REPORT_OBTAINER_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_TEST_WEBRTC_STATS_REPORT_OBTAINER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_TEST_WEBRTC_STATS_REPORT_OBTAINER_H_ #include <memory> -#include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "third_party/blink/public/platform/web_rtc_stats.h" +#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" namespace blink { @@ -20,13 +20,10 @@ // thread are executed (see base::RunLoop::Run()) making it safe to wait on the // same thread that the stats report callback occurs on without blocking the // callback. -// -// TODO(crbug.com/787254): Move this class out of the Blink API -// when all its clients get Onion souped. -class WebRTCStatsReportObtainer - : public base::RefCountedThreadSafe<WebRTCStatsReportObtainer> { +class TestWebRTCStatsReportObtainer + : public WTF::ThreadSafeRefCounted<TestWebRTCStatsReportObtainer> { public: - WebRTCStatsReportObtainer(); + TestWebRTCStatsReportObtainer(); blink::WebRTCStatsReportCallback GetStatsCallbackWrapper(); @@ -34,9 +31,9 @@ blink::WebRTCStatsReport* WaitForReport(); private: - friend class base::RefCountedThreadSafe<WebRTCStatsReportObtainer>; + friend class WTF::ThreadSafeRefCounted<TestWebRTCStatsReportObtainer>; friend class CallbackWrapper; - virtual ~WebRTCStatsReportObtainer(); + virtual ~TestWebRTCStatsReportObtainer(); void OnStatsDelivered(std::unique_ptr<blink::WebRTCStatsReport> report); @@ -46,4 +43,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_PEERCONNECTION_WEBRTC_STATS_REPORT_OBTAINER_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_TEST_WEBRTC_STATS_REPORT_OBTAINER_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/webrtc_stats_report_obtainer.cc b/third_party/blink/renderer/modules/peerconnection/webrtc_stats_report_obtainer.cc deleted file mode 100644 index f27836d..0000000 --- a/third_party/blink/renderer/modules/peerconnection/webrtc_stats_report_obtainer.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2017 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/public/web/modules/peerconnection/webrtc_stats_report_obtainer.h" - -#include "base/bind.h" -#include "base/callback.h" - -namespace blink { - -WebRTCStatsReportObtainer::WebRTCStatsReportObtainer() {} - -WebRTCStatsReportObtainer::~WebRTCStatsReportObtainer() {} - -blink::WebRTCStatsReportCallback -WebRTCStatsReportObtainer::GetStatsCallbackWrapper() { - return base::BindOnce(&WebRTCStatsReportObtainer::OnStatsDelivered, this); -} - -blink::WebRTCStatsReport* WebRTCStatsReportObtainer::report() const { - return report_.get(); -} - -blink::WebRTCStatsReport* WebRTCStatsReportObtainer::WaitForReport() { - run_loop_.Run(); - return report_.get(); -} - -void WebRTCStatsReportObtainer::OnStatsDelivered( - std::unique_ptr<blink::WebRTCStatsReport> report) { - report_ = std::move(report); - run_loop_.Quit(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index bbeca4e..ca1b6e89 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -192,10 +192,6 @@ RuntimeEnabledFeatures::SetFallbackCursorModeEnabled(enable); } -void WebRuntimeFeatures::EnableFastMobileScrolling(bool enable) { - RuntimeEnabledFeatures::SetFastMobileScrollingEnabled(enable); -} - void WebRuntimeFeatures::EnableFeaturePolicyForSandbox(bool enable) { RuntimeEnabledFeatures::SetFeaturePolicyForSandboxEnabled(enable); } @@ -296,6 +292,10 @@ RuntimeEnabledFeatures::SetNetInfoDownlinkMaxEnabled(enable); } +void WebRuntimeFeatures::EnableNeverSlowMode(bool enable) { + RuntimeEnabledFeatures::SetNeverSlowModeEnabled(enable); +} + void WebRuntimeFeatures::EnableOnDeviceChange(bool enable) { RuntimeEnabledFeatures::SetOnDeviceChangeEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/heap/heap.cc b/third_party/blink/renderer/platform/heap/heap.cc index 02abf6859..ac57a2b 100644 --- a/third_party/blink/renderer/platform/heap/heap.cc +++ b/third_party/blink/renderer/platform/heap/heap.cc
@@ -98,13 +98,6 @@ address_cache_(std::make_unique<AddressCache>()), free_page_pool_(std::make_unique<PagePool>()), process_heap_reporter_(std::make_unique<ProcessHeapReporter>()), - marking_worklist_(nullptr), - not_fully_constructed_worklist_(nullptr), - weak_callback_worklist_(nullptr), - movable_reference_worklist_(nullptr), - weak_table_worklist_(nullptr), - backing_store_callback_worklist_(nullptr), - v8_references_worklist_(nullptr), vector_backing_arena_index_(BlinkGC::kVector1ArenaIndex), current_arena_ages_(0) { if (ThreadState::Current()->IsMainThread()) @@ -158,6 +151,7 @@ void ThreadHeap::SetupWorklists() { marking_worklist_.reset(new MarkingWorklist()); + write_barrier_worklist_.reset(new WriteBarrierWorklist()); not_fully_constructed_worklist_.reset(new NotFullyConstructedWorklist()); previously_not_fully_constructed_worklist_.reset( new NotFullyConstructedWorklist()); @@ -171,6 +165,7 @@ void ThreadHeap::DestroyMarkingWorklists(BlinkGC::StackState stack_state) { marking_worklist_.reset(nullptr); + write_barrier_worklist_.reset(nullptr); previously_not_fully_constructed_worklist_.reset(nullptr); weak_callback_worklist_.reset(nullptr); weak_table_worklist_.reset(); @@ -326,6 +321,18 @@ if (!finished) break; + finished = DrainWorklistWithDeadline( + deadline, write_barrier_worklist_.get(), + [visitor](HeapObjectHeader* header) { + DCHECK(!header->IsInConstruction()); + GCInfoTable::Get() + .GCInfoFromIndex(header->GcInfoIndex()) + ->trace(visitor, header->Payload()); + }, + WorklistTaskId::MutatorThread); + if (!finished) + break; + // Iteratively mark all objects that were previously discovered while // being in construction. The objects can be processed incrementally once // a safepoint was reached. @@ -351,17 +358,29 @@ bool ThreadHeap::AdvanceConcurrentMarking(ConcurrentMarkingVisitor* visitor, base::TimeTicks deadline) { + bool finished = false; // Iteratively mark all objects that are reachable from the objects // currently pushed onto the marking worklist. - return DrainWorklistWithDeadline( + finished = DrainWorklistWithDeadline( deadline, marking_worklist_.get(), [visitor](const MarkingItem& item) { - DCHECK( - !HeapObjectHeader::FromPayload(item.object) - ->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()); + DCHECK(!HeapObjectHeader::FromPayload(item.object)->IsInConstruction()); item.callback(visitor, item.object); }, visitor->task_id()); + if (!finished) + return false; + + finished = DrainWorklistWithDeadline( + deadline, write_barrier_worklist_.get(), + [visitor](HeapObjectHeader* header) { + DCHECK(!header->IsInConstruction()); + GCInfoTable::Get() + .GCInfoFromIndex(header->GcInfoIndex()) + ->trace(visitor, header->Payload()); + }, + visitor->task_id()); + return finished; } void ThreadHeap::WeakProcessing(MarkingVisitor* visitor) {
diff --git a/third_party/blink/renderer/platform/heap/heap.h b/third_party/blink/renderer/platform/heap/heap.h index fd05b97..d624dd1 100644 --- a/third_party/blink/renderer/platform/heap/heap.h +++ b/third_party/blink/renderer/platform/heap/heap.h
@@ -82,6 +82,7 @@ // Segment size of 512 entries necessary to avoid throughput regressions. Since // the work list is currently a temporary object this is not a problem. using MarkingWorklist = Worklist<MarkingItem, 512 /* local entries */>; +using WriteBarrierWorklist = Worklist<HeapObjectHeader*, 256>; using NotFullyConstructedWorklist = Worklist<NotFullyConstructedItem, 16 /* local entries */>; using WeakCallbackWorklist = @@ -227,6 +228,10 @@ return marking_worklist_.get(); } + WriteBarrierWorklist* GetWriteBarrierWorklist() const { + return write_barrier_worklist_.get(); + } + NotFullyConstructedWorklist* GetNotFullyConstructedWorklist() const { return not_fully_constructed_worklist_.get(); } @@ -438,6 +443,11 @@ // contain almost all objects. std::unique_ptr<MarkingWorklist> marking_worklist_; + // Objects on this worklist have been collected in the write barrier. The + // worklist is different from |marking_worklist_| to minimize execution in the + // path where a write barrier is executed. + std::unique_ptr<WriteBarrierWorklist> write_barrier_worklist_; + // Objects on this worklist were observed to be in construction (in their // constructor) and thus have been delayed for processing. They have not yet // been assigned a valid header and trace callback. @@ -524,11 +534,6 @@ template <typename Derived> static void* AllocateObject(size_t size) { - if (IsGarbageCollectedMixin<T>::value) { - // Ban large mixin so we can use PageFromObject() on them. - CHECK_GE(kLargeObjectSizeThreshold, size) - << "GarbageCollectedMixin may not be a large object"; - } return ThreadHeap::Allocate<GCInfoFoldedType<Derived>>(size); } @@ -577,7 +582,10 @@ internal::IsGarbageCollectedContainer<T>::value || internal::HasFinalizeGarbageCollectedObject<T>::value, "Finalized GarbageCollected class should either have a virtual " - "destructor or be marked as final."); + "destructor or be marked as final"); + static_assert(!IsGarbageCollectedMixin<T>::value || + sizeof(T) <= kLargeObjectSizeThreshold, + "GarbageCollectedMixin may not be a large object"); void* memory = T::template AllocateObject<T>(sizeof(T)); HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory); // Placement new as regular operator new() is deleted. @@ -605,8 +613,13 @@ internal::HasFinalizeGarbageCollectedObject<T>::value, "Finalized GarbageCollected class should either have a virtual " "destructor or be marked as final."); - void* memory = - T::template AllocateObject<T>(sizeof(T) + additional_bytes.value); + const size_t size = sizeof(T) + additional_bytes.value; + if (IsGarbageCollectedMixin<T>::value) { + // Ban large mixin so we can use PageFromObject() on them. + CHECK_GE(kLargeObjectSizeThreshold, size) + << "GarbageCollectedMixin may not be a large object"; + } + void* memory = T::template AllocateObject<T>(size); HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory); // Placement new as regular operator new() is deleted. T* object = ::new (memory) T(std::forward<Args>(args)...);
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc index 478fac4e..f7cf5fe8 100644 --- a/third_party/blink/renderer/platform/heap/heap_test.cc +++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -1660,7 +1660,7 @@ }; TEST(HeapDeathTest, LargeGarbageCollectedMixin) { - EXPECT_DEATH(MakeGarbageCollected<LargeMixin>(), ""); + EXPECT_DEATH(MakeGarbageCollected<LargeMixin>(AdditionalBytes(1)), ""); } TEST_F(HeapTest, Transition) {
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc index e30bbba..22f6957 100644 --- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc +++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -111,12 +111,14 @@ : IncrementalMarkingScopeBase(thread_state), gc_forbidden_scope_(thread_state), marking_worklist_(heap_.GetMarkingWorklist()), + write_barrier_worklist_(heap_.GetWriteBarrierWorklist()), not_fully_constructed_worklist_( heap_.GetNotFullyConstructedWorklist()) { thread_state_->SetGCPhase(ThreadState::GCPhase::kMarking); ThreadState::AtomicPauseScope atomic_pause_scope_(thread_state_); ScriptForbiddenScope script_forbidden_scope; EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); + EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); EXPECT_TRUE(not_fully_constructed_worklist_->IsGlobalEmpty()); thread_state->EnableIncrementalMarkingBarrier(); thread_state->current_gc_data_.visitor = std::make_unique<MarkingVisitor>( @@ -125,6 +127,7 @@ ~IncrementalMarkingScope() { EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); + EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); EXPECT_TRUE(not_fully_constructed_worklist_->IsGlobalEmpty()); thread_state_->DisableIncrementalMarkingBarrier(); // Need to clear out unused worklists that might have been polluted during @@ -135,6 +138,9 @@ } MarkingWorklist* marking_worklist() const { return marking_worklist_; } + WriteBarrierWorklist* write_barrier_worklist() const { + return write_barrier_worklist_; + } NotFullyConstructedWorklist* not_fully_constructed_worklist() const { return not_fully_constructed_worklist_; } @@ -142,6 +148,7 @@ protected: ThreadState::GCForbiddenScope gc_forbidden_scope_; MarkingWorklist* const marking_worklist_; + WriteBarrierWorklist* const write_barrier_worklist_; NotFullyConstructedWorklist* const not_fully_constructed_worklist_; }; @@ -156,6 +163,7 @@ objects_(objects), backing_visitor_(thread_state_, &objects_) { EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); + EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); for (void* object : objects_) { // Ensure that the object is in the normal arena so we can ignore backing // objects on the marking stack. @@ -168,9 +176,8 @@ } ~ExpectWriteBarrierFires() { - EXPECT_FALSE(marking_worklist_->IsGlobalEmpty()); + // All objects watched should be on the marking or write barrier worklist. MarkingItem item; - // All objects watched should be on the marking stack. while (marking_worklist_->Pop(WorklistTaskId::MutatorThread, &item)) { // Inspect backing stores to allow specifying objects that are only // reachable through a backing store. @@ -184,6 +191,21 @@ if (objects_.end() != pos) objects_.erase(pos); } + HeapObjectHeader* header; + while ( + write_barrier_worklist_->Pop(WorklistTaskId::MutatorThread, &header)) { + // Inspect backing stores to allow specifying objects that are only + // reachable through a backing store. + if (!ThreadHeap::IsNormalArenaIndex( + PageFromObject(header->Payload())->Arena()->ArenaIndex())) { + backing_visitor_.ProcessBackingStore(header); + continue; + } + auto** pos = + std::find(objects_.begin(), objects_.end(), header->Payload()); + if (objects_.end() != pos) + objects_.erase(pos); + } EXPECT_TRUE(objects_.IsEmpty()); // All headers of objects watched should be marked at this point. for (HeapObjectHeader* header : headers_) { @@ -191,6 +213,7 @@ header->Unmark(); } EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); + EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); } private: @@ -208,6 +231,7 @@ std::initializer_list<void*> objects) : IncrementalMarkingScope(thread_state) { EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); + EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); for (void* object : objects_) { HeapObjectHeader* header = HeapObjectHeader::FromPayload(object); headers_.push_back(std::make_pair(header, header->IsMarked())); @@ -216,6 +240,7 @@ ~ExpectNoWriteBarrierFires() { EXPECT_TRUE(marking_worklist_->IsGlobalEmpty()); + EXPECT_TRUE(write_barrier_worklist_->IsGlobalEmpty()); for (const auto& pair : headers_) { EXPECT_EQ(pair.second, pair.first->IsMarked()); pair.first->Unmark(); @@ -1442,7 +1467,6 @@ // Clear any objects that have been added to the regular marking worklist in // the process of calling the constructor. - EXPECT_FALSE(scope.marking_worklist()->IsGlobalEmpty()); MarkingItem marking_item; while (scope.marking_worklist()->Pop(WorklistTaskId::MutatorThread, &marking_item)) { @@ -1452,6 +1476,14 @@ header->Unmark(); } EXPECT_TRUE(scope.marking_worklist()->IsGlobalEmpty()); + // Clear any write barriers so far. + HeapObjectHeader* header; + while (scope.write_barrier_worklist()->Pop(WorklistTaskId::MutatorThread, + &header)) { + if (header->IsMarked()) + header->Unmark(); + } + EXPECT_TRUE(scope.write_barrier_worklist()->IsGlobalEmpty()); EXPECT_FALSE(scope.not_fully_constructed_worklist()->IsGlobalEmpty()); NotFullyConstructedItem partial_item;
diff --git a/third_party/blink/renderer/platform/heap/marking_visitor.cc b/third_party/blink/renderer/platform/heap/marking_visitor.cc index f789e3a..868640f6 100644 --- a/third_party/blink/renderer/platform/heap/marking_visitor.cc +++ b/third_party/blink/renderer/platform/heap/marking_visitor.cc
@@ -95,12 +95,16 @@ return false; HeapObjectHeader* header; + size_t size; if (LIKELY(!base_page->IsLargeObjectPage())) { header = reinterpret_cast<HeapObjectHeader*>( static_cast<NormalPage*>(base_page)->FindHeaderFromAddress( reinterpret_cast<Address>(value))); + size = header->size(); } else { - header = static_cast<LargeObjectPage*>(base_page)->ObjectHeader(); + LargeObjectPage* large_page = static_cast<LargeObjectPage*>(base_page); + header = large_page->ObjectHeader(); + size = large_page->size(); } DCHECK(header->IsValid()); @@ -117,10 +121,8 @@ } MarkingVisitor* visitor = thread_state->CurrentVisitor(); - visitor->AccountMarkedBytes(header); - visitor->marking_worklist_.Push( - {header->Payload(), - GCInfoTable::Get().GCInfoFromIndex(header->GcInfoIndex())->trace}); + visitor->AccountMarkedBytes(size); + visitor->write_barrier_worklist_.Push(header); return true; } @@ -144,7 +146,9 @@ } MarkingVisitor::MarkingVisitor(ThreadState* state, MarkingMode marking_mode) - : MarkingVisitorBase(state, marking_mode, WorklistTaskId::MutatorThread) { + : MarkingVisitorBase(state, marking_mode, WorklistTaskId::MutatorThread), + write_barrier_worklist_(Heap().GetWriteBarrierWorklist(), + WorklistTaskId::MutatorThread) { DCHECK(state->InAtomicMarkingPause()); DCHECK(state->CheckThread()); }
diff --git a/third_party/blink/renderer/platform/heap/marking_visitor.h b/third_party/blink/renderer/platform/heap/marking_visitor.h index a75facec..d5ad0d8 100644 --- a/third_party/blink/renderer/platform/heap/marking_visitor.h +++ b/third_party/blink/renderer/platform/heap/marking_visitor.h
@@ -125,9 +125,9 @@ // marked upon calling. inline bool MarkHeaderNoTracing(HeapObjectHeader*); - // Account for an object's live bytes. Should only be adjusted when + // Account for |size| live bytes. Should only be adjusted when // transitioning an object from unmarked to marked state. - ALWAYS_INLINE void AccountMarkedBytes(HeapObjectHeader*); + ALWAYS_INLINE void AccountMarkedBytes(size_t size); void RegisterBackingStoreReference(void** slot); @@ -142,12 +142,8 @@ int task_id_; }; -ALWAYS_INLINE void MarkingVisitorBase::AccountMarkedBytes( - HeapObjectHeader* header) { - marked_bytes_ += - header->IsLargeObject() - ? reinterpret_cast<LargeObjectPage*>(PageFromObject(header))->size() - : header->size(); +ALWAYS_INLINE void MarkingVisitorBase::AccountMarkedBytes(size_t size) { + marked_bytes_ += size; } inline bool MarkingVisitorBase::MarkHeaderNoTracing(HeapObjectHeader* header) { @@ -161,7 +157,11 @@ DCHECK(!header->IsFree()); if (header->TryMark<HeapObjectHeader::AccessMode::kAtomic>()) { - AccountMarkedBytes(header); + const size_t size = + header->IsLargeObject() + ? reinterpret_cast<LargeObjectPage*>(PageFromObject(header))->size() + : header->size(); + AccountMarkedBytes(size); return true; } return false; @@ -216,6 +216,8 @@ // Exact version of the marking write barriers. static bool WriteBarrierSlow(void*); static void TraceMarkedBackingStoreSlow(void*); + + WriteBarrierWorklist::View write_barrier_worklist_; }; ALWAYS_INLINE bool MarkingVisitor::WriteBarrier(void* value) {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index da9b3b1..a1047d8 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -651,10 +651,6 @@ status: "experimental", }, { - name: "FastMobileScrolling", - status: {"Android": "stable"}, - }, - { name: "FeaturePolicyForClientHints", status: "experimental", }, @@ -1087,6 +1083,9 @@ // Only Android, ChromeOS support NetInfo downlinkMax, type and ontypechange now status: {"Android": "stable", "ChromeOS": "stable"}, }, + { + name: "NeverSlowMode", + }, // Not a web exposed feature, enabled from the command line. { name: "NewRemotePlaybackPipeline",
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc index c751d9c..ef55b44 100644 --- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc +++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
@@ -41,7 +41,7 @@ DCHECK(sequence_manager_); sequence_manager_->SetDefaultTaskRunner(default_task_runner_); - simple_task_executor_.emplace(default_task_runner_); + blink_task_executor_.emplace(default_task_runner_, sequence_manager_); } SchedulerHelper::~SchedulerHelper() { @@ -182,5 +182,18 @@ return false; } +SchedulerHelper::BlinkTaskExecutor::BlinkTaskExecutor( + scoped_refptr<base::SingleThreadTaskRunner> default_task_queue, + base::sequence_manager::SequenceManager* sequence_manager) + : base::SimpleTaskExecutor(sequence_manager, std::move(default_task_queue)), + sequence_manager_(sequence_manager) {} + +SchedulerHelper::BlinkTaskExecutor::~BlinkTaskExecutor() = default; + +const scoped_refptr<base::SequencedTaskRunner>& +SchedulerHelper::BlinkTaskExecutor::GetContinuationTaskRunner() { + return sequence_manager_->GetTaskRunnerForCurrentTask(); +} + } // namespace scheduler } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h index 3f2267e..52b84746 100644 --- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h +++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
@@ -130,12 +130,29 @@ private: friend class SchedulerHelperTest; + // Like SimpleTaskExecutor except it knows how to get the current task runner + // from the SequenceManager to implement GetContinuationTaskRunner. + class BlinkTaskExecutor : public base::SimpleTaskExecutor { + public: + BlinkTaskExecutor( + scoped_refptr<base::SingleThreadTaskRunner> default_task_queue, + base::sequence_manager::SequenceManager* sequence_manager); + + ~BlinkTaskExecutor() override; + + // base::TaskExecutor implementation. + const scoped_refptr<base::SequencedTaskRunner>& GetContinuationTaskRunner() + override; + + private: + base::sequence_manager::SequenceManager* sequence_manager_; // NOT OWNED + }; scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; Observer* observer_; // NOT OWNED UkmTaskSampler ukm_task_sampler_; - base::Optional<base::SimpleTaskExecutor> simple_task_executor_; + base::Optional<BlinkTaskExecutor> blink_task_executor_; DISALLOW_COPY_AND_ASSIGN(SchedulerHelper); };
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc index afd86e3..e6d27f9 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -19,6 +19,7 @@ #include "base/task/sequence_manager/test/sequence_manager_for_test.h" #include "base/task/task_executor.h" #include "base/test/bind_test_util.h" +#include "base/test/gtest_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/simple_test_tick_clock.h" @@ -46,6 +47,7 @@ // To avoid symbol collisions in jumbo builds. namespace main_thread_scheduler_impl_unittest { +using testing::IsNull; using testing::Mock; using testing::NotNull; using InputEventState = WebThreadScheduler::InputEventState; @@ -2135,6 +2137,25 @@ {base::CurrentThread(), base::TaskPriority::BEST_EFFORT})); } +TEST_P(MainThreadSchedulerImplTest, GetContinuationTaskRunner) { + scoped_refptr<MainThreadTaskQueue> timer_tq = scheduler_->NewTimerTaskQueue( + MainThreadTaskQueue::QueueType::kFrameThrottleable, nullptr); + auto task_runner = timer_tq->CreateTaskRunner(TaskType::kJavascriptTimer); + + base::RunLoop run_loop; + task_runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() { + EXPECT_EQ(task_runner, + base::GetContinuationTaskRunner()); + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_P(MainThreadSchedulerImplTest, + GetContinuationTaskRunnerWithNoTaskRunning) { + EXPECT_DCHECK_DEATH(base::GetContinuationTaskRunner()); +} + class MainThreadSchedulerImplWithMessageLoopTest : public MainThreadSchedulerImplTest { public:
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index d6bbb62..247f626a 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5770,3 +5770,5 @@ # Sheriff 2019-10-18 crbug.com/996250 external/wpt/web-nfc/NFCReader_scan_iframe.https.html [ Timeout ] +crbug.com/1015254 [ Mac ] external/wpt/pointerevents/extension/pointerevent_coalesced_events_attributes.html [ Pass Failure ] +crbug.com/1015859 [ Linux ] http/tests/devtools/a11y-axe-core/performance/landing-page-a11y-test.js [ Pass Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index c2caca74..efb5506 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -747,16 +747,9 @@ "--site-per-process"] }, { - "prefix": "split-http-cache-not-site-per-process", - "base": "http/tests/devtools/isolated-code-cache", - "args": ["--enable-features=SplitCacheByNetworkIsolationKey", - "--disable-site-isolation-trials"] - }, - { "prefix": "not-site-per-process", "base": "http/tests/devtools/isolated-code-cache", - "args": ["--disable-site-isolation-trials", - "--disable-features=SplitCacheByNetworkIsolationKey"] + "args": ["--disable-site-isolation-trials"] }, { "prefix": "not-site-per-process",
diff --git a/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental-expected.txt b/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental-expected.txt index 1d2d8f0..8c983648 100644 --- a/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental-expected.txt +++ b/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental-expected.txt
@@ -3,7 +3,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". PASS [object Internals] is defined. -PASS internals.updateStyleAndReturnAffectedElementCount() is 1 +PASS internals.updateStyleAndReturnAffectedElementCount() is 0 PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental.html b/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental.html index e07439e..806e1241 100644 --- a/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental.html +++ b/third_party/blink/web_tests/fast/css/invalidation/input-search-incremental.html
@@ -19,9 +19,6 @@ getComputedStyle(searchInput); // Force recalc. searchInput.setAttribute("incremental", ""); -// Ideally, the expected value below should be "0", but the search control -// button has its opacity changed unconditionally through inline style on -// every attribute change on the input element. -shouldBe("internals.updateStyleAndReturnAffectedElementCount()", "1"); +shouldBe("internals.updateStyleAndReturnAffectedElementCount()", "0"); </script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt index 63fe5f66..b525efd 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt
@@ -2,29 +2,17 @@ "layers": [ { "name": "Scrolling background of LayoutView #document", - "bounds": [785, 5000], + "bounds": [800, 5016], "contentsOpaque": true, "backgroundColor": "#FFFFFF", "paintInvalidations": [ { "object": "Scrolling background of LayoutView #document", - "rect": [0, 0, 785, 5000], + "rect": [0, 0, 800, 5016], "reason": "background" } ], "transform": 1 - }, - { - "name": "VerticalScrollbar", - "position": [785, 0], - "bounds": [15, 600], - "paintInvalidations": [ - { - "object": "VerticalScrollbar", - "rect": [0, 0, 15, 600], - "reason": "scroll control" - } - ] } ], "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt new file mode 100644 index 0000000..25efb1dc --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt
@@ -0,0 +1,28 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutNGBlockFlow HTML", + "position": [8, 8], + "bounds": [758, 39], + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -1000, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt b/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt index d305e9b1..24bc46b 100644 --- a/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt +++ b/third_party/blink/web_tests/inspector-protocol/emulation/set-css-media-feature-override-expected.txt
@@ -1,6 +1,6 @@ Tests that CSS media features can be overridden. matchMedia("(prefers-color-scheme: __invalid__)").matches: false -matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 2px x 2px +matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px matchMedia("(prefers-color-scheme: no-preference)").matches: true matchMedia("(prefers-color-scheme: no-preference)").matches applied: 2px x 2px matchMedia("(prefers-color-scheme: light)").matches: true @@ -8,17 +8,17 @@ matchMedia("(prefers-color-scheme: dark)").matches: true matchMedia("(prefers-color-scheme: dark)").matches applied: 4px x 2px matchMedia("(prefers-color-scheme: __invalid__)").matches: false -matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 2px x 2px +matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px matchMedia("(prefers-reduced-motion: __invalid__)").matches: false -matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 2px x 2px +matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 3px x 2px matchMedia("(prefers-reduced-motion: no-preference)").matches: true -matchMedia("(prefers-reduced-motion: no-preference)").matches applied: 2px x 2px +matchMedia("(prefers-reduced-motion: no-preference)").matches applied: 3px x 2px matchMedia("(prefers-reduced-motion: reduce)").matches: true -matchMedia("(prefers-reduced-motion: reduce)").matches applied: 2px x 3px +matchMedia("(prefers-reduced-motion: reduce)").matches applied: 3px x 3px matchMedia("(prefers-reduced-motion: __invalid__)").matches: false -matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 2px x 2px +matchMedia("(prefers-reduced-motion: __invalid__)").matches applied: 3px x 2px matchMedia("(prefers-color-scheme: dark) and (prefers-reduced-motion: reduce)").matches: true matchMedia("(prefers-color-scheme: dark) and (prefers-reduced-motion: reduce)").matches applied: 999px x 999px matchMedia("(prefers-color-scheme: __invalid__)").matches: false -matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 2px x 2px +matchMedia("(prefers-color-scheme: __invalid__)").matches applied: 3px x 2px
diff --git a/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.html b/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.html new file mode 100644 index 0000000..6f03dbf --- /dev/null +++ b/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<style> +::-webkit-scrollbar { display: none; } +html { background-image: linear-gradient(red, blue); height: 100% } +</style>
diff --git a/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt b/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt index 6ca88eb3..e224e0c 100644 --- a/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.txt
@@ -2,23 +2,22 @@ "layers": [ { "name": "Scrolling Contents Layer", - "bounds": [785, 5000], + "bounds": [800, 5016], "contentsOpaque": true, "backgroundColor": "#FFFFFF", "paintInvalidations": [ { "object": "Scrolling background of LayoutView #document", - "rect": [0, 0, 785, 5000], + "rect": [0, 0, 800, 5016], "reason": "background" } ], "transform": 1 }, { - "name": "ContentsLayer for Vertical Scrollbar Layer", - "position": [785, 0], - "bounds": [15, 600], - "contentsOpaque": true + "name": "Vertical Scrollbar Layer", + "position": [800, 0], + "bounds": [0, 600] } ], "transforms": [
diff --git a/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed.html b/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed.html index f0972dd5..4fccb84d 100644 --- a/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed.html +++ b/third_party/blink/web_tests/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed.html
@@ -1,9 +1,9 @@ <!DOCTYPE html> <style> +::-webkit-scrollbar { display: none; } body { background-image: linear-gradient(red, blue); background-attachment: fixed; - margin: 0; } </style> <script src="../resources/text-based-repaint.js" type="text/javascript"></script>
diff --git a/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.html b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.html new file mode 100644 index 0000000..6f03dbf --- /dev/null +++ b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<style> +::-webkit-scrollbar { display: none; } +html { background-image: linear-gradient(red, blue); height: 100% } +</style>
diff --git a/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt new file mode 100644 index 0000000..659170ee --- /dev/null +++ b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed-expected.txt
@@ -0,0 +1,33 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 5016], + "backgroundColor": "#FFFFFF", + "transform": 1 + }, + { + "name": "Vertical Scrollbar Layer", + "position": [800, 0], + "bounds": [0, 600] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -1000, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed.html b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed.html new file mode 100644 index 0000000..cb7a30a --- /dev/null +++ b/third_party/blink/web_tests/paint/invalidation/background/no-repaint-for-composited-background-attachment-fixed.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<style> +::-webkit-scrollbar { display: none; } +body { + background-image: linear-gradient(red, blue); + background-attachment: fixed; +} +</style> +<script src="../resources/text-based-repaint.js"></script> +<script> +if (window.internals) + internals.settings.setPreferCompositingToLCDTextEnabled(true); +function repaintTest() { + window.scrollTo(0, 1000); +} +onload = runRepaintAndPixelTest; +</script> +<div style="height: 5000px"> +Tests that scrolling a frame with background-attachment: fixed doesn't invalidate when preferCompositingToLCDText is enabled. +</div>
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/pointerevents/extension/pointerevent_coalesced_events_attributes-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/pointerevents/extension/pointerevent_coalesced_events_attributes-expected.txt deleted file mode 100644 index e7df530..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/pointerevents/extension/pointerevent_coalesced_events_attributes-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -This is a testharness.js-based test. -PASS touch coalesced events attributes in pointerevents -PASS touch pointercancel should not have any coalesced events -PASS touch pointerover should not have any coalesced events -PASS touch pointerenter should not have any coalesced events -PASS touch pointerdown should not have any coalesced events -FAIL touch pointermove should have >2 coalesced events as main thread is busy. -PASS touch pointermove coalesced events should all be marked as trusted. -PASS touch time stamps of coalesced events must be ascending. -PASS touch pointermove coalesced events should all bubbles and cancelable as false. -PASS touch pointerup should not have any coalesced events -PASS touch pointerout should not have any coalesced events -PASS touch pointerleave should not have any coalesced events -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.png deleted file mode 100644 index 8b31bf9bf..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.png deleted file mode 100644 index 9cf654dc..0000000 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/background/full-viewport-repaint-for-background-attachment-fixed-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-site-per-process/README.md b/third_party/blink/web_tests/virtual/not-site-per-process/README.md index 7da7f6c6..2c70610a 100644 --- a/third_party/blink/web_tests/virtual/not-site-per-process/README.md +++ b/third_party/blink/web_tests/virtual/not-site-per-process/README.md
@@ -15,11 +15,7 @@ Tests under `virtual/not-site-per-process` are run with `--disable-site-isolation-trials` cmdline flag which turns off site isolation. This is needed to preserve test coverage provided by around -60 tests that fail when run with site isolation. `isolated-code-cache` tests are -also run with `--disable-features=SplitCacheByNetworkIsolationKey` which turns -off HTTP cache partitioning. This is needed as a test expects cross-origin -resources to be cached. Equivalent tests with the feature enabled can be found -under `virtual/split-http-cache-not-site-per-process`. +60 tests that fail when run with site isolation. When modifying the list of files that behave differently with and without OOPIFs, please consider modifying all the locations below:
diff --git a/third_party/blink/web_tests/virtual/split-http-cache-not-site-per-process/http/tests/devtools/isolated-code-cache/README.txt b/third_party/blink/web_tests/virtual/split-http-cache-not-site-per-process/http/tests/devtools/isolated-code-cache/README.txt deleted file mode 100644 index 58f5e0e..0000000 --- a/third_party/blink/web_tests/virtual/split-http-cache-not-site-per-process/http/tests/devtools/isolated-code-cache/README.txt +++ /dev/null
@@ -1,6 +0,0 @@ -# This suite runs the tests in http/tests/devtools/isolated-code-cache with -# --enable-features=SplitCacheByNetworkIsolationKey -# --disable-site-isolation-trials -# This feature partitions the HTTP cache by network isolation key for improved -# security. Tracking bug: crbug.com/910708. This test disables site isolation, -# which would cause similar results.
diff --git a/third_party/blink/web_tests/virtual/split-http-cache-not-site-per-process/http/tests/devtools/isolated-code-cache/cross-origin-test-expected.txt b/third_party/blink/web_tests/virtual/split-http-cache-not-site-per-process/http/tests/devtools/isolated-code-cache/cross-origin-test-expected.txt deleted file mode 100644 index 81e758db..0000000 --- a/third_party/blink/web_tests/virtual/split-http-cache-not-site-per-process/http/tests/devtools/isolated-code-cache/cross-origin-test-expected.txt +++ /dev/null
@@ -1,82 +0,0 @@ -Tests V8 code cache for javascript resources - ----First navigation - produce and consume code cache ------ - -v8.compile Properties: -{ - data : { - columnNumber : 0 - lineNumber : 0 - notStreamedReason : "script too small" - streamed : <boolean> - url : .../devtools/resources/v8-cache-script.js - } - endTime : <number> - startTime : <number> - type : "v8.compile" -} -Text details for v8.compile: v8-cache-script.js:1 -v8.compile Properties: -{ - data : { - columnNumber : 0 - lineNumber : 0 - notStreamedReason : "already used streamed data" - streamed : <boolean> - url : .../devtools/resources/v8-cache-script.js - } - endTime : <number> - startTime : <number> - type : "v8.compile" -} -Text details for v8.compile: v8-cache-script.js:1 -v8.compile Properties: -{ - data : { - columnNumber : 0 - lineNumber : 0 - notStreamedReason : "already used streamed data" - producedCacheSize : <number> - streamed : <boolean> - url : .../devtools/resources/v8-cache-script.js - } - endTime : <number> - startTime : <number> - type : "v8.compile" -} -Text details for v8.compile: v8-cache-script.js:1 -v8.compile Properties: -{ - data : { - cacheConsumeOptions : "code" - cacheRejected : false - columnNumber : 0 - consumedCacheSize : <number> - lineNumber : 0 - notStreamedReason : "already used streamed data" - streamed : <boolean> - url : .../devtools/resources/v8-cache-script.js - } - endTime : <number> - startTime : <number> - type : "v8.compile" -} -Text details for v8.compile: v8-cache-script.js:1 - ---- Second navigation - from a different origin ------ - -v8.compile Properties: -{ - data : { - columnNumber : 0 - lineNumber : 0 - notStreamedReason : "script too small" - streamed : <boolean> - url : .../devtools/resources/v8-cache-script.js - } - endTime : <number> - startTime : <number> - type : "v8.compile" -} -Text details for v8.compile: v8-cache-script.js:1 -
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 907127bf..b30a6be5 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: fe52a01df1e9c8a5fe8b92872d4bf8689d0cd3b4 +Revision: 661a07a41b8809b9df32914c11542a0c76e709d5 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_test.cc b/third_party/crashpad/crashpad/client/crash_report_database_test.cc index ca66bce6..ef217c1 100644 --- a/third_party/crashpad/crashpad/client/crash_report_database_test.cc +++ b/third_party/crashpad/crashpad/client/crash_report_database_test.cc
@@ -20,7 +20,6 @@ #include "test/errors.h" #include "test/file.h" #include "test/filesystem.h" -#include "test/gtest_disabled.h" #include "test/scoped_temp_dir.h" #include "util/file/file_io.h" #include "util/file/filesystem.h" @@ -671,7 +670,7 @@ TEST_F(CrashReportDatabaseTest, Attachments) { #if defined(OS_MACOSX) || defined(OS_WIN) // Attachments aren't supported on Mac and Windows yet. - DISABLED_TEST(); + GTEST_SKIP(); #else std::unique_ptr<CrashReportDatabase::NewReport> new_report; ASSERT_EQ(db()->PrepareNewCrashReport(&new_report), @@ -717,7 +716,7 @@ TEST_F(CrashReportDatabaseTest, OrphanedAttachments) { #if defined(OS_MACOSX) || defined(OS_WIN) // Attachments aren't supported on Mac and Windows yet. - DISABLED_TEST(); + GTEST_SKIP(); #else // TODO: This is using paths that are specific to the generic implementation // and will need to be generalized for Mac and Windows.
diff --git a/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h b/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h index f105f94..a83d2a4 100644 --- a/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h +++ b/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h
@@ -59,4 +59,16 @@ #define MAC_OS_X_VERSION_10_13 101300 #endif +// 10.14 SDK + +#ifndef MAC_OS_X_VERSION_10_14 +#define MAC_OS_X_VERSION_10_14 101400 +#endif + +// 10.15 SDK + +#ifndef MAC_OS_X_VERSION_10_15 +#define MAC_OS_X_VERSION_10_15 101500 +#endif + #endif // CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc index d767700..5b57236 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
@@ -38,7 +38,6 @@ #include "build/build_config.h" #include "gtest/gtest.h" #include "test/errors.h" -#include "test/gtest_disabled.h" #include "test/linux/fake_ptrace_connection.h" #include "test/linux/get_tls.h" #include "test/multiprocess.h" @@ -428,7 +427,7 @@ } void MultiprocessChild() override { - const LinuxVMSize stack_size = page_size_ * 3; + const LinuxVMSize stack_size = page_size_ * 4; GrowStack(stack_size, reinterpret_cast<LinuxVMAddress>(&stack_size)); } @@ -441,7 +440,7 @@ } else { // Write-protect a page on our stack to split up the mapping LinuxVMAddress page_addr = - stack_address - (stack_address % page_size_) + page_size_; + stack_address - (stack_address % page_size_) + 2 * page_size_; ASSERT_EQ( mprotect(reinterpret_cast<void*>(page_addr), page_size_, PROT_READ), 0) @@ -809,7 +808,7 @@ // presence of a libc symbol which was introduced in Q. if (!crashpad::internal::Dlsym(RTLD_DEFAULT, "android_fdsan_close_with_tag")) { - DISABLED_TEST(); + GTEST_SKIP(); } android_set_abort_message(kTestAbortMessage);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc index 3ca5646c..a76c3eb 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
@@ -19,6 +19,7 @@ #include <sys/types.h> #include <algorithm> +#include <limits> #include <type_traits> #include "base/logging.h" @@ -26,6 +27,7 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "snapshot/mac/process_types/internal.h" +#include "util/mac/mac_util.h" #include "util/process/process_memory_mac.h" #if !DOXYGEN @@ -140,8 +142,8 @@ offsetof(dyld_all_image_infos<Traits>, sharedCacheSlide), // 11 offsetof(dyld_all_image_infos<Traits>, sharedCacheUUID), // 12 offsetof(dyld_all_image_infos<Traits>, infoArrayChangeTimestamp), // 13 - offsetof(dyld_all_image_infos<Traits>, end_14_15), // 14 - offsetof(dyld_all_image_infos<Traits>, end_14_15), // 15 + offsetof(dyld_all_image_infos<Traits>, end_14), // 14 + std::numeric_limits<size_t>::max(), // 15, see below sizeof(dyld_all_image_infos<Traits>), // 16 }; @@ -151,7 +153,27 @@ static_assert(std::is_unsigned<decltype(version)>::value, "version must be unsigned"); - return kSizeForVersion[version]; + + if (version == 15) { + // Disambiguate between the two different layouts for version 15. The + // original one introduced in macOS 10.12 had the same size as version 14. + // The revised one in macOS 10.13 grew. It’s safe to assume that the + // dyld_all_image_infos structure came from the same system that’s now + // interpreting it, so use an OS version check. + int mac_os_x_minor_version = MacOSXMinorVersion(); + if (mac_os_x_minor_version == 12) { + return offsetof(dyld_all_image_infos<Traits>, end_14); + } + + DCHECK_GE(mac_os_x_minor_version, 13); + DCHECK_LE(mac_os_x_minor_version, 14); + return offsetof(dyld_all_image_infos<Traits>, platform); + } + + size_t size = kSizeForVersion[version]; + DCHECK_NE(size, std::numeric_limits<size_t>::max()); + + return size; } // static
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype b/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype index f92a800..3b040854 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype
@@ -121,23 +121,29 @@ // the runtimes that use versions 14 and 15 were built with SDKs that did not // have this extra padding, it’s necessary to treat the element at index 4 on // 32-bit systems as outside of the version 14 and 15 structure. This is why - // |reserved| is only declared a 4-element array, with a special end_14_15 - // member (not present in the native definition) available to indicate the - // end of the native version 14 and 15 structure, preceding the padding in the - // 32-bit structure that would natively be addressed at index 4 of |reserved|. - // Treat reserved_4_32 as only available in version 16 of the structure. + // |reserved| is only declared a 4-element array, with a special end_14 member + // (not present in the native definition) available to indicate the end of the + // native version 14 structure and the 10.12 version 15 structure, preceding + // the padding in the 32-bit structure that would natively be addressed at + // index 4 of |reserved|. Treat reserved_4_32 as only available in version 16 + // of the structure. PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, reserved, [4]) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_4_64) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_5) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_6) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_7) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_8) - PROCESS_TYPE_STRUCT_MEMBER(Nothing, end_14_15) + PROCESS_TYPE_STRUCT_MEMBER(Nothing, end_14) PROCESS_TYPE_STRUCT_MEMBER(Reserved32_32Only, reserved_4_32) - // Version 16 (macOS 10.13) + // Version 15 (macOS 10.13). <mach-o/dyld_images.h> incorrectly claims that + // these were introduced at version 16. These fields are not present in macOS + // 10.12, which also identifies its structure as version 15. PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, compact_dyld_image_info_addr) PROCESS_TYPE_STRUCT_MEMBER(ULong, compact_dyld_image_info_size) // size_t + + // Version 16 (macOS 10.15) + PROCESS_TYPE_STRUCT_MEMBER(uint32_t, platform) // dyld_platform_t PROCESS_TYPE_STRUCT_END(dyld_all_image_infos) #endif // ! PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO &&
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc index 2ab3034c..8523b9c 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
@@ -18,6 +18,7 @@ #include <mach/mach.h> #include <string.h> +#include <limits> #include <vector> #include "base/stl_util.h" @@ -47,13 +48,11 @@ TEST(ProcessTypes, DyldImagesSelf) { // Get the in-process view of dyld_all_image_infos, and check it for sanity. const dyld_all_image_infos* self_image_infos = DyldGetAllImageInfos(); - int mac_os_x_minor_version = MacOSXMinorVersion(); + const int mac_os_x_minor_version = MacOSXMinorVersion(); - // The 10.13 SDK defines dyld_all_image_infos version 16 and says that it’s - // used on 10.13, but 10.13db1 17A264c uses version 15. - // - // TODO(mark): Recheck later in the beta period, up to the 10.13 release. - if (mac_os_x_minor_version >= 12) { + if (mac_os_x_minor_version >= 15) { + EXPECT_GE(self_image_infos->version, 16u); + } else if (mac_os_x_minor_version >= 12) { EXPECT_GE(self_image_infos->version, 15u); } else if (mac_os_x_minor_version >= 9) { EXPECT_GE(self_image_infos->version, 13u); @@ -104,7 +103,7 @@ ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15 constexpr uint32_t kDyldAllImageInfosVersionInSDK = 16; #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 constexpr uint32_t kDyldAllImageInfosVersionInSDK = 15; @@ -120,12 +119,33 @@ // Make sure that the size of the structure as declared in the SDK matches the // size expected for the version of the structure that the SDK describes. - EXPECT_EQ(process_types::dyld_all_image_infos::ExpectedSizeForVersion( - &process_reader, kDyldAllImageInfosVersionInSDK), - sizeof(dyld_all_image_infos)); + // + // There are two possible layouts for version 15, and the + // ExpectedSizeForVersion() implementation infers the correct one based on the + // run-time OS version, so if the SDK defines the version 15 structure, this + // test can only be performed if the run-time OS natively uses the same format + // structure as the SDK. + bool test_expected_size_for_version_matches_sdk_sizeof; +#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_12 + test_expected_size_for_version_matches_sdk_sizeof = + mac_os_x_minor_version == 12; +#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 && \ + MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_14 + test_expected_size_for_version_matches_sdk_sizeof = + mac_os_x_minor_version >= 13 && mac_os_x_minor_version <= 14; +#else + test_expected_size_for_version_matches_sdk_sizeof = true; +#endif + + if (test_expected_size_for_version_matches_sdk_sizeof) { + EXPECT_EQ(process_types::dyld_all_image_infos::ExpectedSizeForVersion( + &process_reader, kDyldAllImageInfosVersionInSDK), + sizeof(dyld_all_image_infos)); + } // Make sure that the computed sizes of various versions of this structure are // correct at different bitnessses. + constexpr size_t kSpecialCase = std::numeric_limits<size_t>::max(); constexpr struct { uint32_t version; size_t size_32; @@ -144,13 +164,40 @@ {12, 84, 160}, {13, 104, 184}, {14, 164, 304}, - {15, 164, 304}, - {16, 176, 320}, + {15, kSpecialCase, kSpecialCase}, + {16, 184, 328}, }; for (size_t index = 0; index < base::size(kVersionsAndSizes); ++index) { uint32_t version = kVersionsAndSizes[index].version; SCOPED_TRACE(base::StringPrintf("index %zu, version %u", index, version)); + if (version == 15) { + if (mac_os_x_minor_version == 12) { + EXPECT_EQ(process_types::internal::dyld_all_image_infos< + process_types::internal::Traits32>:: + ExpectedSizeForVersion(version), + 164u); + EXPECT_EQ(process_types::internal::dyld_all_image_infos< + process_types::internal::Traits64>:: + ExpectedSizeForVersion(version), + 304u); + } else if (mac_os_x_minor_version >= 13 && mac_os_x_minor_version <= 14) { + EXPECT_EQ(process_types::internal::dyld_all_image_infos< + process_types::internal::Traits32>:: + ExpectedSizeForVersion(version), + 176u); + EXPECT_EQ(process_types::internal::dyld_all_image_infos< + process_types::internal::Traits64>:: + ExpectedSizeForVersion(version), + 320u); + } + + continue; + } + + ASSERT_NE(kVersionsAndSizes[index].size_32, kSpecialCase); + ASSERT_NE(kVersionsAndSizes[index].size_64, kSpecialCase); + EXPECT_EQ( process_types::internal::dyld_all_image_infos< process_types::internal::Traits32>::ExpectedSizeForVersion(version), @@ -306,7 +353,7 @@ #endif #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 - if (proctype_image_infos.version >= 16) { + if (proctype_image_infos.version >= 15 && mac_os_x_minor_version >= 13) { EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_addr, self_image_infos->compact_dyld_image_info_addr); EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_size, @@ -314,6 +361,12 @@ } #endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15 + if (proctype_image_infos.version >= 16) { + EXPECT_EQ(proctype_image_infos.platform, self_image_infos->platform); + } +#endif + if (proctype_image_infos.version >= 1) { std::vector<process_types::dyld_image_info> proctype_image_info_vector( proctype_image_infos.infoArrayCount);
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc index 486e6df..b4c44a83 100644 --- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
@@ -23,7 +23,6 @@ #include "gtest/gtest.h" #include "snapshot/win/process_snapshot_win.h" #include "test/errors.h" -#include "test/gtest_disabled.h" #include "test/test_paths.h" #include "test/win/child_launcher.h" #include "util/file/file_io.h" @@ -176,7 +175,7 @@ #if defined(ARCH_CPU_64_BITS) TEST(ExceptionSnapshotWinTest, ChildCrashWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestCrashingChild(TestPaths::Architecture::k32Bit); @@ -293,7 +292,7 @@ #if defined(ARCH_CPU_64_BITS) TEST(SimulateCrash, ChildDumpWithoutCrashingWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestDumpWithoutCrashingChild(TestPaths::Architecture::k32Bit);
diff --git a/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc b/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc index dcef805..e0c17a20 100644 --- a/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc
@@ -25,7 +25,6 @@ #include "client/simple_address_range_bag.h" #include "gtest/gtest.h" #include "snapshot/win/process_snapshot_win.h" -#include "test/gtest_disabled.h" #include "test/test_paths.h" #include "test/win/child_launcher.h" #include "util/file/file_io.h" @@ -110,7 +109,7 @@ #if defined(ARCH_CPU_64_BITS) TEST(ExtraMemoryRanges, DontCrashWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestExtraMemoryRanges(kDontCrash, TestPaths::Architecture::k32Bit); @@ -118,7 +117,7 @@ TEST(ExtraMemoryRanges, CrashDebugBreakWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestExtraMemoryRanges(kCrashDebugBreak, TestPaths::Architecture::k32Bit);
diff --git a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win_test.cc index 6a14cf5e..d9786cf 100644 --- a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win_test.cc
@@ -30,7 +30,6 @@ #include "snapshot/annotation_snapshot.h" #include "snapshot/win/pe_image_reader.h" #include "snapshot/win/process_reader_win.h" -#include "test/gtest_disabled.h" #include "test/test_paths.h" #include "test/win/child_launcher.h" #include "util/file/file_io.h" @@ -152,7 +151,7 @@ #if defined(ARCH_CPU_64_BITS) TEST(ModuleSnapshotWinTest, DontCrashWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestAnnotationsOnCrash(kDontCrash, TestPaths::Architecture::k32Bit); @@ -160,7 +159,7 @@ TEST(ModuleSnapshotWinTest, CrashDebugBreakWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestAnnotationsOnCrash(kCrashDebugBreak, TestPaths::Architecture::k32Bit);
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc index 8a3e6a4..7192aa85 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc
@@ -20,7 +20,6 @@ #include "snapshot/win/pe_image_reader.h" #include "snapshot/win/process_reader_win.h" #include "test/errors.h" -#include "test/gtest_disabled.h" #include "test/test_paths.h" #include "test/win/child_launcher.h" #include "util/file/file_io.h" @@ -120,7 +119,7 @@ #if defined(ARCH_CPU_64_BITS) TEST(ProcessSnapshotTest, CrashpadInfoChildWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestImageReaderChild(TestPaths::Architecture::k32Bit);
diff --git a/third_party/crashpad/crashpad/test/BUILD.gn b/third_party/crashpad/crashpad/test/BUILD.gn index fb99bce6..7f44863 100644 --- a/third_party/crashpad/crashpad/test/BUILD.gn +++ b/third_party/crashpad/crashpad/test/BUILD.gn
@@ -25,8 +25,6 @@ "filesystem.cc", "filesystem.h", "gtest_death.h", - "gtest_disabled.cc", - "gtest_disabled.h", "hex_string.cc", "hex_string.h", "main_arguments.cc",
diff --git a/third_party/crashpad/crashpad/test/gtest_disabled.cc b/third_party/crashpad/crashpad/test/gtest_disabled.cc deleted file mode 100644 index fab6802..0000000 --- a/third_party/crashpad/crashpad/test/gtest_disabled.cc +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2017 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "test/gtest_disabled.h" - -#include <stdio.h> - -#include "base/format_macros.h" -#include "base/logging.h" -#include "base/strings/stringprintf.h" - -namespace crashpad { -namespace test { - -namespace { - -DisabledTestGtestEnvironment* g_instance; - -} // namespace - -// static -DisabledTestGtestEnvironment* DisabledTestGtestEnvironment::Get() { - if (!g_instance) { - g_instance = new DisabledTestGtestEnvironment(); - } - return g_instance; -} - -void DisabledTestGtestEnvironment::DisabledTest() { - const testing::TestInfo* test_info = - testing::UnitTest::GetInstance()->current_test_info(); - std::string disabled_test = base::StringPrintf( - "%s.%s", test_info->test_case_name(), test_info->name()); - - // Show a DISABLED message using a format similar to gtest, along with a hint - // explaining that OK or FAILED will also appear. - printf( - "This test has been disabled dynamically.\n" - "It will appear as both DISABLED and OK or FAILED.\n" - "[ DISABLED ] %s\n", - disabled_test.c_str()); - - disabled_tests_.push_back(disabled_test); -} - -DisabledTestGtestEnvironment::DisabledTestGtestEnvironment() - : testing::Environment(), - disabled_tests_() { - DCHECK(!g_instance); -} - -DisabledTestGtestEnvironment::~DisabledTestGtestEnvironment() { - DCHECK_EQ(this, g_instance); - g_instance = nullptr; -} - -void DisabledTestGtestEnvironment::TearDown() { - if (!disabled_tests_.empty()) { - printf( - "[ DISABLED ] %" PRIuS " dynamically disabled test%s, listed below:\n" - "[ DISABLED ] %s also counted in PASSED or FAILED below.\n", - disabled_tests_.size(), - disabled_tests_.size() == 1 ? "" : "s", - disabled_tests_.size() == 1 ? "This test is" : "These tests are"); - for (const std::string& disabled_test : disabled_tests_) { - printf("[ DISABLED ] %s\n", disabled_test.c_str()); - } - } -} - -} // namespace test -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/gtest_disabled.h b/third_party/crashpad/crashpad/test/gtest_disabled.h deleted file mode 100644 index 9415cba..0000000 --- a/third_party/crashpad/crashpad/test/gtest_disabled.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2017 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_TEST_GTEST_DISABLED_H_ -#define CRASHPAD_TEST_GTEST_DISABLED_H_ - -#include <string> -#include <vector> - -#include "base/macros.h" -#include "gtest/gtest.h" - -//! \file - -namespace crashpad { -namespace test { - -//! \brief Provides support for dynamically disabled gtest tests. -//! -//! A test runner must register this with gtest as follows prior to calling -//! `RUN_ALL_TESTS()`: -//! \code -//! testing::AddGlobalTestEnvironment( -//! crashpad::test::DisabledTestGtestEnvironment::Get()); -//! \endcode -class DisabledTestGtestEnvironment final : public testing::Environment { - public: - //! \brief Returns the DisabledTestGtestEnvironment singleton instance, - //! creating it if necessary. - static DisabledTestGtestEnvironment* Get(); - - //! \brief Displays a message about a test being disabled, and arranges for - //! this information to be duplicated in TearDown(). - //! - //! This method is for the internal use of the DISABLED_TEST() macro. Do not - //! call it directly, use the macro instead. - void DisabledTest(); - - private: - DisabledTestGtestEnvironment(); - ~DisabledTestGtestEnvironment() override; - - // testing::Environment: - void TearDown() override; - - std::vector<std::string> disabled_tests_; - - DISALLOW_COPY_AND_ASSIGN(DisabledTestGtestEnvironment); -}; - -} // namespace test -} // namespace crashpad - -//! \brief Displays a message about a test being disabled, and returns early. -//! -//! gtest only provides a mechanism for tests to be disabled statically, by -//! prefixing test case names or test names with `DISABLED_`. When it is -//! necessary to disable tests dynamically, gtest provides no assistance. This -//! macro displays a message about the disabled test and returns early. The -//! dynamically disabled test will also be displayed during gtest global test -//! environment tear-down before the test executable exits. -//! -//! This macro may only be invoked from the context of a gtest test. -//! -//! There’s a long-standing <a -//! href="https://groups.google.com/d/topic/googletestframework/Nwh3u7YFuN4">gtest -//! feature request</a> to provide this functionality directly in gtest, but -//! since it hasn’t been implemented, this macro provides a local mechanism to -//! achieve it. -#define DISABLED_TEST() \ - do { \ - ::crashpad::test::DisabledTestGtestEnvironment::Get()->DisabledTest(); \ - return; \ - } while (false) - -#endif // CRASHPAD_TEST_GTEST_DISABLED_H_
diff --git a/third_party/crashpad/crashpad/test/gtest_main.cc b/third_party/crashpad/crashpad/test/gtest_main.cc index ebdbeb9d5..5a54691 100644 --- a/third_party/crashpad/crashpad/test/gtest_main.cc +++ b/third_party/crashpad/crashpad/test/gtest_main.cc
@@ -14,7 +14,6 @@ #include "build/build_config.h" #include "gtest/gtest.h" -#include "test/gtest_disabled.h" #include "test/main_arguments.h" #include "test/multiprocess_exec.h" @@ -51,8 +50,6 @@ int main(int argc, char* argv[]) { crashpad::test::InitializeMainArguments(argc, argv); - testing::AddGlobalTestEnvironment( - crashpad::test::DisabledTestGtestEnvironment::Get()); std::string child_func_name; if (GetChildTestFunctionName(&child_func_name)) {
diff --git a/third_party/crashpad/crashpad/test/test.gyp b/third_party/crashpad/crashpad/test/test.gyp index 8101f8f..d00256a7 100644 --- a/third_party/crashpad/crashpad/test/test.gyp +++ b/third_party/crashpad/crashpad/test/test.gyp
@@ -37,8 +37,6 @@ 'filesystem.cc', 'filesystem.h', 'gtest_death.h', - 'gtest_disabled.cc', - 'gtest_disabled.h', 'hex_string.cc', 'hex_string.h', 'linux/fake_ptrace_connection.cc',
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn index dec7d5c4..c233f96 100644 --- a/third_party/crashpad/crashpad/util/BUILD.gn +++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -281,7 +281,7 @@ if (crashpad_use_boringssl_for_http_transport_socket) { defines += [ "CRASHPAD_USE_BORINGSSL" ] - if (crashpad_is_in_fuchsia) { + if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) { deps += [ "//third_party/boringssl" ] } else { libs = [ @@ -545,7 +545,7 @@ ] defines = [ "CRASHPAD_USE_BORINGSSL" ] - if (crashpad_is_in_fuchsia) { + if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) { deps += [ "//third_party/boringssl" ] } else { libs = [
diff --git a/third_party/crashpad/crashpad/util/file/directory_reader_test.cc b/third_party/crashpad/crashpad/util/file/directory_reader_test.cc index f03669e2..812deaf 100644 --- a/third_party/crashpad/crashpad/util/file/directory_reader_test.cc +++ b/third_party/crashpad/crashpad/util/file/directory_reader_test.cc
@@ -22,7 +22,6 @@ #include "base/strings/utf_string_conversions.h" #include "gtest/gtest.h" #include "test/filesystem.h" -#include "test/gtest_disabled.h" #include "test/scoped_temp_dir.h" #include "util/file/file_io.h" #include "util/file/filesystem.h" @@ -48,7 +47,7 @@ TEST(DirectoryReader, BadPaths_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } ScopedTempDir temp_dir; @@ -144,7 +143,7 @@ TEST(DirectoryReader, FilesAndDirectories_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestFilesAndDirectories(true);
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test.cc b/third_party/crashpad/crashpad/util/file/filesystem_test.cc index 3430c3f..37a9290b 100644 --- a/third_party/crashpad/crashpad/util/file/filesystem_test.cc +++ b/third_party/crashpad/crashpad/util/file/filesystem_test.cc
@@ -21,7 +21,6 @@ #include "gtest/gtest.h" #include "test/errors.h" #include "test/filesystem.h" -#include "test/gtest_disabled.h" #include "test/scoped_temp_dir.h" #include "util/misc/time.h" @@ -93,7 +92,7 @@ TEST(Filesystem, FileModificationTime_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } ScopedTempDir temp_dir; @@ -224,7 +223,7 @@ TEST(Filesystem, MoveFileOrDirectory_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } ScopedTempDir temp_dir; @@ -302,7 +301,7 @@ TEST(Filesystem, IsRegularFile_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } ScopedTempDir temp_dir; @@ -344,7 +343,7 @@ TEST(Filesystem, IsDirectory_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } ScopedTempDir temp_dir; @@ -393,7 +392,7 @@ TEST(Filesystem, RemoveFile_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } ScopedTempDir temp_dir; @@ -450,7 +449,7 @@ TEST(Filesystem, RemoveDirectory_SymbolicLinks) { if (!CanCreateSymbolicLinks()) { - DISABLED_TEST(); + GTEST_SKIP(); } ScopedTempDir temp_dir;
diff --git a/third_party/crashpad/crashpad/util/linux/auxiliary_vector_test.cc b/third_party/crashpad/crashpad/util/linux/auxiliary_vector_test.cc index d4cfcb7..00af5abe 100644 --- a/third_party/crashpad/crashpad/util/linux/auxiliary_vector_test.cc +++ b/third_party/crashpad/crashpad/util/linux/auxiliary_vector_test.cc
@@ -120,8 +120,9 @@ #if defined(AT_SYSINFO_EHDR) LinuxVMAddress vdso_addr; - ASSERT_TRUE(aux.GetValue(AT_SYSINFO_EHDR, &vdso_addr)); - EXPECT_TRUE(mappings.FindMapping(vdso_addr)); + if (aux.GetValue(AT_SYSINFO_EHDR, &vdso_addr)) { + EXPECT_TRUE(mappings.FindMapping(vdso_addr)); + } #endif // AT_SYSINFO_EHDR #if defined(AT_EXECFN)
diff --git a/third_party/crashpad/crashpad/util/net/tls.gni b/third_party/crashpad/crashpad/util/net/tls.gni index f979b62..eb968450 100644 --- a/third_party/crashpad/crashpad/util/net/tls.gni +++ b/third_party/crashpad/crashpad/util/net/tls.gni
@@ -18,5 +18,6 @@ # TODO(scottmg): https://crbug.com/crashpad/266 fuchsia:DX-690: BoringSSL # was removed from the Fuchsia SDK. Re-enable it when we have a way to acquire # a BoringSSL lib again. - crashpad_use_boringssl_for_http_transport_socket = crashpad_is_in_fuchsia + crashpad_use_boringssl_for_http_transport_socket = + crashpad_is_in_fuchsia || (crashpad_is_linux && crashpad_is_in_chromium) }
diff --git a/third_party/crashpad/crashpad/util/win/process_info_test.cc b/third_party/crashpad/crashpad/util/win/process_info_test.cc index 59aaa7a9..a43358d 100644 --- a/third_party/crashpad/crashpad/util/win/process_info_test.cc +++ b/third_party/crashpad/crashpad/util/win/process_info_test.cc
@@ -26,7 +26,6 @@ #include "build/build_config.h" #include "gtest/gtest.h" #include "test/errors.h" -#include "test/gtest_disabled.h" #include "test/scoped_temp_dir.h" #include "test/test_paths.h" #include "test/win/child_launcher.h" @@ -203,7 +202,7 @@ #if defined(ARCH_CPU_64_BITS) TEST(ProcessInfo, OtherProcessWOW64) { if (!TestPaths::Has32BitBuildArtifacts()) { - DISABLED_TEST(); + GTEST_SKIP(); } TestOtherProcess(TestPaths::Architecture::k32Bit);
diff --git a/tools/mb/docs/user_guide.md b/tools/mb/docs/user_guide.md index fd5823b5..2bbf65f 100644 --- a/tools/mb/docs/user_guide.md +++ b/tools/mb/docs/user_guide.md
@@ -166,6 +166,25 @@ In either case, any flags past `--` will be passed on to the command to be run inside the isolate. +### mb try + +Tries your change on the trybots. Right now this is essentially a fancy tryjob, +like one you could trigger via `git cl try` or via CQ dry runs. Basic usage is + +`mb.py try -m tryserver.chromium.linux -b linux-rel //base:base_unittests` + +Your change must be uploaded to Gerrit. Local changes will not be uploaded for +you. It uses the gerrit CL associated with your given git branch. + +You still have to specify the mastername (`-m`) and buildername (`-b`) arguments. +See [trybots.py](https://cs.chromium.org/chromium/build/scripts/slave/recipe_modules/chromium_tests/trybots.py) +for a mapping of which bots are on which tryservers, and what those bots mirror. +Any trybot in `trybots.py` is supported; you can test your code on windows, for +example. The tryjob will compile and run your code on windows. + +The target (`base_unittests`) in the example is a GN build target. Most GN +unittest targets can be put here which currently runs on the bots. + ### mb validate Does internal checking to make sure the config file is syntactically
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 6d2784a..f6428ce 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -64,7 +64,6 @@ mbw = MetaBuildWrapper() return mbw.Main(args) - class MetaBuildWrapper(object): def __init__(self): self.chromium_src_dir = CHROMIUM_SRC_DIR @@ -214,6 +213,13 @@ 'implies --quiet') subp.set_defaults(func=self.CmdLookup) + subp = subps.add_parser('try', + description='Try your change on a remote builder') + AddCommonOptions(subp) + subp.add_argument('target', + help='ninja target to build and run') + subp.set_defaults(func=self.CmdTry) + subp = subps.add_parser( 'run', formatter_class=argparse.RawDescriptionHelpFormatter) subp.description = ( @@ -377,6 +383,61 @@ self.PrintCmd(cmd, env) return 0 + def CmdTry(self): + target = self.args.target + if not target.startswith('//'): + self.Print("Expected a GN target like //:foo, got %s" % target) + return 1 + + recipe_name = None + isolate_map = self.ReadIsolateMap() + for name, config in isolate_map.iteritems(): + if 'label' in config and config['label'] == target: + recipe_name = name + break + if not recipe_name: + self.Print("Unable to find a recipe entry for %s." % target) + + json_path = self.PathJoin(self.chromium_src_dir, 'out.json') + try: + ret, out, err = self.Run( + ['git', 'cl', 'issue', '--json=out.json'], force_verbose=False) + if ret != 0: + self.Print( + "Unable to fetch current issue. Output and error:\n%s\n%s" % ( + out, err + )) + return ret + with open(json_path) as f: + issue_data = json.load(f) + finally: + if self.Exists(json_path): + os.unlink(json_path) + + if not issue_data['issue']: + self.Print("Missing issue data. Upload your CL to Gerrit and try again.") + return 1 + + def run_cmd(previous_res, cmd): + res, out, err = self.Run(cmd, force_verbose=False, stdin=previous_res) + if res != 0: + self.Print("Err while running", cmd) + self.Print("Output", out) + raise Exception(err) + return out + + result = LedResult(None, run_cmd).then( + # TODO(martiniss): maybe don't always assume the bucket? + 'led', 'get-builder', 'luci.chromium.try:%s' % self.args.builder).then( + 'led', 'edit', '-r', 'chromium_trybot_experimental', + '-p', 'tests=["%s"]' % recipe_name).then( + 'led', 'edit-cr-cl', issue_data['issue_url']).then( + 'led', 'launch').result + + swarming_data = json.loads(result)['swarming'] + self.Print("Launched task at https://%s/task?id=%s" % ( + swarming_data['host_name'], swarming_data['task_id'])) + def CmdRun(self): vals = self.GetConfig() if not vals: @@ -1658,14 +1719,16 @@ ret, _, _ = self.Run(ninja_cmd, buffer_output=False) return ret - def Run(self, cmd, env=None, force_verbose=True, buffer_output=True): + def Run(self, cmd, env=None, force_verbose=True, buffer_output=True, + stdin=None): # This function largely exists so it can be overridden for testing. if self.args.dryrun or self.args.verbose or force_verbose: self.PrintCmd(cmd, env) if self.args.dryrun: return 0, '', '' - ret, out, err = self.Call(cmd, env=env, buffer_output=buffer_output) + ret, out, err = self.Call(cmd, env=env, buffer_output=buffer_output, + stdin=stdin) if self.args.verbose or force_verbose: if ret: self.Print(' -> returned %d' % ret) @@ -1676,12 +1739,12 @@ self.Print(err, end='', file=sys.stderr) return ret, out, err - def Call(self, cmd, env=None, buffer_output=True): + def Call(self, cmd, env=None, buffer_output=True, stdin=None): if buffer_output: p = subprocess.Popen(cmd, shell=False, cwd=self.chromium_src_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - env=env) - out, err = p.communicate() + env=env, stdin=subprocess.PIPE) + out, err = p.communicate(input=stdin) else: p = subprocess.Popen(cmd, shell=False, cwd=self.chromium_src_dir, env=env) @@ -1761,6 +1824,28 @@ return fp.write(contents) +class LedResult(object): + """Holds the result of a led operation. Can be chained using |then|.""" + + def __init__(self, result, run_cmd): + self._result = result + self._run_cmd = run_cmd + + @property + def result(self): + """The mutable result data of the previous led call as decoded JSON.""" + return self._result + + def then(self, *cmd): + """Invoke led, passing it the current `result` data as input. + + Returns another LedResult object with the output of the command. + """ + return self.__class__( + self._run_cmd(self._result, cmd), self._run_cmd) + + + class MBErr(Exception): pass
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py index 35957e8e..c8431f10 100755 --- a/tools/mb/mb_unittest.py +++ b/tools/mb/mb_unittest.py
@@ -70,7 +70,7 @@ abpath = self._AbsPath(path) self.files[abpath] = contents - def Call(self, cmd, env=None, buffer_output=True): + def Call(self, cmd, env=None, buffer_output=True, stdin=None): self.calls.append(cmd) if self.cmds: return self.cmds.pop(0) @@ -273,7 +273,7 @@ }'''} mbw = self.fake_mbw(files) - mbw.Call = lambda cmd, env=None, buffer_output=True: (0, '', '') + mbw.Call = lambda cmd, env=None, buffer_output=True, stdin=None: (0, '', '') self.check(['analyze', '-c', 'debug_goma', '//out/Default', '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) @@ -297,7 +297,7 @@ }'''} mbw = self.fake_mbw(files) - mbw.Call = lambda cmd, env=None, buffer_output=True: (0, '', '') + mbw.Call = lambda cmd, env=None, buffer_output=True, stdin=None: (0, '', '') self.check(['analyze', '-c', 'debug_goma', '//out/Default', '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) @@ -320,7 +320,7 @@ }'''} mbw = self.fake_mbw(files) - mbw.Call = lambda cmd, env=None, buffer_output=True: (0, '', '') + mbw.Call = lambda cmd, env=None, buffer_output=True, stdin=None: (0, '', '') self.check(['analyze', '-c', 'debug_goma', '//out/Default', '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) @@ -347,7 +347,7 @@ }'''} mbw = self.fake_mbw(files) - mbw.Call = lambda cmd, env=None, buffer_output=True: (0, '', '') + mbw.Call = lambda cmd, env=None, buffer_output=True, stdin=None: (0, '', '') self.check(['analyze', '-c', 'debug_goma', '//out/Default', '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) @@ -407,7 +407,7 @@ def test_gen_fails(self): mbw = self.fake_mbw() - mbw.Call = lambda cmd, env=None, buffer_output=True: (1, '', '') + mbw.Call = lambda cmd, env=None, buffer_output=True, stdin=None: (1, '', '') self.check(['gen', '-c', 'debug_goma', '//out/Default'], mbw=mbw, ret=1) def test_gen_swarming(self): @@ -424,10 +424,11 @@ mbw = self.fake_mbw(files) - def fake_call(cmd, env=None, buffer_output=True): + def fake_call(cmd, env=None, buffer_output=True, stdin=None): del cmd del env del buffer_output + del stdin mbw.files['/fake_src/out/Default/base_unittests.runtime_deps'] = ( 'base_unittests\n') return 0, '', '' @@ -457,10 +458,11 @@ } mbw = self.fake_mbw(files=files) - def fake_call(cmd, env=None, buffer_output=True): + def fake_call(cmd, env=None, buffer_output=True, stdin=None): del cmd del env del buffer_output + del stdin mbw.files['/fake_src/out/Default/cc_perftests.runtime_deps'] = ( 'cc_perftests\n') return 0, '', '' @@ -491,10 +493,11 @@ mbw = self.fake_mbw(files=files) - def fake_call(cmd, env=None, buffer_output=True): + def fake_call(cmd, env=None, buffer_output=True, stdin=None): del cmd del env del buffer_output + del stdin mbw.files['/fake_src/out/Default/cc_perftests_fuzzer.runtime_deps'] = ( 'cc_perftests_fuzzer\n') return 0, '', '' @@ -533,10 +536,11 @@ } mbw = self.fake_mbw(files=files) - def fake_call(cmd, env=None, buffer_output=True): + def fake_call(cmd, env=None, buffer_output=True, stdin=None): del cmd del env del buffer_output + del stdin mbw.files['/fake_src/out/Default/cc_perftests.runtime_deps'] = ( 'cc_perftests_fuzzer\n') return 0, '', ''
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 823baa4..d706874 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2167,6 +2167,12 @@ <int value="7" label="Cached Data Cleared"/> </enum> +<enum name="AppListAddPageType"> + <int value="0" label="By Dragging App"/> + <int value="1" label="By Moving App With Keyboard"/> + <int value="2" label="By Syncing or Intalling App"/> +</enum> + <enum name="AppListAppMovingType"> <int value="0" label="MOVE_BY_DRAG_INTO_FOLDER"/> <int value="1" label="MOVE_BY_DRAG_OUT_OF_FOLDER"/> @@ -6022,6 +6028,11 @@ <int value="1" label="Chose CONTINUE"/> </enum> +<enum name="BooleanCorrect"> + <int value="0" label="Incorrect"/> + <int value="1" label="Correct"/> +</enum> + <enum name="BooleanCorrupt"> <int value="0" label="Not Corrupt"/> <int value="1" label="Corrupt"/> @@ -26413,6 +26424,27 @@ <int value="2" label="Not found"/> </enum> +<enum name="FingerprintRecordFormatVersion"> + <int value="0" label="None"/> + <int value="1" label="Record format version without validation value"/> + <int value="2" label="Record format version with validation value"/> +</enum> + +<enum name="FingerprintSensorMode"> + <int value="0" label="None"/> + <int value="1" label="Deepsleep"/> + <int value="2" label="FingerDown"/> + <int value="3" label="FingerUp"/> + <int value="4" label="Capture"/> + <int value="5" label="EnrollSession"/> + <int value="6" label="EnrollSessionFingerUp"/> + <int value="7" label="EnrollSessionEnrollImage"/> + <int value="8" label="EnrollImage"/> + <int value="9" label="Match"/> + <int value="10" label="ResetSensor"/> + <int value="11" label="DontChange"/> +</enum> + <enum name="FingerprintUpdaterReason"> <int value="0" label="None"/> <int value="1" label="Mismatched RW Version"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 5fa17af0..1acf5241 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -4999,6 +4999,16 @@ </summary> </histogram> +<histogram name="Apps.AppList.AppsGridAddPage" enum="AppListAddPageType" + expires_after="2020-10-16"> + <owner>anasalazar@chromium.org</owner> + <owner>newcomer@chromium.org</owner> + <summary> + The different ways to add page in app list's apps grid. Logged when the page + is created. + </summary> +</histogram> + <histogram name="Apps.AppList.DriveQuickAccessProvider.ApiResults" units="count"> <owner>tby@chromium.org</owner> @@ -48691,6 +48701,30 @@ </summary> </histogram> +<histogram name="Fingerprint.Reset.ResetContextMode" + enum="FingerprintSensorMode" expires_after="M85"> + <owner>tomhughes@chromium.org</owner> + <owner>norvez@chromium.org</owner> + <owner>chromeos-fingerprint@google.com</owner> + <summary>The mode FPMCU was in when we reset context.</summary> +</histogram> + +<histogram name="Fingerprint.SetContext.SetContextMode" + enum="FingerprintSensorMode" expires_after="M85"> + <owner>yichengli@chromium.org</owner> + <owner>norvez@chromium.org</owner> + <owner>chromeos-fingerprint@google.com</owner> + <summary>The mode FPMCU was in when we set its context.</summary> +</histogram> + +<histogram name="Fingerprint.SetContext.Success" enum="BooleanSuccess" + expires_after="M85"> + <owner>yichengli@chromium.org</owner> + <owner>norvez@chromium.org</owner> + <owner>chromeos-fingerprint@google.com</owner> + <summary>Whether setting FPMCU mode succeeded.</summary> +</histogram> + <histogram name="Fingerprint.Unlock.AttemptsCountBeforeSuccess" units="count" expires_after="M85"> <owner>rsorokin@chromium.org</owner> @@ -48756,6 +48790,17 @@ </summary> </histogram> +<histogram name="Fingerprint.Unlock.Match.PositiveMatchSecretCorrect" + enum="BooleanCorrect" expires_after="M85"> + <owner>yichengli@chromium.org</owner> + <owner>norvez@chromium.org</owner> + <owner>chromeos-fingerprint@google.com</owner> + <summary> + Whether the hash of the positive match secret read from FPMCU matches the + record. + </summary> +</histogram> + <histogram name="Fingerprint.Unlock.MatchIgnoredDueToPowerButtonPress" enum="BooleanIgnored" expires_after="M85"> <owner>norvez@chromium.org</owner> @@ -48765,6 +48810,16 @@ </summary> </histogram> +<histogram name="Fingerprint.Unlock.MigrationForPositiveMatchSecretResult" + enum="BooleanSuccess" expires_after="M85"> + <owner>yichengli@chromium.org</owner> + <owner>norvez@chromium.org</owner> + <owner>chromeos-fingerprint@google.com</owner> + <summary> + Whether migrating a record to positive match secret succeeded. + </summary> +</histogram> + <histogram name="Fingerprint.Unlock.NoMatch.Duration.Capture" units="ms" expires_after="M85"> <owner>norvez@chromium.org</owner> @@ -48800,6 +48855,26 @@ </summary> </histogram> +<histogram name="Fingerprint.Unlock.ReadPositiveMatchSecret.Success" + enum="BooleanSuccess" expires_after="M85"> + <owner>yichengli@chromium.org</owner> + <owner>norvez@chromium.org</owner> + <owner>chromeos-fingerprint@google.com</owner> + <summary> + Whether successfully read positive match secret from FPMCU when needed. + </summary> +</histogram> + +<histogram name="Fingerprint.Unlock.RecordFormatVersion" + enum="FingerprintRecordFormatVersion" expires_after="M85"> + <owner>yichengli@chromium.org</owner> + <owner>norvez@chromium.org</owner> + <owner>chromeos-fingerprint@google.com</owner> + <summary> + Format version of a fingerprint template record read from storage. + </summary> +</histogram> + <histogram name="Fingerprint.UnlockEnabled" enum="BooleanEnabled" expires_after="M85"> <owner>rsorokin@chromium.org</owner> @@ -132564,7 +132639,7 @@ <histogram name="SessionRestore.TabLoadTimeout" enum="BooleanTimedOut" expires_after="M77"> - <owner>zhenw@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The boolean indicates whether the tab load was initiated because a previous tab load completed (including the tab was closed) or whether the tab load @@ -146993,8 +147068,7 @@ <histogram name="TabManager.BackgroundTabOpening.ForegroundTab.ExpectedTaskQueueingDuration" units="ms" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The expected queueing duration of tasks in a foreground tab during a background tab opening session (the duration of time from when the browser @@ -147009,8 +147083,8 @@ </histogram> <histogram name="TabManager.BackgroundTabOpening.SwitchToTab" - enum="TabLoadingState"> - <owner>zhenw@chromium.org</owner> + enum="TabLoadingState" expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> The loading state of a tab at the time the user switches to it during a background tab opening session (the duration of time from when the browser @@ -147024,8 +147098,9 @@ </summary> </histogram> -<histogram name="TabManager.BackgroundTabOpening.TabCount" units="tabs"> - <owner>zhenw@chromium.org</owner> +<histogram name="TabManager.BackgroundTabOpening.TabCount" units="tabs" + expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> The max number of background tabs pending or loading when opening background tabs. This is recorded at the end of the background tab opening session (the @@ -147037,8 +147112,8 @@ </histogram> <histogram name="TabManager.BackgroundTabOpening.TabLoadAutoStartedCount" - units="tabs"> - <owner>zhenw@chromium.org</owner> + units="tabs" expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> The number of background tabs whose loading was triggered by TabManager automatically when opening background tabs. This is recorded at the end of @@ -147050,8 +147125,8 @@ </histogram> <histogram name="TabManager.BackgroundTabOpening.TabLoadTimeout" - enum="BooleanTimedOut"> - <owner>zhenw@chromium.org</owner> + enum="BooleanTimedOut" expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> Whether the tab load is timed out during background tab opening session (the duration of time from when the browser starts to open background tabs until @@ -147062,8 +147137,8 @@ </histogram> <histogram name="TabManager.BackgroundTabOpening.TabLoadUserInitiatedCount" - units="tabs"> - <owner>zhenw@chromium.org</owner> + units="tabs" expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> The number of background tabs whose loading was triggered by user action when opening background tabs. For example, when the user selects a @@ -147076,8 +147151,9 @@ </summary> </histogram> -<histogram name="TabManager.BackgroundTabOpening.TabPausedCount" units="tabs"> - <owner>zhenw@chromium.org</owner> +<histogram name="TabManager.BackgroundTabOpening.TabPausedCount" units="tabs" + expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> The max number of background tabs paused to load due to memory pressure when opening background tabs. This is recorded at the end of the background tab @@ -147256,8 +147332,7 @@ <histogram name="TabManager.Experimental.BackgroundTabOpening.CompressedPagesPerSecond" units="pages/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of pages compressed per second when opening background tabs. This is recorded at the end of the background tab opening session as an average @@ -147274,8 +147349,7 @@ <histogram name="TabManager.Experimental.BackgroundTabOpening.DecompressedPagesPerSecond" units="pages/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of pages decompressed per second when opening background tabs. This is recorded at the end of the background tab opening session as an @@ -147291,8 +147365,7 @@ <histogram name="TabManager.Experimental.BackgroundTabOpening.SwapInPerSecond" units="swaps/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of swap-ins per second when opening background tabs. This is recorded at the end of the background tab opening session as an average over @@ -147307,8 +147380,7 @@ <histogram name="TabManager.Experimental.BackgroundTabOpening.SwapOutPerSecond" units="swaps/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of swap-outs per second when opening background tabs. This is recorded at the end of the background tab opening session as an average over @@ -147348,8 +147420,8 @@ <histogram name="TabManager.Experimental.BackgroundTabOpening.TabSwitchLoadTime.UntilTabIsLoaded" - units="ms"> - <owner>zhenw@chromium.org</owner> + units="ms" expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> The tab load time of a tab that is switched to during a background tab opening session (the duration of time from when the browser starts to open @@ -147370,8 +147442,7 @@ <histogram name="TabManager.Experimental.SessionRestore.CompressedPagesPerSecond" units="pages/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of pages compressed per second during session restore. Recorded at the end of session restore as an average over the entire period, defined @@ -147389,8 +147460,7 @@ <histogram name="TabManager.Experimental.SessionRestore.DecompressedPagesPerSecond" units="pages/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of pages decompressed per second during session restore. Recorded at the end of session restore as an average over the entire period, defined @@ -147408,8 +147478,7 @@ <histogram name="TabManager.Experimental.SessionRestore.ForegroundTab.FirstContentfulPaint" units="ms" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> Elapsed time between the start of the loading and the first contentful paint of foreground tabs when the browser loads tabs in session restore. @@ -147419,8 +147488,7 @@ <histogram name="TabManager.Experimental.SessionRestore.ForegroundTab.FirstMeaningfulPaint" units="ms" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> Elapsed time between the start of the loading and the first meaningful paint of foreground tabs when the browser loads tabs in session restore. @@ -147430,8 +147498,7 @@ <histogram name="TabManager.Experimental.SessionRestore.ForegroundTab.FirstPaint" units="ms" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> Elapsed time between the start of the loading and the first paint of foreground tabs when the browser loads tabs in session restore. @@ -147440,8 +147507,7 @@ <histogram name="TabManager.Experimental.SessionRestore.SwapInPerSecond" units="swaps/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of swap-ins per second during session restore. Recorded at the end of session restore as an average over the entire period, defined as the @@ -147457,8 +147523,7 @@ <histogram name="TabManager.Experimental.SessionRestore.SwapOutPerSecond" units="swaps/s" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The number of swap-outs per second during session restore. Recorded at the end of session restore as an average over the entire period, defined as the @@ -147478,8 +147543,7 @@ Deprecated 08/2017, and replaced by TabManager.Experimental.SessionRestore.TabSwitchLoadTime.UntilTabIsLoaded. </obsolete> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The tab load time of a tab that is switched to during a session restore. Tab load time is defined as the time between when the user switches to a @@ -147501,8 +147565,7 @@ <histogram name="TabManager.Experimental.SessionRestore.TabSwitchLoadTime.UntilTabIsLoaded" units="ms" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The tab load time of a tab that is switched to during a session restore. Tab load time is defined as the time between when the user switches to a @@ -147585,8 +147648,8 @@ </histogram> <histogram name="TabManager.SessionOverlap.BackgroundTabOpening" - units="BooleanOverlap"> - <owner>zhenw@chromium.org</owner> + units="BooleanOverlap" expires_after="M79"> + <owner>chrisha@chromium.org</owner> <summary> Whether background tab opening session is overlapped with other types of session, e.g., session restore. Background tab opening session is the @@ -147599,7 +147662,7 @@ <histogram name="TabManager.SessionOverlap.SessionRestore" units="BooleanOverlap" expires_after="M77"> - <owner>zhenw@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> Whether session restore is overlapped with other types of session, e.g., background tab opening. Session restore is the duration from the time when @@ -147647,8 +147710,7 @@ <histogram name="TabManager.SessionRestore.ForegroundTab.ExpectedTaskQueueingDuration" units="ms" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The expected queueing duration of tasks in a foreground tab during session restore. This metric reflects the responsiveness of a tab. A lower value @@ -147695,8 +147757,7 @@ <histogram name="TabManager.SessionRestore.SwitchToTab" enum="TabLoadingState" expires_after="M79"> - <owner>shaseley@chromium.org</owner> - <owner>panicker@chromium.org</owner> + <owner>chrisha@chromium.org</owner> <summary> The loading state of a tab at the time the user switched to it during a session restore. The metric is only recorded when a tab is switched to from
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py index e8f9fc4..a508d02 100644 --- a/tools/perf/benchmarks/benchmark_smoke_unittest.py +++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -15,8 +15,6 @@ from chrome_telemetry_build import chromium_config -from core import path_util - from telemetry import benchmark as benchmark_module from telemetry import decorators from telemetry.testing import options_for_unittests @@ -87,17 +85,8 @@ benchmark_cls=SinglePageBenchmark, environment=chromium_config.GetDefaultChromiumConfig()) options.pageset_repeat = 1 # For smoke testing only run the page once. - single_page_benchmark = SinglePageBenchmark() - # TODO(crbug.com/985103): Remove this code once - # AugmentExpectationsWithFile is deleted and replaced with functionality - # in story_filter.py. - if hasattr(single_page_benchmark, 'AugmentExpectationsWithFile'): - with open(path_util.GetExpectationsPath()) as fp: - single_page_benchmark.AugmentExpectationsWithFile(fp.read()) - return_code = single_page_benchmark.Run(options) - if return_code == -1: self.skipTest('The benchmark was not run.') self.assertEqual(0, return_code, msg='Failed: %s' % benchmark)
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py index e025326f..2f65fb7 100644 --- a/tools/perf/benchmarks/system_health_smoke_test.py +++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -14,7 +14,6 @@ from chrome_telemetry_build import chromium_config -from core import path_util from core import perf_benchmark from telemetry import decorators @@ -254,17 +253,8 @@ if (simplified_test_name in _DISABLED_TESTS and not options.run_disabled_tests): self.skipTest('Test is explicitly disabled') - single_page_benchmark = SinglePageBenchmark() - # TODO(crbug.com/985103): Remove this code once - # AugmentExpectationsWithFile is deleted and replaced with functionality - # in story_filter.py. - if hasattr(single_page_benchmark, 'AugmentExpectationsWithFile'): - with open(path_util.GetExpectationsPath()) as fp: - single_page_benchmark.AugmentExpectationsWithFile(fp.read()) - return_code = single_page_benchmark.Run(options) - if return_code == -1: self.skipTest('The benchmark was not run.') self.assertEqual(0, return_code, msg='Failed: %s' % benchmark_class)
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index c52af632..edf8b348 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -4,6 +4,7 @@ # found in the LICENSE file. # pylint: disable=too-many-lines +# pylint: disable=line-too-long """Generates chromium.perf{,.fyi}.json from a set of condensed configs. @@ -686,9 +687,10 @@ 'platform': 'win', 'target_bits': 64, 'dimension': { - 'pool': 'chrome.tests.perf', - 'os': 'Windows-2008ServerR2-SP1', - 'gpu': '10de:1cb3' + 'gpu': '10de:1cb3-23.21.13.8792', + 'os': 'Windows-2008ServerR2-SP1', + 'pool': 'chrome.tests.perf', + 'synthetic_product_name': 'PowerEdge R220 [01] (Dell Inc.)' }, }, 'mac-10_12_laptop_low_end-perf': { @@ -815,13 +817,15 @@ ], 'platform': 'mac', 'dimension': { - 'pool': 'chrome.tests.perf', - 'os': 'Mac-10.13', - 'gpu': '1002:6821' + 'gpu': '1002:6821-4.0.20-3.2.8', + 'os': 'Mac-10.13.3', + 'pool': 'chrome.tests.perf', + 'synthetic_product_name': 'MacBookPro11,5_x86-64-i7-4870HQ_AMD Radeon R8 M370X 4.0.20 [3.2.8]_Intel Haswell Iris Pro Graphics 5200 4.0.20 [3.2.8]_16384_1_475936.0', }, }, } +# pylint: enable=line-too-long def update_all_tests(builders_dict, file_path): tests = {}
diff --git a/ui/base/cocoa/tool_tip_base_view.mm b/ui/base/cocoa/tool_tip_base_view.mm index 059889a..d7d1536 100644 --- a/ui/base/cocoa/tool_tip_base_view.mm +++ b/ui/base/cocoa/tool_tip_base_view.mm
@@ -146,8 +146,15 @@ // Sends a fake NSMouseEntered event to the view for its current tracking rect. - (void)_sendToolTipMouseEntered { - // Nothing matters except window, trackingNumber, and userData. int windowNumber = [[self window] windowNumber]; + + // Only send a fake mouse enter if the mouse is actually over the window, + // versus over a window which overlaps it (see http://crbug.com/883269). + if ([NSWindow windowNumberAtPoint:[NSEvent mouseLocation] + belowWindowWithWindowNumber:0] != windowNumber) + return; + + // Nothing matters except window, trackingNumber, and userData. NSTimeInterval eventTime = [[NSApp currentEvent] timestamp]; NSEvent* fakeEvent = [NSEvent enterExitEventWithType:NSMouseEntered location:NSZeroPoint
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index bd8491ad..03078f1c 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc
@@ -192,6 +192,29 @@ } } +// Replace the unicode control characters ISO 6429 (block C0) by their +// corresponsing visual symbols. Control chracters can't be displayed but +// their visual symbols can. +void ReplaceControlCharactersWithSymbols(bool multiline, base::string16* text) { + // Control Pictures block (see: https://unicode.org/charts/PDF/U2400.pdf). + constexpr base::char16 kSymbolsCodepoint = 0x2400; + for (size_t offset = 0; offset < text->size(); ++offset) { + base::char16 control_codepoint = (*text)[offset]; + if (control_codepoint >= 0 && control_codepoint <= 0x1F) { + // The newline character should be kept as-is when rendertext is + // multiline. + if (control_codepoint == '\n' && multiline) + continue; + // Replace codepoints with their visual symbols, which are at the same + // offset from kSymbolsCodepoint. + (*text)[offset] = kSymbolsCodepoint + control_codepoint; + } else if (control_codepoint == 0x7F) { + // Replace the 'del' codepoint by its symbol (u2421). + (*text)[offset] = kSymbolsCodepoint + 0x21; + } + } +} + } // namespace namespace internal { @@ -507,14 +530,6 @@ } } -void RenderText::SetReplaceNewlineCharsWithSymbols(bool replace) { - if (replace_newline_chars_with_symbols_ == replace) - return; - replace_newline_chars_with_symbols_ = replace; - cached_bounds_and_offset_valid_ = false; - OnTextAttributeChanged(); -} - void RenderText::SetMinLineHeight(int line_height) { if (min_line_height_ == line_height) return; @@ -1137,7 +1152,6 @@ multiline_(false), max_lines_(0), word_wrap_behavior_(IGNORE_LONG_WORDS), - replace_newline_chars_with_symbols_(true), subpixel_rendering_suppressed_(false), clip_to_display_rect_(true), baseline_(kInvalidBaseline), @@ -1661,10 +1675,10 @@ layout_text_.assign(text.substr(0, iter.getIndex()) + kEllipsisUTF16); } } - static const base::char16 kNewline[] = { '\n', 0 }; - static const base::char16 kNewlineSymbol[] = { 0x2424, 0 }; - if (!multiline_ && replace_newline_chars_with_symbols_) - base::ReplaceChars(layout_text_, kNewline, kNewlineSymbol, &layout_text_); + + // Handle unicode control characters ISO 6429 (block C0). Range from 0 to 0x1F + // and 0x7F. + ReplaceControlCharactersWithSymbols(multiline_, &layout_text_); OnLayoutTextAttributeChanged(true); }
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h index d0dc1d0..511d534 100644 --- a/ui/gfx/render_text.h +++ b/ui/gfx/render_text.h
@@ -292,9 +292,6 @@ WordWrapBehavior word_wrap_behavior() const { return word_wrap_behavior_; } void SetWordWrapBehavior(WordWrapBehavior behavior); - // Set whether newline characters should be replaced with newline symbols. - void SetReplaceNewlineCharsWithSymbols(bool replace); - // Returns true if this instance supports multiline rendering. virtual bool MultilineSupported() const = 0; @@ -931,9 +928,6 @@ // |multiline_| is set. The default value is IGNORE_LONG_WORDS. WordWrapBehavior word_wrap_behavior_; - // Whether newline characters should be replaced with newline symbols. - bool replace_newline_chars_with_symbols_; - // Set to true to suppress subpixel rendering due to non-font reasons (eg. // if the background is transparent). The default value is false. bool subpixel_rendering_suppressed_;
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index d9ade56..81d3bec6 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -4290,6 +4290,20 @@ } } +TEST_F(RenderTextTest, ControlCharacterReplacement) { + static const char kTextWithControlCharacters[] = "\b\r\a\t\n\v\f"; + + RenderText* render_text = GetRenderText(); + render_text->SetText(UTF8ToUTF16(kTextWithControlCharacters)); + + // The control characters should have been replaced by their symbols. + EXPECT_EQ(WideToUTF16(L"␈␍␇␉␊␋␌"), render_text->GetDisplayText()); + + // Setting multiline, the newline character will be back to the original text. + render_text->SetMultiline(true); + EXPECT_EQ(WideToUTF16(L"␈␍␇␉\n␋␌"), render_text->GetDisplayText()); +} + // Make sure the horizontal positions of runs in a line (left-to-right for // LTR languages and right-to-left for RTL languages). TEST_F(RenderTextTest, HarfBuzz_HorizontalPositions) {
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc index 1837167..72d94f1 100644 --- a/ui/views/controls/label.cc +++ b/ui/views/controls/label.cc
@@ -239,7 +239,6 @@ return; multi_line_ = multi_line; full_text_->SetMultiline(multi_line); - full_text_->SetReplaceNewlineCharsWithSymbols(!multi_line); OnPropertyChanged(&multi_line_, kPropertyEffectsLayout); }
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn index 68e8f369..88675f5 100644 --- a/weblayer/BUILD.gn +++ b/weblayer/BUILD.gn
@@ -44,6 +44,7 @@ "browser/browser_main_parts_impl.h", "browser/content_browser_client_impl.cc", "browser/content_browser_client_impl.h", + "browser/isolated_world_ids.h", "browser/navigation_controller_impl.cc", "browser/navigation_controller_impl.h", "browser/navigation_impl.cc",
diff --git a/weblayer/browser/browser_controller_impl.cc b/weblayer/browser/browser_controller_impl.cc index 880f2c10..c373975 100644 --- a/weblayer/browser/browser_controller_impl.cc +++ b/weblayer/browser/browser_controller_impl.cc
@@ -21,7 +21,10 @@ #endif #if defined(OS_ANDROID) +#include "base/android/callback_android.h" #include "base/android/jni_string.h" +#include "base/json/json_writer.h" +#include "weblayer/browser/isolated_world_ids.h" #include "weblayer/browser/java/jni/BrowserControllerImpl_jni.h" #include "weblayer/browser/top_controls_container_view.h" #endif @@ -40,6 +43,14 @@ #if defined(OS_ANDROID) BrowserController* g_last_browser_controller; + +void JavaScriptResultCallback( + const base::android::ScopedJavaGlobalRef<jobject>& callback, + base::Value result) { + std::string json; + base::JSONWriter::Write(result, &json); + base::android::RunStringCallbackAndroid(callback, json); +} #endif } // namespace @@ -149,6 +160,17 @@ native_top_controls_container_view); } +void BrowserControllerImpl::ExecuteScript( + JNIEnv* env, + const base::android::JavaParamRef<jstring>& script, + const base::android::JavaParamRef<jobject>& callback) { + base::android::ScopedJavaGlobalRef<jobject> jcallback(env, callback); + web_contents_->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld( + base::android::ConvertJavaStringToUTF16(script), + base::BindOnce(&JavaScriptResultCallback, jcallback), + ISOLATED_WORLD_ID_WEBLAYER); +} + #endif void BrowserControllerImpl::LoadingStateChanged(content::WebContents* source,
diff --git a/weblayer/browser/browser_controller_impl.h b/weblayer/browser/browser_controller_impl.h index 59d9676d..ec14c599 100644 --- a/weblayer/browser/browser_controller_impl.h +++ b/weblayer/browser/browser_controller_impl.h
@@ -54,6 +54,9 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& caller, jlong native_top_controls_container_view); + void ExecuteScript(JNIEnv* env, + const base::android::JavaParamRef<jstring>& script, + const base::android::JavaParamRef<jobject>& callback); #endif DownloadDelegate* download_delegate() { return download_delegate_; }
diff --git a/weblayer/browser/isolated_world_ids.h b/weblayer/browser/isolated_world_ids.h new file mode 100644 index 0000000..ecef6ad --- /dev/null +++ b/weblayer/browser/isolated_world_ids.h
@@ -0,0 +1,18 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBLAYER_BROWSER_ISOLATED_WORLD_IDS_H_ +#define WEBLAYER_BROWSER_ISOLATED_WORLD_IDS_H_ + +#include "content/public/common/isolated_world_ids.h" + +namespace weblayer { + +enum IsolatedWorldIDs { + ISOLATED_WORLD_ID_WEBLAYER = content::ISOLATED_WORLD_ID_CONTENT_END + 1, +}; + +} // namespace weblayer + +#endif // WEBLAYER_BROWSER_ISOLATED_WORLD_IDS_H_
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java index 51348b2..0fec708 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java
@@ -13,6 +13,7 @@ import android.webkit.ValueCallback; import android.widget.FrameLayout; +import org.chromium.base.Callback; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; import org.chromium.content_public.browser.ViewEventSink; @@ -161,6 +162,22 @@ } } + @Override + public void executeScript(String script, IObjectWrapper callback) { + Callback<String> nativeCallback = new Callback<String>() { + @Override + public void onResult(String result) { + ValueCallback<String> unwrappedCallback = + (ValueCallback<String>) ObjectWrapper.unwrap(callback, ValueCallback.class); + if (unwrappedCallback != null) { + unwrappedCallback.onReceiveValue(result); + } + } + }; + BrowserControllerImplJni.get().executeScript( + mNativeBrowserController, script, nativeCallback); + } + public void destroy() { BrowserControllerImplJni.get().setTopControlsContainerView( mNativeBrowserController, BrowserControllerImpl.this, 0); @@ -206,5 +223,7 @@ BrowserControllerImpl caller, long nativeTopControlsContainerView); void deleteBrowserController(long browserController); WebContents getWebContents(long nativeBrowserControllerImpl, BrowserControllerImpl caller); + void executeScript( + long nativeBrowserControllerImpl, String script, Callback<String> callback); } }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/aidl/IBrowserController.aidl b/weblayer/browser/java/org/chromium/weblayer_private/aidl/IBrowserController.aidl index 63de6348..0d42322 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/aidl/IBrowserController.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/aidl/IBrowserController.aidl
@@ -17,4 +17,6 @@ void setDownloadDelegateClient(IDownloadDelegateClient client) = 2; void setFullscreenDelegateClient(in IFullscreenDelegateClient client) = 3; + + void executeScript(in String script, in IObjectWrapper callback) = 4; }
diff --git a/weblayer/public/java/org/chromium/weblayer/BrowserController.java b/weblayer/public/java/org/chromium/weblayer/BrowserController.java index f1c4e352..33fe878 100644 --- a/weblayer/public/java/org/chromium/weblayer/BrowserController.java +++ b/weblayer/public/java/org/chromium/weblayer/BrowserController.java
@@ -8,6 +8,9 @@ import android.os.RemoteException; import android.webkit.ValueCallback; +import org.json.JSONException; +import org.json.JSONObject; + import org.chromium.weblayer_private.aidl.APICallException; import org.chromium.weblayer_private.aidl.IBrowserController; import org.chromium.weblayer_private.aidl.IBrowserControllerClient; @@ -17,6 +20,9 @@ import org.chromium.weblayer_private.aidl.ObjectWrapper; public final class BrowserController { + /** The top level key of the JSON object returned by executeScript(). */ + public static final String SCRIPT_RESULT_KEY = "result"; + private final IBrowserController mImpl; private FullscreenDelegateClientImpl mFullscreenDelegateClient; private final NavigationController mNavigationController; @@ -66,6 +72,32 @@ return mDownloadDelegateClient != null ? mDownloadDelegateClient.getDelegate() : null; } + /** + * Executes the script in an isolated world, and returns the result as a JSON object to the + * callback if provided. The object passed to the callback will have a single key + * SCRIPT_RESULT_KEY which will hold the result of running the script. + */ + public void executeScript(String script, ValueCallback<JSONObject> callback) { + try { + ValueCallback<String> stringCallback = (String result) -> { + if (callback == null) { + return; + } + + try { + callback.onReceiveValue( + new JSONObject("{\"" + SCRIPT_RESULT_KEY + "\":" + result + "}")); + } catch (JSONException e) { + // This should never happen since the result should be well formed. + throw new RuntimeException(e); + } + }; + mImpl.executeScript(script, ObjectWrapper.wrap(stringCallback)); + } catch (RemoteException e) { + throw new APICallException(e); + } + } + public FullscreenDelegate getFullscreenDelegate() { return mFullscreenDelegateClient != null ? mFullscreenDelegateClient.getDelegate() : null; }
diff --git a/weblayer/shell/android/BUILD.gn b/weblayer/shell/android/BUILD.gn index 76f75d3..f04b45d2 100644 --- a/weblayer/shell/android/BUILD.gn +++ b/weblayer/shell/android/BUILD.gn
@@ -258,6 +258,7 @@ "javatests/src/org/chromium/weblayer/test/BrowserObserverTest.java", "javatests/src/org/chromium/weblayer/test/NavigationTest.java", "javatests/src/org/chromium/weblayer/test/SmokeTest.java", + "javatests/src/org/chromium/weblayer/test/ExecuteScriptTest.java", "javatests/src/org/chromium/weblayer/test/RenderingTest.java", "javatests/src/org/chromium/weblayer/test/WebLayerShellActivityTestRule.java", "javatests/src/org/chromium/weblayer/test/FragmentRestoreTest.java",
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/ExecuteScriptTest.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/ExecuteScriptTest.java new file mode 100644 index 0000000..f39768c --- /dev/null +++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/ExecuteScriptTest.java
@@ -0,0 +1,86 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.weblayer.test; + +import android.support.test.filters.SmallTest; + +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.UrlUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.weblayer.BrowserController; +import org.chromium.weblayer.shell.WebLayerShellActivity; + +/** + * Tests that script execution works as expected. + */ +@RunWith(BaseJUnit4ClassRunner.class) +public class ExecuteScriptTest { + @Rule + public WebLayerShellActivityTestRule mActivityTestRule = new WebLayerShellActivityTestRule(); + + private static final String DATA_URL = UrlUtils.encodeHtmlDataUri( + "<html><head><script>var bar = 10;</script></head><body>foo</body></html>"); + + @Test + @SmallTest + public void testBasicScript() throws Exception { + WebLayerShellActivity activity = mActivityTestRule.launchShellWithUrl(DATA_URL); + mActivityTestRule.waitForNavigation(DATA_URL); + JSONObject result = mActivityTestRule.executeScriptSync("document.body.innerHTML"); + Assert.assertEquals(result.getString(BrowserController.SCRIPT_RESULT_KEY), "foo"); + } + + @Test + @SmallTest + public void testScriptIsolatedFromPage() throws Exception { + WebLayerShellActivity activity = mActivityTestRule.launchShellWithUrl(DATA_URL); + mActivityTestRule.waitForNavigation(DATA_URL); + JSONObject result = mActivityTestRule.executeScriptSync("bar"); + Assert.assertTrue(result.isNull(BrowserController.SCRIPT_RESULT_KEY)); + } + + @Test + @SmallTest + public void testScriptNotIsolatedFromOtherScript() throws Exception { + WebLayerShellActivity activity = mActivityTestRule.launchShellWithUrl(DATA_URL); + mActivityTestRule.waitForNavigation(DATA_URL); + mActivityTestRule.executeScriptSync("var foo = 20;"); + JSONObject result = mActivityTestRule.executeScriptSync("foo"); + Assert.assertEquals(result.getInt(BrowserController.SCRIPT_RESULT_KEY), 20); + } + + @Test + @SmallTest + public void testClearedOnNavigate() throws Exception { + WebLayerShellActivity activity = mActivityTestRule.launchShellWithUrl(DATA_URL); + mActivityTestRule.waitForNavigation(DATA_URL); + mActivityTestRule.executeScriptSync("var foo = 20;"); + + String newUrl = UrlUtils.encodeHtmlDataUri("<html></html>"); + mActivityTestRule.loadUrl(newUrl); + mActivityTestRule.waitForNavigation(newUrl); + JSONObject result = mActivityTestRule.executeScriptSync("foo"); + Assert.assertTrue(result.isNull(BrowserController.SCRIPT_RESULT_KEY)); + } + + @Test + @SmallTest + public void testNullCallback() throws Exception { + WebLayerShellActivity activity = mActivityTestRule.launchShellWithUrl(DATA_URL); + mActivityTestRule.waitForNavigation(DATA_URL); + TestThreadUtils.runOnUiThreadBlocking(() -> { + // Null callback should not crash. + activity.getBrowserController().executeScript("null", null); + }); + // Execute a sync script to make sure the other script finishes. + mActivityTestRule.executeScriptSync("null"); + } +}
diff --git a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/WebLayerShellActivityTestRule.java b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/WebLayerShellActivityTestRule.java index 78df02da..aa9d91c7 100644 --- a/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/WebLayerShellActivityTestRule.java +++ b/weblayer/shell/android/javatests/src/org/chromium/weblayer/test/WebLayerShellActivityTestRule.java
@@ -14,6 +14,9 @@ import android.support.test.InstrumentationRegistry; import android.support.test.rule.ActivityTestRule; +import org.json.JSONObject; + +import org.chromium.base.test.util.CallbackHelper; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -21,6 +24,7 @@ import org.chromium.weblayer.shell.WebLayerShellActivity; import java.lang.reflect.Field; +import java.util.concurrent.TimeoutException; /** * ActivityTestRule for WebLayerShellActivity. @@ -30,6 +34,19 @@ public class WebLayerShellActivityTestRule extends ActivityTestRule<WebLayerShellActivity> { private static final long WAIT_FOR_NAVIGATION_TIMEOUT = 10000L; + private static final class JSONCallbackHelper extends CallbackHelper { + private JSONObject mResult; + + public JSONObject getResult() { + return mResult; + } + + public void notifyCalled(JSONObject result) { + mResult = result; + notifyCalled(); + } + } + public WebLayerShellActivityTestRule() { super(WebLayerShellActivity.class, false, false); } @@ -102,4 +119,22 @@ throw new RuntimeException(e); } } + + /** + * Executes the script passed in and waits for the result. + */ + public JSONObject executeScriptSync(String script) { + JSONCallbackHelper callbackHelper = new JSONCallbackHelper(); + int count = callbackHelper.getCallCount(); + TestThreadUtils.runOnUiThreadBlocking(() -> { + getActivity().getBrowserController().executeScript( + script, (JSONObject result) -> { callbackHelper.notifyCalled(result); }); + }); + try { + callbackHelper.waitForCallback(count); + } catch (TimeoutException e) { + throw new RuntimeException(e); + } + return callbackHelper.getResult(); + } }